使用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 字符串转列表 list 出现\ufeff的解决方法
Jun 22 Python
Python3实现的画图及加载图片动画效果示例
Jan 19 Python
对pyqt5中QTabWidget的相关操作详解
Jun 21 Python
PyQt Qt Designer工具的布局管理详解
Aug 07 Python
python中下标和切片的使用方法解析
Aug 27 Python
Python 使用多属性来进行排序
Sep 01 Python
使用Python的turtle模块画国旗
Sep 24 Python
Django框架HttpResponse对象用法实例分析
Nov 01 Python
基于python调用psutil模块过程解析
Dec 20 Python
Python线程协作threading.Condition实现过程解析
Mar 12 Python
简单了解python列表和元组的区别
May 14 Python
Python单元测试及unittest框架用法实例解析
Jul 09 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
《DOTA3》开发工作已经开始 《DOTA3》将代替《DOTA2》
2021/03/06 DOTA
php的正则处理函数总结分析
2008/06/20 PHP
ThinkPHP调用百度翻译类实现在线翻译
2014/06/26 PHP
Laravle eloquent 多对多模型关联实例详解
2017/11/22 PHP
PHP-FPM和Nginx的通信机制详解
2019/02/01 PHP
PHP常用正则表达式精选(推荐)
2019/05/28 PHP
Laravel框架下载,安装及路由操作图文详解
2019/12/04 PHP
jq选项卡鼠标延迟的插件实例
2013/05/13 Javascript
jquery选择器大全 全面详解jquery选择器
2014/03/06 Javascript
jquery.ajax之beforeSend方法使用介绍
2014/12/08 Javascript
node.js中的http.response.getHeader方法使用说明
2014/12/14 Javascript
Angularjs 动态改变title标题(兼容ios)
2016/12/29 Javascript
angularJS 指令封装回到顶部示例详解
2017/01/22 Javascript
nodejs基础知识
2017/02/03 NodeJs
Bootstrap Multiselect 常用组件实现代码
2017/07/09 Javascript
基于Jquery Ajax type的4种类型(详解)
2017/08/02 jQuery
JavaScript实现单例模式实例分享
2017/12/22 Javascript
微信小程序中button去除默认的边框实例代码
2019/08/01 Javascript
javascript实现超好看的3D烟花特效
2020/01/01 Javascript
JS实现炫酷雪花飘落效果
2020/08/19 Javascript
Python语言的12个基础知识点小结
2014/07/10 Python
Python实现批量更换指定目录下文件扩展名的方法
2016/09/19 Python
python实现图片批量压缩程序
2018/07/23 Python
Django中提供的6种缓存方式详解
2019/08/05 Python
PyCharm MySQL可视化Database配置过程图解
2020/06/09 Python
python进度条显示-tqmd模块的实现示例
2020/08/23 Python
html5中canvas学习笔记2-判断浏览器是否支持canvas
2013/01/06 HTML / CSS
Sandro Paris美国官网:典雅别致的法国时尚服饰品牌
2017/12/26 全球购物
KTV的创业计划书范文
2014/02/02 职场文书
汉语言文学专业自荐信
2014/06/11 职场文书
大学生志愿者活动总结
2014/06/27 职场文书
2014年导购员工作总结
2014/11/18 职场文书
导师对论文的学术评语
2015/01/04 职场文书
新员工试用期自我评价
2015/03/10 职场文书
写作指导:怎么书写竞聘演讲稿?
2019/07/04 职场文书
Python中22个万用公式的小结
2021/07/21 Python