栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

极小化极大算法的无敌井字棋

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

极小化极大算法的无敌井字棋

工程目录:

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/950204.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号