工程目录:
board.py文件
from __future__ import annotations
from typing import NewType, List
from abc import ABC, abstractmethod
Move = NewType('Move', int)
class Piece:
@property
def opposite(self) -> Piece:
raise NotImplementedError("需要通过子类实现")
class Board(ABC):
@property
@abstractmethod
def turn(self) -> Piece:
...
@abstractmethod
def move(self, location: Move) -> Board:
...
@property
@abstractmethod
def legal_moves(self) -> List[Move]:
...
@property
@abstractmethod
def is_win(self) -> bool:
...
@property
def is_draw(self) -> bool:
return (not self.is_win) and (len(self.legal_moves) == 0)
@abstractmethod
def evaluate(self, player: Piece) -> float:
...
minimax.py
from __future__ import annotations
from board import Piece,Board,Move
def minimax(board:Board,maximizing:bool,original_player:Piece,max_depth:int=8)->float:
if board.is_win or board.is_draw or max_depth==0:
return board.evaluate(original_player)
if maximizing:
best_eval:float=float("-inf")
for move in board.legal_moves:
result:float=minimax(board.move(move),False,original_player,max_depth-1)
best_eval=max(result,best_eval)
return best_eval
else:
worst_eval:float=float("inf")
for move in board.legal_moves:
result: float = minimax(board.move(move), True, original_player, max_depth - 1)
worst_eval = min(result, worst_eval)
return worst_eval
def find_best_move(board:Board,max_depth:int=8)->Move:
best_eval:float=float("-inf")
best_move:Move=Move(-1)
for move in board.legal_moves:
result:float=minimax(board.move(move),False,board.turn,max_depth)
if result>best_eval:
best_eval=result
best_move=move
return best_move
tictactoe.py
from __future__ import annotations
from typing import List
from enum import Enum
from board import Piece,Board,Move
class TTTPiece(Piece,Enum):
X="X"
O="O"
E=" "
@property
def opposite(self) -> TTTPiece:
if self==TTTPiece.X:
return TTTPiece.O
elif self==TTTPiece.O:
return TTTPiece.X
else:
return TTTPiece.E
def __str__(self)->str:
return self.value
class TTTBoard(Board):
def __init__(self,position:List[TTTPiece]=[TTTPiece.E] * 9,turn:TTTPiece=TTTPiece.X)->None:
self.position:List[TTTPiece]=position
self._turn:TTTPiece=turn
@property
def turn(self) ->Piece:
return self._turn
def move(self,location:Move) ->Board:
temp_position:List[TTTPiece]=self.position.copy()
temp_position[location]=self._turn
return TTTBoard(temp_position,self._turn.opposite)
@property
def legal_moves(self) ->List[Move]:
return [Move(c) for c in range(len(self.position)) if self.position[c]==TTTPiece.E]
@property
def is_win(self) ->bool:
return self.position[0]==self.position[1] and self.position[0]==self.position[2]
and self.position[0] !=TTTPiece.E or
self.position[3]==self.position[4] and self.position[3]==self.position[5]
and self.position[3] !=TTTPiece.E or
self.position[6] == self.position[7] and self.position[6] == self.position[8]
and self.position[6] != TTTPiece.E or
self.position[0] == self.position[3] and self.position[0] == self.position[6]
and self.position[0] != TTTPiece.E or
self.position[1] == self.position[4] and self.position[1] == self.position[7]
and self.position[1] != TTTPiece.E or
self.position[2] == self.position[5] and self.position[2] == self.position[8]
and self.position[2] != TTTPiece.E or
self.position[0] == self.position[4] and self.position[0] == self.position[8]
and self.position[0] != TTTPiece.E or
self.position[2] == self.position[4] and self.position[2] == self.position[6]
and self.position[2] != TTTPiece.E
def evaluate(self,player:Piece)->float:
if self.is_win and self.turn==player:
return -1
elif self.is_win and self.turn!=player:
return 1
else:
return 0
def __repr__(self)->str:
return f"""
{self.position[0]}|{self.position[1]}|{self.position[2]}
-------
{self.position[3]}|{self.position[4]}|{self.position[5]}
-------
{self.position[6]}|{self.position[7]}|{self.position[8]}
"""
程序入口在:无敌井字棋.py文件
无敌井字棋.py
from minimax import find_best_move
from tictactoe import TTTBoard
from board import Move,Board
board:Board=TTTBoard()
def get_player_move()->Move:
player_move:Move=Move(-1)
while player_move not in board.legal_moves:
play:int=int(input("(你是X)请选择下的位置:"))
player_move=Move(play)
return player_move
if __name__=="__main__":
while True:
human_move:Move=get_player_move()
board=board.move(human_move)
if board.is_win:
print("对局结束,结果为:人胜利")
break
elif board.is_draw:
print("对局结束,结果为:平局")
break
computer_move:Move=find_best_move(board)
print(f"(AI是O)AI选择下在 {computer_move}")
board=board.move(computer_move)
print(board)
if board.is_win:
print("对局结束,结果为:AI胜利(你个小垃圾)")
break
elif board.is_draw:
print("对局结束,结果为:平局")
break
没有使用剪枝,运行结果为:最多与AI打成平手,人不可能赢AI



