Skip to content

Instantly share code, notes, and snippets.

@yuitest
Created September 25, 2013 09:31
Show Gist options
  • Save yuitest/6697267 to your computer and use it in GitHub Desktop.
Save yuitest/6697267 to your computer and use it in GitHub Desktop.
Python で書いた何の変哲もない 3 目ならべ。 技術的に特別なことは何もしていない。 ただ、これを Wrap して Console -> Web API -> Web Application としていくにはどういう設計がいいか、 どうしたら美しく書けるか、を考えながら書いていた。
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from __future__ import print_function
def enum(**enums):
return type(str('Enum'), (), enums)
class TicTacToeException(Exception):
pass
class TicTacToe(object):
STATUS = enum(INIT=0, MAIN=1, GAMEOVER=2)
MARK = enum(EMPTY=0, A=1, B=2)
def __init__(
self,
size=3,
state=STATUS.INIT,
current=MARK.A,
winner=None,
board=None,
):
if board is None:
board = self.plain_board(size=size)
self.size = size
self.state = state
self.current = current
self.winner = winner
self.board = board
@classmethod
def plain_board(cls, size=3, fillwith=MARK.EMPTY):
range_ = range(size)
return [[fillwith for _ in range_] for __ in range_]
def start(self):
if self.state != self.STATUS.INIT:
raise TicTacToeException()
self.state = self.STATUS.MAIN
def is_puttable(self, i, j):
try:
return self.board[i][j] == self.MARK.EMPTY
except Exception:
return False
def put(self, i, j):
if self.state != self.STATUS.MAIN:
raise TicTacToeException()
if not self.is_puttable(i, j):
raise TicTacToeException()
self.board[i][j] = self.current
def board_lines(self):
board = self.board
size = self.size
horizonal = [tuple(line) for line in board]
vertical = zip(*board)
diagonal = [
tuple(board[x][x] for x in range(size)),
tuple(board[x][size - 1 - x] for x in range(size)),
]
return tuple(horizonal + vertical + diagonal)
def judge(self):
all_lines = self.board_lines()
if (self.MARK.A, ) * self.size in all_lines:
winner = self.MARK.A
elif (self.MARK.B, ) * self.size in all_lines:
winner = self.MARK.B
else:
return
self.winner = winner
self.state = self.STATUS.GAMEOVER
def next_turn(self):
if self.current == self.MARK.A:
next = self.MARK.B
elif self.current == self.MARK.B:
next = self.MARK.A
self.current = next
def dump(self):
return {
'state': self.state,
'current': self.current,
'winner': self.winner,
'board': self.board,
}
@classmethod
def load(cls, data):
return cls(**data)
if __name__ == '__main__':
'''
実際のゲームの流れをテスト
'''
t = TicTacToe()
print(t.dump())
t.start()
putting = (
(0, 1),
(1, 2),
(1, 1),
(2, 2),
(1, 0),
(0, 0),
(2, 1),
)
for i, j in putting:
if t.is_puttable(i, j):
t.put(i, j)
t.judge()
if t.winner is None:
t.next_turn()
print(t.dump())
print(t.winner)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment