def __init__(self, board_col, board_row, mode, win_length=4): global NONE, PLAYER1, PLAYER2 self.BOARD_COLUMNS = board_col self.BOARD_ROWS = board_row self.WINNING_LENGTH = win_length self.turn = PLAYER1 self.winner = NONE self.board = self._new_game_board() self.firstMove = True self.mode = mode self.moveindex = 1 #=========================================================== # Input AI here? #=========================================================== if mode == 2: self.ai = BasicAi(PLAYER2, self.board, len(self.board), self.firstMove) if mode == 3: self.firstMove1 = True self.ai1 = AdvAi(PLAYER1, self.board, len(self.board), self.firstMove1) #self.ai1 = TrueAlphaAi(PLAYER1, self.board, len(self.board), self.firstMove1) self.firstMove2 = True self.ai2 = BasicAi(PLAYER2, self.board, len(self.board), self.firstMove2)
class ConnectFourGame: def __init__(self, board_col, board_row, mode, win_length=4): global NONE, PLAYER1, PLAYER2 self.BOARD_COLUMNS = board_col self.BOARD_ROWS = board_row self.WINNING_LENGTH = win_length self.turn = PLAYER1 self.winner = NONE self.board = self._new_game_board() self.firstMove = True self.mode = mode self.moveindex = 1 #=========================================================== # Input AI here? #=========================================================== if mode == 2: self.ai = BasicAi(PLAYER2, self.board, len(self.board), self.firstMove) if mode == 3: self.firstMove1 = True self.ai1 = AdvAi(PLAYER1, self.board, len(self.board), self.firstMove1) #self.ai1 = TrueAlphaAi(PLAYER1, self.board, len(self.board), self.firstMove1) self.firstMove2 = True self.ai2 = BasicAi(PLAYER2, self.board, len(self.board), self.firstMove2) #self.ai2 = RandomAi(PLAYER1, self.board, len(self.board), self.firstMove2) def _new_game_board(self): global NONE, PLAYER1, PLAYER2 self.board = [] for col in range(self.BOARD_COLUMNS): self.board.append([]) for row in range(self.BOARD_ROWS): self.board[-1].append(NONE) return self.board def _col_check(self, col): if type(col) != int or not 0 <= col < self.BOARD_COLUMNS: raise ValueError('column number must be int between 0 and {}'.format(self.BOARD_COLUMNS - 1)) def _row_check(self, row): if type(row) != int or not 0 <= row < self.BOARD_ROWS: raise ValueError('column number must be int between 0 and {}'.format(self.BOARD_COLUMNS - 1)) def check_winner_exist(self): global NONE, PLAYER1, PLAYER2 if self.winning_player() != NONE: return True return False def check_within_boundary(self, col, row): return 0 <= col < self.BOARD_COLUMNS and 0 <= row < self.BOARD_ROWS def check_empty(self, col, row): ''' check if a tile is empty, return True if it is empty; this can be used by AI to check available moves ''' if self.board[col][row] == NONE: return True else: return False def turn(self): global NONE, PLAYER1, PLAYER2 if (self.turn == NONE): return "NONE" elif (self.turn == PLAYER1): return "PLAYER1" else: return "PLAYER2" def drop_piece_without_ai(self, column_number, row_number): global NONE, PLAYER1, PLAYER2 self._col_check(column_number) self._row_check(row_number) if (not self.check_empty(column_number, row_number)): raise ValueError('row ' + str(row_number) + ', column ' + str(column_number) + ' has been taken') self.board[column_number][row_number] = self.turn self._opposite_turn() self.moveindex = self.moveindex + 1 def drop_piece(self, column_number=None, row_number=None): ''' drop a piece on the board''' global NONE, PLAYER1, PLAYER2 if (column_number != None and row_number != None): if (not self.check_empty(column_number, row_number)): raise ValueError('row ' + str(row_number) + ', column ' + str(column_number) + ' has been taken') if self.mode == 1: self.drop_piece_without_ai(column_number, row_number) elif self.mode == 2: if (self.moveindex % 2): self.drop_piece_without_ai(column_number, row_number) else: (row, col) = self.ai.make_move(self.board, len(self.board)) self.drop_piece_without_ai(col, row) self.firstMove = False elif self.mode == 3: if (self.moveindex % 2): (row, col) = self.ai1.make_move(self.board, len(self.board)) self.drop_piece_without_ai(col, row) self.firstMove1 = False else: (row, col) = self.ai2.make_move(self.board, len(self.board)) self.drop_piece_without_ai(col, row) self.firstMove2 = False def winning_player(self): ''' get winnner, if no winner, return NONE ''' global NONE, PLAYER1, PLAYER2 winner = NONE for col in range(self.BOARD_COLUMNS): for row in range(self.BOARD_ROWS): if self._winning_sequence_begins_at(col, row): if winner == NONE: winner = self.board[col][row] else: self._opposite_turn() self.winner = winner return self.winner def print_board(self): ''' print the board in console ''' print('\n'.join([''.join(['{:3}'.format(item) for item in row]) for row in self.board])) print ('\n') def _find_empty_row_number_in_column(self, column_number): global NONE, PLAYER1, PLAYER2 for i in range(self.BOARD_ROWS - 1, -1, -1): if self.board[column_number][i] == NONE: return i return -1 def _opposite_turn(self): global PLAYER1, PLAYER2 if self.turn == PLAYER1: self.turn = PLAYER2 return else: self.turn = PLAYER1 return def _winning_sequence_begins_at(self, col, row): return self._check_sequence_in_a_row(col, row, 0, 1) \ or self._check_sequence_in_a_row(col, row, 1, 1) \ or self._check_sequence_in_a_row(col, row, 1, 0) \ or self._check_sequence_in_a_row(col, row, 1, -1) \ or self._check_sequence_in_a_row(col, row, 0, -1) \ or self._check_sequence_in_a_row(col, row, -1, -1) \ or self._check_sequence_in_a_row(col, row, -1, 0) \ or self._check_sequence_in_a_row(col, row, -1, 1) def _check_sequence_in_a_row(self, col, row, coldelta, rowdelta): global NONE, PLAYER1, PLAYER2 start_cell = self.board[col][row] if start_cell == NONE: return False else: for i in range(1, self.WINNING_LENGTH): if not 0 <= col + coldelta * i < self.BOARD_COLUMNS \ or not 0 <= row + rowdelta * i < self.BOARD_ROWS \ or self.board[col + coldelta * i][row + rowdelta * i] != start_cell: return False return True