当前位置:   article > 正文

五子棋ai:极大极小搜索和α-β剪枝算法的思想和实现(qt和c++)(二)贪心算法和评估函数_为什么贪心算法五子棋

为什么贪心算法五子棋

我查找了大量的网上资料,结合自己编程实践,走了很多弯路,总结了一些关于五子棋ai的经验以供大家参考借鉴。

一、贪心算法(相当于ai只思考一步的情况)

对于五子棋ai,大部分人想到的是做一个评估函数。这里的评估函数网上大概有两种,但是很多人会弄混淆

第一种我称为K函数(只是一个代号,与第二种相区别),是对一个可走的空位子进行打分,如果ai白子落在这个空位置的分数越高,说明这个位置就越好,每次ai走棋就找到一个最好的空位置就行了。

第二种我称为F函数,是对现在的棋盘局面进行打分。 ai白子首先找所有可以走的空位置,模拟走了这个位置以后,用f函数进行局面评分,如果走了这样的一个空位置的得分越高,说明这个位置就越好,每次ai走棋就找这样一个分数最高的位置。

那么你可能就要问了,这两个评估函数有什么区别呢?区别非常大!如果你只是想实现一个只看一步的ai,那么你可以用K函数也可以用F函数。但是如果你想要实现基于博弈树的极大极小搜索和α-β剪枝算法的“聪明”ai,就只能用F函数因为博弈树必须要对局面打分,而不是对位置打分。如果你明白了这一点,那么接下来就好办了。

二、评估函数(对白子走了一步的局面评估)

怎么对局势有一个比较准确的估计呢?我查阅了大量资料。五子棋的局势无非就是对棋型个数和权重的统计。(对某一方而言的)

五子棋棋型

我分为8种:
1.连5或者长连
连5 长连
2.活4(有两个位置可以形成连5)
活4
3.冲4(有一个位置可以形成连5)
冲4(a)
冲4(b)
还有其他情况,比如边界,总之再下一步(只能是1步而不是2步)就能连5的就是冲4。
4.活3(走一步可以形成活4)
活3(a) 活3(b)
5.眠3(走一步可以形成冲4)
眠3(a)
眠3(b)
6.活2(走一步可以形成活3):形状自行脑补
7.眠2(走一步可以形成眠3)
8.活1(走一步可以形成活2)

具体评分规则

我用六元组一条直线上连续六个位置的状态)来表示棋型,通过检查棋盘上所有六元组来得分。最容易漏掉的地方是边界,比如如果一个斜线只有5个位置也有可能连5、但六元组没考虑进来等等问题,办法是用一个更大的、包括了边界的数组保存棋盘和边界信息

1.六元组所有棋型辨识

用一个棋型辨识数组保存所有棋型。

#define C_NONE 0//棋子:黑子,白子,无子
#define C_BLACK 1
#define C_WHITE 2

//棋型代号 下标 权重
#define OTHER 0//0,其他棋型不考虑
#define WIN 1//100000,白赢
#define LOSE 2//-10000000
#define FLEX4 3//50000,白活4
#define flex4 4//-80000
#define BLOCK4 5//400
#define block4 6//-80000
#define FLEX3 7//400
#define flex3 8//-8000
#define BLOCK3 9//20
#define block3 10//-40
#define FLEX2 11//20
#define flex2 12//-40
#define BLOCK2 13//1
#define block2 14//-2
#define FLEX1 15//1
#define flex1 16//-2

int tuple6type[4][4][4][4][4][4];//棋型辨识数组,0无子,1黑子,2白子,3边界
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

需要对这个数组进行初始化。

void chessAi::init_tuple6type(){
   
    memset(tuple6type,0,sizeof (tuple6type));//全部设为0
    //白连5,ai赢
    tuple6type[2][2][2][2][2][2]=WIN;
    tuple6type[2][2][2][2][2][0]=WIN;
    tuple6type[0][2][2][2][2][2]=WIN;
    tuple6type[2][2][2][2][2][1]=WIN;
    tuple6type[1][2][2][2][2][2]=WIN;
    tuple6type[3][2][2][2][2][2]=WIN;//边界考虑
    tuple6type[2][2][2][2][2][3]=WIN;
    //黑连5,ai输
    tuple6type[1][1][1][1][1][1]=LOSE;
    tuple6type[1][1][1][1][1][0]=LOSE;
    tuple6type[0][1][1][1][1][1]=LOSE;
    tuple6type[1][1][1][1][1][2]=LOSE;
    tuple6type[2][1][1][1][1][1]=LOSE;
    tuple6type[3][1][1][1][1][1]=LOSE;
    tuple6type[1][1][1][1][1][3]=LOSE;
    //白活4
    tuple6type[0][2][2][2][2][0]=FLEX4;
    //黑活4
    tuple6type[0][1][1][1][1][0]=flex4;
    //白活3
    tuple6type[0][2][2][2][0][0]=FLEX3;
    tuple6type[0][0][2][2][2][0]=FLEX3;
    tuple6type[0][2][0][2][2][0]=FLEX3;
    tuple6type[0][2][2][0][2][0]=FLEX3;
    //黑活3
    tuple6type[0][1][1][1][0][0]=flex3;
    tuple6type[0][0][1][1][1][0]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/243674
推荐阅读
相关标签
  

闽ICP备14008679号