根据博弈树的图,使用最小值最大值算法,当棋子fakemove一步之后,人必然会走局面分最小的一步,所以选择的走法就是最小值的最大值,修改几个关键的函数
Step* SingleGame::getBestMove()
{
QVector<Step *> steps;
//看看有哪些步骤可以走
getAllPossibleMove(steps);
int maxScore=-100000;
Step* ret;
for(QVector<Step*>::iterator it=steps.begin();it!=steps.end();++it)
{
Step* step=*it;
//试着走一下
fakeMove(step);
//评估局面分
int score=getMinScore();
//再走回来
unfakeMove(step);
//取最高的分数
if(score>maxScore)
{
maxScore=score;
ret=step;
}
}
return ret;
}
getMinScore由人的视角进行评估
int SingleGame::getMinScore()
{
QVector<Step*> steps;
//获取人类的所有走棋路径
getAllPossibleMove(steps);
int minScore=100000;
for(QVector<Step*>::iterator it=steps.begin();it!=steps.end();++it)
{
Step* step=*it;
//以人类的视角试着走一下
fakeMove(step);
//评估局面分
int score=calcScore();
//再走回来
unfakeMove(step);
//找到对电脑最不利的分数作为返回值返回
if(score<minScore)
{
minScore=score;
}
}
return minScore;
}
所以此时getAllPossbileMove不仅搜索红棋,还要搜索黑棋
//获取所有走的通的走法存放在数组steps里
void SingleGame::getAllPossibleMove(QVector<Step *>& steps)
{
int min=16,max=32;
if(this->_bRedTurn)
{
min=0,max=16;
}
//遍历所有棋子
for(int i=min;i<max;i++)
{
//如果棋子已死则直接跳过
if(_s[i]._dead) continue;
//遍历所有行坐标
for(int row=0;row<=9;row++)
{
//遍历所有列坐标
for(int col=0;col<=8;col++)
{
//获取想要杀死的棋子的id
int killid=this->getStoneId(row,col);
//若想要杀死的棋子与行走的棋子颜色相同则跳过
if(sameColor(killid,i)) continue;
//判断某一棋子能不能行走
if(canMove(i,killid,row,col))
{
//将可以行走的“步”存放到steps中
saveStep(i,killid,row,col,steps);
}
}
}
}
}
这就构成了两部搜索的算法。