黑白棋人機對戰完整代碼

      網友投稿 1006 2022-05-29

      本文所有內容(包括每一行代碼)都是筆者原創。

      在我的?控制臺上的黑白棋?這篇博客中,給出了起初我寫的雙人對戰的代碼,在本文中,我加入了人機對戰的功能,并完善了代碼。

      完整代碼:

      #include "stdafx.h"

      #include

      #include

      #include

      using namespace std;

      int list[8][8] = { 0 }; //棋盤狀態,1是黑子,2是白子,0是空的

      int p = 1, aip = 0, air, aic, lastr = 0, lastc = 0; //p是現在該誰下,1是黑方,2是白方

      int p1, p2, p3, p4, temp1[8][8], temp2[8][8], temp3[8][8], temp4[8][8];//4層博弈對應的AI分數和棋局

      const int dr[8] = { 0, 0, 1, 1, 1, -1, -1, -1 }, dc[8] = { 1, -1, 0, 1, -1, 0, 1, -1 };//8個方向向量

      int book[65]; //棋譜

      const int no = 1000;//AI的分數不可能達到的上界值

      const int prio[8][8] =

      { //prio是每個位置的優先級,數值越高越好

      { 80, -20, 8, 6, 6, 8, -20, 80 },

      { -20, -20, 0, -1, -1, 0, -20, -20 },

      { 8, 0, 3, 5, 5, 3, 0, 8 },

      { 6, -1, 5, 1, 1, 5, -1, 6 },

      { 6, -1, 5, 1, 1, 5, -1, 6 },

      { 8, 0, 3, 5, 5, 3, 0, 8 },

      { -20, -20, 0, -1, -1, 0, -20, -20 },

      { 80, -20, 8, 6, 6, 8, -20, 80 }

      };

      bool playOK(int r, int c, int dr, int dc) //判斷某個格子的某個方向能否下子

      {

      if (list[r][c] != 0)return false;

      int tr = r, tc = c; //tr和tc分別表示該點通過行和列往特定方向移動后的坐標

      while (tr + dr >= 0 && tr + dr < 8 && tc + dc >= 0 && tc + dc < 8 && list[tr + dr][tc + dc] == 3 - p)

      { //循環遍歷,未到達邊界或者右邊的棋子是對方的則循環繼續,否則循環退出

      tr += dr, tc += dc; //移動坐標

      }

      //若使循環退出的那一格里,是對方的棋子,則(r,c)可落子,否則不可落子

      if (tr == r && tc == c)return false; //難點,這一句不可少

      if (tr + dr >= 0 && tr + dr < 8 && tc + dc >= 0 && tc + dc < 8 && list[tr + dr][tc + dc] == p)return true;

      return false;

      黑白棋人機對戰完整代碼

      }

      bool OK(int r, int c) //判斷某個格子能否下子

      {

      if (list[r][c])return false;

      for (int i = 0; i < 8; i++) //只要一個方向滿足可以下的條件,就可以下

      if (playOK(r, c, dr[i], dc[i]))return true; //調用

      return false;

      }

      int num(int k) //統計棋子數目,1是黑子,2是白子

      {

      int s = 0;

      for (int i = 0; i < 8; i++)for (int j = 0; j < 8; j++)if (list[i][j] == k)s++;

      return s;

      }

      void display() //顯示棋盤和棋子

      {

      system("cls");

      for (int i = 0; i < 8; i++)

      {

      if (!i)

      {

      cout << " ";

      for (int j = 0; j < 8; j++)cout << char('A' + j) << " ";

      cout << endl;

      }

      cout << i + 1 << " ";

      for (int j = 0; j < 8; j++)

      {

      if (list[i][j] == 2)cout << "○"; else if (list[i][j] == 1)cout << "●";

      else if (OK(i, j))cout << "?"; else cout << " ."; //調用

      cout << " ";

      }

      cout << endl << endl;

      }

      cout << "黑方:" << num(1) << " 白方:" << num(2) << " 輪到"; //調用

      if (p == 1)cout << "黑方下\n"; else cout << "白方下\n";

      cout << "候選項:";

      for (int i = 0; i < 8; i++)for (int j = 0; j < 8; j++)if (OK(i, j)) //調用

      cout << " " << char('1' + i) << char('A' + j);

      cout << "\n最后一個落子位置是" << lastr + 1 << char(lastc + 'A');

      }

      void init() //初始化

      {

      list[3][3] = list[4][4] = 2;

      list[3][4] = list[4][3] = 1;

      while (aip != 1 && aip != 2 && aip != 3)

      {

      cout << "選擇\n1,人機對戰,AI先\n2,人機對戰,玩家先\n3,雙人對戰\n";

      cin >> aip;

      }

      display(); //調用

      }

      bool end_() //判斷游戲是否結束

      {

      for (int i = 0; i < 8; i++)for (int j = 0; j < 8; j++)if (OK(i, j))return false; //調用

      p = 3 - p; //改變p的2個地方之一

      for (int i = 0; i < 8; i++)for (int j = 0; j < 8; j++)if (OK(i, j))return false; //調用

      display();

      cout << "\n游戲結束\n";

      if (num(1) < num(2))cout << "白方勝利"; //調用

      else if (num(1)>num(2))cout << "黑方勝利"; //調用

      else cout << "平局";

      return true;

      }

      void turn(int tr, int tc, int dr, int dc) //吃子函數play()的一個方向

      {

      if (!playOK(tr, tc, dr, dc))return; //難點,這一句不可少 //調用

      while (tr + dr >= 0 && tr + dr < 8 && tc + dc >= 0 && tc + dc < 8 && list[tr + dr][tc + dc] == 3 - p)

      {

      list[tr + dr][tc + dc] = p; //在該處換掉棋子的顏色

      tr += dr, tc += dc;

      }

      }

      void play(int r, int c)

      {

      lastr = r, lastc = c;

      for (int i = 0; i < 8; i++)turn(r, c, dr[i], dc[i]); //調用

      list[r][c] = p;

      book[num(1) + num(2)] = r * 8 + c; //調用

      p = 3 - p; //改變p的2個地方之一

      }

      int getPoint()

      {

      int point = 0;

      for (int i1 = 0; i1<8; i1++)for (int j1 = 0; j1<8; j1++)

      {

      if (list[i1][j1] == aip)point += prio[i1][j1]; //若是ai的子,則加上該位置的積分

      if (list[i1][j1] == 3 - aip) point -= prio[i1][j1]; //若是玩家的子,則減去該位置的積分

      }

      return point;

      }

      void AI3()//函數里面會改變p,但是調用函數不會改變p

      {

      p4 = no;

      for (int iiii = 0; iiii < 8; iiii++)for (int jjjj = 0; jjjj < 8; jjjj++) //第四層

      {

      if (!OK(iiii, jjjj))continue; //調用

      for (int i = 0; i<8; i++)for (int j = 0; j<8; j++)temp4[i][j] = list[i][j];

      play(iiii, jjjj);//調用

      p = 3 - p;

      if (p4 > getPoint())p4 = getPoint();//調用

      for (int i = 0; i<8; i++)for (int j = 0; j<8; j++)list[i][j] = temp4[i][j];

      }

      if (p4 == no)p4 = getPoint(); //調用

      if (p3 < p4)p3 = p4;

      }

      void AI2()//函數里面會改變p,但是調用函數不會改變p

      {

      p3 = -no;

      for (int iii = 0; iii < 8; iii++)for (int jjj = 0; jjj < 8; jjj++) //第三層

      {

      if (!OK(iii, jjj))continue; //調用

      for (int i = 0; i<8; i++)for (int j = 0; j<8; j++)temp3[i][j] = list[i][j];

      play(iii, jjj);//調用

      AI3();

      p = 3 - p;

      for (int i = 0; i<8; i++)for (int j = 0; j<8; j++)list[i][j] = temp3[i][j];

      }

      if (p3 == -no)

      {

      p = 3 - p;

      AI3();

      p = 3 - p;

      }

      if (p2 > p3)p2 = p3;

      }

      void AI() //函數里面會改變p,但是調用函數不會改變p

      {

      p1 = -no;

      for (int i = 0; i<8; i++)for (int j = 0; j<8; j++) //第一層

      {

      if (!OK(i, j))continue; //調用

      for (int i = 0; i<8; i++)for (int j = 0; j<8; j++)temp1[i][j] = list[i][j];

      play(i, j);//調用

      p2 = no;

      for (int ii = 0; ii < 8; ii++)for (int jj = 0; jj < 8; jj++) //第二層

      {

      if (!OK(ii, jj))continue; //調用

      for (int i = 0; i<8; i++)for (int j = 0; j<8; j++)temp2[i][j] = list[i][j];

      play(ii, jj);//調用

      AI3(); //調用

      p = 3 - p;

      for (int i = 0; i<8; i++)for (int j = 0; j<8; j++)list[i][j] = temp2[i][j];

      }

      if (p2 == no)

      {

      p = 3 - p;

      AI2(); //調用

      p = 3 - p;

      }

      if (p1 < p2)p1 = p2, air = i, aic = j; //難點,如果調用AI函數卻1次都沒有執行這條語句,那么AI就會下錯位置

      p = 3 - p;

      for (int i = 0; i<8; i++)for (int j = 0; j<8; j++)list[i][j] = temp1[i][j];

      }

      }

      void go() //落下一個子

      {

      display(); //調用

      if (p == aip)

      {

      AI();//調用

      play(air, aic);//調用

      Sleep(1000);

      return;

      }

      cout << "\n輸入落子位置:行(1-8)和列(A-H) 輸入00查看棋譜" << endl;

      char x, y;

      cin >> x >> y;

      if (x == '0')

      {

      for (int i = 5; i <= num(1) + num(2); i++)cout << " " << book[i] / 8 + 1 << char(book[i] % 8 + 'A');

      cout << "\n按任意鍵退出";

      system("pause>nul");

      return;

      }

      int r = x - '1', c = y - 'a';

      if (y >= 'A' && y < 'Z')c = y - 'A';

      if (!OK(r, c)) //調用

      {

      cout << "ERROR!";

      return;

      }

      play(r, c); //調用

      }

      int main()

      {

      system("color f0");//白底黑字

      init();

      while (!end_())go();

      system("pause>nul");

      return 0;

      }

      AI的算法是分析四層的博弈樹,即考慮 AI-玩家-AI-玩家 輪流下完4步之后可能出現的所有情況。

      對每個局面賦予一個值point,用來表示該局面對AI的有利程度,玩家總是盡量使得point小,而AI總是盡量使得point大。至于如何計算point,有一個專門完成該工作的函數getPoint()

      計算的方法比較簡陋,直接對每個格子賦予一個權值prio,然后用AI的所有格子權值之和減掉玩家的所有格子權值之和即可。

      AI

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:日常Java練習題(每天進步一點點系列)
      下一篇:WinForm——ComboBox總結
      相關文章
      亚洲色av性色在线观无码| 另类小说亚洲色图| 亚洲А∨精品天堂在线| 亚洲中文字幕无码中文| 亚洲色图.com| 亚洲免费观看在线视频| 亚洲视频国产精品| 亚洲精品视频免费看| 久久水蜜桃亚洲av无码精品麻豆| 国产亚洲一区二区三区在线观看 | 国产亚洲精品看片在线观看| 亚洲人AV永久一区二区三区久久| 国产在亚洲线视频观看| 国产尤物在线视精品在亚洲| 亚洲AⅤ无码一区二区三区在线| 无码天堂亚洲国产AV| 内射无码专区久久亚洲| 亚洲高清偷拍一区二区三区| 亚洲欧洲中文日韩久久AV乱码| 亚洲一区无码精品色| 国产亚洲精品自在线观看| 亚洲熟妇丰满多毛XXXX| 久久九九亚洲精品| 亚洲AV永久无码区成人网站 | 久久久久亚洲Av片无码v | 久久亚洲精品无码gv| 国产精品亚洲а∨天堂2021| 国产成人亚洲毛片| 亚洲中文字幕丝袜制服一区| 国产亚洲精久久久久久无码77777 国产亚洲精品成人AA片新蒲金 | 亚洲精品GV天堂无码男同| 亚洲av成人中文无码专区| 四虎精品亚洲一区二区三区 | 亚洲精品在线免费看| 亚洲成a人片在线看| 亚洲精品宾馆在线精品酒店| 亚洲成人一区二区| 亚洲伊人色欲综合网| 亚洲国产成人久久综合碰碰动漫3d | 亚洲日韩乱码久久久久久| 亚洲综合激情五月色一区|