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实现截屏的函数
Jul 25 Python
python开发之thread实现布朗运动的方法
Nov 11 Python
Django自定义认证方式用法示例
Jun 23 Python
numpy.ndarray 交换多维数组(矩阵)的行/列方法
Aug 02 Python
ERLANG和PYTHON互通实现过程详解
Jul 05 Python
Python爬虫运用正则表达式的方法和优缺点
Aug 25 Python
python对常见数据类型的遍历解析
Aug 27 Python
python线程定时器Timer实现原理解析
Nov 30 Python
Python正则表达式学习小例子
Mar 03 Python
python实现简单的tcp 文件下载
Sep 16 Python
Python在后台自动解压各种压缩文件的实现方法
Nov 10 Python
python 实时调取摄像头的示例代码
Nov 25 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
通过文字传递创建的图形按钮
2006/10/09 PHP
PHP+swoole实现简单多人在线聊天群发
2016/01/19 PHP
thinkphp实现把数据库中的列的值存到下拉框中的方法
2017/01/20 PHP
PHP计算近1年的所有月份
2017/03/13 PHP
动态表格Table类的实现
2009/08/26 Javascript
jQuery validate 中文API 附validate.js中文api手册
2010/07/31 Javascript
javascript运行机制之this详细介绍
2014/02/07 Javascript
ajax提交表单实现网页无刷新注册示例
2014/05/08 Javascript
jQuery制作简洁的多级联动Select下拉框
2014/12/23 Javascript
jQuery中:lt选择器用法实例
2014/12/29 Javascript
浅谈js中的闭包
2015/03/16 Javascript
javascript生成img标签的3种实现方法(对象、方法、html)
2015/12/25 Javascript
ES6新特性五:Set与Map的数据结构实例分析
2017/04/21 Javascript
js随机生成一个验证码
2017/06/01 Javascript
ES6 javascript中class静态方法、属性与实例属性用法示例
2017/10/30 Javascript
讲解vue-router之命名路由和命名视图
2018/05/28 Javascript
JavaScript反射与依赖注入实例详解
2018/05/29 Javascript
Vue中的v-for循环key属性注意事项小结
2018/08/12 Javascript
更改BootStrap popover的默认样式及popover简单用法
2018/09/13 Javascript
[52:03]Secret vs VG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
Python OpenCV实现鼠标画框效果
2020/08/19 Python
python查找特定名称文件并按序号、文件名分行打印输出的方法
2020/04/24 Python
python向企业微信发送文字和图片消息的示例
2020/09/28 Python
雅虎笔试题(字符串操作)
2015/03/24 面试题
人力资源管理专业毕业生自我评价
2013/09/21 职场文书
我的画教学反思
2014/04/28 职场文书
大学生求职信
2014/06/17 职场文书
安全生产目标管理责任书
2014/07/25 职场文书
计划生育诚信协议书
2014/11/02 职场文书
2014年财务工作总结与计划
2014/12/08 职场文书
个人年终总结结尾
2015/03/06 职场文书
2015年九一八事变纪念日演讲稿
2015/03/19 职场文书
信息技术远程培训心得体会
2016/01/09 职场文书
同学会演讲稿
2019/04/02 职场文书
eclipse创建项目没有dynamic web的解决方法
2021/06/24 Java/Android
Redis高并发防止秒杀超卖实战源码解决方案
2021/11/01 Redis