使用QT creator实现一个五子棋AI包括GUI实现(8K字超详细) (3)

使用QT creator实现一个五子棋AI包括GUI实现(8K字超详细)

估值函数: 估值函数的定义:

用于估计当前棋盘局面的函数 \(score(x)\), 来评价MAX距离游戏胜利的远近。MAX越容易获得胜利,\(score(x)\)的值就越大。

估值函数实现思路:

多玩几盘五子棋就会发现 (也许也不会发现) ,评估一个局面某一玩家是否容易取得胜利主要是看棋盘横竖边以及斜边中含有的棋型,假设\(A\)棋子表示MAX下的棋子,\(B\)表示MIN下的棋子,\(0\)表示没有棋子。如果某一行列中有"0AAAA0"的话,说明MAX就要获得胜利了,所以棋盘评估的得分就高,如果某一行列中有"0BBBB0"的话,说明MIN要获得胜利了,棋盘评估的得分就低。而且比对的话会发现棋盘中有"0AAAA0"比棋盘中有“00AAA0”MAX更容易获得胜利,因此棋型"0AAAA0"的分值要比“00AAA0”的分值要更高。

所以,经过分析,实现估值函数的思路就是先找出五子棋中出现的所有棋型并为其打分,然后遍历当前棋盘中每一行每一列每一斜边,寻找出所有符合的棋型,如果棋型对MAX有利,则在总分数上加上该棋型所对应的分值,如果棋型对MIN有利,则减去该棋型对应的分值。

经过多次的调整,确定棋型以及得分如下:(这里显示的为MAX的棋型,MIN的话要把所有的A改成B)

// MAX MIN // 死二 A: BAA000 或 000AAB 150 140 // 死二 B: BA0A00 或 00A0AB 250 240 // 死二 C: BA00A0 或 0A00AB 200 190 // 活二 A: 0AA000 或 000AA0 650 640 // 活二 B: 00A0A0 或 0A0A00 400 390 // 死三 A: BAAA00 或 00AAAB 500 490 // 死三 B: BA0AA0 或 0AA0AB 800 790 // 死三 C: A00AA 600 590 // 死三 D: A0A0A 600 590 // 活三 A: 0A0AA0 2000 1990 // 活三 B: 0AAA00 或 00AAA0 3000 2990 // 死四 A: BAAAA0 或 0AAAAB 2500 2490 // 死四 B: AAA0A 3000 2990 // 死四 C: AA0AA 2600 2590 // 活四 0AAAA0 300000 299990 // 连棋 AAAAA 30000000 299999990 估值函数代码实现: 实现细节:

使用一个15*15的char型数组来存储棋盘,四种数组储存行,列,左下到右上的斜行,左上到右下的斜行一共 \(15+15+21+21=72\)个数组,将整个棋盘划分成72份,每次遍历预测的时候动态更新棋盘和这72个数组,然后每次只要寻找这72个数组中有无匹配的字符串就行了。这个部分的难点就是斜边的42个数组该如何取出来以及如何更新。

各个具体分值定义: partern chess_type_all_my[25] = {{"BAA000", 150, 140}, {"000AAB", 150, 140}, {"BA0A00", 250, 240}, {"00A0AB", 250, 240}, {"BA00A0", 200, 190}, {"0A00AB", 200, 190}, {"0AA000", 650, 640}, {"000AA0", 650, 640},{"0A0A00", 300, 290}, {"00A0A0", 300, 290}, {"BAAA00", 500, 490}, {"00AAAB", 500, 490}, {"BA0AA0", 800, 790}, {"0AA0AB", 800, 790}, {"A00AA", 600, 590}, {"A0A0A", 600, 590}, {"0A0AA0", 2000, 1990}, {"0AAA00", 3000, 2990}, {"00AAA0", 3000, 2990}, {"BAAAA0", 2500, 2490}, {"0AAAAB", 2500, 2490}, {"AAA0A", 3000, 2990}, {"AA0AA", 2600, 2590}, {"0AAAA0", 300000, 299990}, {"AAAAA", 3000000, 29999990}}; partern chess_type_all_opt[25] = {{"ABB000", 150, 140}, {"000BBA", 150, 140}, {"AB0B00", 250, 240}, {"00B0BA", 250, 240}, {"AB00B0", 200, 190}, {"0B00BA", 200, 190}, {"0BB000", 650, 640}, {"000BB0", 650, 640},{"0B0B00", 300, 290}, {"00B0B0", 300, 290}, {"ABBB00", 500, 490}, {"00BBBA", 500, 490}, {"AB0BB0", 800, 790}, {"0BB0BA", 800, 790}, {"B00BB", 600, 590}, {"B0B0B", 600, 590}, {"0B0BB0", 2000, 1990}, {"0BBB00", 3000, 2990}, {"00BBB0", 3000, 2990}, {"ABBBB0", 2500, 2490}, {"0BBBBA", 2500, 2490}, {"BBB0B", 3000, 2990}, {"BB0BB", 2600, 2590}, {"0BBBB0", 300000, 299990}, {"BBBBB", 3000000, 29999990}}; 函数解析: int find_count(const char* temp,const char*partern)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzddzf.html