python实现井字棋小游戏


Posted in Python onMarch 04, 2020

本文为大家分享了python实现井字棋小游戏,供大家参考,具体内容如下

周五晚上上了python的选修课,本来以为老师是从python的基础语法开始的,没想到是从turtle画图开始,正好补上了我以前一些不懂的地方,有人讲一下还是比啃书好一点。

之前从图书馆借了一本python游戏编程,看了前面几章后就没怎么看了,晚上突然想看看,然后跟着教程写个游戏的。最后就有了这个井字棋的诞生,其实代码并不是很长,主要是思路,需要考虑的周全一点。代码写完后就和电脑下了好久的井字棋,一局都没赢,真的是很无奈了,比不过比不过。

开发环境 :windows10 + pycharm(因为下棋时候需要输入,sublime不知道怎么弄输入,所以就用了pycharm)

需要用到的包也只有一个 :random

游戏的话首先要弄清楚的是游戏的流程,首先做什么然后做什么。因为井字棋相对来说不算是一个复杂的游戏,所以流程就不多讲了,我首先做的是画棋盘、电脑和玩家的棋子、谁先落子等,下面通过代码来解释 :

# 画棋盘的函数,传入一个放置棋子的列表
def drawBoard(board) :
 
 print(" " + board[7] + " | " + board[8] + " | " + board[9])
 print("------------")
 print(" " + board[4] + " | " + board[5] + " | " + board[6])
 print("------------")
 print(" " + board[1] + " | " + board[2] + " | " + board[3])
 
# 玩家选择所想用的棋子种类
def inputPlayerLetter() :
 
 letter = ''
 while not (letter == 'X' or letter == 'O') :
 print("Do you want to be X or O")
 # 自动将小写转化为大写
 letter = input().upper()
 
 # 如果玩家选择的X,则自动将O赋给电脑,反之一样
 if letter == 'X' :
 return ['X','O']
 else :
 return ['O','X']
 
# 这里随机生成0或者1来表示谁先落子
def whoGoesFirst() :
 
 if random.randint(0,1) == 0 :
 return 'computer'
 else :
 return 'player'
 
# 如果玩家选择y或者Y则游戏重新开始
def playAgain():
 
 print("Do you want to play again?(yes or no)")
 return input().lower().startswith('y')
 
# 将棋子放置到棋盘上面
# board参数是储存棋子的列表
# letter参数是棋子的类型
# move是选择将棋子放在哪
def makeMove(board, letter, move) :
 
 board[move] = letter
 
# 根据井字棋规则判断是否获胜
def isWinner(bo, le) :
 
 return ((bo[7] == le and bo[8] == le and bo[9] == le) or
  (bo[4] == le and bo[5] == le and bo[6] == le) or
  (bo[1] == le and bo[2] == le and bo[3] == le) or
  (bo[7] == le and bo[4] == le and bo[1] == le) or
  (bo[8] == le and bo[5] == le and bo[2] == le) or
  (bo[9] == le and bo[6] == le and bo[3] == le) or
  (bo[7] == le and bo[5] == le and bo[3] == le) or
  (bo[9] == le and bo[5] == le and bo[1] == le))
 
# 将已经在棋盘上的棋子备份,随时更新
def getBoardCopy(board) :
 
 dupeBoard = []
 for i in board :
 dupeBoard.append(i)
 
 return dupeBoard
 
# 判断棋盘是否还有可落子的地方
def isSpaceFree(board, move) :
 
 return board[move] == ' '
 
# 获取玩家落子的位置
def getPlayerMove(board) :
 
 move = ' '
 # 判断落子的位置是否正确以及棋盘是否还能落子
 while move not in '1 2 3 4 5 6 7 8 9'.split() or not isSpaceFree(board, int(move)) :
 
 print("What is your next move?(1-9)")
 move = input()
 return int(move)
 
# 找到可以落子的地方,主要是计算机使用的
def chooseRandomMoveFromList(board, moveList) :
 
 possibleMoves = []
 for i in moveList :
 if isSpaceFree(board, i) :
  possibleMoves.append(i)
 
 if len(possibleMoves) != 0 :
 return random.choice(possibleMoves)
 else :
 return None

上述代码实现了部分简单的功能,然后是实现计算机的落子部分,毕竟是计算机,得看着不那么傻,所以下面相当于是一个小小的AI,电脑能在备份的副本上判断,根据判断的结果来指定落子的位置 :

# 电脑落子
def getComputerMove(board, computerLetter) :
 
 # 给出棋盘上电脑和玩家棋子的类型
 if computerLetter == 'X' :
 playerLetter = 'O'
 else :
 playerLetter = 'X'
 
 for i in range(1,10) :
 # 在备份的棋盘中判断是否有可以落子的地方
 copy = getBoardCopy(board)
 if isSpaceFree(copy, i) :
  # 如果有可以落子的地方,则先在备份的棋盘上落子
  makeMove(copy, computerLetter, i)
  # 落子后判断电脑是否能赢,并且返回能赢的落子的位置
  if isWinner(copy, computerLetter) :
  return i
 
 for i in range(1,10) :
 copy = getBoardCopy(board)
 if isSpaceFree(copy, i) :
  # 在备份的棋盘上模拟玩家落子
  makeMove(copy, playerLetter, i)
  # 如果下一次玩家落子就可以赢,返回玩家落子的位置,用于堵住玩家
  if isWinner(copy, playerLetter) :
  return i
 
 # 随机在四个角处落子
 move = chooseRandomMoveFromList(board,[1,3,7,9])
 if move != None :
 return move
 
 # 如果角处已被占满,则落子在中间位置5处
 if isSpaceFree(board, 5) :
 return 5
 
 # 如果角和中间都被占满,则随机选择边上落子
 return chooseRandomMoveFromList(board,[2,4,6,8])
 
# 判断棋盘是否已满
def isBoardFull(board) :
 
 for i in range(1,10) :
 if isSpaceFree(board, i) :
  return False
 return True
 
 
print("Welcome to Tictactoe !!!")
 
while True :
 
 # 初始化棋盘为空
 theBoard = [' '] * 10
 # 玩家和电脑棋子类型的选择
 playerLetter, computerLetter = inputPlayerLetter()
 # 先后顺序的决定
 turn = whoGoesFirst()
 print('The ' + turn + ' will go first')
 # 游戏开始的标志位,当游戏结束时变成False
 gameIsPlaying = True
 
 while gameIsPlaying :
 # 玩家先行
 if turn == 'player' :
  drawBoard(theBoard)
  # 获取玩家下棋的位置
  move = getPlayerMove(theBoard)
  # 将玩家的棋子传入列表相应的位置
  makeMove(theBoard, playerLetter, move)
 
  # 如果玩家获胜,标志位变为False
  if isWinner(theBoard, playerLetter) :
  drawBoard(theBoard)
  print("You win !")
  gameIsPlaying = False
  # 否则则判断棋盘是否已满
  else :
  if isBoardFull(theBoard) :
   drawBoard(theBoard)
   print("Tie")
   break
  # 若棋盘未满,且玩家已落子,则下一次落到计算机落子
  else :
   turn = 'computer'
 # 电脑先行
 else :
  # 电脑随机选择位置落子
  move = getComputerMove(theBoard, computerLetter)
  makeMove(theBoard, computerLetter, move)
 
  # 如果电脑落子获胜,则游戏结束
  if isWinner(theBoard, computerLetter) :
  drawBoard(theBoard)
  print("You lose !")
  gameIsPlaying = False
  else :
  if isBoardFull(theBoard) :
   drawBoard(theBoard)
   print("Tie")
   break
  else :
   turn = 'player'
 
 # 玩家没有再次开始游戏,则跳出循环
 if not playAgain():
 break

上述所有代码实现了井字棋的人机对战,整合起来就可以玩了,反正我是没有下赢过的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python Sleep休眠函数使用简单实例
Feb 02 Python
在IIS服务器上以CGI方式运行Python脚本的教程
Apr 25 Python
python生成器generator用法实例分析
Jun 04 Python
python Django批量导入不重复数据
Mar 25 Python
Python中的TCP socket写法示例
May 11 Python
在Python中使用gRPC的方法示例
Aug 08 Python
python实现通过队列完成进程间的多任务功能示例
Oct 28 Python
Python tkinter 下拉日历控件代码
Mar 04 Python
Python socket处理client连接过程解析
Mar 18 Python
python基础之爬虫入门
May 10 Python
Pandas加速代码之避免使用for循环
May 30 Python
python基础之类属性和实例属性
Oct 24 Python
python tkinter 设置窗口大小不可缩放实例
Mar 04 #Python
Python tkinter 下拉日历控件代码
Mar 04 #Python
Python Tkinter Entry和Text的添加与使用详解
Mar 04 #Python
Python列表倒序输出及其效率详解
Mar 04 #Python
python tkinter之顶层菜单、弹出菜单实例
Mar 04 #Python
python tkinter之 复选、文本、下拉的实现
Mar 04 #Python
自定义Django默认的sitemap站点地图样式
Mar 04 #Python
You might like
地球防卫队:陪着奥特曼打小怪兽的人类力量 那些经典队服
2020/03/08 日漫
PHP文本数据库的搜索方法
2006/10/09 PHP
ThinkPHP实现更新数据实例详解(demo)
2016/06/29 PHP
thinkPHP5框架中widget的功能与用法详解
2018/06/11 PHP
PHP 实现 WebSocket 协议原理与应用详解
2020/04/22 PHP
javascript编程起步(第二课)
2007/01/10 Javascript
js 蒙版进度条(结合图片)
2010/03/10 Javascript
JS动态添加option和删除option(附实例代码)
2013/04/01 Javascript
html+js实现动态显示本地时间
2013/09/21 Javascript
jquery 无限级下拉菜单的简单实现代码
2014/02/21 Javascript
alert出数组中的随即值代码
2014/09/25 Javascript
浅析Bootstrip的select控件绑定数据的问题
2016/05/10 Javascript
JavaScript如何实现跨域请求
2016/08/05 Javascript
十大 Node.js 的 Web 框架(快速提升工作效率)
2017/06/30 Javascript
nodejs实现解析xml字符串为对象的方法示例
2018/03/14 NodeJs
JavaScript数组方法的错误使用例子
2018/09/13 Javascript
菜鸟使用python实现正则检测密码合法性
2016/01/05 Python
利用arcgis的python读取要素的X,Y方法
2018/12/22 Python
python 串口读取+存储+输出处理实例
2019/12/26 Python
Python底层封装实现方法详解
2020/01/22 Python
浅谈keras的深度模型训练过程及结果记录方式
2020/01/24 Python
Django添加bootstrap框架时无法加载静态文件的解决方式
2020/03/27 Python
HTML5 Canvas实现360度全景图的示例代码
2018/01/29 HTML / CSS
DVF官方网站:美国时装界尊尚品牌
2017/08/29 全球购物
SKECHERS官方旗舰店:美国舒适运动休闲品牌
2017/12/22 全球购物
const和static readonly区别
2013/05/20 面试题
课程设计心得体会
2013/12/28 职场文书
2014年高三毕业生自我评价
2014/01/11 职场文书
运动会入场词50字
2014/02/20 职场文书
高中军训感言1000字
2014/03/01 职场文书
物流管理专业毕业生自荐信
2014/03/04 职场文书
信息管理应届生求职信
2014/03/07 职场文书
城市规划应届毕业生自荐信
2014/07/04 职场文书
单位工作证明格式模板
2014/10/04 职场文书
在酒桌上的敬酒词
2015/08/12 职场文书
mongodb清除连接和日志的正确方法分享
2021/09/15 MongoDB