其实五子棋呢主要包括三部分:五子棋棋盘和下棋子等关于Swing界面的应用;然后就是计算输赢的算法;最后就是人机对战的人工智能。刚刚开始做的时候是老老实实的画的棋盘,通过后来的学习知道了其实棋盘是可以找合适的棋盘图片粘贴的,目前还没找到想要的。。。。。。画棋盘就是一个循环画线的过程:
//画格子的方法 private void drawchessbosrd(java.awt.Graphics g){ //设置线条颜色 g.setColor(java.awt.Color.BLACK); //循环画横线 for(int i=0;i<Config.H_LINE;i++){ g.drawLine(Config.X, Config.Y+i*Config.SIZE, Config.X+(Config.S_LINE-1)*Config.SIZE, Config.Y+i*Config.SIZE); } //循环画竖线 for(int i=0;i<Config.S_LINE;i++){ g.drawLine(Config.X+i*Config.SIZE, Config.Y, Config.X+i*Config.SIZE, Config.Y+(Config.S_LINE-1)*Config.SIZE); } }
现在呢,棋盘有了,我们就需要在鼠标点击的格子交叉处下棋子,刚开始的棋子也是在窗体上得到一个画板然后画一个实心圆......后来学会了在那交叉点上画一个棋子的图片,图片怎么看上去也比一个平面圆有立体感啊!画图片的之前当然的计算出交叉点的坐标,这样才能在离点击的最近的地方画图片:
//点击鼠标得到坐标 int x1=e.getX(); int y1=e.getY(); //计算离鼠标点击地点最近的一个交叉点 if((x1-Config.X)%Config.SIZE<Config.SIZE/2){ j=(x1-Config.X)/Config.SIZE; }else if((x1-Config.X)%Config.SIZE>Config.SIZE/2){ j=(x1-Config.X)/Config.SIZE+1; }else{ j=(x1-Config.X-Config.SIZE/2)/Config.SIZE; } if((y1-Config.Y)%Config.SIZE<Config.SIZE/2){ i=(y1-Config.Y)/Config.SIZE; }else if((y1-Config.Y)%Config.SIZE>Config.SIZE/2){ i=(y1-Config.Y)/Config.SIZE+1; }else{ i=(y1-Config.Y-Config.SIZE/2)/Config.SIZE; } //开始下棋子,只能在没有下棋子的地方下 if(data[i][j]==0){ if(count==1){//在交叉点下黑子 //在交叉点画一个圆 URL url=this.getClass().getResource("b.png"); //根据url创建图片对象 ImageIcon imageb=new ImageIcon(url); g.drawImage(imageb.getImage(),(Config.X + j * Config.SIZE) - Config.CHESS/ 2, (Config.Y + i * Config.SIZE)- Config.CHESS / 2, Config.CHESS, Config.CHESS,back); count++; } }else{//在交叉点下白子 //在交叉点画一个圆 URL url=this.getClass().getResource("w.png"); //根据url创建图片对象 ImageIcon imagew=new ImageIcon(url); g.drawImage(imagew.getImage(),(Config.X + j * Config.SIZE) - Config.CHESS/ 2, (Config.Y + i * Config.SIZE)- Config.CHESS / 2, Config.CHESS, Config.CHESS,back); count--; } } }
现在呢,棋子画上去了,我们就要判断一下输赢了。判断输赢的条件就是五子连珠,一颗棋子周围大家都知道有八个方向,所以呢就要向八个方向判断一下是否有相同的棋子,如果有就继续判断,一直到某个方向上有五颗相同的棋子,让程序输出一下输赢了就ok咯。判断输赢的方法大致都是一样的:
public boolean horizontalWin(int r,int c) { //定义一个计数器,默认等于,当前下的棋子 int count = 1; boolean state = false; //循环遍历数组,此处是遍历当前行的每一个单元格,现在是往右边判断 for(int j=c+1;j<chesses[r].length;j++){ //判断当前数组中的元素是否想等 if(chesses[r][j] == chesses[r][c]) //相等计数器加1 count++; //不相等,则退出循环 else break; } //循环遍历数组,此处是遍历当前行的每一个单元格,现在是往左边判断 for(int j=c-1;j>0;j--){ //判断当前数组中的元素是否想等 if(chesses[r][j] == chesses[r][c]) //相等计数器加1 count++; //不相等,则退出循环 else break; } //如果统计的数据大于4,就表示已经五颗相同颜色的棋子连在一起了,表示已经赢了 if(count > 4) //状态修改为true. state = true; //} //返回状态 return state; }
不同的是每个方向的循环方式不一样而已,当有五颗棋子连珠的时候,就可以显示输赢了,显示之后当然要清空棋盘:
if(win.erectWin(i,j)||win.horizontalWin(i, j)||win.leftObliqueWin(i, j)||win.rightObliqueWin(i, j)){ javax.swing.JOptionPane.showMessageDialog(null, "黑子赢了(*^__^*) " ); for(int i=0;i<data.length;i++){ for(int j=0;j<data[i].length;j++){ data[i][j]=0; } } paint(g); }
然而这时的五子棋还有很多不完善,比如:重绘等等,所以我们在下棋子的时候一定要用一个东西来保存当前棋子的信息,这个东西可以是二维数组,也可以是自定义队列,有了保存棋子的东西,那么重绘也就很简单了。如果我们想保存某一局棋局的时候,就需要用到文件保存了,吧当前棋局的所有信息存入一个文件中,读取的按照信息进行重绘:
public void savefile(int[][] data) { //保存的文件名 String filename="src\\cn\\tan\\lesson6\\chess"; try { //新建输出流对象 FileWriter fw = new FileWriter(filename); //循环输出数据 for(int i=0;i<data.length;i++){ for(int j=0;j<data[i].length;j++){ fw.write(data[i][j]+"\t"); } fw.write("\r\n"); } //强制写入并关闭流对象 fw.flush(); fw.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
打开文件时的方法:
open.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { String command=e.getActionCommand(); if(command.equals("打开文件")){ String s = ""; //读取文件文件名 String fielname="src\\cn\\tan\\lesson6\\chess"; try { //新建输入流对象 FileReader fr=new FileReader(fielname); BufferedReader br=new BufferedReader(fr); int [][] set=new int[12][12]; for(int i=0;i<set.length;i++){ s=br.readLine(); String value[]=s.split("\t"); // paint(g); for(int j=0;j<set.length;j++){ //得到第i行j列的元素值 int m=Integer.parseInt(value[j]); data[i][j]=m; if(m==1){ //设置颜色 g.setColor(java.awt.Color.WHITE); //画棋子 URL url=this.getClass().getResource("w.png"); //根据url创建图片对象 ImageIcon imagew=new ImageIcon(url); g.drawImage(imagew.getImage(),(Config.X + j * Config.SIZE) - Config.CHESS/ 2, (Config.Y + i * Config.SIZE)- Config.CHESS / 2, Config.CHESS, Config.CHESS,back); } if(m==2){ //设置颜色 // g.setColor(java.awt.Color.BLACK); //画棋子 URL url=this.getClass().getResource("b.png"); //根据url创建图片对象 ImageIcon imageb=new ImageIcon(url); g.drawImage(imageb.getImage(),(Config.X + j * Config.SIZE) - Config.CHESS/ 2, (Config.Y + i * Config.SIZE)- Config.CHESS / 2, Config.CHESS, Config.CHESS,back); } } } fr.close(); br.close(); } catch (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } } } });
当然还有其他的比如重新开始、悔棋等功能就不再一一列举代码咯......至于人机对战仍在思索ing