使用python实现简单五子棋游戏


Posted in Python onJune 18, 2019

用python实现五子棋简单人机模式的练习过程,供大家参考,具体内容如下

第一次写博客,我尽力把它写好。

最近在初学python,今天就用自己的一些粗浅理解,来记录一下这几天的python简单人机五子棋游戏的练习,下面是实现过程的理解(是在cmd中运行的):

主要流程: *重点内容*

- 首先是模块及类的划分
- 棋子类和棋盘类的方法
- 对策略类里的功能进行细分,调用棋子类和棋盘类
- 写出判断输赢的方法
- 用main函数进行整个游戏进度的控制

模块及类的划分

类的划分涉及到了面向对象的内容,根据五子棋游戏的设定,人和机器依次在一个棋盘里下棋,一方五子连线为赢,初步分为棋子类、棋盘类策略类,每个类单独放一个模块,加上main模块一共四个模块。

  • 棋子类包含棋子的坐标和棋子颜色(阵营),及相关get、set方法
  • 棋盘类包含了棋盘的大小和棋盘的状态 ,及相关get、set方法
  • 棋盘类的功能:接收要放入的棋子,清空棋盘,打印(显示)棋盘,给出对应位置的状态
  • 策略类:一个策略类对应一个棋盘类,在构造器里导入一个棋盘类
  • 策略类的功能:人把棋子放入棋盘、机器把棋子放入棋盘、判断棋局的输赢

棋子类和棋盘类

棋子类比较简单,在棋子的角度,只要接收位置和颜色(阵营),传出位置和颜色(阵营)即可,其中位置用元组打包传递

class Chessman(object):
 #初始化
 def __init__(self):
 pass

 def set_pos(self,pos):
 self.pos = pos

 def get_pos(self):
 return self.pos

 def set_color(self,color):
 self.color = color

 def get_color(self):
 return self.color

棋盘类需要用到棋子类,在这之前,先要进行棋盘的设定
在这里棋盘是用列表来构建,分为两层,实现x,y的位置,棋盘大小设为类属性

#类属性
 board_size =15
#初始化棋盘
 def __init__(self):
 self.__board = [[0 for i in range(0,Chessboard.board_size+1)] for j in range(0,Chessboard.board_size+1)]

清空棋盘类似

#清空棋盘,‘+'为棋盘的样子
def init_board(self):
 #忽略第0行
 for i in range(1,Chessboard.board_size+1):
 for j in range(1,Chessboard.board_size+1):
 self.__board[i][j] = '+'

打印也差不多,注意在坐标轴旁放上序列号,这里纵坐标为1-15,横坐标为a-o

# 打印棋盘
 def print_board(self):
 #打印列号
 print(' ', end='')
 for i in range(1,Chessboard.board_size+1):
 c = chr(ord('a') + i-1) # ord 字母转ASCLL码
 print(c,end='')
 print()
 #棋盘
 for i in range(1,Chessboard.board_size+1):
 if 1<= i <=9:
 print(' ', end='')
 print(i, end='')
 for j in range(1,Chessboard.board_size+1):
 print(self.__board[i][j], end='')
 print()

效果为如下

使用python实现简单五子棋游戏

接下来是棋子的放入:

这个可分为两个方法,一个根据传入的位置放置传入的颜色;另一个接收一个棋子类的实例对象,获取该实例的位置和颜色,调用第一个方法并传入数值,一定要注意在传参的时候验证

#写入对应位置的颜色
 def set_chess(self,pos, color):
 if not isinstance(pos,tuple):
 raise RuntimeError('第一个参数必须为元组')
 if pos[0] <= 0 or pos[0] > Chessboard.board_size:
 raise RuntimeError('行下标越界')
 if pos[1] <=0 or pos[1] > Chessboard.board_size:
 raise RuntimeError('纵下标越界')
 self.__board[pos[0]][pos[1]] = color 

 #把棋子对象摆放到棋盘上 
 def set_chessman(self,chessman):
 if not isinstance(chessman, Chessman):
 raise RuntimeError('类型不对,第一个参数应为ChessMan对象')
 pos = chessman.get_pos()
 color = chessman.get_color()
 self.set_chess(pos,color)

接下来的根据棋盘位置获取棋子颜色的方法主要是为了策略类的判定输赢准备的

#根据棋盘位置获取棋子的颜色
 def get_chess(self,pos):
 if pos[0] <= 0 or pos[0] > Chessboard.board_size:
 raise RuntimeError('行下标越界')
 if pos[1] <=0 or pos[1] > Chessboard.board_size:
 raise RuntimeError('纵下标越界')
 return self.__board[pos[0]][pos[1]]

策略类

策略类要用到前面两类,有更多名称的方法或属性的要用,所以要更仔细一点搞清楚哪个是哪个
首先传入一个棋盘实例对象

#初始化要把棋盘对象传入
 def __init__(self,chessboard):
 self.__chessboard = chessboard

人下棋:策略类负责把人输入的东西字符串变成x,y坐标,写入棋子对象

def parse_user_input(self,input,chessman):
 if not isinstance(chessman,Chessman):
 raise RuntimeError('类型不对,第一个参数必须为Chessman对象')

 ret = input.split(',')
 value1 = ret[0]
 value2 = ret[1]
 #转换成坐标
 pos_x = int(value1)
 pos_y = ord(value2) - ord('a') +1
 chessman.set_pos((pos_x, pos_y))
 #print(ret)

机器下棋:这里具体策略暂用随机数代替了(有空在想,略过略过~)

#电脑下棋的策略
 def computer_go(self, chessman):
 if not isinstance(chessman,Chessman):
 raise RuntimeError('类型不对,第一个参数必须为Chessman对象')
 while True:

 # pos_x和pos_y在1~15之间随机生成一个数
 pos_x = math.ceil(random.random()*Chessboard.board_size)
 pos_y = random.randint(1,15)
 #判断是否为空,否则重新生成坐标
 if self.__chessboard.get_chess((pos_x,pos_y)) == '+':
 print('电脑下棋的位置:%d,%d'%(pos_x,pos_y))
 chessman.set_pos((pos_x,pos_y))
 break

判断当前棋局的胜负:每一方下棋都要判断一次,因此可根据当前下的一子的范围来判断是否在上下左右和两斜排有连续五子,如果有则胜利。

斜排主要是x,y的判断范围比较难定,其他的差不多。以下是本宝宝绞尽脑汁想到的判断方法(特别是斜排的),检查到目前是没有问题的,或许还有更好的方法:

#判断胜负
 #当摆放一个棋子,判断是否赢
 def is_won(self,pos,color):
 #垂直方向的范围
 start_x = 1
 end_x = 15
 if pos[0] -4 >=1:
 start_x =pos[0] - 4
 if pos[0] +4 <=15:
 end_x = pos[0]+4
 #垂直方向的判断
 count = 0
 for pos_x in range(start_x, end_x+1):
 if self.__chessboard.get_chess((pos_x, pos[1])) == color:
 count +=1
 if count >=5:
 return True
 else:
 # 一旦断开 统计数清0
 count = 0

 #水平方向的范围 
 start_y = 1
 end_y = 15
 if pos[1] -4 >=1:
 start_y =pos[1] - 4
 if pos[1] +4 <=15:
 end_y = pos[1]+4
 #水平方向的判断
 count = 0
 for pos_y in range(start_y, end_y+1):
 if self.__chessboard.get_chess((pos[0], pos_y)) == color:
 count +=1
 if count >=5:
 return True
 else:
 # 一旦断开 统计数清0
 count = 0

 #左上右下方向判断
 count = 0
 s=pos[0] - pos[1]
 start=start_x
 end=end_y+s
 if pos[0]>pos[1]:
 start=start_y+s
 end=end_x
 for index in range(start, end+1):
 if self.__chessboard.get_chess((index, index-s)) == color:
 count +=1
 if count >=5:
 return True
 else:
 # 一旦断开 统计数清0
 count = 0

 #左下右上方向判断
 count = 0
 s=pos[0] + pos[1]
 if pos[0]+pos[1]<=16:
 start=start_x
 end=s-start_y

 if pos[0]+pos[1]>16:
 start=s-start_y
 end=start_x

 if s>=6 and s<=12:
 for index in range(start, end+1):
 if self.__chessboard.get_chess((index, s-index)) == color:
 count +=1
 if count >=5:
 return True
 else:
 # 一旦断开 统计数清0
 count = 0
 return False

接下来再用一个判断胜利方的方法调用上面的策略

#判断对象放置后,胜负是否已分
 def is_wonman(self,chessman):
 if not isinstance(chessman,Chessman):
 raise RuntimeError('类型不对,第一个参数必须为Chessman对象')
 pos = chessman.get_pos()
 color = chessman.get_color()
 #调用is_won()获取它的返回值
 return self.is_won(pos,color)

main模块

main模块用来对整个游戏的玩法格局进行控制。
main函数实现一局的流程,这里用循环来实现简单的人机轮流下棋。因为添加了用户选择先后的功能,所以代码暂时被我弄得繁琐了(捂脸)还可以精简的,这里就先放这个:

def main():
 chessboard =Chessboard()
 chessboard.init_board()
 chessboard.print_board()
 engine = Engine(chessboard)
 count=0
 select = int(input('用户选择先后:(先:1,后:2)'))
 #先
 while True:
 chessman = Chessman()
 chessman.set_color('x')
 if select==1:
 i = input('人下棋,请输入下棋坐标(格式:x,y):')
 engine.parse_user_input(i, chessman)#转换成坐标
 else:
 #电脑下棋
 print('电脑下棋:')
 engine.computer_go(chessman)
 # 把该棋子对象放到棋盘上
 chessboard.set_chessman(chessman)
 count +=1
 #打印棋盘
 chessboard.print_board()
 if engine.is_wonman(chessman):
 if select==1:
 print('人赢了!')

 else:
 print('电脑赢了!')
 break
 if count == 225:
 print('平局!')
 break


 #后 
 chessman = Chessman()
 chessman.set_color('o')
 if k==1:
 #电脑下棋
 print('电脑下棋:')
 #电脑给棋子生成策略(位置)
 engine.computer_go(chessman)
 else:
 i = input('人下棋,请输入下棋坐标(格式:x,y):')
 engine.parse_user_input(i, chessman)#转换成坐标
 #下棋
 chessboard.set_chessman(chessman)
 count +=1
 chessboard.print_board()
 if engine.is_wonman(chessman):
 if k==1:
 print('电脑赢了!')
 else:
 print('人赢了!')
 break
 if count == 225:
 print('平局!')
 break

主线程作为程序入口操控每个棋局:

if __name__ == '__main__':
 while True:
 print('开始一局!')
 #调用main方法
 main()
 s=int(input('是否再来一局:(是:1,否:0)'))
 if s!=1:
 break
 print('游戏结束!')

五子棋的简单人机模式就是综上所述的了,不过这个代码中输入的地方没加检查,所以坐标输入一定要是数字加逗号加字母的格式才行,可以加正则表达式进行判断。放上效果图:

使用python实现简单五子棋游戏

使用python实现简单五子棋游戏

使用python实现简单五子棋游戏

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

Python 相关文章推荐
Python multiprocessing.Manager介绍和实例(进程间共享数据)
Nov 21 Python
Python利用multiprocessing实现最简单的分布式作业调度系统实例
Nov 14 Python
Python3 log10()函数简单用法
Feb 19 Python
解决Django生产环境无法加载静态文件问题的解决
Apr 23 Python
Django为窗体加上防机器人的验证码功能过程解析
Aug 14 Python
Python计算两个矩形重合面积代码实例
Sep 16 Python
Python aiohttp百万并发极限测试实例分析
Oct 26 Python
Django Xadmin多对多字段过滤实例
Apr 07 Python
Django vue前后端分离整合过程解析
Nov 20 Python
五种Python转义表示法
Nov 27 Python
Python数据分析之绘图和可视化详解
Jun 02 Python
Python万能模板案例之matplotlib绘制直方图的基本配置
Apr 13 Python
Pycharm新手教程(只需要看这篇就够了)
Jun 18 #Python
pyqt5 获取显示器的分辨率的方法
Jun 18 #Python
PyQt5 实现字体大小自适应分辨率的方法
Jun 18 #Python
Python3网络爬虫中的requests高级用法详解
Jun 18 #Python
在Qt5和PyQt5中设置支持高分辨率屏幕自适应的方法
Jun 18 #Python
基于python的socket实现单机五子棋到双人对战
Mar 24 #Python
pyqt弹出新对话框,以及关闭对话框获取数据的实例
Jun 18 #Python
You might like
PHP 如何向 MySQL 发送数据
2006/10/09 PHP
PHP 5.3.1 安装包 VC9 VC6不同版本的区别是什么
2010/07/04 PHP
基于PHP编程注意事项的小结
2013/04/27 PHP
PHP中使用匿名函数操作数据库的例子
2014/11/17 PHP
Yii数据读取与跳转参数传递用法实例分析
2016/07/12 PHP
JS加jquery简单实现标签元素的显示或隐藏
2013/09/23 Javascript
js取消单选按钮选中并判断对象是否为空
2013/11/14 Javascript
jQuery控制TR显示隐藏的三种常用方法
2014/08/21 Javascript
javascript中的遍历for in 以及with的用法
2014/12/22 Javascript
jQuery之DOM对象和jQuery对象的转换与区别分析
2015/01/08 Javascript
PHP守护进程实例
2015/03/06 Javascript
js实现String.Fomat的实例代码
2016/09/02 Javascript
JavaScript 函数模式详解及示例
2016/09/07 Javascript
获取JavaScript异步函数的返回值
2016/12/21 Javascript
使用bat打开多个cmd窗口执行gulp、node
2017/02/17 Javascript
扩展bootstrap的modal模态框-动态添加modal框-弹出多个modal框
2017/02/21 Javascript
vue中倒计时组件的实例代码
2018/07/06 Javascript
vue数据操作之点击事件实现num加减功能示例
2019/01/19 Javascript
微信小程序云开发如何实现数据库自动备份实现
2019/08/16 Javascript
javascript二维数组和对象的深拷贝与浅拷贝实例分析
2019/10/26 Javascript
Postman如何实现参数化执行及断言处理
2020/07/28 Javascript
Vue 同步异步存值取值实现案例
2020/08/05 Javascript
javascript全局自定义鼠标右键菜单
2020/12/08 Javascript
Python实现Const详解
2015/01/27 Python
Python加pyGame实现的简单拼图游戏实例
2015/05/15 Python
python通过加号运算符操作列表的方法
2015/07/28 Python
python验证码识别教程之滑动验证码
2018/06/04 Python
python 多线程中子线程和主线程相互通信方法
2018/11/09 Python
对Python中的条件判断、循环以及循环的终止方法详解
2019/02/08 Python
利用pandas合并多个excel的方法示例
2019/10/10 Python
分享8点超级有用的Python编程建议(推荐)
2019/10/13 Python
丝芙兰加拿大官方网站:SEPHORA加拿大
2018/11/20 全球购物
创联软件面试题笔试题
2012/10/07 面试题
函授生自我鉴定
2014/03/25 职场文书
在 Python 中利用 Pool 进行多线程
2022/04/24 Python
MySQL数据库中的锁、解锁以及删除事务
2022/05/06 MySQL