井字游戏/一字棋——Max-Min智能算法

内容介绍

井字棋 / 一字棋游戏

西安电子科技大学

人工智能概论大作业1

问题规约方法之博弈与博弈树

用最大最小算法 Max-Min博弈树的一阶展开形式

后面附有具体的算法(Python代码 附有详细的注释)

该算法的难点在于估值函数的定义,这个函数不好写。

问题规约法

什么是问题规约法

博弈与博弈树

博弈树的基本思想

请添加图片描述

请添加图片描述

请添加图片描述
请添加图片描述

一字棋的估价函数定义

请添加图片描述
请添加图片描述

代码部分

import random
import sys
import math
import copy
import time


class TicTacToe(object):
    """一字棋游戏的类:"""

    def __init__(self):
        """初始化类属性:"""
        self.begin()
        self.rule()

        # 定义棋盘属性:
        self.position = {
    
    }
        for i in range(1, 10):
            self.position[str(i)] = ' '
        # 绘制棋盘:
        self.board = None
        self.update()
        # 玩家和电脑的棋子:
        self.player, self.computer, self.goFirst = None, None, None
        self.choose()
        self.whoGoFirst()

    def update(self):
        """更新棋盘的函数:"""
        self.board = f"{
      
      self.position['1']}|{
      
      self.position['2']}|{
      
      self.position['3']}\n-+-+-\n{
      
      self.position['4']}|{
      
      self.position['5']}|{
      
      self.position['6']}\n-+-+-\n{
      
      self.position['7']}|{
      
      self.position['8']}|{
      
      self.position['9']}"

    def printf(self):
        """输出棋盘的函数:"""
        self.update()
        print(self.board)

    @staticmethod
    def begin():
        """控制游戏开始:"""
        massage = input("输入任选信息开始一字棋游戏,输入 q 退出程序:")
        if massage == 'q':
            sys.exit()

    @staticmethod
    def rule():
        """简述游戏规则:"""
        print("规则如下:\n输入下棋的位置为对应拨号系统的九字键")
        board = """1|2|3\n-+-+-\n4|5|6\n-+-+-\n7|8|9"""
        print(board)

    def choose(self):
        """选择棋子的函数:"""
        chess = input("请输入选择的棋子(X or O):")
        while chess != 'X' and chess != 'O' and chess != 'x' and chess != 'o':
            chess = input("请选择正确的棋子(X or O):")
        if chess == 'X' or chess == 'x':
            self.player = 'X'
            self.computer = 'O'
        else:
            self.player = 'O'
            self.computer = 'X'

    def whoGoFirst(self):
        """判断计算机和玩家谁先走:"""
        if random.randint(0, 1) == 0:
            self.goFirst = 'computer'
            print("本轮计算机先走!")
            return
        self.goFirst = 'player'
        print("本轮玩家先走!")

    def playerMove(self):
        """让玩家下棋的函数:"""
        self.printf()
        while True:
            b = 1
            position = input("请输入下棋的位置(1~9):")
            if position.isdigit():
                if int(position) < 1 or int(position) > 9:
                    print("请输入正确的下棋位置!")
                    b = 0
                elif self.position[position] != ' ':
                    print("该位置已有棋子,请重新选择!")
                    b = 0
                if b == 1:
                    self.position[position] = self.player
                    break
            else:
                print("请输入正确的下棋位置!")

    def computerMove(self):
        """让计算机下棋的函数:"""

        # 复制当前棋盘:
        position = copy.deepcopy(self.position)

        # 用估价函数得到最优的下棋位置:
        best = self.ect(position)

        # 下棋:
        self.position[best] = self.computer

    @staticmethod
    def fill(position, chess):
        """填充棋盘的函数:"""
        p = copy.deepcopy(position)
        for i in range(1, 10):
            if p[str(i)] == ' ':
                p[str(i)] = chess
        return p

    def ect(self, position):
        """Max-Min搜索的估值函数:"""

        # 记录不同位置的 alpha 值:
        alpha = {
    
    }
        targe = '1'

        # 先让计算机模拟下棋:
        for i in range(1, 10):
            copyComputerPosition = copy.deepcopy(position)
            if copyComputerPosition[str(i)] == ' ':
                copyComputerPosition[str(i)] = self.computer

                # 定义评估值 alpha, beta, 初始值为负无穷和正无穷:
                beta = math.inf

                # 让玩家模拟下棋:
                for j in range(1, 10):
                    copyPlayerPosition = copy.deepcopy(copyComputerPosition)
                    if copyPlayerPosition[str(j)] == ' ':
                        copyPlayerPosition[str(j)] = self.player

                        # 分别用两种棋子填充该棋盘:
                        player_position = self.fill(copyPlayerPosition, self.player)
                        computer_position = self.fill(copyPlayerPosition, self.computer)

                        """以下算法计算 beta 的值,并从中确定 alpha:"""

                        # 该情况玩家获胜的期望值:
                        Min = 0
                        if player_position['1'] == self.player and player_position['2'] == self.player and \
                                player_position['3'] == self.player:
                            Min += 1
                        if player_position['1'] == self.player and player_position['4'] == self.player and \
                                player_position['7'] == self.player:
                            Min += 1
                        if player_position['4'] == self.player and player_position['5'] == self.player and \
                                player_position['6'] == self.player:
                            Min += 1
                        if player_position['2'] == self.player and player_position['5'] == self.player and \
                                player_position['8'] == self.player:
                            Min += 1
                        if player_position['7'] == self.player and player_position['8'] == self.player and \
                                player_position['9'] == self.player:
                            Min += 1
                        if player_position['3'] == self.player and player_position['6'] == self.player and \
                                player_position['9'] == self.player:
                            Min += 1
                        if player_position['1'] == self.player and player_position['5'] == self.player and \
                                player_position['9'] == self.player:
                            Min += 1
                        if player_position['3'] == self.player and player_position['5'] == self.player and \
                                player_position['7'] == self.player:
                            Min += 1

                        # 该情况计算机获胜的期望值:
                        Max = 0
                        if computer_position['1'] == self.computer and computer_position['2'] == self.computer and \
                                computer_position['3'] == self.computer:
                            Max += 1
                        if computer_position['1'] == self.computer and computer_position['4'] == self.computer and \
                                computer_position['7'] == self.computer:
                            Max += 1
                        if computer_position['4'] == self.computer and computer_position['5'] == self.computer and \
                                computer_position['6'] == self.computer:
                            Max += 1
                        if computer_position['2'] == self.computer and computer_position['5'] == self.computer and \
                                computer_position['8'] == self.computer:
                            Max += 1
                        if computer_position['7'] == self.computer and computer_position['8'] == self.computer and \
                                computer_position['9'] == self.computer:
                            Max += 1
                        if computer_position['3'] == self.computer and computer_position['6'] == self.computer and \
                                computer_position['9'] == self.computer:
                            Max += 1
                        if computer_position['1'] == self.computer and computer_position['5'] == self.computer and \
                                computer_position['9'] == self.computer:
                            Max += 1
                        if computer_position['3'] == self.computer and computer_position['5'] == self.computer and \
                                computer_position['7'] == self.computer:
                            Max += 1

                        # 判断是否需要更换 beta 的值:
                        exp_beta = Max - Min
                        if exp_beta < beta:
                            beta = exp_beta

                # 创建模拟计算机下棋的字典记录每个位置的 alpha值 和 下棋的位置:
                alpha[str(i)] = beta

        # 返回出下棋的位置:(定位到最优解)
        max_value = -math.inf
        for key, value in alpha.items():
            if value > max_value:
                max_value = value
                targe = key

        # 保证计算机不输:
        for i in range(1, 10):
            position = self.position.copy()
            if position[str(i)] == ' ':
                position[str(i)] = self.computer
                if self.checkWinner(position, self.computer):
                    targe = str(i)
                    break
                position[str(i)] = self.player
                if self.checkWinner(position, self.player):
                    targe = str(i)
                    break

        return targe

    @staticmethod
    def checkWinner(position, chess):
        """判断胜负的函数:"""
        return (position['1'] == chess and position['2'] == chess and position['3'] == chess) or \
               (position['1'] == chess and position['4'] == chess and position['7'] == chess) or \
               (position['4'] == chess and position['5'] == chess and position['6'] == chess) or \
               (position['2'] == chess and position['5'] == chess and position['8'] == chess) or \
               (position['7'] == chess and position['8'] == chess and position['9'] == chess) or \
               (position['3'] == chess and position['6'] == chess and position['9'] == chess) or \
               (position['1'] == chess and position['5'] == chess and position['9'] == chess) or \
               (position['3'] == chess and position['5'] == chess and position['7'] == chess)

    def checkDraw(self):
        """判断平局的函数:"""
        end = True
        for i in range(1, 10):
            if self.position[str(i)] == ' ':
                end = False
        if not self.checkWinner(self.position, self.player) and not self.checkWinner(self.position, self.computer) and end:
            return True
        return False

    def checkBoard(self):
        """检测棋局的函数:"""
        if self.checkWinner(self.position, self.player):
            self.printf()
            print("程序结束,玩家获胜!")
            time.sleep(5)
            sys.exit()
        if self.checkWinner(self.position, self.computer):
            self.printf()
            print("程序结束,计算机获胜!")
            time.sleep(5)
            sys.exit()
        if self.checkDraw():
            self.printf()
            print("程序结束,游戏平局!")
            time.sleep(5)
            sys.exit()

    def run(self):
        """启动程序:"""
        while True:
            if self.goFirst == 'player':
                self.playerMove()
                self.checkBoard()
                self.computerMove()
                self.checkBoard()
            if self.goFirst == 'computer':
                self.computerMove()
                self.checkBoard()
                self.playerMove()
                self.checkBoard()


if __name__ == '__main__':
    t = TicTacToe()
    t.run()



猜你喜欢

转载自blog.csdn.net/wwx1239021388/article/details/129333179
今日推荐