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在Windows和在Linux下调用动态链接库的教程
Aug 18 Python
编写Python脚本抓取网络小说来制作自己的阅读器
Aug 20 Python
Python使用爬虫猜密码
Feb 19 Python
PyQt5每天必学之日历控件QCalendarWidget
Apr 19 Python
Django Web开发中django-debug-toolbar的配置以及使用
May 06 Python
解决Pycharm 包已经下载,但是运行代码提示找不到模块的问题
Aug 31 Python
python实现网站微信登录的示例代码
Sep 18 Python
将tensorflow.Variable中的某些元素取出组成一个新的矩阵示例
Jan 04 Python
4行Python代码生成图像验证码(2种)
Apr 07 Python
虚拟机下载python是否需要联网
Jul 27 Python
Python用Jira库来操作Jira
Dec 28 Python
python 可视化库PyG2Plot的使用
Jan 21 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中防止恶意刷新页面的代码小结
2012/10/31 PHP
深入Apache与Nginx的优缺点比较详解
2013/06/17 PHP
完善CodeIgniter在IDE中代码提示功能的方法
2014/07/19 PHP
php处理复杂xml数据示例
2016/07/11 PHP
Yii2中YiiBase自动加载类、引用文件方法分析(autoload)
2016/07/25 PHP
PHP+fiddler抓包采集微信文章阅读数点赞数的思路详解
2019/12/20 PHP
轻轻松松学习JavaScript
2007/02/25 Javascript
javascript与CSS复习(《精通javascript》)
2010/06/29 Javascript
JavaScript初学者应注意的七个细节小结
2012/01/30 Javascript
使用ajaxfileupload.js实现ajax上传文件php版
2014/06/26 Javascript
Node.js中使用Buffer编码、解码二进制数据详解
2014/08/16 Javascript
jQuery中prepend()方法用法实例
2014/12/25 Javascript
jQuery中:radio选择器用法实例
2015/01/03 Javascript
AngularJS中的$watch(),$digest()和$apply()区分
2016/04/04 Javascript
js 动态生成json对象、时时更新json对象的方法
2016/12/02 Javascript
javascript中setAttribute兼容性用法分析
2016/12/12 Javascript
JavaScript和jQuery制作光棒效果
2017/02/24 Javascript
AngularJs1.x自定义指令独立作用域的函数传入参数方法
2018/10/09 Javascript
深入了解Vue.js 混入(mixins)
2020/07/23 Javascript
JavaScript动画实例之粒子文本的实现方法详解
2020/07/28 Javascript
Node快速切换版本、版本回退(降级)、版本更新(升级)
2021/01/07 Javascript
windows系统下Python环境搭建教程
2017/03/28 Python
python编辑用户登入界面的实现代码
2018/07/16 Python
python使用response.read()接收json数据的实例
2018/12/19 Python
python实现广度优先搜索过程解析
2019/10/19 Python
Python通过递归获取目录下指定文件代码实例
2019/11/07 Python
python 求两个向量的顺时针夹角操作
2021/03/04 Python
一家专门做特卖的网站:唯品会
2016/10/09 全球购物
世界最大的票务市场:viagogo
2017/02/16 全球购物
什么情况下你必须要把一个类定义为abstract的
2013/01/06 面试题
新闻学毕业生自荐信
2013/11/15 职场文书
公司收款委托书范本
2014/09/20 职场文书
安全保证书怎么写
2015/02/28 职场文书
2015年售后服务工作总结
2015/04/25 职场文书
红楼梦读书笔记
2015/06/25 职场文书
Django路由层如何获取正确的url
2021/07/15 Python