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标准算法实现数组全排列的方法
Mar 17 Python
python图像处理之镜像实现方法
May 30 Python
实例Python处理XML文件的方法
Aug 31 Python
解决Python下json.loads()中文字符出错的问题
Dec 19 Python
Python 堆叠柱状图绘制方法
Jul 29 Python
python2.7实现复制大量文件及文件夹资料
Aug 31 Python
解析Python3中的Import
Oct 13 Python
torch 中各种图像格式转换的实现方法
Dec 26 Python
Python模块的定义,模块的导入,__name__用法实例分析
Jan 07 Python
Python作用域与名字空间原理详解
Mar 21 Python
如何基于Python按行合并两个txt
Nov 03 Python
python 高阶函数简单介绍
Feb 19 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
gd库图片下载类实现下载网页所有图片的php代码
2012/08/20 PHP
使用php实现快钱支付功能(涉及到接口)
2013/07/01 PHP
php使用FFmpeg接口获取视频的播放时长、码率、缩略图以及创建时间
2016/11/07 PHP
php PDO实现的事务回滚示例
2017/03/23 PHP
PHP5.6新增加的可变函数参数用法分析
2017/08/25 PHP
DOM相关内容速查手册
2007/02/07 Javascript
js右键菜单效果代码
2007/07/21 Javascript
模仿jQuery each函数的链式调用
2009/07/22 Javascript
jQuery Deferred和Promise创建响应式应用程序详细介绍
2013/03/05 Javascript
JS实现简单的Canvas画图实例
2013/07/04 Javascript
js和as的稳定传值问题解决
2013/07/14 Javascript
jQuery中验证表单提交方式及序列化表单内容的实现
2014/01/06 Javascript
innerHTML动态添加html代码和脚本兼容多个浏览器
2014/10/11 Javascript
node.js中的console.timeEnd方法使用说明
2014/12/09 Javascript
深入理解JavaScript系列(27):设计模式之建造者模式详解
2015/03/03 Javascript
纯CSS3代码实现滑动开关效果
2015/08/19 Javascript
深入剖析JavaScript中的函数currying柯里化
2016/04/29 Javascript
关于JavaScript中事件绑定的方法总结
2016/10/26 Javascript
老生常谈javascript中逻辑运算符&&和||的返回值问题
2017/04/13 Javascript
JS生成随机打乱数组的方法示例
2017/12/23 Javascript
修改npm全局安装模式的路径方法
2018/05/15 Javascript
vue使用@scroll监听滚动事件时,@scroll无效问题的解决方法详解
2019/10/15 Javascript
[00:35]DOTA2上海特级锦标赛 EG战队宣传片
2016/03/04 DOTA
python处理中文编码和判断编码示例
2014/02/26 Python
python Django框架实现自定义表单提交
2016/03/25 Python
深入理解NumPy简明教程---数组3(组合)
2016/12/17 Python
python爬虫之验证码篇3-滑动验证码识别技术
2019/04/11 Python
基于python实现语音录入识别代码实例
2020/01/17 Python
完美解决keras 读取多个hdf5文件进行训练的问题
2020/07/01 Python
matplotlib 多个图像共用一个colorbar的实现示例
2020/09/10 Python
详解python对象之间的交互
2020/09/29 Python
用python监控服务器的cpu,磁盘空间,内存,超过邮件报警
2021/01/29 Python
施华洛世奇西班牙官网:SWAROVSKI西班牙
2019/06/06 全球购物
通信工程专业毕业生推荐信
2013/12/25 职场文书
校园活动策划书范文
2014/01/10 职场文书
如何做好员工培训计划?
2019/07/09 职场文书