Python实现五子棋人机对战 | CSDN博文精选「建议收藏」

Python实现五子棋人机对战 | CSDN博文精选「建议收藏」作者|吴小鹏来源|数据札记倌(ID:Data_Groom)五子棋是常见的一款小游戏,五子棋问题是人工智能中的一个经典问题。这篇文章主要介绍了Python版本五子棋的实现代码,大家可以做个参考,与我的傻儿子对弈一下。简述虽然计算机已经几乎激活成功教程了五子棋的取胜秘籍,甚至给出了取胜的具体方案,然而,对人来说,五子棋还是非常有玩头的。我们往往有五子棋的技巧性和全局观远远比不上象棋,围棋之类的感…

大家好,又见面了,我是你们的朋友全栈君。

640?wx_fmt=jpeg

作者 | 吴小鹏  

来源 | 数据札记倌(ID:Data_Groom)

五子棋是常见的一款小游戏,五子棋问题是人工智能中的一个经典问题。这篇文章主要介绍了Python版本五子棋的实现代码,大家可以做个参考,与我的傻儿子对弈一下。

简 述

虽然计算机已经几乎激活成功教程了五子棋的取胜秘籍,甚至给出了取胜的具体方案,然而,对人来说,五子棋还是非常有玩头的。

我们往往有五子棋的技巧性和全局观远远比不上象棋,围棋之类的感觉:

这个真不一定,先说技巧性:五子棋、象棋、围棋的最初级技巧都是死活题。围棋那高难度的生死题我就不多说了。而象棋如果只是说铁门栓天地炮等等杀法,其实还是很好掌握的;如果加上各种基础的残局估计差不多。五子棋的话,坂田三手胜与天狗道场,或者是贴吧里边各种变态杀法题,也不敢说简单。

扯远啦~,这篇文章主要是要用python来实现五子棋的人机对战,可以趣味性地玩一下,远没有到不可战胜的程度。

问题描述

人机对弈算法属于策略型人工智能算法,本游戏中设置了人机对弈的游戏模式,整个程序我们有几个大的问题需要解决:

1)、计算机需要判断胜负

2)、计算机落子的逻辑

第一个问题的核心思想是要设置对局结束的判断逻辑,在这部分我们只需要写出五子相连的判断条件;

第二个问题的核心思想是要比较不同落子的优劣势,需要评估每一步的胜算。

其算法如下:

  • 写出获胜逻辑或者设置所有获胜组合

640?wx_fmt=png

获胜逻辑:一个二维坐标上,判断上下、左右、两个45度直线,是否有五个相同的直连棋子。

  • 评估棋格获胜分数

在计算机下棋之前,会计算空白棋格上的获胜分数,根据分数高低获取最佳位置。计算机会将棋子下在获胜分数最高的地方。

当已放置4颗棋子时,必须在第五个空棋格上设置绝对高的分值。

当获胜组合上有部分位置已被对手的棋格占据而无法连成五子时,获胜组合上空棋格的获胜分数会直接设置为0。

当有两组及其以上的获胜组合位置交叉时,对该位置的分数进行叠加,形成分数比周围位置明显高。

  • 计算机的攻击与防守

计算机计算获胜分值越高的棋格,就能确定能让自己的棋子最有可能达成联机的位置,也就是最佳进攻位置,而一旦计算机能确定自己的最高分值的位置,计算机就具备了进攻能力。同理,计算机能计算出玩家的最大分值位置,并抢先玩家获得该位置,这样计算机就具有了防御的能力。

代码实现

  • 棋盘

棋盘是我们整个游戏的落子范围,需要提前定义好大小:


# 画棋盘
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)

640?wx_fmt=jpeg

  • 落子

通过鼠标点击的位置记录落子,这里核心是要实现的点击鼠标获取坐标,可以使用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度直线,是否有五个相同的直连棋子,只要五子相连则游戏结束。或者遍历每一种获胜情况都可以做出判断:



# 四种情况
def is_GameOver(list_now):
    for c in range(COLUMN):
        for r in range(ROW):
            if r < ROW – 4 and (r, c) in list_now and (r+1, c) in list_now and (r+2, c) in list_now and (r+3, c) in list_now and (r+4, c) in list_now:
                return True
            elif c < COLUMN – 4 and (r, c) in list_now and (r, c+1in list_now and (r, c+2in list_now and (r, c+3in list_now and (r, c+4in list_now:
                return True
            elif r < ROW – 4 and c < COLUMN – 4 and (r, c) in list_now and (r+1, c+1in list_now and (r+2, c+2in list_now and (r+3, c+3in list_now and (r+4, c+4in list_now:
                return True
            elif r > 3 and c < COLUMN – 4 and (r, c) in list_now and (r-1, c+1in list_now and (r-2, c+2in list_now and (r-3, c+3in list_now and (r-4, c+4in list_now:
                return True
    return False

演示操作

下面直接看一下实际操作结果吧~

这里执行起来还是挺慢的,在执行逻辑的判断方面还有很多可以优化的地方。

呼~,傻儿子玩得还不错,还好赢了~

代码下载地址:

https://pan.baidu.com/s/16aSLqCKXNX1XVAt_cTcV4Q  

密码:u7ao

另外这个不是深度学习的实现办法,如果想尝试深度学习方法戳这里:

AlphaZero实战:从零学下五子棋(附代码)

https://github.com/junxiaosong/AlphaZero_Gomoku

如果你喜欢的话点个再看,让更多人看到~

扫码查看原文
▼▼▼

640?wx_fmt=jpeg

(*本文为AI科技大本营转载文章,转载联系作者


精彩推荐

2019 中国大数据技术大会(BDTC)再度来袭!豪华主席阵容及百位技术专家齐聚,15 场精选专题技术和行业论坛,超强干货+技术剖析+行业实践立体解读,深入解析热门技术在行业中的实践落地。
6.6 折票限时特惠(立减1400元),学生票仅 599 元!

640?wx_fmt=png


推荐阅读

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/151686.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ORA-01453: SET TRANSACTION must be first statement of transaction

    ORA-01453: SET TRANSACTION must be first statement of transaction

    2021年5月9日
    143
  • hashmap数组什么时候扩容_hashmap是数组还是链表

    hashmap数组什么时候扩容_hashmap是数组还是链表为什么需要扩容?因为HashMap为了节省创建出的对象的内存占用,一开始只默认分配:staticfinalintDEFAULT_INITIAL_CAPACITY=1<<4;也就是默认的数组大小是16个,而在HashMap的源码中可以发现HashMap扩容方法如下,就是说当HashMap里存储元素的个数大于threshold(capacity*loadFactor时,会进行扩容,…

    2025年12月11日
    1
  • 苹果系统自带的计算机怎么恢复出厂设置,苹果Macbook电脑怎么恢复出厂设置【图文】…

    苹果系统自带的计算机怎么恢复出厂设置,苹果Macbook电脑怎么恢复出厂设置【图文】…苹果电脑预装Mac系统,简洁又安全,不过使用时间长了,难免会碰到一些问题,导致系统运行速度变得卡顿。恢复出厂设置是一个不错的办法,之前windows系统恢复出厂设置比较简单,但苹果Macbook电脑怎么恢复出厂设置?Mac系统提供恢复出厂系统的功能,主要分为离线和在线两种方法,感兴趣的一起来学习。苹果Macbook恢复出厂设置删除数据的方法:提醒:恢复出厂设置前请做好数据备份,以免对您造成损失。1…

    2022年6月17日
    60
  • 我的世界区块显示_我的世界怎么显示区块线

    我的世界区块显示_我的世界怎么显示区块线我的世界手游区块是一个独特的机制,很多玩家对于区块是什么不太了解,区块显示指令以及区块的产生不是很熟悉,为了帮助到大家,今天小编就为大家带来我的世界手游区块显示指令分享:区块玩法操作详解的内容,希望大家能够喜欢,下面就让我们一起来看看吧!区块相关1.出生点区块在出生点附近的区块是一块围绕世界出生点的区域中的一个区块,只要有玩家在主世界,它就不会被从内存中卸载。这意味着像红石元件和刷怪会继续,甚至所…

    2025年12月11日
    2
  • SpringBoot异步调用

    SpringBoot异步调用除了异步请求,一般上我们用的比较多的应该是异步调用。通常在开发过程中,会遇到一个方法是和实际业务无关的,没有紧密性的。比如记录日志信息等业务。这个时候正常就是启一个新线程去做一些业务处理,让主线程异步的执行其他业务。何为异步调用说异步调用前,我们说说它对应的同步调用。通常开发过程中,一般上我们都是同步调用,即:程序按定义的顺序依次执行的过程,每一行代码执行过程必须等待上一行代码执行完毕后才…

    2022年7月11日
    22
  • matlab 三维数据多项式拟合,matlab多项式拟合

    matlab 三维数据多项式拟合,matlab多项式拟合在命令窗口下输入 x y cftool 在 CurveFitting 界面中 单击 Data 选择 xData 和 yData 选择 Createdatase 选择 Close 在 CurveFitting 界面中 单击 Fitting 选择 Newfit 选择 Typeoffit 选择 Polynomial 选择 9thdegreepol 打勾 Centerandsca

    2025年11月12日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号