编写五子棋的完整python代码_Python:游戏:五子棋之人机对战 Python:游戏:贪吃蛇 Python:游戏:扫雷(附源码) Python:游戏:300行代码实现俄罗斯方块...

本文介绍了如何使用Python的pygame库创建五子棋游戏,包括棋盘绘制、棋子抗锯齿效果、落子判断以及胜利条件检查。通过pygame.gfxdraw实现抗锯齿棋子,并详细讲解了电脑AI的简单实现,即评估每个空位得分并选择最高分的点落子。虽然这种方法可能使AI水平较低,但它提供了一个理解五子棋AI策略的基础。
摘要由CSDN通过智能技术生成

本文代码基于 python3.6 和 pygame1.9.4。html

五子棋比起我以前写的几款游戏来讲,难度提升了很多。若是是人与人对战,那么,电脑只须要判断是否赢了就能够。若是是人机对战,那你还得让电脑知道怎么下。python

咱们先从简单的问题来看。数组

开端

画棋盘

首先确定是要画出棋盘来,用 pygame 画出一个 19 × 19 或 15 × 15 的棋盘并非什么难事,这在以前的文章中已经屡次用到,就不赘述了。app

画棋子

须要说一下的是画棋子,由于没找到什么合适的棋子图片,因此只要本身来画棋子。

咱们用 pygame.draw.circle 画出来的圆形是这样的:函数

70f86de809ca4ed89795f21679fcafb0-2.png

锯齿状十分明显,

pygame.draw 中有画抗锯齿直线的函数

aaline,可是并无

aacircle 这样的函数来画一个抗锯齿的圆。

这里就须要用到 pygame.gfxdraw 啦。pygame.gfxdraw 目前还仅是实验版本,这意味着这个 API 可能会在之后的 pygame 版本中发生变化或消失。post

要绘制抗锯齿和填充形状,请首先使用函数的aa *版本,而后使用填充版本。例如:学习

col = (255, 0, 0)

surf.fill((255, 255, 255))

pygame.gfxdraw.aacircle(surf, x, y, 30, col)

pygame.gfxdraw.filled_circle(surf, x, y, 30, col)

咱们用这个方法在棋盘上画一个棋子试试看。url

916e5f79bfa240ada79f19ca68307db3-2.png 能够看到效果已明显改善。

落子

落子须要判断鼠标事件,当鼠标左键点击,获取鼠标点击的位置,而后根据棋盘的位置,计算出棋子落在棋盘的位置。spa

while True:

for event in pygame.event.get():

if event.type == QUIT:

sys.exit()

elif event.type == MOUSEBUTTONDOWN:

pressed_array = pygame.mouse.get_pressed()

if pressed_array[0]: # 鼠标左键点击

mouse_pos = pygame.mouse.get_pos()

click_point = _get_clickpoint(mouse_pos)

胜利断定

当一子落下,如何断定是否胜利?3d

能够确定的是,当某一子落下的时候,若是出现了 5 连,那么落下的这颗子一定在这条 5 连线上。那么这个问题就能够简化了,咱们无需全盘扫描,只须要在落子位置上横竖撇捺扫描一下,判断是否出现 5 连便可。

咱们定义一个棋盘类,类中实例化一个 19 × 19 的二维数组,初始值皆为 0,表示空,用 1 表示黑子,2 表示白子。这个类对外提供一个落子方法 drop,接收参数落子方和落子坐标,若是落子后胜利,则返回胜利者,不然返回 None。

Chessman = namedtuple('Chessman', 'Name Value Color')

Point = namedtuple('Point', 'X Y')

BLACK_CHESSMAN = Chessman('黑子', 1, (45, 45, 45))

WHITE_CHESSMAN = Chessman('白子', 2, (219, 219, 219))

offset = [(1, 0), (0, 1), (1, 1), (1, -1)]

class Checkerboard:

def __init__(self, line_points):

self._line_points = line_points

self._checkerboard = [[0] * line_points for _ in range(line_points)]

def _get_checkerboard(self):

return self._checkerboard

checkerboard = property(_get_checkerboard)

# 判断是否可落子

def can_drop(self, point):

return self._checkerboard[point.Y][point.X] == 0

def drop(self, chessman, point):

"""

落子

:param chessman: 黑子/白子

:param point:落子位置

:return:若该子落下以后便可获胜,则返回获胜方,不然返回 None

"""

print(f'{chessman.Name} ({point.X}, {point.Y})')

self._checkerboard[point.Y][point.X] = chessman.Value

if self._win(point):

print(f'{chessman.Name}获胜')

return chessman

# 判断是否赢了

def _win(self, point):

cur_value = self._checkerboard[point.Y][point.X]

for os in offset:

if self._get_count_on_direction(point, cur_value, os[0], os[1]):

return True

def _get_count_on_direction(self, point, value, x_offset, y_offset):

count = 1

for step in range(1, 5):

x = point.X + step * x_offset

y = point.Y + step * y_offset

if 0 <= x < self._line_points and 0 <= y < self._line_points and self._checkerboard[y][x] == value:

count += 1

else:

break

for step in range(1, 5):

x = point.X - step * x_offset

y = point.Y - step * y_offset

if 0 <= x < self._line_points and 0 <= y < self._line_points and self._checkerboard[y][x] == value:

count += 1

else:

break

return count >= 5

这里我定义了一个偏移量,咱们一共要计算横竖撇捺 4 条线,任意一条线出现 5 连就算获胜。计算方法其实是同样的,只是方向不一样,因此定义一个偏移量数组,不一样的偏移量表示不一样的方向,这样就能够利用循环来实现了,节省了不少代码。

电脑落子

这就是全篇的重头戏了,要怎么教电脑下五子棋。

首先声明,我用的是相对传统的方式,不是深度学习。

五子棋就是要实现 5 连,因此,一开始,个人想法是:将全部连线保存在一个数组中,落子的时候选择最长的连线落子。但这样有个问题解决不掉,如何让电脑识别“三三”呢?

后来网上看到篇文章,使用的方法是:遍历棋盘上的空位,计算每个位置其横竖撇捺 8 个方向上是否有己方的子,有一个就加 10 分,最后选得分最高的位置落子。

这样不太严谨,写出来的电脑估计水平很菜,可是这个思路倒是对的,落子就是要找到最值得的地方,那么咱们干脆对每个可落子的地方来作一个评估,选出最优解。

这里咱们须要了解一下五子棋的几种基本棋形:连五,活四,冲四,活三,眠三,活二,眠二。

连五

顾名思义,五颗同色棋子连在一块儿,赢了。

e5dc1c575cbf4df3b2089b6b4edccbdb-2.png

活四

四颗同色棋子连在一块儿,而且左右两边都没有对方棋子阻挡,有两个连五点。

dad13c80f75e41ec9917e5387cf1c204-2.png

冲四

四颗同色棋子连在一块儿,而且一边有对方棋子阻挡,或者四颗棋子不是连的,当中有个空挡,这时只有一个连五点。

345b3d03cf0f4dc58e39acc42ebc7916-2.png

活3、跳活三

活三:三颗同色棋子连在一块儿。

0de32e4fe72f4564ba7e53152698280e-2.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值