Python实现简单五子棋人机对战:面向对象设计与核心逻辑解析
本文详细解析使用Python实现简单五子棋人机对战的完整过程。文章基于面向对象思想,将系统划分为棋子类、棋盘类和策略类三个核心模块。重点介绍了15x15棋盘的数据结构构建、坐标解析逻辑以及通过遍历判断五子连珠的胜负算法。代码在CMD环境中运行,展示了从初始化、用户交互到游戏循环控制的完整实现,适合Python初学者理解类与模块的组织方式。
本文分享使用Python实现五子棋简单人机对战模式的练习过程,供读者参考。
近期在深入研习Python语言,本文旨在通过个人理解,记录这几天关于五子棋人机对战游戏的开发实践。以下为实现思路的详细梳理(运行环境为CMD命令行)。
整体开发流程如下:
- 首先进行模块与类的架构划分 - 定义棋子类和棋盘类的基础方法 - 对策略类功能进行细化,并调用棋子与棋盘类 - 编写判断胜负的核心逻辑 - 通过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()运行效果如下所示:

接下来是棋子的放置逻辑:
该功能可分为两个方法:一个方法根据传入的位置放置指定颜色;另一个方法接收一个棋子类的实例对象,获取该实例的位置和颜色,调用第一个方法并传入相应数值。务必注意在传参时进行类型验证。
#写入对应位置的颜色
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('游戏结束!') 五子棋的简单人机模式即如上所述。需注意,代码中输入部分未加入严格检查,因此坐标输入必须严格遵循“数字+逗号+字母”的格式,建议后续可加入正则表达式进行校验。附上运行效果图:



以上就是本文的全部内容,希望对大家的学习有所帮助,也欢迎大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













