├── Renju ├── 提交版.exe └── src │ ├── AI.c │ ├── AI.h │ ├── set.c │ ├── set.h │ ├── common.c │ ├── common.h │ ├── forbid.c │ ├── forbid.h │ ├── main.c │ ├── main.h │ ├── evaluate.c │ ├── evaluate.h │ ├── bit_board.c │ ├── bit_board.h │ ├── game_mode.c │ └── game_mode.h └── README.md /Renju/提交版.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/提交版.exe -------------------------------------------------------------------------------- /Renju/src/AI.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/AI.c -------------------------------------------------------------------------------- /Renju/src/AI.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/AI.h -------------------------------------------------------------------------------- /Renju/src/set.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/set.c -------------------------------------------------------------------------------- /Renju/src/set.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/set.h -------------------------------------------------------------------------------- /Renju/src/common.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/common.c -------------------------------------------------------------------------------- /Renju/src/common.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/common.h -------------------------------------------------------------------------------- /Renju/src/forbid.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/forbid.c -------------------------------------------------------------------------------- /Renju/src/forbid.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/forbid.h -------------------------------------------------------------------------------- /Renju/src/main.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/main.c -------------------------------------------------------------------------------- /Renju/src/main.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/main.h -------------------------------------------------------------------------------- /Renju/src/evaluate.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/evaluate.c -------------------------------------------------------------------------------- /Renju/src/evaluate.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/evaluate.h -------------------------------------------------------------------------------- /Renju/src/bit_board.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/bit_board.c -------------------------------------------------------------------------------- /Renju/src/bit_board.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/bit_board.h -------------------------------------------------------------------------------- /Renju/src/game_mode.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/game_mode.c -------------------------------------------------------------------------------- /Renju/src/game_mode.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tututugege/UCAS-Renju/HEAD/Renju/src/game_mode.h -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 介绍 2 | 3 | 这学期的五子棋对我来说真是意义非凡,他驱动我从一个只是对c语言略知一二的几乎纯小白学会了很多东西,上网查资料,翻阅各种博客,提前预习一些数据结构,一个学期一大半空闲时间都花在了写五子棋,从最初的完全无从下手,到能够自己创新出一些优化的东西。 4 | 5 | 依稀记得我的五子棋第一次动起来会堵人那个晚上,内心激动无比,感觉我就是“c语言大佬”QAQ,不过后来发现其实都是bug,会堵人纯属意外。 6 | 7 | 我这学期第一个月写出了能和我这个五子棋小白对打的版本,但后续的改进陷入了瓶颈,大部分时间花在了改进时间性能,没有优化算法,最后甚至没时间仔细研究一下VCT和VCF,棋力很一般,和几个网上找到的几个AI下都是完败,为此还是有些遗憾。 8 | 9 | 最后期末比赛中决赛平局,我们双方都是黑胜白负,最后猜大小输了喜提亚军。不过和冠军在小组赛比赛时我是黑白都负,所以这个亚军一点也不冤。 10 | 11 | 参考资料: 12 | 13 | + 象棋百科全书: 14 | + gobang: 15 | + 清月连珠: 16 | + 《PC游戏编程(人机博弈)》 王小春 17 | 18 | # 实现的东西 19 | 20 | 本AI采用PVS改进的alphabeta剪枝算法为主干,通过启发评估早期裁剪选出每步15-20个走法实现9层搜索加15层算杀。 21 | 22 | + PVS主要变例搜索 23 | + 迭代加深 24 | + 位棋盘生成走法 25 | + 5-15长度行评分缓存 26 | + 早期裁剪 27 | 28 | # 未实现的东西 29 | 30 | 当初立下壮志,结果最后一个星期成了小阳人,加上最后也有点懒惰,一些已经有了思路的东西最终没有实现。 31 | 32 | ## **冲棋点哈希表** 33 | 34 | 我预先缓存了一行最多15个棋子所有情况对应的评分,因此大大缩短了评估时间。 35 | 36 | 事实上不仅可以缓存评分,还可以缓存对应棋盘的冲棋信息,即一行哪些点可以冲棋,是活三还是冲四,如此一来在获取走法的时候也会相当迅速,特别是在已经有活三冲四的情况下,我们很多时候只需要搜索冲四活四点进行防守或反击,在五子棋中后阶段大多都是这种情况。更精确更少的走法同时也意味着更深的深度。 37 | 38 | 39 | ## **开局库** 40 | 41 | 已经证明即使有禁手,黑棋也是必胜的。我在网上也找到了一些开局的必胜谱,但是我不知道怎么解析这些lib文件,貌似是什么静态库,虽然通过Renlib软件打开可以看谱,但是总不能纯靠手打录入这些信息吧,最后还是放弃了。 42 | 43 | ## **威胁空间搜索** 44 | 45 | 原文应该是Go-Moku and Threat-Space Search,作者:LV Allis,H.J. Van Den Herik,MPH Huntjens,不过国内十多年前的某篇五子棋论文里面有雷同的中文版,大概就是阐述了VCT和VCF的理论基础,给出了一个找致胜威胁的具体方法。 46 | 47 | # 一些被弃用的东西 48 | 49 | 50 | 51 | ## **空着裁剪** 52 | 53 | 参考,其实就是一步不下棋,然后给对方下,最后返回值仍然好到超过该层的beta值,说明正常下那肯定也会超过beta,那就直接返回beta。 54 | 55 | ## **zobrist置换表** 56 | 57 | 因为刚开始没有接触哈希表这种东西,一直想不通怎么才能实现这个置换表,查了好多资料终于实现以后却发现效果非常一般,占了好几百兆也就快了20%左右,然而评价方式改为局部刷新后,存储整个局面分的置换表感觉就不太有用了,但是这种哈希表缓存的思想特别有用。 58 | 59 | ## **历史表排序** 60 | 61 | alpha-beta剪枝的顺序特别重要,因此可以通过迭代加深获取浅层节点的历史评分对节点进行排序,为每层搜索的最好节点和beta截断节点设置一个历史分,根据历史分排序显著提高速度,实现简单效果立竿见影。不过为了早期剪枝,同时有了评分表,就放弃了这种排序,直接通过评分排序。 62 | 63 | ## **MTD(f)搜索算法** 64 | 65 | mtd(f)和pvs都是alphabeta剪枝的优化算法,只需要加几行就可以带来一定的速度优化,不过mtd(f)要略复杂一点,并且非常依赖于每次搜索的评分期望值,因此mtd(f)耗时不稳定。据说mtd(f)在并行计算上有优势,奈何本人水平太次,看不懂c语言并行计算的部分。 66 | --------------------------------------------------------------------------------