本文实例为大家分享了ai算法实现五子棋的具体代码,供大家参考,具体内容如下
首先,实现一个五子棋要有一个棋盘,然后在这个棋盘上我们再来画出图画,五子棋棋盘有固定的行数和列数,再加上界面的大小和菜单栏,这些数据可能很多个类都需要用到,我们可以先考虑自己写一个接口用来存储这些数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public interface config { public static final int size= 703 ; //面板大小 public static final int x0=size/ 19 * 2 - 8 ; public static final int y0=x0- 15 ; //棋盘网格起始点 public static final int wid=size/ 19 ; //行宽 public static final int line= 15 ; //行数 public static final int chess=wid; //五子棋棋子大小
} |
这个时候我们来考虑写一个五子棋界面,除了常用的界面写法之外,考虑到五子棋的悔棋和重新开始,我们需要重写paint方法,在需要的时候调用来达到更新棋盘的作用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
import java.awt.basicstroke; import java.awt.borderlayout; import java.awt.color; import java.awt.dimension; import java.awt.graphics; import java.awt.graphics2d;
import javax.swing.jpanel;
public class fivebord extends jpanel implements config{ private static final long serialversionuid = 1l; private int point[][]= new int [size][size];
public static void main(string[] args) { fivebord fb = new fivebord(); fb.showfivebord(); }
public void showfivebord() { //一下是关于界面的常规设置 javax.swing.jframe jf = new javax.swing.jframe(); jf.settitle( "fivebord" ); jf.setsize(size+ 100 , size); jf.setdefaultcloseoperation( 3 ); jf.setlocationrelativeto( null ); jf.setlayout( new borderlayout());
jpanel jp1= new jpanel(); jp1.setbackground(color.orange); jp1.setpreferredsize( new dimension( 100 , size)); jf.add(jp1,borderlayout.east);
javax.swing.jbutton jbu1 = new javax.swing.jbutton( "悔棋" ); jp1.add(jbu1);
javax.swing.jbutton jbu2 = new javax.swing.jbutton( "人机" ); jp1.add(jbu2);
javax.swing.jbutton jbu3 = new javax.swing.jbutton( "人人" ); jp1.add(jbu3);
this .setbackground(color.yellow); jf.add( this ,borderlayout.center);
jf.setvisible( true );
//以下给界面添加监听器,包括画板和按钮 drawmouse mouse= new drawmouse( this ); jbu1.addactionlistener(mouse); jbu2.addactionlistener(mouse); jbu3.addactionlistener(mouse); this .addmouselistener(mouse); //监听器中需要考虑当前棋盘上的棋子和位置 mouse.setpoint(point);
} public void paint(graphics g) { super .paint(g); //super.paint //由于paint函数是界面自带的函数且在某些时候会自动调用 //super.paint(g)表示屏蔽父类的函数内容,换做自己接下来改写的内容 graphics2d gr = (graphics2d)g; gr.setstroke( new basicstroke( 1 )); //2d画笔变粗度为1 for ( int i=x0;i<=x0+line*wid;i+=wid){ for ( int j=y0;j<=y0+line*wid;j+=wid){ g.drawline(x0, j, x0+line*wid, j); g.drawline(i, y0, i,y0+line*wid); } } //画内部16格 gr.setstroke( new basicstroke( 2 )); //画笔粗度变为2 g.drawline(x0-wid, y0-wid, x0-wid, y0+(line+ 1 )*wid); g.drawline(x0-wid, y0-wid, x0+(line+ 1 )*wid, y0-wid); g.drawline(x0+(line+ 1 )*wid, y0-wid, x0+(line+ 1 )*wid, y0+(line+ 1 )*wid); g.drawline(x0-wid, y0+(line+ 1 )*wid, x0+(line+ 1 )*wid, y0+(line+ 1 )*wid); //画四周较粗的边框(美观起见,没有实际意义) for ( int i=x0;i<=x0+(wid*(line+ 1 ));i+=wid){ for ( int j=y0;j<=y0+(line+ 1 )*wid;j+=wid){ if (point[i][j]== 1 ){ //画黑棋 g.setcolor(color.black); g.filloval(i-wid/ 2 , j-wid/ 2 , wid, wid); } else if (point[i][j]== 2 ){ //画白棋 g.setcolor(color.white); g.filloval(i-wid/ 2 , j-wid/ 2 , wid, wid); } } } //根据point的内容画出相应的点(即棋子) }
} |
最最重要的就是监听器部分了,除了具有相应的监听功能,还要在每次人下棋之后智能判断出机器所需要下的位置,于此同时,每下一个棋子,都要判断是否已经有五子连成线进而提示输赢。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
import java.awt.color; import java.awt.graphics; import java.awt.event.actionevent; import java.awt.event.actionlistener; import java.awt.event.mouseadapter; import java.awt.event.mouseevent; import java.util.hashmap;
import javax.swing.joptionpane;
public class drawmouse extends mouseadapter implements config,actionlistener{ //添加动作监听器(监听按钮)和鼠标监听器(鼠标所点位置画棋子) private graphics g; private int x,y,co= 1 ,index= 0 ; private int point[][]; private int pointweight[][]= new int [x0+(line+ 1 )*wid][y0+(line+ 1 )*wid]; private int orderx[]= new int [x0+(line+ 1 )*wid],ordery[]= new int [y0+(line+ 1 )*wid]; private fivebord fb; private int pc= 0 ; public hashmap <string,integer> hm = new hashmap <string,integer>(); //哈希表用来存放不同棋子布局下的不同权值
drawmouse(fivebord fb) { this .g = fb.getgraphics(); this .fb=fb; sethashmap(); } //传棋子数组 public void setpoint( int point[][]){ this .point=point; } public void sethashmap(){ hm.put( "1" , 1 ); //某一方向线上只有一个黑棋 hm.put( "12" , 5 ); //某一方向线上紧接着一个黑棋有一个白棋 hm.put( "11" , 10 ); hm.put( "112" , 15 ); //某一方向线上紧接着两个相邻的黑棋后有一个白棋(以此类推) hm.put( "111" , 100 ); hm.put( "1112" , 105 ); hm.put( "1111" , 1000 );
hm.put( "2" , 1 ); hm.put( "21" , 5 ); hm.put( "22" , 10 ); hm.put( "221" , 15 ); hm.put( "222" , 100 ); hm.put( "2221" , 105 ); hm.put( "2222" , 1000 ); }
public void actionperformed(actionevent e){ //悔棋操作,将棋子数目减一,然后重绘界面即可 if ( "悔棋" .equals(e.getactioncommand())&&index> 0 ){ system.out.println( "悔棋" ); index--; point[orderx[index]][ordery[index]]= 0 ; fb.paint(g); } //人机模式一旦点击,界面所有棋子清零,开始人机对战(pc=1) if ( "人机" .equals(e.getactioncommand())){ system.out.println( "人机" ); pc= 1 ; index= 0 ; for ( int i=x0;i<=x0+wid*line;i+=wid){ for ( int j=y0;j<=y0+wid*line;j+=wid){ point[i][j]= 0 ; } } fb.paint(g); } //人人对战,也是点击按钮棋子清零,开始人人对战(pc=0) if ( "人人" .equals(e.getactioncommand())){ system.out.println( "人机" ); pc= 0 ; index= 0 ; for ( int i=x0;i<=x0+wid*line;i+=wid){ for ( int j=y0;j<=y0+wid*line;j+=wid){ point[i][j]= 0 ; } } fb.paint(g); } }
public void mouseclicked(mouseevent e) { x=e.getx(); y=e.gety(); //得到点击的点 if ((x-x0)%wid>=wid/ 2 ){ x=x-(x-x0)%wid+wid; } else { x=x-(x-x0)%wid; } if ((y-y0)%wid>=wid/ 2 ){ y=y-(y-y0)%wid+wid; } else { y=y-(y-y0)%wid; } //对点的位置进行修正(保证每次点击都正好下在网格交汇处) if (point[x][y]== 0 &&x>=x0&&x<=x0+wid*line&&y>=y0&&y<=y0+wid*line){ //人人对战:直接用鼠标检测,依次变换颜色黑或白 if (pc== 0 ){ if (g.getcolor()==color.black){ g.setcolor(color.white); co= 2 ; } else { g.setcolor(color.black); co= 1 ; } } //人机对战,每次人下过棋子之后,计算机根据现有棋盘布局对棋局分析和总和并判断机器需要下的位置 else if (pc== 1 ){ g.setcolor(color.black); co= 1 ; } g.filloval(x-wid/ 2 , y-wid/ 2 , wid, wid); point[x][y]=co; system.out.println(index+ " " + x+ " " +y); orderx[index]=x; ordery[index]=y; index++; if (exam()== 0 ){ //自己敲代码过程中的验证、、、、、、可以不用在意这类输出。 system.out.println( "hahahahhhaahhahah" ); if (pc== 1 ){ system.out.println( "hehehehehehehehehehehe" ); g.setcolor(color.white); co= 2 ; ai(); exam(); } } }
} //检测是否有一方获胜,跳出提示框提示某一方获胜 public int exam(){ int w= 0 ; for ( int i=x0-wid;i<=x0+wid*(line+ 1 );i+=wid){ for ( int j=y0-wid;j<=y0+wid*(line+ 1 );j+=wid){ if (point[i][j]!= 0 ){ int exam1= 0 ,exam2= 0 ,exam3= 0 ,exam4= 0 ; //水平、竖直、左斜、右斜四个方向上同色棋子相连最多的个数 for ( int t=wid;t< 5 *wid;t+=wid){ if (i+t<=x0+wid*(line+ 1 )&&point[i+t][j]==point[i][j]){ exam1++; } if (j+t<=y0+wid*(line+ 1 )&&point[i][j+t]==point[i][j]){ exam2++; } if (i+t<=x0+wid*(line+ 1 )&&j+t<=y0+wid*(line+ 1 )&&point[i+t][j+t]==point[i][j]){ exam3++; } if (i+t<=x0+wid*(line+ 1 )&&j>=t&&point[i+t][j-t]==point[i][j]){ exam4++; } } system.out.println(exam1+ " " +exam2+ " " +exam3+ " " +exam4); if (exam1== 4 ||exam2== 4 ||exam3== 4 ||exam4== 4 ){ //某一方向上同色5子相连,一方获胜 if (point[i][j]== 1 ){ w= 1 ; //弹出提示框 joptionpane.showmessagedialog( null , "黑子胜" ); } else { w= 2 ; joptionpane.showmessagedialog( null , "白子胜" ); } i=x0+wid*(line+ 1 )+ 1 ; break ; } } } } return w; } //ai算法 //分别向左、香油、左下、、、、、等8个方向检测棋子布局情况并累加在该点的权值上 //再找出图片上没有棋子并且权值最大的点下棋子 //记得每次下棋将各个空位置的权值归0,以便下一次计算权值累加 public void ai(){ for ( int i=x0;i<x0+wid*(line+ 1 );i+=wid){ for ( int j=y0;j<y0+wid*(line+ 1 );j+=wid){ if (point[i][j]== 0 ){ //像右寻找 //system.out.print("pointweight["+(i-x0)/wid+"]["+(j-y0)/wid+"]:"); int color= 0 ; string code= "" ; for ( int k=i+wid;k<=x0+wid*line;k+=wid){ if (point[k][j]!= 0 ){ if (color== 0 ){ color=point[k][j]; code+=point[k][j]; } else { if (point[k][j]==color){ code+=point[k][j]; } else { code+=point[k][j]; break ; } } } else { break ; } } integer value=hm.get(code); if (value != null ){ pointweight[i][j] += value; } //向下寻找 // system.out.print(pointweight[i][j]+" "); code= "" ; color= 0 ; for ( int k=j+wid;k<=x0+wid*line;k+=wid){ if (point[i][k]!= 0 ){ if (color== 0 ){ color=point[i][k]; code+=point[i][k]; } else { if (point[i][k]==color){ code+=point[i][k]; } else { code+=point[i][k]; break ; } } } else { break ; } } value=hm.get(code); if (value != null ){ pointweight[i][j] += value; } //向左 // system.out.print(pointweight[i][j]+" "); code= "" ; color= 0 ; for ( int k=i-wid;k>=x0;k-=wid){ if (point[k][j]!= 0 ){ if (color== 0 ){ color=point[k][j]; code+=point[k][j]; } else { if (point[k][j]==color){ code+=point[k][j]; } else { code+=point[k][j]; break ; } } } else { break ; } } value=hm.get(code); if (value != null ){ pointweight[i][j] += value; } //向上 // system.out.print(pointweight[i][j]+" "); code= "" ; color= 0 ; for ( int k=j-wid;k>=y0;k-=wid){ if (point[i][k]!= 0 ){ if (color== 0 ){ color=point[i][k]; code+=point[i][k]; } else { if (point[i][k]==color){ code+=point[i][k]; } else { code+=point[i][k]; break ; } } } else { break ; } } value=hm.get(code); if (value != null ){ pointweight[i][j] += value; } //向右上寻找 // system.out.print(pointweight[i][j]+" "); code= "" ; color= 0 ; for ( int k=i+wid,w=j+wid;k<=x0+wid*line&&w<=y0+wid*line;k+=wid,w+=wid){ if (point[k][w]!= 0 ){ if (color== 0 ){ color=point[k][w]; code+=point[k][w]; } else { if (point[k][w]==color){ code+=point[k][w]; } else { code+=point[k][w]; break ; } } } else { break ; } } value=hm.get(code); if (value != null ){ pointweight[i][j] += value; } // system.out.print(pointweight[i][j]+" "); code= "" ; color= 0 ; for ( int k=i-wid,w=j-wid;k>=x0&&w>=y0;k-=wid,w-=wid){ if (point[k][w]!= 0 ){ if (color== 0 ){ color=point[k][w]; code+=point[k][w]; } else { if (point[k][w]==color){ code+=point[k][w]; } else { code+=point[k][w]; break ; } } } else { break ; } } value=hm.get(code); if (value != null ){ pointweight[i][j] += value; } // system.out.print(pointweight[i][j]+" "); code= "" ; color= 0 ; for ( int k=i+wid,w=j-wid;k<=x0+line*wid&&w>=y0;k+=wid,w-=wid){ if (point[k][w]!= 0 ){ if (color== 0 ){ color=point[k][w]; code+=point[k][w]; } else { if (point[k][w]==color){ code+=point[k][w]; } else { code+=point[k][w]; break ; } } } else { break ; } } value=hm.get(code); if (value != null ){ pointweight[i][j] += value; } // system.out.print(pointweight[i][j]+" "); code= "" ; color= 0 ; for ( int k=i-wid,w=j+wid;k>=x0&&w<=y0+line*wid;k-=wid,w+=wid){ if (point[k][w]!= 0 ){ if (color== 0 ){ color=point[k][w]; code+=point[k][w]; } else { if (point[k][w]==color){ code+=point[k][w]; } else { code+=point[k][w]; break ; } } } else { break ; } } value=hm.get(code); if (value != null ){ pointweight[i][j] += value; } // system.out.println(pointweight[i][j]); } } } //寻找最大权值的点并画棋子 int maxx=x0,maxy=y0; for ( int i=x0;i<=x0+wid*line;i+=wid){ for ( int j=y0;j<=y0+wid*line;j+=wid){ system.out.print(pointweight[i][j]+ " " ); if (pointweight[i][j]>pointweight[maxx][maxy]){ maxx=i; maxy=j; }
} system.out.println(); } g.filloval(maxx-wid/ 2 , maxy-wid/ 2 , wid, wid); point[maxx][maxy]=co; system.out.println(index+ " " + maxx+ " " +maxy); orderx[index]=maxx; ordery[index]=maxy; index++; //全部权值归零方便下次使用 for ( int i=x0;i<=x0+wid*line;i+=wid){ for ( int j=y0;j<=y0+wid*line;j+=wid){ pointweight[i][j]= 0 ; } } }
} |
大概就是这个样子了,权值那里设置的还是需要调整一下。运行结果截图如下:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
原文链接:https://blog.csdn.net/weixin_42372777/article/details/81432083