使用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的函数嵌套的使用方法
Jan 24 Python
Python实现替换文件中指定内容的方法
Mar 19 Python
基于循环神经网络(RNN)实现影评情感分类
Mar 26 Python
python调用外部程序的实操步骤
Mar 04 Python
python socket 聊天室实例代码详解
Nov 14 Python
Python实现井字棋小游戏
Mar 09 Python
python对一个数向上取整的实例方法
Jun 18 Python
keras K.function获取某层的输出操作
Jun 29 Python
python 实现围棋游戏(纯tkinter gui)
Nov 13 Python
python 多线程爬取壁纸网站的示例
Feb 20 Python
Python 实现绘制子图及子图刻度的变换等问题
May 31 Python
Python实现为PDF去除水印的示例代码
Apr 03 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
海贼王动画变成“真人”后,凯多神还原,雷利太帅了!
2020/04/09 日漫
PHP脚本的10个技巧(2)
2006/10/09 PHP
php 获得汉字拼音首字母的函数
2009/08/01 PHP
PHP 裁剪图片成固定大小代码方法
2009/09/09 PHP
php图片加中文水印实现代码分享
2012/10/31 PHP
laravel安装zend opcache加速器教程
2015/03/02 PHP
浅谈PHP中单引号和双引号到底有啥区别呢?
2015/03/04 PHP
php支付宝手机网页支付类实例
2015/03/04 PHP
jQuery中live方法的重复绑定说明
2011/10/21 Javascript
JavaScript打字小游戏代码
2011/12/26 Javascript
JS注册/移除事件处理程序(ExtJS应用程序设计实战)
2013/05/07 Javascript
div拖拽插件——JQ.MoveBox.js(自制JQ插件)
2013/05/17 Javascript
浅析LigerUi开发中谨慎载入common.css文件
2013/07/09 Javascript
document.forms[].submit()使用介绍
2014/02/19 Javascript
浅谈jQuery中setInterval()方法
2015/07/07 Javascript
javascript与jquery动态创建html元素示例
2016/07/25 Javascript
vue之数据交互实例代码
2017/06/16 Javascript
JavaScript hasOwnProperty() 函数实例详解
2017/08/04 Javascript
[js高手之路]原型式继承与寄生式继承详解
2017/08/28 Javascript
Linux Centos7.2下安装nodejs&amp;npm配置全局路径的教程
2018/05/15 NodeJs
BootStrap模态框闪退问题实例代码详解
2018/12/10 Javascript
js实现课堂随机点名系统
2019/11/21 Javascript
简单介绍Python中用于求最小值的min()方法
2015/05/15 Python
python爬取NUS-WIDE数据库图片
2016/10/05 Python
matplotlib 输出保存指定尺寸的图片方法
2018/05/24 Python
Python实现截取PDF文件中的几页代码实例
2019/03/11 Python
Python第三方库安装缓慢的解决方法
2021/02/06 Python
html Table 表头固定的实现
2019/01/22 HTML / CSS
HTML5中使用postMessage实现两个网页间传递数据
2016/06/22 HTML / CSS
罗德与泰勒百货官网:Lord & Taylor
2016/08/12 全球购物
联想墨西哥官方网站:Lenovo墨西哥
2016/08/17 全球购物
美国最好的葡萄酒网上商店:Wine Library
2019/11/02 全球购物
日语专业毕业生求职信
2013/12/04 职场文书
房地产销售计划书
2014/01/10 职场文书
科技活动周标语
2014/10/08 职场文书
厉害!这是Redis可视化工具最全的横向评测
2021/07/15 Redis