创建一个窗体来承载五子棋

如何创建一个窗体,以及如何在窗体上添加必要的按钮组件等操作,可以查看我的第一篇文章,里面有详细的讲解,这里就不在重新累述。具体的代码如下:

public class DrawUI{public void ShowUI(){MyFrame jf=new MyFrame();//这里原本应该是使用JFrame但,后续重绘中创建了子类MyFrame继承父类JFrame,这里就换成了MyFrame//设置窗体属性jf.setSize(500,500);jf.setLocationRelativeTo(null);jf.setTitle("五子棋");jf.setResizable(true);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);FlowLayout fl=new FlowLayout();//设置窗体格式jf.setLayout(fl);JButton jb=new JButton("人人对战");//添加按钮JButton jb1=new JButton("悔棋");JButton jb2=new JButton("清空棋盘");JButton jb3=new JButton("人机对战");jf.add(jb);jf.add(jb1);jf.add(jb2);jf.add(jb3);jf.setVisible(true);Graphics g=jf.getGraphics();//给窗体添加画笔UIListener ul=new UIListener();jb.addActionListener(ul);//给按钮添加监听器jb1.addActionListener(ul);jb2.addActionListener(ul);jb3.addActionListener(ul);jf.addMouseListener(ul);//给窗体添加监听器ul.gr=g;//将画笔倒给UIlistener中的grjf.ul=ul;//为了在Myframe中使用ChessArray,将UIistener中的ul倒给Myframe中的ulul.jb11=jb;//将按钮jb倒给ul中的jb11,方便其使用jbul.mf=jf;//为了在UIlistener中重绘,将jf倒给其中的mf}
}

五子棋基本程序编写

绘制棋盘

第一步肯定是要在创建好的窗体上绘制出五子棋的棋盘。思路也很简单,就是画出横竖两条线,然后设置一个固定间隔,不断循环,绘制出一个棋盘。

这里注意,因为如果只是在窗体中绘制出棋盘,那么每次窗体被拖动,刷新后,窗体中的绘制好的棋盘就会被刷新掉,所以需要重绘,确保棋盘永久存在,所以在这里,我们就直接将棋盘绘制在窗体重绘方法中。

public class MyFrame extends JFrame{//MyFrame子类继承JFrame父类public void paint(Graphics g) {//重绘棋盘,确保刷新网页时候,棋盘还在super.paint(g);int x1,x2,y1,y2;int X1,X2,Y1,Y2;x1=50;x2=450;y1=70;y2=470;X1=50;X2=450;Y1=70;Y2=470;for(int i=0; i<21; i++) {g.drawLine(x1,y1,x2,y1);y1=y1+20;}for(int i=0; i<21; i++) {g.drawLine(X1,Y1,X1,Y2);X1=X1+20;}}
}

这里也需要注意:因为重绘方法是需要写在MyFrame类中的,由于后续还会有需要重绘的东西,所以后续会在这部分继续扩充需要重绘的内容代码。

绘制棋子(人人对战中棋子黑白交替出现,人机对战中玩家下黑子,电脑下白子)

绘制棋子时候,我们应该能清楚思路。

首先,鼠标点击的位置,这个位置不一定正好是在棋盘的网格交汇处的节点上,我们就要将这个鼠标点击的坐标优化至附近的交汇节点上。原理也很简单,将鼠标点击获取的坐标,计算转化成其在哪两个焦点之间,然后将两个节点之间一分为二,如果坐标在前部分,则优化到前面的节点上,如果在后半部分,则优化到后面的节点上。

其次,将鼠标点击的坐标优化到棋盘网格节点上后,则需要在这个网格节点上绘制棋子即可,但这里我们会发现,程序中绘制的圆形图形的时候,输入的绘制坐标点是绘制出来圆形的外切长方形的左上角的坐标,并非是圆形的圆心坐标。这时同样需要优化,将坐标分别减去它的半径,就能优化在鼠标点击转化过来的网格点上。

最后,我们需要存储已经下过的棋子的信息,方便后续判定输赢,已经棋子重绘时使用。这里为了存储棋子信息,我们就可以设立一个二维数组,二维数组正好对应横竖棋盘的网格,我们可以将黑棋的数组值定为1,白棋的数组值定为2。那么没有棋子的地方的数组值就为默认的0.

具体来看代码:

public class UIListener implements MouseListener ,ActionListener{//监听器是接口
//后续可能会用到的一些变量Graphics gr;int[][] ChessArray=new int[22][22];//黑白棋子数组int[][] ChessValue=new int[22][22];//AI人机中权值数组JButton jb11;int nb=0;int count=0;int a,b,x,y,X,Y;JFrame mf;HashMap<String,Integer> hm=new HashMap<String,Integer>();//设置AI人机中权值量表public void mouseClicked(MouseEvent e) {int z=50,c=20;Color c1=new Color(0,0,0);Color c2=new Color(255,255,255);a=e.getX();b=e.getY();//获得鼠标点击坐标if(nb==1) {//确定是否可以下棋if((a-z)%c>c/2) {//帮助x轴上点击点优化到坐标格子上x=(a-z)/c+1;}else {x=(a-z)/c;}if((b-z)%c>c/2) {//帮助y轴上点击点优化到坐标格子上y=(b-z)/c+1;}else {y=(b-z)/c;}if(ChessArray[x][y]==0) {//确保棋子只能下在没有棋子的地方if(zifu.equals("人机对战")) {gr.setColor(c1);gr.fillOval(x*c+z-10, y*c+z-10, 20, 20);ChessArray[x][y]=1;gr.setColor(c2);AI();}else if(zifu.equals("人人对战")) {if(count==0) {gr.setColor(c1);count++;gr.fillOval(x*c+z-10, y*c+z-10, 20, 20);ChessArray[x][y]=1;//黑子数组值为1,方便重绘使用}else if(count==1) {gr.setColor(c2);count--;gr.fillOval(x*c+z-10, y*c+z-10, 20, 20);ChessArray[x][y]=2;//白子数组值为21,方便重绘使用}}}else{System.out.println("该位置已有棋子");}}else {System.out.println("请选择对战类型");}
}

重绘棋子

在绘制出棋子后,我们同样需要去意识到,拖动窗体或者任何会让窗体刷新的操作后,已经下好的棋子都会消失,那么我们就需要在重绘方法中,同样加入棋子的重绘,也就是正在绘制棋盘这个标题下的代码行中加入重绘棋子的代码。

原理则是,因为我们设置了数组保存棋子,黑棋都赋值了1,白棋都赋值了2,那么我就遍历整个棋盘上上的所有数组,然后把数组等于1和2的都重绘出来即可。

加入了棋子重绘的代码后,整个重绘部分的代码就如下:

public class MyFrame extends JFrame{//MyFrame子类继承JFrame父类public UIListener ul;
//  int[][] ChessArray;int z=50,c=20;public void paint(Graphics g) {//重绘棋盘,确保刷新网页时候,棋盘还在super.paint(g);int x1,x2,y1,y2;int X1,X2,Y1,Y2;x1=50;x2=450;y1=70;y2=470;X1=50;X2=450;Y1=70;Y2=470;for(int i=0; i<21; i++) {g.drawLine(x1,y1,x2,y1);y1=y1+20;}for(int i=0; i<21; i++) {g.drawLine(X1,Y1,X1,Y2);X1=X1+20;}int[][] ChessArray = ul.ChessArray;for(int i=0;i<ChessArray.length;i++) {//重绘棋子,网页刷新后,之前下过的棋子还在for(int j=0;j<ChessArray.length;j++) {if(ChessArray[i][j]==1) {g.setColor(Color.black);g.fillOval(i*c+z-10, j*c+z-10, 20, 20);}if(ChessArray[i][j]==2) {g.setColor(Color.white);g.fillOval(i*c+z-10, j*c+z-10, 20, 20);}}}}}

判定输赢

当棋子都下好了之后,我们就需要在每下一颗棋子后进行输赢的判定。五子棋中,有五颗棋子连在一起即为获胜。因此我们就需要对横竖斜四个大方向上的棋子,进行查找判定。

原理则是因为黑棋的数组值都为1,白棋都为2,那么就在每一次所下棋子的地方为起点,向各个方向查找,每有一个相连的棋子是同色,设置一个变量count,count就加1,当count变为5时候,就证明有五个同色棋子相连,游戏就结束,如果所下棋子是黑棋,黑棋就获胜,如果所下棋子是白棋,白棋就获胜。

下列代码是判定寻找各个方向的同色棋子的方法:

public int Win1(int xx,int yy) {//判定横向棋子是否有相连的int count1=0;for(int i=xx-1;i>=0;i--) {if(ChessArray[i][yy]==ChessArray[xx][yy]) {count1++;}else break;}for(int j=xx;j<ChessArray.length;j++) {if(ChessArray[j][yy]==ChessArray[xx][yy]) {count1++;}else break;}return count1;}public int Win2(int xx,int yy) {//判定纵向棋子是否有相连的int count2=0;for(int n=yy-1;n>=0;n--) {if(ChessArray[xx][n]==ChessArray[xx][yy]) {count2++;}else break;}for(int m=yy;m<ChessArray.length;m++) {if(ChessArray[xx][m]==ChessArray[xx][yy]) {count2++;}else break;}return count2;}public int Win3(int xx,int yy) {//判定左下右上棋子是否有相连的int count3=0;for(int o=xx-1,p=yy+1;o>=0&&p<ChessArray.length;o--,p++) {if(ChessArray[o][p]==ChessArray[xx][yy]) {count3++;}else break;}for(int o=xx,p=yy;o<ChessArray.length&&p>=0;o++,p--) {if(ChessArray[o][p]==ChessArray[xx][yy]) {count3++;}else break;}return count3;}public int Win4(int xx,int yy) {//判定左上右下棋子是否有相连的int count4=0;for(int o=xx-1,p=yy-1;o>=0&&p>=0;o--,p--) {if(ChessArray[o][p]==ChessArray[xx][yy]) {count4++;}else break;}for(int o=xx,p=yy;o<ChessArray.length&&p<ChessArray.length;o++,p++) {if(ChessArray[o][p]==ChessArray[xx][yy]) {count4++;}else break;}return count4;}

之后,在写完判定胜负方法后,我们需要在每次下棋后,去调用这些方法,判定是否获胜。也就是在绘制棋子这部分的代码片中,继续加上调用判定的方法代码。加上后,这部分的代码如下所示:

public class UIListener implements MouseListener ,ActionListener{//监听器是接口Graphics gr;int[][] ChessArray=new int[22][22];int[][] ChessValue=new int[22][22];JButton jb11;int nb=0;int count=0;int a,b,x,y,X,Y;JFrame mf;HashMap<String,Integer> hm=new HashMap<String,Integer>();public void mouseClicked(MouseEvent e) {//      int a,b,x,y,X,Y;int z=50,c=20;Color c1=new Color(0,0,0);Color c2=new Color(255,255,255);a=e.getX();b=e.getY();//获得鼠标点击坐标if(nb==1) {//确定是否可以下棋if((a-z)%c>c/2) {//帮助x轴上点击点优化到坐标格子上x=(a-z)/c+1;}else {x=(a-z)/c;}if((b-z)%c>c/2) {//帮助y轴上点击点优化到坐标格子上y=(b-z)/c+1;}else {y=(b-z)/c;}if(ChessArray[x][y]==0) {//确保棋子只能下在没有棋子的地方if(zifu.equals("人机对战")) {gr.setColor(c1);gr.fillOval(x*c+z-10, y*c+z-10, 20, 20);ChessArray[x][y]=1;gr.setColor(c2);AI();}else if(zifu.equals("人人对战")) {if(count==0) {gr.setColor(c1);count++;gr.fillOval(x*c+z-10, y*c+z-10, 20, 20);ChessArray[x][y]=1;//黑子数组值为1,方便重绘使用}else if(count==1) {gr.setColor(c2);count--;gr.fillOval(x*c+z-10, y*c+z-10, 20, 20);ChessArray[x][y]=2;//白子数组值为21,方便重绘使用}}}else{System.out.println("该位置已有棋子");}}else {System.out.println("请选择对战类型");}if(Win1(x,y)==5||Win2(x,y)==5||Win3(x,y)==5||Win4(x,y)==5) {//确定获胜标准if(ChessArray[x][y]==1) {nb=0;JOptionPane.showMessageDialog(null, "黑棋胜利");}else if(ChessArray[x][y]==2) {nb=0;JOptionPane.showMessageDialog(null, "白棋胜利");}}

当然这里要注意,这里判定的方法只能判定人人对战中的黑白棋子,以及人机对战中的玩家所下的黑色棋子,因为导入其中的x,y坐标是鼠标点击优化过来的,所以人机对战中电脑所下的白子不会调用这个方法,所以人机对战中的电脑白棋获胜判定我们会在电脑下棋方法AI中单独写一个。

人机方法

这里的电脑人机方法我们选择使用一种简单的方法,利用HashMap建立一个权值表,赋予不同棋盘情况不同的权值,然后让电脑选择在权值最大的地方下棋即可实现。

因为之前数组中我们将黑白棋分别赋值1,2,那么就可以根据此情况来设置权值表,可以如下图所示:

 //创建权值表hm.put("1", 10);hm.put("11", 100);hm.put("111", 5000);hm.put("1111", 8000);hm.put("12", 5);hm.put("112", 80);hm.put("1112", 3000);hm.put("11112", 10000);hm.put("21", 11);hm.put("211", 110);hm.put("2111", 1100);hm.put("21111", 11000);hm.put("2", 20);hm.put("22", 200);hm.put("222", 4500);hm.put("2222", 10000);hm.put("221", 100);hm.put("2221", 3000);hm.put("22221", 12000);hm.put("122", 5);hm.put("1222", 500);hm.put("12222", 10000);

之后,就同样是遍历棋盘,找到每一个空位置,然后以这个空位置为起点,去看每个方向上棋盘的情况,然后设置一个ChessValue[][]数组来存储每一个空位置的最终各个方向上棋盘情况的权值总和,那么权值最大的地方,就是电脑需要下棋的地方。

在电脑下棋之后,同样要调用我们之前写过的判定胜负的方法来进行判定,确保电脑和玩家每下一次棋子就可以进行一次判定。

完整的电脑下棋AI方法的代码如下:

 public void AI() {//人机对战,电脑怎么下棋判定//创建权值表hm.put("1", 10);hm.put("11", 100);hm.put("111", 5000);hm.put("1111", 8000);hm.put("12", 5);hm.put("112", 80);hm.put("1112", 3000);hm.put("11112", 10000);hm.put("21", 11);hm.put("211", 110);hm.put("2111", 1100);hm.put("21111", 11000);hm.put("2", 20);hm.put("22", 200);hm.put("222", 4500);hm.put("2222", 10000);hm.put("221", 100);hm.put("2221", 3000);hm.put("22221", 12000);hm.put("122", 5);hm.put("1222", 500);hm.put("12222", 10000);for(int i=0;i<ChessArray.length;i++) {for(int j=0;j<ChessArray[i].length;j++) {if(ChessArray[i][j]==0) {//判断是否有棋子String code="";int color=0;for(int k=i+1;k<ChessArray.length;k++) {//向右开始时遍历if(ChessArray[k][j]==0) {break;}else {if(color==0) {color=ChessArray[k][j];code+=ChessArray[k][j];}else if(color==ChessArray[k][j]) {code+=ChessArray[k][j];}else {code+=ChessArray[k][j];break;}}}Integer value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int k=i-1;k>0;k--) {//向左开始时遍历if(ChessArray[k][j]==0) {break;}else {if(color==0) {color=ChessArray[k][j];code+=ChessArray[k][j];}else if(color==ChessArray[k][j]) {code+=ChessArray[k][j];}else {code+=ChessArray[k][j];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int k=j-1;k>0;k--) {//向上开始时遍历if(ChessArray[i][k]==0) {break;}else {if(color==0) {color=ChessArray[i][k];code+=ChessArray[i][k];}else if(color==ChessArray[i][k]) {code+=ChessArray[i][k];}else {code+=ChessArray[i][k];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int k=j+1;k<ChessArray.length;k++) {//向下开始时遍历if(ChessArray[i][k]==0) {break;}else {if(color==0) {color=ChessArray[i][k];code+=ChessArray[i][k];}else if(color==ChessArray[i][k]) {code+=ChessArray[i][k];}else {code+=ChessArray[i][k];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int o=i-1,k=j-1;k>0&&o>0;k--,o--) {//向左上开始时遍历if(ChessArray[o][k]==0) {break;}else {if(color==0) {color=ChessArray[o][k];code+=ChessArray[o][k];}else if(color==ChessArray[o][k]) {code+=ChessArray[o][k];}else {code+=ChessArray[o][k];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int o=i+1,k=j-1;k>0&&o<ChessArray.length;k--,o++) {//向右上开始时遍历if(ChessArray[o][k]==0) {break;}else {if(color==0) {color=ChessArray[o][k];code+=ChessArray[o][k];}else if(color==ChessArray[o][k]) {code+=ChessArray[o][k];}else {code+=ChessArray[o][k];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int o=i+1,k=j+1;k<ChessArray.length&&o<ChessArray.length;k++,o++) {//向右下开始时遍历if(ChessArray[o][k]==0) {break;}else {if(color==0) {color=ChessArray[o][k];code+=ChessArray[o][k];}else if(color==ChessArray[o][k]) {code+=ChessArray[o][k];}else {code+=ChessArray[o][k];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int o=i-1,k=j+1;k<ChessArray.length&&o>0;k++,o--) {//向左下开始时遍历if(ChessArray[o][k]==0) {break;}else {if(color==0) {color=ChessArray[o][k];code+=ChessArray[o][k];}else if(color==ChessArray[o][k]) {code+=ChessArray[o][k];}else {code+=ChessArray[o][k];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}}}}//找到ChessValue中的最大值点让电脑下棋int max=0;int goalx = 0,goaly = 0;for(int i=0;i<ChessArray.length;i++) {for(int j=0;j<ChessArray.length;j++) {if(ChessValue[i][j]>max) {max=ChessValue[i][j];goalx=i;goaly=j;}}}if(max !=0) {gr.fillOval(goalx*20+50-10, goaly*20+50-10, 20, 20);ChessArray[goalx][goaly]=2;if(Win1(goalx,goaly)==5||Win2(goalx,goaly)==5||Win3(goalx,goaly)==5||Win4(goalx,goaly)==5) {//确定获胜标准{  nb=0;JOptionPane.showMessageDialog(null, "白棋胜利");}}}//清空权值for(int i=0;i<ChessArray.length;i++) {for(int j=0;j<ChessArray.length;j++) {ChessValue[i][j]=0;}}}

完整代码,以及悔棋、清空棋盘功能

这样基本就完成了一个简单的五子棋创作,当然其中还包含着一些悔棋功能,清空棋盘功能,这些功能也基本上都是利用重绘来实现的,具体的操作就不在讲述,完整代码中有写,自行理解即可。

整个五子棋分为三个大类,分别是窗体DrawUI类,监听器UIListener类,以及MyFrame类,每个类完整的代码如下所示:

DrawUI:

public class DrawUI
{public static void main(String args[]) {DrawUI drawui=new DrawUI();//设置对象drawui.ShowUI();//让对象运行创建窗体的方法}public void ShowUI() {MyFrame jf=new MyFrame();//创建窗体jf.setSize(500,500);jf.setLocationRelativeTo(null);//设置窗体属性jf.setTitle("五子棋");jf.setResizable(true);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);FlowLayout fl=new FlowLayout();//设置窗体格式jf.setLayout(fl);JButton jb=new JButton("人人对战");//添加按钮JButton jb1=new JButton("悔棋");JButton jb2=new JButton("清空棋盘");JButton jb3=new JButton("人机对战");jf.add(jb);jf.add(jb1);jf.add(jb2);jf.add(jb3);jf.setVisible(true);Graphics g=jf.getGraphics();//给窗体添加画笔UIListener ul=new UIListener();jb.addActionListener(ul);//给按钮添加监听器jb1.addActionListener(ul);jb2.addActionListener(ul);jb3.addActionListener(ul);jf.addMouseListener(ul);//给窗体添加监听器ul.gr=g;//将画笔倒给UIlistener中的gr
//      jf.ChessArray = ul.ChessArray;jf.ul=ul;//为了在Myframe中使用ChessArray,将UIistener中的ul倒给Myframe中的ulul.jb11=jb;//将按钮jb倒给ul中的jb11,方便其使用jbul.mf=jf;//为了在UIlistener中重绘,将jf倒给其中的mf}
}

UIListener:

public class UIListener implements MouseListener ,ActionListener{//监听器是接口Graphics gr;int[][] ChessArray=new int[22][22];int[][] ChessValue=new int[22][22];JButton jb11;int nb=0;int count=0;int a,b,x,y,X,Y;JFrame mf;String zifu;HashMap<String,Integer> hm=new HashMap<String,Integer>();public void mouseClicked(MouseEvent e) {//      int a,b,x,y,X,Y;int z=50,c=20;Color c1=new Color(0,0,0);Color c2=new Color(255,255,255);a=e.getX();b=e.getY();//获得鼠标点击坐标if(nb==1) {//确定是否可以下棋if((a-z)%c>c/2) {//帮助x轴上点击点优化到坐标格子上x=(a-z)/c+1;}else {x=(a-z)/c;}if((b-z)%c>c/2) {//帮助y轴上点击点优化到坐标格子上y=(b-z)/c+1;}else {y=(b-z)/c;}if(ChessArray[x][y]==0) {//确保棋子只能下在没有棋子的地方if(zifu.equals("人机对战")) {gr.setColor(c1);gr.fillOval(x*c+z-10, y*c+z-10, 20, 20);ChessArray[x][y]=1;gr.setColor(c2);AI();}else if(zifu.equals("人人对战")) {if(count==0) {gr.setColor(c1);count++;gr.fillOval(x*c+z-10, y*c+z-10, 20, 20);ChessArray[x][y]=1;//黑子数组值为1,方便重绘使用}else if(count==1) {gr.setColor(c2);count--;gr.fillOval(x*c+z-10, y*c+z-10, 20, 20);ChessArray[x][y]=2;//白子数组值为21,方便重绘使用}}}else{System.out.println("该位置已有棋子");}}else {System.out.println("请选择对战类型");}if(Win1(x,y)==5||Win2(x,y)==5||Win3(x,y)==5||Win4(x,y)==5) {//确定获胜标准if(ChessArray[x][y]==1) {nb=0;JOptionPane.showMessageDialog(null, "黑棋胜利");}else if(ChessArray[x][y]==2) {nb=0;JOptionPane.showMessageDialog(null, "白棋胜利");}}}public void AI() {//人机对战,电脑怎么下棋判定//创建权值表hm.put("1", 10);hm.put("11", 100);hm.put("111", 5000);hm.put("1111", 8000);hm.put("12", 5);hm.put("112", 80);hm.put("1112", 3000);hm.put("11112", 10000);hm.put("21", 11);hm.put("211", 110);hm.put("2111", 1100);hm.put("21111", 11000);hm.put("2", 20);hm.put("22", 200);hm.put("222", 4500);hm.put("2222", 10000);hm.put("221", 100);hm.put("2221", 3000);hm.put("22221", 12000);hm.put("122", 5);hm.put("1222", 500);hm.put("12222", 10000);for(int i=0;i<ChessArray.length;i++) {for(int j=0;j<ChessArray[i].length;j++) {if(ChessArray[i][j]==0) {//判断是否有棋子String code="";int color=0;for(int k=i+1;k<ChessArray.length;k++) {//向右开始时遍历if(ChessArray[k][j]==0) {break;}else {if(color==0) {color=ChessArray[k][j];code+=ChessArray[k][j];}else if(color==ChessArray[k][j]) {code+=ChessArray[k][j];}else {code+=ChessArray[k][j];break;}}}Integer value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int k=i-1;k>0;k--) {//向左开始时遍历if(ChessArray[k][j]==0) {break;}else {if(color==0) {color=ChessArray[k][j];code+=ChessArray[k][j];}else if(color==ChessArray[k][j]) {code+=ChessArray[k][j];}else {code+=ChessArray[k][j];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int k=j-1;k>0;k--) {//向上开始时遍历if(ChessArray[i][k]==0) {break;}else {if(color==0) {color=ChessArray[i][k];code+=ChessArray[i][k];}else if(color==ChessArray[i][k]) {code+=ChessArray[i][k];}else {code+=ChessArray[i][k];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int k=j+1;k<ChessArray.length;k++) {//向下开始时遍历if(ChessArray[i][k]==0) {break;}else {if(color==0) {color=ChessArray[i][k];code+=ChessArray[i][k];}else if(color==ChessArray[i][k]) {code+=ChessArray[i][k];}else {code+=ChessArray[i][k];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int o=i-1,k=j-1;k>0&&o>0;k--,o--) {//向左上开始时遍历if(ChessArray[o][k]==0) {break;}else {if(color==0) {color=ChessArray[o][k];code+=ChessArray[o][k];}else if(color==ChessArray[o][k]) {code+=ChessArray[o][k];}else {code+=ChessArray[o][k];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int o=i+1,k=j-1;k>0&&o<ChessArray.length;k--,o++) {//向右上开始时遍历if(ChessArray[o][k]==0) {break;}else {if(color==0) {color=ChessArray[o][k];code+=ChessArray[o][k];}else if(color==ChessArray[o][k]) {code+=ChessArray[o][k];}else {code+=ChessArray[o][k];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int o=i+1,k=j+1;k<ChessArray.length&&o<ChessArray.length;k++,o++) {//向右下开始时遍历if(ChessArray[o][k]==0) {break;}else {if(color==0) {color=ChessArray[o][k];code+=ChessArray[o][k];}else if(color==ChessArray[o][k]) {code+=ChessArray[o][k];}else {code+=ChessArray[o][k];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}code="";color=0;value=null;for(int o=i-1,k=j+1;k<ChessArray.length&&o>0;k++,o--) {//向左下开始时遍历if(ChessArray[o][k]==0) {break;}else {if(color==0) {color=ChessArray[o][k];code+=ChessArray[o][k];}else if(color==ChessArray[o][k]) {code+=ChessArray[o][k];}else {code+=ChessArray[o][k];break;}}}value=hm.get(code);if(value != null) {ChessValue[i][j]+=value;}}}}//找到ChessValue中的最大值点让电脑下棋int max=0;int goalx = 0,goaly = 0;for(int i=0;i<ChessArray.length;i++) {for(int j=0;j<ChessArray.length;j++) {if(ChessValue[i][j]>max) {max=ChessValue[i][j];goalx=i;goaly=j;}}}if(max !=0) {gr.fillOval(goalx*20+50-10, goaly*20+50-10, 20, 20);ChessArray[goalx][goaly]=2;if(Win1(goalx,goaly)==5||Win2(goalx,goaly)==5||Win3(goalx,goaly)==5||Win4(goalx,goaly)==5) {//确定获胜标准{  nb=0;JOptionPane.showMessageDialog(null, "白棋胜利");}}}}//清空权值for(int i=0;i<ChessArray.length;i++) {for(int j=0;j<ChessArray.length;j++) {ChessValue[i][j]=0;}}}//判定获胜的方法public int Win1(int xx,int yy) {//判定横向棋子是否有相连的int count1=0;for(int i=xx-1;i>=0;i--) {if(ChessArray[i][yy]==ChessArray[xx][yy]) {count1++;}else break;}for(int j=xx;j<ChessArray.length;j++) {if(ChessArray[j][yy]==ChessArray[xx][yy]) {count1++;}else break;}return count1;}public int Win2(int xx,int yy) {//判定纵向棋子是否有相连的int count2=0;for(int n=yy-1;n>=0;n--) {if(ChessArray[xx][n]==ChessArray[xx][yy]) {count2++;}else break;}for(int m=yy;m<ChessArray.length;m++) {if(ChessArray[xx][m]==ChessArray[xx][yy]) {count2++;}else break;}return count2;}public int Win3(int xx,int yy) {//判定左下右上棋子是否有相连的int count3=0;for(int o=xx-1,p=yy+1;o>=0&&p<ChessArray.length;o--,p++) {if(ChessArray[o][p]==ChessArray[xx][yy]) {count3++;}else break;}for(int o=xx,p=yy;o<ChessArray.length&&p>=0;o++,p--) {if(ChessArray[o][p]==ChessArray[xx][yy]) {count3++;}else break;}return count3;}public int Win4(int xx,int yy) {//判定左上右下棋子是否有相连的int count4=0;for(int o=xx-1,p=yy-1;o>=0&&p>=0;o--,p--) {if(ChessArray[o][p]==ChessArray[xx][yy]) {count4++;}else break;}for(int o=xx,p=yy;o<ChessArray.length&&p<ChessArray.length;o++,p++) {if(ChessArray[o][p]==ChessArray[xx][yy]) {count4++;}else break;}return count4;}public void Restart() {//重绘,删除之前的棋子,只保留棋盘for(int i=0;i<ChessArray.length;i++) {for(int j=0;j<ChessArray.length;j++) {if(ChessArray[i][j]==1||ChessArray[i][j]==2) {ChessArray[i][j]=0;}}}mf.repaint();}public void Hq() {//悔棋ChessArray[x][y]=0; mf.paint(gr);}public void mousePressed(MouseEvent e) {}public void mouseReleased(MouseEvent e) {}public void mouseEntered(MouseEvent e){}public void mouseExited(MouseEvent e) {}public void actionPerformed(ActionEvent e) {//按钮监听器执行一些操作if(jb11==e.getSource()) {nb=1;}zifu=e.getActionCommand();if(zifu.equals("清空棋盘")) {Restart();}if(zifu.equals("悔棋")) {Hq();}if(zifu.equals("人机对战")) {nb=1;}}
}

MyFrame:

public class MyFrame extends JFrame{//MyFrame子类继承JFrame父类public UIListener ul;
//  int[][] ChessArray;int z=50,c=20;public void paint(Graphics g) {//重绘棋盘,确保刷新网页时候,棋盘还在super.paint(g);int x1,x2,y1,y2;int X1,X2,Y1,Y2;x1=50;x2=450;y1=70;y2=470;X1=50;X2=450;Y1=70;Y2=470;for(int i=0; i<21; i++) {g.drawLine(x1,y1,x2,y1);y1=y1+20;}for(int i=0; i<21; i++) {g.drawLine(X1,Y1,X1,Y2);X1=X1+20;}int[][] ChessArray = ul.ChessArray;for(int i=0;i<ChessArray.length;i++) {//重绘棋子,网页刷新后,之前下过的棋子还在for(int j=0;j<ChessArray.length;j++) {if(ChessArray[i][j]==1) {g.setColor(Color.black);g.fillOval(i*c+z-10, j*c+z-10, 20, 20);}if(ChessArray[i][j]==2) {g.setColor(Color.white);g.fillOval(i*c+z-10, j*c+z-10, 20, 20);}}}}}

收获理解

五子棋这个小项目,在最开始的写的时候会遇到各种各样的问题,但随着不断学习钻研,很多东西都可以慢慢去掌握,例如:如何重绘,如何找最大值,如何设置棋子,如何在不同的类中去调用其他类的方法或者属性。能让自己更好的理解类与对象,属性,变量等一些基础知识,

实现五子棋的简单人人对战和人机对战的万字详细教程相关推荐

  1. Java 五子棋人人对战和人机对战简单实现

    废话不多说,咱直接进入正题 首先,为了方便,咱们先用一个Java接口把一些全局要用的数据写到接口里,这样就不用传来传去了 package wuziqi;public interface Gobang ...

  2. 五子棋程序设计(C语言、人机对战、禁手)

    五子棋程序设计(C语言.人机对战.禁手) 一.程序需求分析 1.1五子棋简介 五子棋是全国智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏. 五子棋有两种玩法.玩法一:双方分别使用黑白两色的棋 ...

  3. 21点双人对战和人机对战C++

    课题背景概述 21 点扑克是牌类游戏中的比较基础游戏,其基本打法为双人共玩一副洗好的 52 张牌(大小王拿走),采用回合制比每回合输赢,直至打完一副牌算总积分决出胜负. 每回合双方轮流拿牌,每人牌数 ...

  4. c语言五子棋源代码vc6,五子棋源码实验报告及人机对战说明.docx

    1. 五子棋对战说明 2. 实验报告 3. 源代码 五 子 棋 作品特点:C 语言程序 五子棋 作品功能:五子棋人机对战,人人对战. 目录:1 五子棋介绍. 五子棋棋型介绍. 人人对战的实现. 电脑下 ...

  5. 【C语言五子棋、三子棋人机对战篇的详细介绍】

    C语言--五子棋.井字棋人机对"战" 针对 "[C语言实现五子棋.三子棋人机对战,包含电脑人工智能对战(可攻可守)](非标题党)" 的详细介绍 五子棋.三子棋人 ...

  6. 完全自制的五子棋人机对战游戏(VC++实现)

    五子棋工作文档 1说明: 这个程序在创建初期的时候是有一个写的比较乱的文档的,但是很可惜回学校的时候没有带回来--所以现在赶紧整理一下,不然再过一段时间就忘干净了. 最初这个程序是受老同学所托做的,一 ...

  7. 介绍一款Android小游戏--交互式人机对战五子棋

    学习Android系统开发之余,编写了一个小游戏--交互式人机对战五子棋,自娱自乐.之所以称之为交互式人机对战五子棋,一是因为在进入人机对战模式这前,你可以任意设置好开局,同时,在对战过程中,你可以看 ...

  8. 五子棋(含较高级的人机对战)

    五子棋(含较高级的人机对战算法) 这是我自己做的五子棋,含有人人对战,人机对战模式,还有悔棋.保存棋局功能. 只要还没有输棋,就可以无限制悔棋. 可以将未下完的棋局保存下来,下次接着下. 五子棋人机对 ...

  9. 【C语言实现五子棋、三子棋人机对战,包含电脑人工智能对战(可攻可守)】(非标题党)

    C语言--五子棋.井字棋人机对"战" 针对C语言学习过程中的五子棋.三子棋实现记录 五子棋人机对战 C语言--五子棋.井字棋人机对"战" 实际效果 一.头文件( ...

最新文章

  1. 一文剖析2020年最火十大物联网应用|IoT Analytics 年度重磅报告出炉!
  2. BZOJ 3211 弗洛拉前往国家 树阵+并检查集合
  3. win7关闭开机启动项_电脑开机全是各种广告?来看看我怎么解决的吧
  4. OC中runtime的使用
  5. 使用ajax+php+mysql实现数据库定时刷新
  6. 简历上的“熟练掌握 RPC”,到底是个什么水平?
  7. 利用缓冲流读取跟写入
  8. c# mysql 连接
  9. 人工智能学习资料之2021图灵大会笔记
  10. 7-16 新浪微博热门话题 (30 分)
  11. OSPF的DR/BDR的选举规则,数据包,接口网络
  12. AI换脸技术再创新高度,DeepMind发布VQ-VAE二代算法
  13. 阿里云python自测答案_阿里云技能测试python初级中级高级
  14. 右键菜单,下拉选项的截屏
  15. 软考中级-结构化开发
  16. 禁道具和连携击败姜世离的两种战术
  17. 实现移动端不同屏幕适配
  18. 摩托罗拉v8能玩java_拯救湿水V8大行动!小伟玩机之:摩托罗拉V8拆解
  19. 植发搞笑图片_植发失败案例实录!历时几个月却迎来头发尽毁,后果太可怕了...
  20. nvm切换node nvm use 17.2.0 exit status 5: �ܾ����ʡ� exit status 1: ���ļ��Ѵ���ʱ���޷��������ļ���

热门文章

  1. Linux---挂载移动硬盘文件系统修复
  2. 64g的u盘只有58g_为啥我买的64G U盘实际只有57G?聊聊存储市场的“不足量”现象...
  3. rtl8139网卡驱动源码解析
  4. 在Mac下安装XAMPP
  5. 信息系统项目管理师核心考点(四十六)采购工作说明书(SOW)
  6. ubuntu使用sudo su进入root报错Cannot execute /bin/csh: No such file or directory解决方法
  7. 你只管粘贴。复制我帮你解决
  8. 剪枝简述(模型压缩加速篇)
  9. 重磅发布!2022大数据十大关键词
  10. 干净实用:装机必备绿色软件集锦