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实现对excel文件列表值进行统计的方法
Jul 25 Python
Python中map,reduce,filter和sorted函数的使用方法
Aug 17 Python
python图片验证码生成代码
Jul 02 Python
浅谈Python浅拷贝、深拷贝及引用机制
Dec 15 Python
python tornado微信开发入门代码
Aug 24 Python
python3 tkinter实现点击一个按钮跳出另一个窗口的方法
Jun 13 Python
python3中类的继承以及self和super的区别详解
Jun 26 Python
Python FTP文件定时自动下载实现过程解析
Nov 12 Python
如何用OpenCV -python3实现视频物体追踪
Dec 04 Python
利用python实现平稳时间序列的建模方式
Jun 03 Python
Django模型验证器介绍与源码分析
Sep 08 Python
Django中日期时间型字段进行年月日时分秒分组统计
Nov 27 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
phpMyAdmin 安装及问题总结
2009/05/28 PHP
封装一个PDO数据库操作类代码
2009/09/09 PHP
在smarty模板中使用PHP函数的方法
2011/04/23 PHP
PHP求最大子序列和的算法实现
2011/06/24 PHP
php后台多用户权限组思路与实现程序代码分享
2012/02/13 PHP
PHP实现自动登入google play下载app report的方法
2014/09/23 PHP
php通过strpos查找字符串出现位置的方法
2015/03/17 PHP
Laravel 自定命令以及生成文件的例子
2019/10/23 PHP
jQuery AnythingSlider滑动效果插件
2010/02/07 Javascript
javascript 自定义回调函数示例代码
2014/09/26 Javascript
JavaScript中判断函数、变量是否存在
2015/06/10 Javascript
JavaScript、jQuery与Ajax的关系
2016/01/24 Javascript
JavaScript模拟数组合并concat
2016/03/06 Javascript
js日期相关函数dateAdd,dateDiff,dateFormat等介绍
2016/09/24 Javascript
如何使用Vuex+Vue.js构建单页应用
2016/10/27 Javascript
JavaScript实现同一个页面打开多张图片
2016/12/29 Javascript
Angularjs实现下拉框联动的示例代码
2017/08/22 Javascript
Python中的二叉树查找算法模块使用指南
2014/07/04 Python
python解决js文件utf-8编码乱码问题(推荐)
2018/05/02 Python
浅谈python标准库--functools.partial
2019/03/13 Python
详解python itertools功能
2020/02/07 Python
python GUI库图形界面开发之PyQt5树形结构控件QTreeWidget详细使用方法与实例
2020/03/02 Python
html5跨域通讯之postMessage的用法总结
2013/11/07 HTML / CSS
香奈儿美国官网:CHANEL美国
2020/05/20 全球购物
为什么会有内存对齐
2016/10/10 面试题
Delphi CS笔试题
2014/01/04 面试题
餐厅考勤管理制度
2014/01/28 职场文书
销售经理竞聘书
2014/03/31 职场文书
公司贷款承诺书
2014/05/30 职场文书
电焊工岗位工作职责
2014/07/09 职场文书
公司新人试用期自我评价
2014/09/17 职场文书
无锡灵山大佛导游词
2015/02/09 职场文书
2015小学教师德育工作总结
2015/05/12 职场文书
行政诉讼答辩状
2015/05/21 职场文书
又涨知识了,自律到底多重要?
2019/06/27 职场文书
nginx搭建图片服务器的过程详解(root和alias的区别)
2021/03/31 Servers