首页 > 编程知识 正文

人工智能下象棋,象棋人工智能vs人工智能

时间:2023-05-04 21:49:58 阅读:202803 作者:2801

中国象棋在我看来最难的人工对战中电脑怎能走这个问题,以下为本人浅见,希望各位多多包涵!

1.初步尝试

电脑的优势在于强大的计算能力,虽然其不知道怎么走合适,但是它能够模拟的将每一种走法都走一遍,选最优的走法来走。我们的思路就有了,首先需要解决两个问题:

(1)怎么判断局面最优?

(2)怎么模拟走?

第一个问题可以用每一个棋子的重要程度来打分,比如将最重要,所以给1000分,而车次之给100分,炮80等等

第二个问题因为每一个中国象棋实现方式不同,所以我分享一下本人代码

电脑模拟走一步的代码:

mov Board::getbestmove(){ /* * 1.获取所有可能走的步数 * 2.试着走一下 * 3.看看局面怎么样 * 4.选择最好的走法 */ QVector<mov> canstep; canstep = getallstep(); int maxscore = -100000; mov ret; for(auto it = canstep.begin();it!=canstep.end();it++) { mov step = *it; fakemove(step); //模拟走一步 int score = ctscore(); //计算局面分 unfakemove(step); //返回 if(score>maxscore) //计算最大的局面分 { maxscore = score; ret.equal(step); } } qDebug()<<"get best move!!!"; return ret; //得到最好走法}

以上代码可以实现电脑模拟走一步的场景,但是缺点也显而易见。就是目光短浅,只考虑到自己走一步,并没有考虑到对手走的一步,例如:我要吃电脑车,它会看着我吃,它只是遍历了自己走一步局面分最大的走法,但是没有考虑我走一步会造成的影响。

2.电脑模拟走两步的走法

我们可以这样设计--在电脑走一步后考虑我再走一步的结果,就是模拟两步,比如轮到电脑走有n种走法,电脑走了一步人又有n种走法,在这n*n种选择中再选最有利的---也就是局面分最大的

                                          

如上图所示,电脑如果走了1分支,人有三种选择,局面分分别为30,40,70分,正常人都会走对电脑最不利的一步棋即30分,所以我们需要找到电脑走每一个分支下的最小值。

3.电脑走n步的走法

很容易知道,电脑多考虑一步计算量就多一个循环。但是理论上让电脑考虑n步算法是可以实现的,先贴代码:

mov Board::getbestmove(){ /* * 1.获取所有可能走的步数 * 2.试着走一下 * 3.看看局面怎么样 * 4.选择最好的走法 */ //qDebug()<<"begin to get best move!!!"; QVector<mov> canstep; canstep = getallstep(0); //电脑走法 qDebug()<<"allstep ==="<<canstep.count(); int maxscore = -100000; mov ret; for(auto it = canstep.begin();it!=canstep.end();it++) { mov step = *it; //qDebug()<<"origin pao position is---"<<weizhi[9]; //qDebug()<<"chess "<<step.name<<" from "<<step.from<<" to "<<step.to; fakemove(step); int score = getminscore(level-1,maxscore); unfakemove(step); qDebug()<<"THE SCORE IS--"<<score; if(score>maxscore) { maxscore = score; ret.equal(step); } } return ret;}int Board::getmaxscore(int level,int curminscore){ if(level==0) return ctscore(); QVector<mov> step; step = getallstep(0); //获取人可以走的步数 int maxscore = -100000; for(auto it = step.begin();it!=step.end();it++) { mov mystep = *it; //qDebug()<<"chess "<<step.name<<" from "<<step.from<<" to "<<step.to; fakemove(mystep); int score = getminscore(level-1,maxscore); unfakemove(mystep); if(score>=curminscore) return score; //qDebug()<<"THE SCORE IS--"<<score; if(score>maxscore) { maxscore = score; } } return maxscore;}int Board::getminscore(int level,int curmaxscore){ if(level==0) return ctscore(); QVector<mov> step; step = getallstep(1); //获取人可以走的步数 int minscore = 100000; for(auto it = step.begin();it!=step.end();it++) { mov mystep = *it; //qDebug()<<"chess "<<step.name<<" from "<<step.from<<" to "<<step.to; fakemove(mystep); int score = getmaxscore(level-1,minscore); unfakemove(mystep); if(curmaxscore>=score) return score; //qDebug()<<"THE SCORE IS--"<<score; if(score<minscore) minscore = score; } return minscore;}

我们首先设置一个level参数,表示需要电脑考虑几步,然后再用getminscore和getmaxscore递归调用,直到最后一层返回。

4.剪枝算法

如上图所示,如果第一个分支得到了最小的局面分30,然后有算出了第二个分支中有一个10,那说明第二个分支情况最好局面分也只有10,小于第一个分支的局面分30,所以第二个分支没用了,第二个分支的n-1中情况都不用在计算了。

具体项目代码见:https://github.com/luoshiyong/AIChess(求各位老铁给个star)

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。