def __canFindWay(self, status, listCellHadCheck, queueWillCheckCell): map = self.map width = self.width height = self.height cell = queueWillCheckCell.pop(0) listCellHadCheck.append([cell.posX, cell.posY]) x = cell.posX y = cell.posY for i in range(x - 1, x + 2): for j in range(y - 1, y + 2): if i in range(height) and j in range(width): if map[i][j] == CellStatus.NONE and [ i, j ] not in listCellHadCheck: queueWillCheckCell.append(Cell(map[i][j], i, j)) elif map[i][j] != status and (map[i][j] == CellStatus.X or map[i][j] == CellStatus.O): return True if len(queueWillCheckCell) > 0: return self.__canFindWay(status, listCellHadCheck, queueWillCheckCell) return False
def __AIMove(self): board = self.board # self.miniMax() if board.checkWin() == GameStatus.UNKNOW: bestValue = -INF for move in board.listCanMove(CellStatus.O): currentBoard = board.deepCopy() cell = Cell(CellStatus.O, move[0], move[1]) currentBoard.setCellStatus(cell) currentBoard.killAllEnemyNearCell(cell) moveValue = self.miniMax(currentBoard, 0, True) if bestValue < moveValue: bestValue = moveValue bestMove = move cell = Cell(CellStatus.O, bestMove[0], bestMove[1]) board.setCellStatus(cell) board.killAllEnemyNearCell(cell)
def __statistics(self): maps = self.map maps_flat = mapFlat(maps) for index, cell in enumerate(maps_flat): if cell == CellStatus.NONE: posX = index // self.width posY = index % self.width if self.__canFindWay(CellStatus.X, [], [Cell(CellStatus.NONE, posX, posY)]): maps_flat[index] = CellStatus.X elif self.__canFindWay(CellStatus.O, [], [Cell(CellStatus.NONE, posX, posY)]): maps[posX][posY] = CellStatus.O point_x = maps_flat.count(CellStatus.X) point_o = maps_flat.count(CellStatus.O) if point_x == point_o: return GameStatus.DRAW return GameStatus.X_WIN if point_x > point_o else GameStatus.O_WIN
def listCanMove(self, status): result = [] maps_flat = mapFlat(self.map) for index, _ in enumerate(maps_flat): posX = index // self.width posY = index % self.width if self.checkMoveAvailable(Cell(status, posX, posY)): result.append([posX, posY]) return result
def checkWin(self): maps = self.map maps_flat = mapFlat(maps) if CellStatus.X not in maps_flat: return GameStatus.O_WIN if CellStatus.O not in maps_flat: return GameStatus.X_WIN # check for index, cell in enumerate(maps_flat): if cell == CellStatus.NONE: x = index // self.width y = index % self.width if self.__canFindWay(CellStatus.O, [], [Cell(CellStatus.NONE, x, y)]): if self.__canFindWay(CellStatus.X, [], [Cell(CellStatus.NONE, x, y)]): return GameStatus.UNKNOW return self.__statistics()
def miniMax(self, board, depth, isTurnAI): # print("----------------------") # board.printBoard() status = CellStatus.O if isTurnAI else CellStatus.X state = board.checkWin() stateValue = { GameStatus.O_WIN: self.score - depth, GameStatus.X_WIN: -self.score + depth, GameStatus.DRAW: 0 } if state != GameStatus.UNKNOW: return stateValue[state] listCanMove = board.listCanMove(status) if isTurnAI: bestValue = INF for move in listCanMove: posX, posY = move cell = Cell(status, posX, posY) nextBoard = board.deepCopy() nextBoard.setCellStatus(cell) # warning nextBoard.killAllEnemyNearCell(cell) value = self.miniMax(nextBoard, depth + 1, False) bestValue = min(value, bestValue) return bestValue else: bestValue = -INF for move in listCanMove: posX, posY = move nextBoard = board.deepCopy() cell = Cell(status, posX, posY) nextBoard.setCellStatus(cell) # warning nextBoard.killAllEnemyNearCell(cell) value = self.miniMax(nextBoard, depth + 1, True) bestValue = max(value, bestValue) return bestValue
def __move(self): board = self.board while True: status = CellStatus.X if self.isTurnX else CellStatus.O position = input('Nhap toa do ' + str(status.value) + ' (Enter "q" to end game): ') pos_x, pos_y = [int(x) for x in position.split()] cell = Cell(status, pos_x, pos_y) if board.checkMoveAvailable(cell): board.setCellStatus(cell) # kill het board.killAllEnemyNearCell(cell) # if len(listCanAttack): # self.__choseKillEnemy(listCanAttack) return else: print('Please try again!')
def killAllEnemyNearCell(self, cell): listCanAttack = self.getListCanAttack(cell) for move in listCanAttack: self.setCellStatus(Cell(CellStatus.BLOCK, move[0], move[1]))
def __choseKillEnemy(self, listCanAttack): while True: position = input('Nhap toa do quan ban dich muon kill: ') pos_x, pos_y = [int(x) for x in position.split()] if [pos_x, pos_y] in listCanAttack: self.board.setCellStatus(Cell(CellStatus.BLOCK, pos_x, pos_y))