使用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 相关文章推荐
python3读取MySQL-Front的MYSQL密码
May 03 Python
基于Django URL传参 FORM表单传数据 get post的用法实例
May 28 Python
python  创建一个保留重复值的列表的补码
Oct 15 Python
python 循环读取txt文档 并转换成csv的方法
Oct 26 Python
详解python之heapq模块及排序操作
Apr 04 Python
python print出共轭复数的方法详解
Jun 25 Python
树莓派安装OpenCV3完整过程的实现
Oct 10 Python
使用tensorflow显示pb模型的所有网络结点方式
Jan 23 Python
使用遗传算法求二元函数的最小值
Feb 11 Python
keras实现调用自己训练的模型,并去掉全连接层
Jun 09 Python
python的dict判断key是否存在的方法
Dec 09 Python
Django与AJAX实现网页动态数据显示的示例代码
Feb 24 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 需要掌握的东西 不做浮躁的人
2009/12/28 PHP
php使用COPY函数更新配置文件的方法
2015/06/18 PHP
php file_get_contents取文件中数组元素的方法
2017/04/01 PHP
PHP排序算法之堆排序(Heap Sort)实例详解
2018/04/21 PHP
PHP预定义超全局数组变量小结
2018/08/20 PHP
PHP+swoole+linux实现系统监控和性能优化操作示例
2019/04/15 PHP
ThinkPHP5框架中使用JWT的方法示例
2020/06/03 PHP
PHP解密支付宝小程序的加密数据、手机号的示例代码
2021/02/26 PHP
Javascript 异步加载详解(浏览器在javascript的加载方式)
2012/05/20 Javascript
图片轮换效果实现代码(点击按钮停止执行)
2013/04/12 Javascript
深入了解javascript中的prototype与继承
2013/04/14 Javascript
js history对象简单实现返回和前进
2013/10/30 Javascript
javascript与jquery中跳出循环的区别总结
2013/11/04 Javascript
使用javascript实现Iframe自适应高度
2014/12/24 Javascript
jQuery插件expander实现图片翻转特效
2015/05/21 Javascript
jquery小火箭返回顶部代码分享
2015/08/19 Javascript
JS实现自动切换文字的导航效果代码
2015/08/27 Javascript
jQuery基于json与cookie实现购物车的方法
2016/04/15 Javascript
animate 实现滑动切换效果【实例代码】
2016/05/05 Javascript
JavaScript 数组中最大最小值
2016/06/05 Javascript
vue实现打印功能的两种方法
2018/09/07 Javascript
VUE-ElementUI 自定义Loading图操作
2020/11/11 Javascript
Python即时网络爬虫项目启动说明详解
2018/02/23 Python
python pyheatmap包绘制热力图
2018/11/09 Python
用python爬取租房网站信息的代码
2018/12/14 Python
Python多线程threading模块用法实例分析
2019/05/22 Python
pandas数据处理进阶详解
2019/10/11 Python
tensorflow查看ckpt各节点名称实例
2020/01/21 Python
Python基于百度AI实现OCR文字识别
2020/04/02 Python
EGO Shoes美国/加拿大:英国时髦鞋类品牌
2018/08/04 全球购物
Gibson London官网:以地道的英国男装而著称
2019/12/06 全球购物
维护民族团结心得体会2016
2016/01/15 职场文书
2019银行员工个人工作自我鉴定
2019/06/27 职场文书
陶瓷类经典广告语集锦
2019/10/25 职场文书
ORACLE数据库应用开发的三十个注意事项
2021/06/07 Oracle
Python获取字典中某个key的value
2022/04/13 Python