def test_init_1_1(self): ''' Test construction parameter and consistency with properties ''' board = Board(1, 1) self.assertEqual(board._cell_free_count, 1) self.assertTrue(board.has_free_cell()) self.assertEqual(board.cell_used_count, 0)
def test_has_free_cell(self): board = Board(3, 3) for x in range(3): for y in range(3): self.assertTrue(board.has_free_cell()) self.assertTrue(board.add_token(Point(x, y), "X")) self.assertFalse(board.has_free_cell())
def test_equal_array(self): import numpy as np a = [1, 1, 1] b = [1, 1, 1] c = [0, 0, 0] d = np.full(3, 1) self.assertTrue(Board.array_equal(a, b)) self.assertFalse(Board.array_equal(a, c)) self.assertTrue(Board.array_equal(a, d))
def test_x_y_order(self): w, h = 5, 3 board = Board(w, h) self.assertTrue(board.add_token(Point(2, 1), 'x')) self.assertTrue(board.add_token(Point(4, 0), 'x')) self.assertTrue(board.add_token(Point(4, 2), 'o')) self.assertTrue(board.add_token(Point(0, 2), 'u')) # print(board) self.assertEqual(board.column_count, w) self.assertEqual(board.row_count, h)
def test_get_diag_down(self): ''' 00|10|20|30|40| 01|11|21|31|41| 02|12|22|32|42| ''' import numpy as np w, h = 5, 3 board = Board(w, h) for y in range(h): for x in range(w): board.add_token(Point(x, y), str(x) + str(y)) line = board.get_diag_down(0, 0) self.assertTrue(np.array_equal(line, ['00', '11', '22'])) line = board.get_diag_down(3, 0) self.assertTrue(np.array_equal(line, ['30', '41'])) line = board.get_diag_down(4, 2) self.assertTrue(np.array_equal(line, ['20', '31', '42'])) line = board.get_diag_down(0, 1) self.assertTrue(np.array_equal(line, ['01', '12'])) line = board.get_diag_down(1, 2) self.assertTrue(np.array_equal(line, ['01', '12']))
def test_anti_diag(self): import numpy as np w, h = 5, 3 board = Board(w, h) for y in range(h): for x in range(w): board.add_token(Point(x, y), str(x) + str(y)) line = np.flipud(board._grid).diagonal(0) self.assertTrue(np.array_equal(line, ['02', '11', '20'])) line = np.flipud(board._grid).diagonal(1) self.assertTrue(np.array_equal(line, ['12', '21', '30'])) line = np.flipud(board._grid).diagonal(-1) self.assertTrue(np.array_equal(line, ['01', '10']))
def test_undo(self): board = Board(4, 2) token = "X" # Add 2 token self.assertTrue(board.add_token(Point(0, 0), token)) self.assertTrue(board.add_token(Point(1, 0), token)) self.assertEqual(board.cell_used_count, 2) # Undo last one board.undo(Point(1, 0)) self.assertEqual(board.cell_used_count, 1) # Check value in grid self.assertEqual(board.grid[0][0], token) self.assertEqual(board.grid[0][1], None)
def __init__(self, p1=None, p2=None, size=9, line_win_size=5): self._board = Board(size, size) self._line_win_size = line_win_size self._p1 = p1 if not p1 is None else Player("Player 1", Token.A) self._p2 = p2 if not p2 is None else Player("Player 2", Token.B) assert (not (self._p1.token == self._p2.token)) self._current_player = self._p1 self._winner_player = None self._is_over = False self._history = list() self._moves_remaining = set( [Point(x, y) for y in range(size) for x in range(size)]) self._patterns = [ np.full(self._line_win_size, token) for token in [Token.A, Token.B] ]
def test_deepcopy(self): w, h = 5, 3 b = Board(w, h) cb = copy.deepcopy(b) self.assertFalse(b is cb) self.assertFalse(b._grid is cb._grid) self.assertFalse(b._moves is cb._moves)
def test_board_array_equal(self): setup = ''' from game_base.board import Board a = ['x' for _ in range(10)] b = ['o' for _ in range(10)] ''' stmt = ''' Board.array_equal(a,b) Board.array_equal(a,a) ''' print("board:", timeit.timeit(setup=setup, stmt=stmt, number=100000))
def test_has_winner_diag_down(self): board = Board(7, 6) token = Token.A board.add_token(Point(0, 2), token) board.add_token(Point(1, 3), token) board.add_token(Point(2, 4), token) board.add_token(Point(3, 5), token) game = ConnectFour() self.assertEqual(game._has_winner_diagonal(board, Point(3, 5)), (True, token))
def test_get_row(self): import numpy as np w, h = 5, 3 board = Board(w, h) # len self.assertEqual(len(board.get_row(0)), w) # Default to None a = [None for i in range(w)] self.assertTrue(np.array_equal(board.get_row(0), a)) # Insert a[4] = 'x' board.add_token(Point(4, 0), 'x') self.assertTrue(np.array_equal(board.get_row(0), a)) # Exception board.get_row(0) board.get_row(1) board.get_row(2) with self.assertRaises(IndexError): board.get_row(3)
def test_add_token_on_used_cell(self): board = Board(2, 4) self.assertTrue(board.add_token(Point(0, 0), "X")) self.assertFalse(board.add_token(Point(0, 0), "X"))
def test_boundaries(self): board = Board(3, 3) self.assertFalse(board.add_token(Point(-1, 0), "X")) self.assertFalse(board.add_token(Point(-2, -3), "X")) self.assertFalse(board.add_token(Point(0, -4), "X")) with self.assertRaises(IndexError): board.add_token(Point(3, 0), "X") with self.assertRaises(IndexError): board.add_token(Point(3, 5), "X") with self.assertRaises(IndexError): board.add_token(Point(0, 5), "X")
def test_cell_used_count(self): board = Board(3, 5) self.assertEqual(board.cell_used_count, 0) self.assertTrue(board.add_token(Point(0, 0), "X")) self.assertEqual(board.cell_used_count, 1)
def test_get_column(self): import numpy as np w, h = 5, 3 board = Board(w, h) # Len self.assertEqual(len(board.get_column(0)), h) # Default to None a = [None for i in range(h)] self.assertTrue(np.array_equal(board.get_column(0), a)) # Insert a[2] = 'x' board.add_token(Point(0, 2), 'x') self.assertTrue(np.array_equal(board.get_column(0), a)) # Exception board.get_column(0) board.get_column(1) board.get_column(2) board.get_column(3) board.get_column(4) with self.assertRaises(IndexError): board.get_row(5)
def test_get_diag_up(self): ''' 00|10|20| 01|11|21| 02|12|22| 03|13|23| 04|14|24| 04|14|24| 03|13|23| 02|12|22| 01|11|21| 00|10|20| ''' import numpy as np w, h = 3, 5 board = Board(w, h) for y in range(h): for x in range(w): board.add_token(Point(x, y), str(x) + str(y)) line = board.get_diag_up(0, 4) self.assertTrue(np.array_equal(line, ['04', '13', '22'])) line = board.get_diag_up(0, 3) self.assertTrue(np.array_equal(line, ['03', '12', '21'])) line = board.get_diag_up(0, 2) self.assertTrue(np.array_equal(line, ['02', '11', '20'])) line = board.get_diag_up(0, 1) self.assertTrue(np.array_equal(line, ['01', '10'])) line = board.get_diag_up(1, 4) self.assertTrue(np.array_equal(line, ['14', '23'])) line = board.get_diag_up(2, 4) self.assertTrue(np.array_equal(line, ['24'])) line = board.get_diag_up(1, 1) self.assertTrue(np.array_equal(line, ['02', '11', '20']))
def test_check_line_horizontal(self): w, h = 5, 3 board = Board(w, h) token = 'x' # Check empty row for y in range(h): self.assertTrue(board.check_line_horizontal(0, y, [None])) self.assertTrue(board.check_line_horizontal(1, y, [None, None])) self.assertFalse(board.check_line_horizontal(2, y, [token])) self.assertTrue(board.check_line_horizontal(3, y, [None, None])) # |-|x|-|x|-| self.assertTrue(board.add_token(Point(1, 1), token)) self.assertTrue(board.add_token(Point(3, 1), token)) self.assertTrue(board.check_line_horizontal(1, 1, [token])) self.assertTrue(board.check_line_horizontal(3, 1, [token])) self.assertTrue(board.check_line_horizontal( 1, 1, [token, None, token])) self.assertTrue(board.check_line_horizontal( 2, 1, [token, None, token])) self.assertTrue(board.check_line_horizontal( 3, 1, [token, None, token])) self.assertFalse(board.check_line_horizontal(2, 1, [token, token])) # |-|x|x|x|-| self.assertTrue(board.add_token(Point(2, 1), token)) self.assertTrue(board.check_line_horizontal( 2, 1, [token, token, token])) self.assertTrue(board.check_line_horizontal( 3, 1, [token, token, token])) self.assertTrue(board.check_line_horizontal( 1, 1, [token, token, token]))
class Gomoku(): def __init__(self, p1=None, p2=None, size=9, line_win_size=5): self._board = Board(size, size) self._line_win_size = line_win_size self._p1 = p1 if not p1 is None else Player("Player 1", Token.A) self._p2 = p2 if not p2 is None else Player("Player 2", Token.B) assert (not (self._p1.token == self._p2.token)) self._current_player = self._p1 self._winner_player = None self._is_over = False self._history = list() self._moves_remaining = set( [Point(x, y) for y in range(size) for x in range(size)]) self._patterns = [ np.full(self._line_win_size, token) for token in [Token.A, Token.B] ] @property def grid(self): return self._board.grid @property def is_over(self): return self._is_over @property def current_player(self): return self._current_player @property def winner(self): return self._winner_player @property def history(self): return self._history def generate_moves(self): ''' @brief All legal moves minus already played moves''' return self._moves_remaining def play(self, point): if self._is_over: self._history.append(None) # bad move return False if not self._board.add_token(point, self._current_player.token): self._history.append(None) # bad move return False self._history.append(point) self._moves_remaining.remove(point) self._compute_ending() self._compute_next_player() return True def undo(self): move = self._history.pop() if move: self._board.undo(move) self._compute_next_player() self._moves_remaining.add(move) self._winner_player = None self._is_over = False def _compute_next_player(self): if self._current_player == self._p1: self._current_player = self._p2 elif self._current_player == self._p2: self._current_player = self._p1 else: assert False def _compute_ending(self): ''' Decide if a game is over ''' # First player need 5 turn to win if self._board.cell_used_count < (self._line_win_size * 2) - 1: return False # Horizontal has_winner, token = self._has_winner_horizontal( self._board, self._board.last_move) # Vertical if not has_winner: has_winner, token = self._has_winner_vertical( self._board, self._board.last_move) # Diagonal if not has_winner: has_winner, token = self._has_winner_diagonal( self._board, self._board.last_move) if has_winner: self._winner_player = self._p1 if token == self._p1.token else self._p2 self._is_over = not self._board.has_free_cell() or has_winner return self._is_over def _has_winner_horizontal(self, board, move): x, y = move.point for pattern in self._patterns: if board.check_line_horizontal(x, y, pattern): return True, pattern[0] return False, None def _has_winner_vertical(self, board, move): x, y = move.point for pattern in self._patterns: if board.check_line_vertical(x, y, pattern): return True, pattern[0] return False, None def _has_winner_diagonal(self, board, move): x, y = move.point for pattern in self._patterns: if board.check_line_diag_down(x, y, pattern): return True, pattern[0] elif board.check_line_diag_up(x, y, pattern): return True, pattern[0] return False, None