AI算法实现五子棋(java)

本文实例为大家分享了AI算法实现五子棋的具体代码,供大家参考,具体内容如下

首先,实现一个五子棋要有一个棋盘,然后在这个棋盘上我们再来画出图画,五子棋棋盘有固定的行数和列数,再加上界面的大小和菜单栏,这些数据可能很多个类都需要用到,我们可以先考虑自己写一个接口用来存储这些数据:

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方法,在需要的时候调用来达到更新棋盘的作用。

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的内容画出相应的点(即棋子)
 } 

}

最最重要的就是监听器部分了,除了具有相应的监听功能,还要在每次人下棋之后智能判断出机器所需要下的位置,于此同时,每下一个棋子,都要判断是否已经有五子连成线进而提示输赢。

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;
  }
  }
 }

}

大概就是这个样子了,权值那里设置的还是需要调整一下。运行结果截图如下:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java压缩之LZW算法字典压缩与解压讲解

    压缩过程: 前面已经写过一篇哈夫曼压缩,LZW字典压缩与哈夫曼压缩的不同之处在于不需要把编码写入文件,编码表是在读文件中生成的,首先将0-255个ASCLL码与对应的数字存入哈希表中,作为基础码表. 这里的后缀为当前 前缀+后缀 如果在码表中存在,前缀等于前缀+后缀.如果不存在,将前缀+后缀所表示的字符串写入编码表编码,同时将前缀写入压缩文件中.这里重点注意一下,一个字节所能表示的数字范围为0-255,所以我们将一个字符的编码变成两个字节写进去,分别写入它的高八位和低八位,比如256即为0000

  • Java五子棋AI实现代码

    思路: ①五子棋界面的实现 ②交互下棋的实现 ③重绘 ④AI,实现人机对战 五子棋和简单AI的实现: 首先将五子棋的界面写出来. 首先我们写一个接口类,定义好棋盘的数据(目的是方便修改). public interface Config { public static final int X0=50;//左上角起点X值 public static final int Y0=50;//左上角起点Y值 public static final int ROWS=15;//横向线数 public sta

  • Java实现五子棋网络版

    本文实例为大家分享了Java实现五子棋网络版的具体代码,供大家参考,具体内容如下 需求分析: 对于网络五子棋而言,在普通五子棋的基础上需要添加以下功能: 1.拥有服务器端和客户端,用户通过客户端登录服务器后可与其他登录的用户进行对弈 2.服务器支持多组用户同时进行对弈 3.用户可以在服务器上创建新游戏或加入已创建的游戏 4.用户在下棋的时候可以进行聊天交流 由上可以知道需要实现的功能: ·提供服务器和客户端的功能 ·服务器将监听客户端的登录情况并允许多个客户端进行登录 ·用户通过客户端可以登录服

  • JavaTCP上传图片代码实例

    1.客户端代码 public class UploadPicClient { public static void main(String[] args) throws UnknownHostException, IOException { // TODO Auto-generated method stub //1,创建客户端socket Socket s = new Socket("localhost",10088); //2,读取客户端要上传的图片文件 FileInputStre

  • Java事件监听机制讲解

    给组件加上监听器 定义一个类,这个类继承ActionListener pubulic class ButListener implements ActionListener{ Public void actionPerformed(ActionEvent e){ }} 给按钮添加动作监听器方法 ButListener but = new ButListen(); jbu.addActionListener(but); 加上监听机制后再监听器ButListener时间处理方法中再创建窗口即可得到点

  • Javascript迭代、递推、穷举、递归常用算法实例讲解

    累加和累积 累加:将一系列的数据加到一个变量里面.最后的得到累加的结果 比如:将1到100的数求累加和 小球从高处落下,每次返回到原来一半,求第十次小球落地时小球走过的路程 <script> var h=100; var s=0; for(var i=0;i<10;i++){ h=h/2; s+=h; } s=s*2+100; </script> 累积:将一系列的数据乘积到一个变量里面,得到累积的结果. 常见的就是n的阶乘 var n=100; var result= 1;

  • Java版AI五子棋游戏

    本文实例为大家分享了java五子棋游戏的具体代码,供大家参考,具体内容如下 AI思路:通过判断棋盘上每个空位的分数,去分数最高的几个点,随机下棋 分数计算思路:能成5个说明能赢了,给最高分 不能成5个,对方能成5个,说明对方要赢了,给第二高分 能成活4,给第三高分 能成活3,给第四高分 能成冲4,给第五高分 能成冲3,给第六高分 能成活2,给第七高分 能成冲2,给第八高分 其他,给最低分 分数设定可自己定义. 因为是去年写的了,思路记得大概就是这样.最近根据书上写了个棋类游戏的设计框架,待完善后

  • java实现单机版五子棋

    这个小游戏是我和我姐们儿的JAVA课程设计,也是我做的第一个JAVA项目,适合初学者,希望能帮到那些被JAVA课设所困扰的孩纸们~~~ 一.该游戏需要实现 1.设计主框架,界面. 2.利用ActionListener接口实现按钮事件的监听. 3.重新开始功能的实现. 4.悔棋功能的实现. 5.退出功能的实现. 6.棋盘中棋子点类的定义. 7.利用MouseListener接口实现事件监听,并实现接口里的所有方法. 8.当鼠标移动到棋盘上的交点上,且该点上无棋子时能够变成小手形状. 9.点击棋盘时

  • Java实现五子棋AI算法

    五子棋AI算法 也算是一个典型的游戏AI算法,一些棋类的AI算法都可以参考实现,下面是Java实现代码 棋盘抽象接口 import java.util.List; public interface IChessboard { //取得棋盘最大横坐标 public int getMaxX(); //最大纵坐标 public int getMaxY(); //取得当前所有空白点,这些点才可以下棋 public List<Point> getFreePoints(); } 棋子类实现 //棋子类 p

  • Java抽象类的概念讲解

    简单来说 抽象类通常用来作为一个类族的最顶端的父类,用最底层的类表示现实中的具体事物,用最顶层的类表示该类族所有事物的共性.用abstract关键字类修饰一个类,该类叫做抽象类. 有抽象类那么肯定也有抽象方法,什么是抽象方法呢? 抽象方法就是有名字,形参列表,返回值,没有方法体的方法就做抽象方法. 抽象方法和抽象类的关系? 凡是没有方法体的方法必须使用关键字abstract修饰为抽象方法. 凡是含有抽象方法的类必须声明为抽象类. abstract class A{ abstract public

随机推荐