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日期操作学习笔记
Oct 07 Python
Python对字符串实现去重操作的方法示例
Aug 11 Python
python pandas中DataFrame类型数据操作函数的方法
Apr 08 Python
tensorflow 打印内存中的变量方法
Jul 30 Python
详解PyCharm配置Anaconda的艰难心路历程
Aug 13 Python
python创建文件备份的脚本
Sep 11 Python
python ddt数据驱动最简实例代码
Feb 22 Python
flask框架蓝图和子域名配置详解
Jan 25 Python
python扫描线填充算法详解
Feb 19 Python
python对文件的操作方法汇总
Feb 28 Python
使用python3 实现插入数据到mysql
Mar 02 Python
python 两种方法删除空文件夹
Sep 29 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
DC最新动画电影:《战争之子》为何内容偏激,毁了一个不错的漫画
2020/04/09 欧美动漫
rephactor 优秀的PHP的重构工具
2011/06/09 PHP
ThinkPHP中URL路径访问与模块控制器之间的关系
2014/08/23 PHP
Ajax提交表单时验证码自动验证 php后端验证码检测
2016/07/20 PHP
php动态读取数据清除最右边距的方法
2017/04/12 PHP
枚举JavaScript对象的函数
2006/12/22 Javascript
Javascript的一种模块模式
2008/03/22 Javascript
JavaScript中出现乱码的处理心得
2009/12/24 Javascript
将函数的实际参数转换成数组的方法
2010/01/25 Javascript
JavaScript 原型继承
2011/12/26 Javascript
javaScript中slice函数用法实例分析
2015/06/08 Javascript
在JavaScript中处理时间之setMinutes()方法的使用
2015/06/11 Javascript
AngularJS中的过滤器使用详解
2015/06/16 Javascript
AngularJS入门之动画
2016/07/27 Javascript
angular.fromJson与toJson方法用法示例
2017/05/17 Javascript
详解Angular-Cli中引用第三方库
2017/05/21 Javascript
JavaScript的六种继承方式(推荐)
2017/06/26 Javascript
JavaScript数据结构之优先队列与循环队列实例详解
2017/10/27 Javascript
Vue2.0实现组件数据的双向绑定问题
2018/03/06 Javascript
vue-router 实现导航守卫(路由卫士)的实例代码
2018/09/02 Javascript
node.js处理前端提交的GET请求
2019/08/30 Javascript
vue跳转页面的几种方法(推荐)
2020/03/26 Javascript
vue 实现图片懒加载功能
2020/12/31 Vue.js
Python的subprocess模块总结
2014/11/07 Python
python获取本地计算机名字的方法
2015/04/29 Python
在Python 3中实现类型检查器的简单方法
2015/07/03 Python
Django项目中用JS实现加载子页面并传值的方法
2018/05/28 Python
目前最全的python的就业方向
2018/06/05 Python
详解Python装饰器
2019/03/25 Python
通过python调用adb命令对App进行性能测试方式
2020/04/23 Python
大学生先进事迹材料
2014/02/16 职场文书
小学社会实践活动总结
2014/07/03 职场文书
商务经理岗位职责
2014/07/30 职场文书
故意伤害辩护词
2015/05/21 职场文书
css中z-index: 0和z-index: auto的区别
2021/08/23 HTML / CSS
「我的青春恋爱物语果然有问题。-妄言录-」第20卷封面公开
2022/03/21 日漫