python 井字棋(Tic Tac Toe)

简介: 说明用python实现了井字棋,整个框架是本人自己构思的,自认为比较满意。另外,90%+的代码也是本人逐字逐句敲的。minimax算法还没完全理解,所以参考了这里的代码,并作了修改。特点可以选择人人、人机、机人、机机四种对战模式之一电脑玩家的AI使用了minimax算法,带apha-beta剪枝电脑玩家在思考时,时时刻刻都有一个“假想敌”。

说明

用python实现了井字棋,整个框架是本人自己构思的,自认为比较满意。另外,90%+的代码也是本人逐字逐句敲的。

minimax算法还没完全理解,所以参考了这里的代码,并作了修改。

特点

  • 可以选择人人、人机、机人、机机四种对战模式之一
  • 电脑玩家的AI使用了minimax算法,带apha-beta剪枝
  • 电脑玩家在思考时,时时刻刻都有一个“假想敌”。以便使得minimax算法运转起来

代码


作者:hhh5460
时间:2017626# 棋盘
class Board(object):
    def __init__(self):
        #self._board = '-'*9 # 坑!!
        self._board = ['-' for _ in range(9)]
        self._history = [] # 棋谱
        
    # 按指定动作,放入棋子
    def _move(self, action, take):
        if self._board[action] == '-':
            self._board[action] = take
            
            self._history.append((action, take)) # 加入棋谱
            
    # 撤销动作,拿走棋子
    def _unmove(self, action):
        self._board[action] = '-'
        
        self._history.pop()
            
    # 棋盘快照
    def get_board_snapshot(self):
        return self._board[:]
        
    # 取棋盘上的合法走法
    def get_legal_actions(self):
        actions = []
        for i in range(9):
            if self._board[i] == '-':
                actions.append(i)
        return actions
        
    # 判断走法是否合法
    def is_legal_action(self, action):
        return self._board[action] == '-'
        
    # 终止检测
    def teminate(self):
        board = self._board
        lines = [board[0:3], board[3:6], board[6:9], board[0::3], board[1::3], board[2::3], board[0::4], board[2:7:2]]
        
        if ['X']*3 in lines or ['O']*3 in lines or '-' not in board:
            return True 
        else:
            return False
            
    # 胜负检查
    def get_winner(self):
        board = self._board
        lines = [board[0:3], board[3:6], board[6:9], board[0::3], board[1::3], board[2::3], board[0::4], board[2:7:2]]
        
        if ['X']*3 in lines:
            return 0 
        elif ['O']*3 in lines:
            return 1 
        else:
            return 2
            
    # 打印棋盘
    def print_b(self):
        board = self._board
        for i in range(len(board)):
            print(board[i], end='')
            if (i+1)%3 == 0:
                print()
    
    # 打印棋谱
    def print_history(self):
        print(self._history)


# 玩家
class Player(object):
    '''
    玩家只做两件事:思考、落子
        1. 思考 --> 得到走法
        2. 落子 --> 执行走法,改变棋盘
    '''
    def __init__(self, take='X'): # 默认执的棋子为 take = 'X'
        self.take=take
    
    def think(self, board):
        pass
        
    def move(self, board, action):
        board._move(action, self.take)


# 人类玩家
class HumanPlayer(Player):
    def __init__(self, take):
        super().__init__(take)
    
    def think(self, board):
        while True:
            action = input('Please input a num in 0-8:')
            if len(action)==1 and action in '012345678' and board.is_legal_action(int(action)):
                return int(action)


# 电脑玩家
class AIPlayer(Player):
    def __init__(self, take):
        super().__init__(take)
    
    def think(self, board):
        print('AI is thinking ...')
        take = ['X','O'][self.take=='X']
        player = AIPlayer(take)     # 假想敌!!!
        _, action = self.minimax(board, player)
        #print('OK')
        return action
        
    # 极大极小法搜索,α-β剪枝
    def minimax(self, board, player, depth=0) :
        '''参考:https://stackoverflow.com/questions/44089757/minimax-algorithm-for-tic-tac-toe-python'''
        if self.take == "O": 
            bestVal = -10
        else:
            bestVal = 10
            
        if board.teminate() :
            if board.get_winner() == 0 :
                return -10 + depth, None
            elif board.get_winner() == 1 :
                return 10 - depth, None
            elif board.get_winner() == 2 :
                return 0, None

        for action in board.get_legal_actions() : # 遍历合法走法
            board._move(action, self.take)
            val, _ = player.minimax(board, self, depth+1) # 切换到 假想敌!!!
            board._unmove(action) # 撤销走法,回溯
            
            if self.take == "O" :
                if val > bestVal:
                    bestVal, bestAction = val, action
            else :
                if val < bestVal:
                    bestVal, bestAction = val, action
        
        return bestVal, bestAction



# 游戏
class Game(object):
    def __init__(self):
        self.board = Board()
        self.current_player = None
        
    # 生成玩家
    def mk_player(self, p, take='X'): # p in [0,1]
        if p==0:
            return HumanPlayer(take)
        else:
            return AIPlayer(take)
            
    # 切换玩家
    def switch_player(self, player1, player2):
        if self.current_player is None:
            return player1
        else:
            return [player1, player2][self.current_player == player1]
            
    # 打印赢家
    def print_winner(self, winner): # winner in [0,1,2]
        print(['Winner is player1','Winner is player2','Draw'][winner])

    # 运行游戏
    def run(self):
        ps = input("Please select two player's type:\n\t0.Human\n\t1.AI\nSuch as:0 0\n")
        p1, p2 = [int(p) for p in ps.split(' ')]
        player1, player2 = self.mk_player(p1, 'X'), self.mk_player(p2, 'O') # 先手执X,后手执O
        
        print('\nGame start!\n')
        self.board.print_b() # 显示棋盘
        while True:
            self.current_player = self.switch_player(player1, player2) # 切换当前玩家
            
            action = self.current_player.think(self.board) # 当前玩家对棋盘进行思考后,得到招法
            
            self.current_player.move(self.board, action)   # 当前玩家执行招法,改变棋盘
            
            self.board.print_b() # 显示当前棋盘
            
            if self.board.teminate(): # 根据当前棋盘,判断棋局是否终止
                winner = self.board.get_winner() # 得到赢家 0,1,2
                break
        
        self.print_winner(winner)
        print('Game over!')
        
        self.board.print_history()
    
    
if __name__ == '__main__':
    Game().run()

效果图

下图是人人对战的结果
img_3b7db89f34a1e2886dce7a06c3ec8df7.jpg

目录
相关文章
|
机器学习/深度学习 自然语言处理 异构计算
Python深度学习面试:CNN、RNN与Transformer详解
【4月更文挑战第16天】本文介绍了深度学习面试中关于CNN、RNN和Transformer的常见问题和易错点,并提供了Python代码示例。理解这三种模型的基本组成、工作原理及其在图像识别、文本处理等任务中的应用是评估技术实力的关键。注意点包括:模型结构的混淆、过拟合的防治、输入序列长度处理、并行化训练以及模型解释性。掌握这些知识和技巧,将有助于在面试中展现优秀的深度学习能力。
976 11
|
存储 SQL 关系型数据库
TiDB的优势:为何选择TiDB作为您的数据库解决方案
【2月更文挑战第25天】随着数据规模的不断增长和业务需求的日益复杂化,现代企业对数据库系统的扩展性、高可用以及分布式处理能力提出了更高的要求。TiDB作为一个新型的开源分布式数据库,以其独特的设计理念与卓越的技术特性,在众多数据库解决方案中脱颖而出。本文将深入剖析TiDB的核心优势,探讨其如何帮助企业从容应对海量数据挑战、实现无缝水平扩展、保障服务高可用性,并提供灵活一致的事务支持。
1092 5
|
7月前
|
供应链 监控 数据可视化
1688库存API:供应链可视化,避免断货风险!
本文介绍如何利用1688库存API构建供应链可视化系统,实现库存实时监控、安全库存预警与智能补货决策。通过API获取精准库存数据,打通ERP等系统,打造数据驱动的智能管理平台,有效避免断货风险,提升运营效率与客户体验。(238字)
|
机器学习/深度学习 人工智能 算法
DeepSeek深度解析:一场「通用人工智能」的觉醒革命
DeepSeek,由幻方量化打造的国产大模型,正以彗星般的速度革新AI领域。它不仅刷新了中文AI技术基准,还在底层架构上实现颠覆性突破。文章从技术逻辑、产业影响和未来挑战三个维度解析这场AI革命。DeepSeek采用多模态神经网络设计,融合异构数据,展现通感能力;引入动态神经元编织与具身智能,提升参数效率。其混合架构在数学推理中表现卓越,并通过认知卸载机制优化长文本处理。DeepSeek正在重塑金融投研范式,推动AI原生开发模式,同时引发对伦理与硬件限制的深思。最终,DeepSeek重新诠释了“智能”本质,促使人类与AI共同进化为认知伙伴。
754 8
|
11月前
|
存储 虚拟化 数据中心
VMware ESXi 9.0 macOS Unlocker & OEM BIOS 2.7 HPE 慧与 定制版
VMware ESXi 9.0 macOS Unlocker & OEM BIOS 2.7 HPE 慧与 定制版
438 0
|
Prometheus 运维 监控
Prometheus+Grafana+NodeExporter:构建出色的Linux监控解决方案,让你的运维更轻松
本文介绍如何使用 Prometheus + Grafana + Node Exporter 搭建 Linux 主机监控系统。Prometheus 负责收集和存储指标数据,Grafana 用于可视化展示,Node Exporter 则采集主机的性能数据。通过 Docker 容器化部署,简化安装配置过程。完成安装后,配置 Prometheus 抓取节点数据,并在 Grafana 中添加数据源及导入仪表盘模板,实现对 Linux 主机的全面监控。整个过程简单易行,帮助运维人员轻松掌握系统状态。
2581 3
|
资源调度 JavaScript 前端开发
搭建和部署nuxt项目
【8月更文挑战第4天】
|
存储 Java 开发者
【编程基础知识】 计算机中的数学魔法:二进制加减运算全解析
本文深入解析了计算机中二进制加减运算的原理,涵盖原码、反码和补码的概念及应用,结合具体示例,帮助读者理解计算机底层数学运算机制,适合Java开发者学习。
657 0
|
Ubuntu Docker 容器
Ubuntu 22.04.3 LTS_安装Docker
Ubuntu 22.04.3 LTS_安装Docker
2226 2
|
JavaScript Java 测试技术
基于SpringBoot+Vue的教学资源管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue的教学资源管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
340 2