Python实现的井字棋(Tic Tac Toe)游戏示例


Posted in Python onJanuary 31, 2018

本文实例讲述了Python实现的井字棋(Tic Tac Toe)游戏。分享给大家供大家参考,具体如下:

说明

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

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

特点

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

代码

#作者:hhh5460
#时间:2017年6月26日
# 棋盘
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()

下图是人人对战的结果

Python实现的井字棋(Tic Tac Toe)游戏示例

更多关于Python相关内容可查看本站专题:《Python游戏开发技巧总结》、《Python数据结构与算法教程》、《Python Socket编程技巧总结》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
python 排列组合之itertools
Mar 20 Python
Python编程之string相关操作实例详解
Jul 22 Python
Python编程之变量赋值操作实例分析
Jul 24 Python
python测试mysql写入性能完整实例
Jan 18 Python
Python数据类型之List列表实例详解
May 08 Python
python ImageDraw类实现几何图形的绘制与文字的绘制
Feb 26 Python
VS2019+python3.7+opencv4.1+tensorflow1.13配置详解
Apr 16 Python
Python类及获取对象属性方法解析
Jun 15 Python
完美解决TensorFlow和Keras大数据量内存溢出的问题
Jul 03 Python
Python爬虫代理池搭建的方法步骤
Sep 28 Python
pytorch学习教程之自定义数据集
Nov 10 Python
用python获取txt文件中关键字的数量
Dec 24 Python
使用Python制作微信跳一跳辅助
Jan 31 #Python
python模块之paramiko实例代码
Jan 31 #Python
Python进度条实时显示处理进度的示例代码
Jan 30 #Python
Python3生成手写体数字方法
Jan 30 #Python
python字符串的方法与操作大全
Jan 30 #Python
Python实现带参数与不带参数的多重继承示例
Jan 30 #Python
Python实现的随机森林算法与简单总结
Jan 30 #Python
You might like
php基础知识:函数基础知识
2006/12/13 PHP
php字符串截取中文截取2,单字节截取模式
2007/12/10 PHP
PHP 字符串长度判断效率更高的方法
2014/03/02 PHP
PHP模块化安装教程
2016/06/01 PHP
php求今天、昨天、明天时间戳的简单实现方法
2016/07/28 PHP
PHP 中使用ajax时一些常见错误总结整理
2017/02/27 PHP
PHP7扩展开发之hello word实现方法详解
2018/01/15 PHP
JavaScript去除空格的几种方法
2006/10/03 Javascript
JavaScript 克隆数组最简单的方法
2009/02/12 Javascript
js split 的用法和定义 js split分割字符串成数组的实例代码
2012/05/13 Javascript
防止文件缓存的js代码
2013/01/10 Javascript
js实现表格字段排序
2014/02/19 Javascript
js清空表单数据的两种方式(遍历+reset)
2014/07/18 Javascript
vue中使用gojs/jointjs的示例代码
2018/08/24 Javascript
VUE-Table上绑定Input通过render实现双向绑定数据的示例
2018/08/27 Javascript
Bootstrap模态对话框用法简单示例
2018/08/31 Javascript
JS使用栈判断给定字符串是否是回文算法示例
2019/03/04 Javascript
js 计算图片内点个数的示例代码
2019/04/04 Javascript
使用Vue.js中的过滤器实现幂方求值的方法
2019/08/27 Javascript
[01:08:24]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第一场 2月5日
2021/03/11 DOTA
python数据结构之二叉树的建立实例
2014/04/29 Python
python 数字类型和字符串类型的相互转换实例
2018/07/17 Python
Django Rest framework认证组件详细用法
2019/07/25 Python
Django xadmin开启搜索功能的实现
2019/11/15 Python
python 计算积分图和haar特征的实例代码
2019/11/20 Python
Django中日期时间型字段进行年月日时分秒分组统计
2020/11/27 Python
详解Python遍历列表时删除元素的正确做法
2021/01/07 Python
详解CSS3:overflow属性
2020/11/17 HTML / CSS
VICHY薇姿美国官方网站:欧洲药房第一的抗衰老品牌
2017/11/22 全球购物
Bibloo罗马尼亚网站:女装、男装、童装及鞋子和配饰
2019/07/20 全球购物
经济信息系毕业生自荐信
2014/06/02 职场文书
大学本科生职业生涯规划书范文
2014/09/14 职场文书
党员剖析材料范文
2014/09/30 职场文书
同学毕业留言寄语
2015/02/27 职场文书
汽车销售员岗位职责
2015/04/11 职场文书
Django drf请求模块源码解析
2021/06/08 Python