2021-05-19

 

五子棋对战项目实践报告
一、学习和使用Python
在第一步中要做一百多道题来把自己熟知的C++语言转化为Python语言,这一步里我们要熟练的运用Python的集成开发环境,我用的是pycharm。在做着些题时,我发现了许多Python语言与C++语言的不同,首先是缩进,在Python中对于缩进的要求比较严格,用不同级别的缩进表示不同级别的代码块,而在C++中,用大括号对 {} 来标示代码块。其次是变量使用的不同,在Python中,不能在函数定义的内部直接修改全局变量的值,否则直接报错,而C++是允许修改的。还有C++导入库函数的方式是“#include <>”,而python导入库函数的方式是“import math”。最后是C++函数调用必须在使用前就声明函数,但python中则没有这个限制,python定义函数要用def。在对比C++和Python语言后,很明显的感受到运用Python语言的优点, python的开发效率远高于C++,C++需要程序员手动回收内存,而python自动回收内存。但是Python运行速度远高于C++,因为Python直接生成机器码,python可以在终端直接敲命令行。所以我们用Python来完成项目大大的提高了效率和降低了难度。
二、基础步骤尝试与失败
第一步是完成Python的一百多题,之后我们通过扫描二维码出现的网址直接到达了第二步。因为没有进行程序的运行,所以再一次返回第一步后尝试用requests库进行获取网址,使用因为没有request库,所以用import urllib.request 进行了对网址的获取
mport urllib.request
url = “http://183.175.12.27:8000/step_01/
print(url)
res =urllib.request.urlopen(url)
print(res.read())
第三步没有技术含量,根据网址直接到达。
第四步希望我们完成一个加密过程,一开始我是先直接用三个数字进行了a^b%c了加密运算,但是很快发现直接运算的数据会超出数据范围,所以最后使用了“模幂”的算法。
def model(a,b,c):
a=a%c
ans=1
while b!=0:
if b&1:
ans=(ansa)%c
b>>=1
a=(a
a)%c
return ans
在第五步里学会了用ord()把字符串转换为ASCII值,还知道了转换为16进制数要用到hex()函数,以及ASCII值用chr()转换为字符。
第七步时一开始使用的是一维数组,这时发现使用一维数组考虑情况太多,并且容易在写的过程中出现错误,所以希望将一维数组转化为了二维数组,但是最终失败了,因为这里用二维数组给后面的程序带来了一定难度。在这一步里用到了point1.append(ord(point[z])-ord(‘a’))进行ASCII值的转换,同时用size1=len(point)计算字符串长度。
三、游戏设计与思考过程
根据五子棋的游戏规则,我们首先根据棋盘的样子输出1515的棋盘,然后,对棋盘进行始化,将可以落子的位置进行统一化处理,接下来,就是进入游戏的环节,双方轮流落子,最后,根据落子的位置判断选手的的输赢情况,游戏结束。
在前几步中,我们已经解决了棋盘的初始化,棋型的输出等基础问题,之后就是最重要的一步,计算出下一步的落子位置,这一步是取胜的关键。
思考一:首先我们基础的用递归函数对已经给出的九种棋型进行判断和加分,在这里,我们就要考虑用什么来储存空点和九个加分的棋型,这里主要是为了比较简单。所以我首先想到的数组,数组之间的比较的最简单的,把空点棋型看出是s[]
4的数组,九个加分的棋型看成去q[],我们可以用s.includes(q[, position]),但是把九个棋型写成数组十分麻烦,而且如果用数组储存空点棋型时,在比较两个数组时需要的循环更加复杂,大大降低了运行效率,但是如果把空点的棋型储存在一个字符串里,就不能正确的比较是否包含那九个加分字符串。所以,我最终把空点的四个棋型看成四个不同的字符串a,b,c,d.这样大大提高了循环效率,我们只需要用“if str1.find(str2)>=0”就可以判断是否包含。
思虑二:找出最大值的坐标,最开始我使用二维数组记录每一个空格点的成绩,目的是为了方便输出最大值的坐标,但是这样有是一个二维数组的循环,所以之后我定义了一个值n,n为第一个空点的值,并记录它的行和列,之每一次算出的值都要与n进行比较,如果比n大,就替换n的值,重新记录此时n的行和列。
思考三:为了让我们的AI更加厉害,我们思考是否可以在已知的九个加分棋型上增加棋型,我们可以将五子棋的连珠可以分为以下几:成5:即构成五子连珠;活4:即构成两边均不被拦截的四子连珠;死4:一边被拦截的四子连珠;活3:两边均不被拦截的三字连珠;死3: -边被拦截的三字连珠;活2:两边均不被拦截的二子连珠;死2:一边被拦截的二子连珠;单子:四周无相连棋子;经过多次与他人对战以及搜索资料,我们在活四上增加了以下棋型:‘MMCMM’,‘MMMCM’,‘MMMMC’。还有以下图片中的棋型:

四、对程序改进的思考
我们用的求值算法是试探法,我们的目的是给棋盘上的空位进行打分,进而算出分数最高的位置。那么我在这里想运用试探法,因为我觉得这样的话代码比较好写。所谓试探法就是,我们找出棋盘上的所有空位,然后我们假设这个空位上放置的是白棋,然后看看相连的情况,然后打分,并将分数加至存储该空位分数的变量;再假设这个空位上放置的是黑棋,然后再看相连的情况,然后打分,并将分数加至存储该空位分数的变量;这样遍历完所有的空位的时候,我们便完成了打分工作,然后再比较空位的分数,选出分数最高的空位,该位置即为最优的位置。
1、应用博弈树,提高AI智能
做五子棋的博弈,自然会用到博弈树,根据下一步由谁来走,AI对任何一-个局面根据前面估分方法给出一个分数,我们把这个估分方法汇总成一个评估函数,并返回分值。据此来选择下一步的走法。由于人和AI是轮流落子,可以将人的估分也算入,并将前面加负号。那么,估值越大表明对AI越有利,估分越小则表明对AI越不利。那么每次AI选择都是从它可能的走法树的某层节点,返回评估值中最大点。而用户总是从走法树的某层节点中选择最小点,从而形成一棵极大极小搜索树,然后根据深度优先搜索,可以最后得到固定搜索深度下的一个最好的走法。
2、让AI自学习,不再同-一个地方犯错
上面的算法还没有自学习的能力,这样AI在下棋时还可能会重蹈覆辙。因此在每盘棋结束时,如果AI输,则进行大于搜索深度的步数回退。
3、减少搜索范围
五子棋棋盘的大小为15* 15,因此每次下子最多可能有200多种下子的方法,在搜索的时候依次考虑每一种走法会大大影响算法的效率。而根据下子的经验,只要考虑与某个棋子距离小于等于2的位置即可。当前节点的子节点的数量和排列顺序对于搜索的速度起着至关重要的影响。根据五子棋的特点,可以产生一个棋面搜索范围。记录当前棋面所有棋子的最左最右最上最下点构成的矩形,我们认为下一步棋的位置不会脱离这个框3步以上。这样在棋子较少:的时候,搜索节点的数量大大减少,可以将AI的速度提高一倍左右。
4、利用棋型得分,提高AI速度
因为每种下法都对应一种得分,所以,可以每次只考虑当前得分前十的节点进行下一步搜索,大大减少了搜索范围,可以进一步增加搜索的深度。
5、利用多线程,提高AI速度
我们其实可以利用多核技术,利用多个线程,让算法实现并行计算,提高AI的速度。我们在第一层用一个线程分配器把第二层的候选节点分配给多个线程每个线程包含着从第二层一个候选节点开始的搜索,然后等所有线程结束后,将所有线程的结果进行汇总,选出最大值。并行的程序,可以将速度提高一倍左右。
6、利用随机化算法,让确定方法不能必胜
由于AI算法的固定性,所以一担玩家一次获胜,按照相同的走法,必然会再次获胜。但除了必杀招或者必防招,一一个局面很多时候没有绝对最好的走法。而是有一些都不错的走法,那么可以把这些评分差不多走法汇集起来,然后随机选择它们中的一种。
7、五子棋的“禁手”
五子棋中“先手必胜”已经得到了论证,类.似“花月定式”和“浦月定式”,很多先手必胜下法虽然需要大量的记忆,但高手确能做到必胜。所以五子棋的规则进行了优化,得到了“有禁手”五子棋。五子棋中,黑棋必然先行。因此“有禁手”五子棋竞技中对黑棋有以下“禁手”限制:“三三禁”:黑棋下子位置同时形成两个以上的三;“四四禁”:黑棋下子位置同时形成两个以上的四;“长连禁”:六子以上的黑棋连成- -线。黑棋如下出“禁手“则马上输掉棋局。不过如果“连五”与“禁手”同时出现这时“禁手”是无效的。所以对于黑棋只有冲四活三(后面会有解释)是无解局面。反观白棋则多了一种获胜方式,那就是逼迫黑棋必定要下在禁点。
五、反思与总结

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mimi____

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值