大家好,又见面了,我是你们的朋友全栈君。
本文转载自数据札记倌,详情可以扫描下方二维码:
五子棋是常见的一款小游戏,五子棋问题是人工智能中的一个经典问题。这篇文章主要介绍了python版本五子棋的实现代码,大家可以做个参考,与我的傻儿子对弈一下。
简 述
虽然计算机已经几乎激活成功教程了五子棋的取胜秘籍,甚至给出了取胜的具体方案,然而,对人来说,五子棋还是非常有玩头的。
我们往往有五子棋的技巧性和全局观远远比不上象棋,围棋之类的感觉:
这个真不一定,先说技巧性:五子棋、象棋、围棋的最初级技巧都是死活题。围棋那高难度的生死题我就不多说了。而象棋如果只是说铁门栓天地炮等等杀法,其实还是很好掌握的;如果加上各种基础的残局估计差不多。五子棋的话,坂田三手胜与天狗道场,或者是贴吧里边各种变态杀法题,也不敢说简单。
扯远啦~,这篇文章主要是要用python来实现五子棋的人机对战,可以趣味性地玩一下,远没有到不可战胜的程度。
问题描述
人机对弈算法属于策略型人工智能算法,本游戏中设置了人机对弈的游戏模式,整个程序我们有几个大的问题需要解决:
1)、计算机需要判断胜负
2)、计算机落子的逻辑
第一个问题的核心思想是要设置对局结束的判断逻辑,在这部分我们只需要写出五子相连的判断条件;
第二个问题的核心思想是要比较不同落子的优劣势,需要评估每一步的胜算。
其算法如下:
-
写出获胜逻辑或者设置所有获胜组合
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
● |
获胜逻辑:一个二维坐标上,判断上下、左右、两个45度直线,是否有五个相同的直连棋子。
-
评估棋格获胜分数
在计算机下棋之前,会计算空白棋格上的获胜分数,根据分数高低获取最佳位置。计算机会将棋子下在获胜分数最高的地方。
当已放置4颗棋子时,必须在第五个空棋格上设置绝对高的分值。
-
计算机的攻击与防守
计算机计算获胜分值越高的棋格,就能确定能让自己的棋子最有可能达成联机的位置,也就是最佳进攻位置,而一旦计算机能确定自己的最高分值的位置,计算机就具备了进攻能力。同理,计算机能计算出玩家的最大分值位置,并抢先玩家获得该位置,这样计算机就具有了防御的能力。
代码实现
-
棋盘
棋盘是我们整个游戏的落子范围,需要提前定义好大小:
# 画棋盘
def GobangWin():
gw = GraphWin('AI Gobang', GRID_WIDTH*COLUMN, GRID_WIDTH*ROW)
gw.setBackground('gray')
for j in range(0, GRID_WIDTH*COLUMN+1, GRID_WIDTH):
l = Line(Point(j, 0), Point(j, GRID_WIDTH*COLUMN))
l.draw(gw)
for i in range(0, GRID_WIDTH*ROW+1, GRID_WIDTH):
l = Line(Point(0, i), Point(GRID_WIDTH*ROW, i))
l.draw(gw)
return gw
-
棋子
在棋盘上画一个棋子:
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)
-
落子
通过鼠标点击的位置记录落子,这里核心是要实现的点击鼠标获取坐标,可以使用Graphics
from graphics import *
#设置画布窗口名和尺寸
win = GraphWin('hehe', 666, 666)
#关闭画布窗口
win.getMouse()
win.close()
#画点
pt = Point(100, 100)
pt.draw(win)
#画圆
cir = Circle(Point(200, 200), 75)
cir.draw(win)
cir.setOutline('red') #外围轮廓颜色
cir.setFill('yellow') #填充颜色
#画线
line = Line(Point(650, 100), Point(250, 100))
line.draw(win)
#画矩形
rect = Rectangle(Point(300, 300), Point(400, 400))
rect.setFill('red') #填充颜色
rect.draw(win)
#画椭圆
oval = Oval(Point(450, 450), Point(600, 600))
oval.setFill('red') #填充颜色
oval.draw(win)
#显示文字
message = Text(Point(win.getWidth()/2, 20), 'Click anywhere to quit.')
message.draw(win)
-
判断输赢
一个二维坐标上,判断上下、左右、两个45度直线,是否有五个相同的直连棋子,只要五子相连则游戏结束。或者遍历每一种获胜情况都可以做出判断:
演示操作
下面直接看一下实际操作结果吧~
这里执行起来还是挺慢的,在执行逻辑的判断方面还有很多可以优化的地方。
呼~,傻儿子玩得还不错,还好赢了,另外这个不是深度学习的实现办法,如果想尝试深度学习方法戳这里:
AlphaZero实战:从零学下五子棋(附代码)
https://github.com/junxiaosong/AlphaZero_Gomoku
如果你喜欢的话点个再看,让更多人看到~
公众号后台回复关键词:五子棋,获取本文源码
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/150602.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...