五子棋,是我们大家都喜爱玩的智力棋类游戏,在学完了界面以及绘图之后便一直想做一个,如今终于如愿以偿,虽然还没有更好的美化该游戏,但是大局已定。高兴!
五子棋我们需要很多常量,比如说棋子的大小,棋盘格子的间距,棋盘行列的其实位置。所以我们需要首先定义一个借口来存储这些常量,以便我们能更好的使用它,以及更快捷的改变其值的大小。
package com.czh130708; public interface Config { public static final int x=45; public static final int y=45;//x,y的起始位置 public static final int row=15; public static final int columns=15; public static final int csize=30; public static final int size=45; public static final int[][] chess = new int[row][columns]; }
其次我们要定义一个棋盘界面,该界面类继承了JFrame。在该类中我们获取了画布,实例化了鼠标事件对象。重写了paint方法,并在该方法中调用了画棋盘的方法,以及棋子和棋盘的重绘方法。
package com.czh130708; import java.awt.Color; import java.awt.Graphics; import javax.swing.JFrame; public class MyDraw extends JFrame{ Graphics g; public static void main(String [] args){ MyDraw dl = new MyDraw(); dl.initUI(); } private void initUI() { this.setName("五子棋"); this.setSize(1100,730);//设置窗口大小 this.setDefaultCloseOperation(3); this.setLocation(00,00);//设置窗口位置 this.setVisible(true); this.g=this.getGraphics(); ChessL cl=new ChessL(g); this.addMouseListener(cl); } public void paint(Graphics g){ //调用父类的重绘方法 super.paint(g); drawChessTable(g); draw(g); } public void drawChessTable(Graphics g){ //绘制棋盘 super.paint(g); //绘制15条横线 for(int i=0;i<Config.row;i++) g.drawLine(Config.x, Config.y+Config.size*i,Config.row*Config.size,Config.y+Config.size*i); //绘制15条竖线 for(int j=0;j<Config.columns;j++) g.drawLine(Config.x+Config.size*j, Config.y,Config.x+Config.size*j,Config.columns*Config.size); } //棋子重绘的方法 public void draw(Graphics g){ for(int i=0;i<Config.chess.length;i++){ //数组的每一个元素其实是一个一维数组 for(int j=0;j<Config.chess[i].length;j++){ if(Config.chess[i][j]==1){ //如果是黑子,就为1 g.setColor(Color.black); g.fillOval(Config.x+Config.size*i-Config.size/2, Config.y+Config.size*j-Config.size/2, Config.size, Config.size); }else if(Config.chess[i][j]==-1){ //如果是白子,就是-1 g.setColor(Color.WHITE); g.fillOval(Config.x+Config.size*i-Config.size/2, Config.y+Config.size*j-Config.size/2, Config.size, Config.size); } } } } }
五子棋游戏的重中之重我觉得就是两个人交互下棋的方法定义。
首先我们要获得鼠标事件发生时,所得到的位置,并循环遍历棋盘,得到该位置最接近的横纵直线的焦点位置,并在该位置上画上一颗棋子。
当下第二颗棋子时,颜色不能与上一颗一样,并且切记已经下过棋子的地方不能再次下棋,所以我们需要一个数组来记住所有下过棋子的地方,并且给该位置设置一个权值,该权值会记住该位置下的是黑棋还是白旗。
判定胜负方式也是重点。因为我们需要判断横向斜向纵向每一条线上是否有五颗棋子相连,若有五颗棋子相连则提示胜出!
在棋子重绘的方法中我们也会用到数组。
五子棋的代码实现如下!
package com.czh130708; import java.awt.Color; import java.awt.Graphics; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JOptionPane; public class ChessL extends MouseAdapter { private Graphics g; private int c=0;//计数器 public ChessL(Graphics g) { this.g=g; } //定义一个鼠标监听器 public void mouseReleased(MouseEvent e){ int x1 = e.getX(); int y1 = e.getY(); for(int i=0;i<Config.columns;i++){ for(int j=0;j<Config.row;j++){ if(Config.chess[i][j] == 0){ int x=Config.x+Config.size*i;//横坐标 int y=Config.y+Config.size*j;//纵坐标 //与圆心的误差为三分之一size/3 if(x1>x-Config.size/3 && x1 < x+Config.size/3 && y1>y-Config.size/3 && y1<y+Config.size/3){ if(c == 0){ Config.chess[i][j]=1;//如果是黑子,就为1 g.setColor(Color.black); c++; }else{ Config.chess[i][j]=-1;//如果是白子,就是-1 g.setColor(Color.WHITE); c--; } //以交叉点为圆心画圆 g.fillOval(x-Config.size/2, y-Config.size/2, Config.size, Config.size); this.checkrow(i,j); this.checkcolumns(i,j); this.checkrowc(i,j); this.checkrcolumns(i,j); } } } } } //检查横向是否有五子相连向右 public int checkrow(int x,int y){ int count=0; for(int i=x;i<Config.row;i++){ if(Config.chess[i][y]==Config.chess[x][y]){ count++; } else{ break; } } //向左 for(int i=x-1;i>=0;i--){ if(Config.chess[i][y]==Config.chess[x][y]){ count++; } else{ break; } } if(count>=5){ JOptionPane.showMessageDialog(null, "大神,你胜利了"); } return count; } //检查纵向是否有五子相连 public int checkcolumns(int x,int y){ int count=0; for(int i=y;i<Config.columns;i++){ if(Config.chess[x][i]==Config.chess[x][y]){ count++; } else{ break; } } for(int i=y-1;i>=0;i--){ if(Config.chess[x][i]==Config.chess[x][y]){ count++; } else{ break; } } if(count>=5){ JOptionPane.showMessageDialog(null, "大神,你胜利了"); } return count; } //斜向方向是否有棋子 public int checkrowc(int x,int y){ int count=0; for(int i=x,j=y;i<Config.row&&j<Config.columns;i++,j++){ if(Config.chess[x][y]==Config.chess[i][j]){ count++; } else{ break; }} for(int i=x-1,j=y-1;i>=0&&j>=0;i--,j--){ if(Config.chess[x][y]==Config.chess[i][j]){ count++; } else{ break; }} if(count>=5){ JOptionPane.showMessageDialog(null, "大神,你胜利了"); } return count; } public int checkrcolumns(int x,int y){ int count=0; for(int i=x,j=y;i<Config.row&&j>=0;i++,j--){ if(Config.chess[x][y]==Config.chess[i][j]){ count++;} else{ break; }} for(int i=x-1,j=y+1;i>=0&&j<Config.columns;i--,j++){ if(Config.chess[x][y]==Config.chess[i][j]){ count++; } else{ break; }} if(count>=5){ JOptionPane.showMessageDialog(null, "大神,你胜利了"); } return count; } }