基于C++实现五子棋AI算法思想
更多精彩,請點擊上方藍字關注我們!
? 今天我想要分享一下我做五子棋AI的思路。因為在做這個之前,我沒有接觸過任何像這種類似的東西。通過這一次,我也算是有所了解,我的思路也是來自很多網絡上的博客,看了很多,最終總結出了自己的這樣一個。
????那我的五子棋是15*15的大小(一般也就是這樣的一個大小)。我的AI算法要求每一次落子之后都要去計算每一個空暇的位置的“分值”,簡單的說,我們需要一個存放棋子的數組,表示是否存放了棋子,還要一個計算每一個空格的數組來記錄“分數”,這個分數是后期AI用來運算的基礎,也是你AI難度控制的點。
? ? ?我現有的思路就是分兩部分。首先是如果是玩家先落子,那么要求電腦AI隨即在你落子的地方的任意一個方向,隨機落子,這是第一步。接下來以后就正式進入到算法中去。
首先初始化你的分數數組,讓他們全部為零。然后在每一次落子之后進行全盤的遍歷,如果發現該處為空白,于是檢查其四周八個方向(當然如果是邊緣位置就相對修改,判斷是否出了邊界)。若在空白處,且發現在某一對角線方向發現有一個其他顏色的棋子,那么相對的給這個空白區域的分數數組加上一定的分值,然后繼續往這個方向檢測是否還有連續的同一顏色的棋子,若沒有則檢查其他方向或者檢測下一個空白位置。若是還在同一方向上面找到了相同顏色的棋子,那么第二個棋子的出現,你可以給改空白處加上雙倍的分值,表明這個空白位置更加重要。一次類推,繼續檢測。(PS:因為最終AI棋子落在什么地方,依靠的是最后遍歷整個分數數組,然后根據分數的高低來進行判斷落子落在哪里的,在下面講)。
? ? ?經過上一遍的遍歷,每一次落子都會使得分數數組得到一些變化,每一次都會導致AI判斷的變化。在這個基礎上,每一次落子還要進行一次對自己本身棋子顏色的一個遍歷,判斷自己的情況,同時加分加在分數數組之中,這樣一來,電腦就會根據自己的棋子的情況以及玩家的落子情況進行判斷,哪一個地方更加適合落子。
? ? ?因為我是第一次做AI,網絡上搜到的一些思想一般也是這種類似的遍歷思想。理解了以后寫代碼就比較方便。最后可能會有一些點的分數是相同的,所以還有設置一下隨機落子。把分數相同的地點隨機落子。
? ? ?個人感覺AI的強弱是根據你每一次給他增加分數的多少來確定的。這個我的AI有時候也會抽風,不過一般情況比較正常,可能運氣也占了一部分,當初設計加分的時候其實沒想那么多,現在卻發現好像還不錯。
? ? ? 大家要多去實踐練習,多改改分數可能就會出來不錯的AI了,o(^▽^)o。
? ? 下面貼上我的代碼!?
void GameScene::Robot(int *x, int *y, int *Sum) {ExWhile1 = true;if (*Sum == 1){while (ExWhile1){ChessOne(*x, *y);if (ch[*x][*y] == 2){ ExWhile1 = false; }}ch[*x][*y] = tp; //記錄這個點printpart(*x, *y, tp); //打印出電腦AI第一次落子isTouch = true;tp++;tp = tp % 2;}else //從第2步開始,使用評分系統{Findscore(*x, *y);} }void GameScene::Findscore(int &x, int &y) //查找評分最高的坐標 {srand((unsigned)time(NULL));int i, j, x1, x2, y1, y2, lx;int Max = 0;ChessScore(); //調用評分函數for (i = 0; i<15; i++){for (j = 0; j<15; j++){if (Score[i][j]>Max){Max = Score[i][j]; //獲取所有點中,評分最高的x1 = i;y1 = j;}}}x2 = x1; y2 = y1;for (i = 0; i<15; i++) //可能的話,有評分相同的多個點{for (j = 0; j<15; j++){if (Score[i][j] == Max&&i != x2&&j != y2) //在這么多個相同分數的點中,隨機找一個{lx = rand() % 10;if (lx<5){x2 = i, y2 = j;break;}}}}if (x2 != x1 || y2 != y1) //棋盤上有2個最高分{lx = rand() % 10; //隨機一個if (lx>6){x = x1, y = y1;}else{x = x2, y = y2;}}else //棋盤上只有一個最高分{x = x1, y = y1;}Max = 0; //清空最大值ch[x][y] = tp; //記錄這個點printpart(x, y, tp); //打印出電腦AI落子if (winerValue==2){isTouch = true;}tp++;tp = tp % 2; }inline void GameScene::ChessOne(int &x, int &y) //玩家走第1步時的落子 {int i, j;srand((unsigned)time(NULL)); //隨機數隨著時間的改變而改變for (i = 0; i<15; i++){for (j = 0; j<15; j++){if (ch[i][j] == 0) //如果找到了玩家的棋子,在它的8個方的任意一點落子{int lx = rand() % 7;if (lx == 0){x = i + 1; y = j + 1;if (ch[x][y] == 2){ break; }}else if (lx == 1){x = i + 1; y = j - 1;if (ch[x][y] == 2){ break; }}else if (lx == 2){x = i - 1; y = j - 1;if (ch[x][y] == 2){ break; }}else if (lx == 3){x = i - 1; y = j + 1;if (ch[x][y] == 2){ break; }}else if (lx == 4){x = i - 1; y = j; //上if (ch[x][y] == 2){ break; }}else if (lx == 5){x = i; y = j - 1; //左if (ch[x][y] == 2){ break; }}else if (lx == 6){x = i; y = j + 1; //右if (ch[x][y] == 2){ break; }}else{x = i + 1; y = j; //下if (ch[x][y] == 2){ break; }}}}} }void GameScene::ChessScore() {int x, y, i, j, k; //循環變量int number1 = 0, number2 = 0; //number用來統計玩家或電腦棋子連成個數int empty = 0; //empty用來統計空點個數memset(Score, 0, sizeof(Score)); //把評分數組先清零for (x = 0; x<15; x++){for (y = 0; y<15; y++){if (ch[x][y] == 2) //如果這個點為空 {for (i = -1; i <= 1; i++){for (j = -1; j <= 1; j++) //判斷8個方向 {if (i != 0 || j != 0) //若是都為0的話,那不就是原坐標嘛{//對玩家落點評分for (k = 1; i <= 4; k++) //循環4次{ //這點沒越界 且這點存在黑子(玩家)if (x + k*i >= 0 && x + k*i <= 14 && y + k*j >= 0 && y + k*j <= 14 && ch[x + k*i][y + k*j] == 0){ number1++;}else if (ch[x + k*i][y + k*j] == 2) //這點是個空點,+1后退出{ empty++; break; } else //否則是墻或者對方的棋子了 { break; } }for (k = -1; k >= -4; k--) //向它的相反方向判斷 { //這點沒越界 且這點存在黑子(玩家)if (x + k*i >= 0 && x + k*i <= 14 &&y + k*j >= 0 && y + k*j <= 14 && ch[x + k*i][y + k*j] == 0){ number1++;}else if (ch[x + k*i][y + k*j] == 2) //這點是個空點,+1后退出{ empty++; break; } else{ break;}}if (number2 == 1) //2個棋子 { Score[x][y] += 1; } else if (number1 == 2) //3個棋子 {if (empty == 1) {Score[x][y] += 5; //有一個空點+5分 死3 } else if (empty == 2) { Score[x][y] += 10; //有兩個空點+10分 活3} }else if (number1 == 3) //4個棋子 {if (empty == 1) { Score[x][y] += 20; //有一個空點+20分 死4 } else if (empty == 2){ Score[x][y] += 100; //有2個空點+100分 活4} }else if (number1 >= 4) { Score[x][y] += 1000; //對方有5個棋子,分數要高點,先堵} empty = 0; //統計空點個數的變量清零 //對電腦落點評分for (k = 1; i <= 4; k++) //循環4次{ //這點沒越界 且這點存在白子(電腦)if (x + k*i >= 0 && x + k*i <= 14 && y + k*j >= 0 && y + k*j <= 14 && ch[x + k*i][y + k*j] == 1){ number2++;}else if (ch[x + k*i][y + k*j] == 2){ empty++; break; //空點} else{break;}}for (k = -1; k >= -4; k--) //向它的相反方向判斷 {if (x + k*i >= 0 && x + k*i <= 14 &&y + k*j >= 0 && y + k*j <= 14 && ch[x + k*i][y + k*j] == 1){ number2++;}else if (ch[x + k*i][y + k*j] == 2){ empty++; break;}else{ break; //注釋與上面玩家版相同} }if (number2 == 0) { Score[x][y] += 1; //1個棋子} else if (number2 == 1) {Score[x][y] += 2; //2個棋子 } else if (number2 == 2) //3個棋子{if (empty == 1) { Score[x][y] += 8; //死3} else if (empty == 2) { Score[x][y] += 30; //活3 } }else if (number2 == 3) //4個棋子{if (empty == 1) { Score[x][y] += 50; //死4} else if (empty == 2) { Score[x][y] += 200; //活4} }else if (number2 >= 4) { Score[x][y] += 10000; //自己落在這點能形成5個,也就能勝利了,分數最高} number1 = 0; //清零,以便下次重新統計number2 = 0; empty = 0;}}}}}} }完
它,
不僅僅是一個碼
掃碼關注
C++資源免費送
總結
以上是生活随笔為你收集整理的基于C++实现五子棋AI算法思想的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 番茄畅听安卓版(番茄有哪些好处)
- 下一篇: C++学习 | 面试官:我们只想要这样的