国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

基于C++實現五子棋AI算法思想

2020-05-23 13:34:30
字體:
來源:轉載
供稿:網友

         今天我想要分享一下我做五子棋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;             }           }         }       }     }   } } 

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 阳信县| 九台市| 海淀区| 长顺县| 稷山县| 巨鹿县| 德庆县| 喀喇沁旗| 江安县| 虹口区| 化州市| 玛曲县| 修文县| 吉隆县| 云浮市| 涪陵区| 定南县| 林州市| 喀喇沁旗| 临湘市| 福清市| 蒲江县| 武威市| 武安市| 遵义县| 新疆| 紫金县| 古浪县| 米易县| 金堂县| 舒城县| 禹州市| 桑植县| 富锦市| 漯河市| 黔西| 正阳县| 错那县| 武强县| 江源县| 满洲里市|