当前位置:   article > 正文

C++五子棋算法Ai 简单的电脑智能博弈_c++五子棋ai算法

c++五子棋ai算法

  111,博客开通有一段时间了,因为太low所以一直没敢写博客,今天再次鼓足勇气把几个月前的五子棋Ai与大家分享一下,讲得不好请见谅(0v0)。

  首先,我们要知道五子棋是两个人之间的博弈,双方轮流下子,肯定每次要将子下到最有用处的地方才是最有利于自己的(感觉说了堆废话。。)。我们将五子棋棋盘看成一个矩阵,用二维数组表示。然后我们可以在人落子后对场上所有空点进行评分,然后将电脑的棋子下在分最高的空点上。这就是五子棋Ai,,简单吧。。

  但是,怎样对空点进行评分呢?这才是关键所在,不同的评分规则会制造出性能不同的Ai,就像百万跑车与几万的面包车一样,可能别人写的Ai会完爆你的Ai(感觉又说了堆废话。。)。评分规则因人而异,我来讲将我的方法吧。

  对每个空点分别搜4个方向(为什么不是8个?因为左上与右下在同一直线上,最好合并算)。对于每个方向,我们可以根据自己平时玩五子棋的经验,来对这行(只需看这行上以这个空点为中心的临近几点即可)可能的每种局势给个分值(当然这局势依然有太多种,为了偷懒我们可以将局势差不多的当成一种来看 ),然后将4个方向上的评分加起来就是这个空点的总分了。是不是越来越糊涂了?可能代码比较直接。codeblocks可以运行,运行不了的将头文件该下就可以了。

(还有那种比较正宗的极大极小值博弈算法,本人能力有限,感兴趣的自行找度娘0.0.....)

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int ch[20][20],Score[20][20];
  4. int fang_a[4]={-1,-1,-1,0};
  5. int fang_b[4]={-1,0,1,-1};
  6. struct Sdian
  7. {
  8. int a,b;
  9. Sdian(int a=0,int b=0):a(a),b(b){}
  10. };
  11. Sdian buzhou[301];
  12. int sign_buzhou_num;
  13. Sdian dian[301];
  14. void ChessScore()
  15. {
  16. int x, y, i, j, k;
  17. int number1 = 0, number2 = 0;
  18. int empty = 0;
  19. memset(Score, 0, sizeof(Score));
  20. for (x = 0; x<15; x++)
  21. for (y = 0; y<15; y++)
  22. if (ch[x][y] == 0)
  23. for(int i=0;i<4;i++) ///4个方向撇竖捺横
  24. {
  25. int a[3]={0},sign_a=1;
  26. int b[4]={0},sign_b=2;
  27. a[1]=1;
  28. int sign_qian=5,sign_hou=-5;
  29. ///对玩家落点评分
  30. for (k = 1; k <= 4; k++)
  31. {
  32. int sign_x=x + k*fang_a[i],sign_y=y + k*fang_b[i];
  33. if (sign_x >= 0 && sign_x <= 14 &&sign_y >= 0 && sign_y <= 14 )
  34. if(ch[sign_x][sign_y] == 2)a[sign_a]++; ///自己
  35. else if (ch[sign_x][sign_y] == 0){++sign_a;b[sign_b++]=0;if(sign_b==4)break;} ///空位
  36. else {b[sign_b]=2;sign_qian=k;break;} ///敌方
  37. else {b[sign_b]=2;sign_qian=k;break;} ///越界
  38. }
  39. sign_a=1;sign_b=1;
  40. for (k = -1; k >= -4; k--)
  41. {
  42. int sign_x=x + k*fang_a[i],sign_y=y + k*fang_b[i];
  43. if (sign_x >= 0 && sign_x <= 14 &&sign_y >= 0 && sign_y <= 14 )
  44. if(ch[sign_x][sign_y] == 2)a[sign_a]++; ///自己
  45. else if (ch[sign_x][sign_y] == 0){--sign_a;b[sign_b--]=0;if(sign_b==-1)break;} ///空位
  46. else {b[sign_b]=2;sign_hou=k;break;} ///敌方
  47. else {b[sign_b]=2;sign_hou=k;break;} ///越界
  48. }
  49. if(sign_qian-sign_hou>5)
  50. {
  51. if(a[1]>=5)Score[x][y]+=100000;
  52. else if(a[1]==4)
  53. {
  54. if(b[1]==2||b[2]==2)Score[x][y]+=1100;
  55. else if(b[0]==2||b[3]==2)Score[x][y]+=5000;
  56. else Score[x][y]+=10000;
  57. }
  58. else if(a[1]==3)
  59. {
  60. if(a[0]+a[1]>=4||a[2]+a[1]>=4)Score[x][y]+=1100;
  61. else if(b[1]==2||b[2]==2)Score[x][y]+=100;
  62. else if(b[0]==2||b[3]==2)Score[x][y]+=500;
  63. else Score[x][y]+=1000;
  64. }
  65. else if(a[1]==2)
  66. {
  67. if(a[0]+a[1]>=4||a[2]+a[1]>=4)Score[x][y]+=1100;
  68. else if((a[0]+a[1]==3&&b[0]!=2&&b[3]!=2)||(a[1]+a[2]==3&&b[1]!=2&&b[4]!=2))Score[x][y]+=800;
  69. else if(a[0]+a[1]==3||a[1]+a[2]==3)Score[x][y]+=80;
  70. else if(b[1]==2||b[2]==2)Score[x][y]+=10;
  71. else if(b[0]==2||b[3]==2)Score[x][y]+=50;
  72. else Score[x][y]+=100;
  73. }
  74. else
  75. {
  76. if(a[0]+a[1]>=4||a[2]+a[1]>=4)Score[x][y]+=1100;
  77. else if((a[0]+a[1]==3&&b[0]!=2&&b[3]!=2)||(a[1]+a[2]==3&&b[1]!=2&&b[4]!=2))Score[x][y]+=800;
  78. else if(a[0]+a[1]==3||a[1]+a[2]==3)Score[x][y]+=80;
  79. else if((a[0]+a[1]==2&&b[0]!=2&&b[3]!=2)||(a[1]+a[2]==2&&b[1]!=2&&b[4]!=2))Score[x][y]+=80;
  80. else if(a[0]+a[1]==2||a[1]+a[2]==2)Score[x][y]+=8;
  81. else if(b[1]==2||b[2]==2)Score[x][y]+=1;
  82. else if(b[0]==2||b[3]==2)Score[x][y]+=5;
  83. else Score[x][y]+=10;
  84. }
  85. }
  86. ///对电脑落点评分
  87. a[0]=a[1]=a[2]=0;sign_a=1;
  88. b[0]=b[1]=b[2]=b[3]=0;sign_b=2;
  89. a[1]=1;
  90. sign_qian=5,sign_hou=-5;
  91. for (k = 1; k <= 4; k++)
  92. {
  93. int sign_x=x + k*fang_a[i],sign_y=y + k*fang_b[i];
  94. if (sign_x >= 0 && sign_x <= 14 &&sign_y >= 0 && sign_y <= 14 )
  95. if(ch[sign_x][sign_y] == 1)a[sign_a]++; ///自己
  96. else if (ch[sign_x][sign_y] == 0){++sign_a;b[sign_b++]=0;if(sign_b==4)break;} ///空位
  97. else {b[sign_b]=2;sign_qian=k;break;} ///敌方
  98. else {b[sign_b]=2;sign_qian=k;break;} ///越界
  99. }
  100. sign_a=1;sign_b=1;
  101. for (k = -1; k >= -4; k--)
  102. {
  103. int sign_x=x + k*fang_a[i],sign_y=y + k*fang_b[i];
  104. if (sign_x >= 0 && sign_x <= 14 &&sign_y >= 0 && sign_y <= 14 )
  105. if(ch[sign_x][sign_y] == 1)a[sign_a]++; ///自己
  106. else if (ch[sign_x][sign_y] == 0){--sign_a;b[sign_b--]=0;if(sign_b==-1)break;} ///空位
  107. else {b[sign_b]=2;sign_hou=k;break;} ///敌方
  108. else {b[sign_b]=2;sign_hou=k;break;} ///越界
  109. }
  110. if(sign_qian-sign_hou>5)
  111. {
  112. if(a[1]>=5)Score[x][y]+=1000000;
  113. else if(a[1]==4)
  114. {
  115. if(b[1]==2||b[2]==2)Score[x][y]+=1200;
  116. else if(b[0]==2||b[3]==2)Score[x][y]+=5000;
  117. else Score[x][y]+=50001;
  118. }
  119. else if(a[1]==3)
  120. {
  121. if(a[0]+a[1]>=4||a[2]+a[1]>=4)Score[x][y]+=1100;
  122. else if(b[1]==2||b[2]==2)Score[x][y]+=100;
  123. else if(b[0]==2||b[3]==2)Score[x][y]+=500;
  124. else Score[x][y]+=1001;
  125. }
  126. else if(a[1]==2)
  127. {
  128. if(a[0]+a[1]>=4||a[2]+a[1]>=4)Score[x][y]+=1160;
  129. else if((a[0]+a[1]==3&&b[0]!=2&&b[3]!=2)||(a[1]+a[2]==3&&b[1]!=2&&b[4]!=2))Score[x][y]+=900;
  130. else if(a[0]+a[1]==3||a[1]+a[2]==3)Score[x][y]+=90;
  131. else if(b[1]==2||b[2]==2)Score[x][y]+=10;
  132. else if(b[0]==2||b[3]==2)Score[x][y]+=50;
  133. else Score[x][y]+=101;
  134. }
  135. else
  136. {
  137. if(a[0]+a[1]>=4||a[2]+a[1]>=4)Score[x][y]+=1196;
  138. else if((a[0]+a[1]==3&&b[0]!=2&&b[3]!=2)||(a[1]+a[2]==3&&b[1]!=2&&b[4]!=2))Score[x][y]+=900;
  139. else if(a[0]+a[1]==3||a[1]+a[2]==3)Score[x][y]+=90;
  140. else if((a[0]+a[1]==2&&b[0]!=2&&b[3]!=2)||(a[1]+a[2]==2&&b[1]!=2&&b[4]!=2))Score[x][y]+=90;
  141. else if(a[0]+a[1]==2||a[1]+a[2]==2)Score[x][y]+=9;
  142. else if(b[1]==2||b[2]==2)Score[x][y]+=1;
  143. else if(b[0]==2||b[3]==2)Score[x][y]+=5;
  144. else Score[x][y]+=11;
  145. }
  146. }
  147. }
  148. }
  149. void print()
  150. {
  151. system("cls");
  152. printf(" ");
  153. for(int i=0;i<=14;i++)
  154. printf("%2d",i);
  155. cout<<endl;
  156. for(int i=0;i<=14;i++){
  157. printf("%2d",i);
  158. for(int j=0;j<=14;j++)
  159. printf(" %c",ch[i][j]==0?'.':(ch[i][j]==1?'O':'X'));
  160. putchar('\n');
  161. }
  162. }
  163. void kaiju(int a,int b,int &aa,int &bb)
  164. {
  165. if((a==6&&b==6)||(a==6&&b==7)){ch[5][6]=1;buzhou[++sign_buzhou_num]=Sdian(5,6);aa=5;bb=6;}
  166. else if((a==6&&b==8)||(a==7&&b==8)){ch[6][9]=1;buzhou[++sign_buzhou_num]=Sdian(6,9);aa=6;bb=9;}
  167. else if((a==8&&b==8)||(a==8&&b==7)){ch[9][8]=1;buzhou[++sign_buzhou_num]=Sdian(9,8);aa=9;bb=8;}
  168. else if((a==8&&b==6)||(a==7&&b==6)){ch[8][5]=1;buzhou[++sign_buzhou_num]=Sdian(8,5);aa=8;bb=5;}
  169. else{
  170. ChessScore();
  171. srand(time(NULL));
  172. int sign_max=Score[0][0],sign_num=0;
  173. for(int i=0;i<15;i++)
  174. for(int j=0;j<15;j++)
  175. sign_max=max(sign_max,Score[i][j]);
  176. for(int i=0;i<15;i++)
  177. for(int j=0;j<15;j++)
  178. {
  179. if(Score[i][j]==sign_max){dian[sign_num++]=Sdian(i,j);/*cout<<"###"<<endl;int aaa;cin>>aaa;*/}
  180. }
  181. Sdian sign_rand=dian[rand()%sign_num];
  182. aa=sign_rand.a;
  183. bb=sign_rand.b;
  184. ch[aa][bb]=1;
  185. buzhou[++sign_buzhou_num]=Sdian(aa,bb);
  186. }
  187. }
  188. int panduan(int a,int b)
  189. {
  190. for(int i=0;i<4;i++){
  191. int num=1;
  192. for(int k=1;k<=4;k++){
  193. int sign=ch[a+k*fang_a[i]][b+k*fang_b[i]];
  194. if(sign==ch[a][b])num++;
  195. else break;
  196. }
  197. for(int k=-1;k>=-4;k--){
  198. int sign=ch[a+k*fang_a[i]][b+k*fang_b[i]];
  199. if(sign==ch[a][b])num++;
  200. else break;
  201. }
  202. if(num>=5)return ch[a][b];
  203. }
  204. return -1;
  205. }
  206. int main()
  207. {
  208. int sign_start=1;
  209. while(sign_start==1){
  210. sign_buzhou_num=-1;
  211. memset(ch,0,sizeof(ch));
  212. ch[7][7]=1;
  213. buzhou[++sign_buzhou_num]=Sdian(7,7);
  214. int a,b,sheng,sign_bushu=1;
  215. print();
  216. cout<<"电脑下子的位置:"<<7<<","<<7<<endl;
  217. while(1){
  218. if(sign_bushu%2==1)
  219. while(1){
  220. if(sign_buzhou_num==0)cout<<"请输入您下子的位置:"<<endl;
  221. else cout<<"请输入您下子的位置(悔棋请输入-1 -1):"<<endl;
  222. cin>>a>>b;
  223. if(a!=-1||b!=-1)
  224. if(a>=0&&a<=14&&b>=0&&b<=14)
  225. if(ch[a][b]!=0) cout<<"该地方已经有子,请重新下子"<<endl;
  226. else {ch[a][b]=2;buzhou[++sign_buzhou_num]=Sdian(a,b);break;}
  227. else cout<<"该地方已越界,请重新下子"<<endl;
  228. else
  229. if(sign_buzhou_num==0)cout<<"悔棋失败"<<endl;
  230. else
  231. {
  232. Sdian dian1=buzhou[sign_buzhou_num--];
  233. Sdian dian2=buzhou[sign_buzhou_num--];
  234. Sdian dian3=buzhou[sign_buzhou_num];
  235. ch[dian1.a][dian1.b]=ch[dian2.a][dian2.b]=0;
  236. print();
  237. cout<<"电脑下子的位置:"<<dian3.a<<","<<dian3.b<<endl;
  238. sign_bushu-=2;
  239. }
  240. }
  241. else{
  242. if(sign_bushu!=2)
  243. {
  244. ChessScore();
  245. srand(time(NULL));
  246. int sign_max=Score[0][0],sign_num=0;
  247. for(int i=0;i<15;i++)
  248. for(int j=0;j<15;j++)
  249. sign_max=max(sign_max,Score[i][j]);
  250. for(int i=0;i<15;i++)
  251. for(int j=0;j<15;j++)
  252. {
  253. if(Score[i][j]==sign_max){dian[sign_num++]=Sdian(i,j);/*cout<<"###"<<endl;int aaa;cin>>aaa;*/}
  254. }
  255. Sdian sign_rand=dian[rand()%sign_num];
  256. a=sign_rand.a;
  257. b=sign_rand.b;
  258. ch[a][b]=1;
  259. buzhou[++sign_buzhou_num]=Sdian(a,b);
  260. ///Sleep(2000);
  261. }
  262. else kaiju(buzhou[sign_buzhou_num].a,buzhou[sign_buzhou_num].b,a,b);
  263. }
  264. print();
  265. if(sign_bushu%2==0)cout<<"电脑下子的位置:"<<a<<","<<b<<endl;
  266. int jieguo=panduan(a,b);
  267. if(jieguo!=-1){sheng=jieguo;break;}
  268. sign_bushu+=1;
  269. }
  270. if(sheng==2)cout<<"恭喜您战胜了电脑!"<<endl;
  271. else cout<<"很遗憾您被电脑击败了,再接再厉!"<<endl;
  272. cout<<"输入1重新开始游戏,输入2退出:"<<endl;
  273. cin>>sign_start;
  274. }
  275. return 0;
  276. }


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/243642?site
推荐阅读
相关标签
  

闽ICP备14008679号