本文实例为大家分享了Java实现简易五子棋小游戏的具体代码,供大家参考,具体内容如下
五子棋 是一个简单小游戏,首先我们先想想五子棋都有什么东西,棋子,棋盘;
首先我们可以定义一个棋子类,棋子类里有棋子的坐标,半径和颜色;还有棋子的构造函数;
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 |
import java.awt.Color; /* * 棋子类 */ public class Chess { private int x; //棋子的x坐标索引 private int y; //棋子的y坐标索引 private Color color; //棋子颜色 public static int DIAMETER= 30 ; //直径 public Chess( int x, int y,Color color){ //棋子构造函数 this .x=x; this .y=y; this .color=color; } public int getX() { return x; } public int getY() { return y; } public Color getColor() { return color; }
} |
接下来我们定义一个主框架,在主框架里有面板对象和三个按钮对象,分别是重新开始游戏按钮,悔棋按钮和退出游戏按钮;还设置一个按钮事件类,用来监听三个按钮,并作出相应的动作;
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 |
import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;
import javax.swing.*; /* * 五子棋主框架 */ public class ChessJFrame extends JFrame { private ChessBord chessbord; //声明一个棋盘对象 private Panel tool; //声明一个面板对象 private Button StartButton; //声明开始按钮 private Button BackButton; //声明悔棋按钮 private Button exitButton; //声明退出按钮 public ChessJFrame() { //构造函数 setTitle( "单机版五子棋" ); //设置标题 MyButtonLister mb= new MyButtonLister(); //按钮事件处理对象 tool= new Panel(); //面板对象 chessbord= new ChessBord(); //棋盘对象 StartButton= new Button( "重新开始" ); //设置开始按钮 BackButton= new Button( "悔棋" ); //设置悔棋按钮 exitButton= new Button( "退出游戏" ); //设置退出游戏按钮 tool.setLayout( new FlowLayout(FlowLayout.CENTER )); //流式布局 tool.add(StartButton); tool.add(BackButton); tool.add(exitButton); //将三个按钮添加到面板对象 StartButton.addActionListener(mb); BackButton.addActionListener(mb); exitButton.addActionListener(mb); //将三个按钮添加到事件监听 add(tool,BorderLayout.SOUTH); //按钮所在的位置 add(chessbord); //添加棋盘对象 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置关闭 pack(); //自适应
} private class MyButtonLister implements ActionListener{ //按钮处理事件类 @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub Object obj=e.getSource(); //获取事件源 if (obj==StartButton) { //事件源是重新开始按钮 System.out.println( "重新开始" ); chessbord.restartGame(); } else if (obj==BackButton) { //事件源是悔棋按钮 System.out.println( "悔棋!" ); chessbord.goback(); } else if (obj==exitButton) { //事件源是退出按钮 System.exit( 0 ); } }
}
public static void main(String[] args) { ChessJFrame jf= new ChessJFrame(); //声明框架对象 jf.setLocationRelativeTo( null ); //居中显示 jf.setVisible( true ); //设置为可见 }
} |
最后一个类是棋盘类,我们要对棋盘的边距,网格的距离进行赋值,设定棋盘的初始状态,如默认黑子先下,定义一个棋子类数组,来保存棋子对象,再定义一个字符串二维数组函数来保存的颜色,用来判断输赢,用匿名内部类来处理当棋子在面板上移动时的一些状态;
代码如下:
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 |
public static int MARGIN= 30 ; //定义边距 public static int ROWS= 15 ; //定义行数 public static int COLS= 15 ; //定义列数 public static int GRID_SPAN= 35 ; //网格间距 Chess[] chessList= new Chess[(ROWS+ 1 )*(COLS+ 1 )]; //定义一个棋子数组 String[][] board= new String[MARGIN* 2 +GRID_SPAN*COLS][MARGIN* 2 +GRID_SPAN*COLS]; //声明一个字符串数组,用来判断输赢 int chessCount; //棋子数目 int xindex,yindex; //棋子的坐标索引 boolean start= true ; //开始默认黑子先下 boolean GameOver= false ; //定义是否游戏结束 public ChessBord() { //棋盘类构造函数 setBackground(Color.LIGHT_GRAY); //设置背景颜色 addMouseListener( this ); //将棋盘类添加到鼠标事件监听器 addMouseMotionListener( new MouseMotionListener() { //匿名内部类
@Override public void mouseMoved(MouseEvent e) { //根据鼠标的移动所在的坐标来设置鼠标光标形状 int x1=(e.getX()-MARGIN+GRID_SPAN/ 2 )/GRID_SPAN; //对鼠标光标的x坐标进行转换 int y1=(e.getY()-MARGIN+GRID_SPAN/ 2 )/GRID_SPAN; //对鼠标光标的y坐标进行转换 if (x1< 0 ||x1>ROWS||y1< 0 ||y1>COLS||GameOver||findchess(x1, y1)) { setCursor( new Cursor(Cursor.DEFAULT_CURSOR)); //设置鼠标光标为默认形状 } else { setCursor( new Cursor(Cursor.HAND_CURSOR)); //设置鼠标光标为手型 }
} @Override public void mouseDragged(MouseEvent e) {
} }); for ( int i= 0 ;i<MARGIN* 2 +GRID_SPAN*COLS;i++) { //对board[][]赋初值 for ( int j = 0 ; j < MARGIN* 2 +GRID_SPAN*COLS; j++) { board[i][j]= "0" ; } } } |
我们再对下棋时鼠标按下时的动作事件类进行解析,当在网格上下棋时,判断是否在棋盘内和判断网格上有没有棋子,当棋子在棋盘内并且网格上没有棋子,我们就开始画棋子,将棋子对象和颜色保存,接下来判断是否胜利,判断棋盘是否下满,如果没有继续下棋;
代码如下;
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 |
public void mousePressed(MouseEvent e) { //鼠标点击事件 if (GameOver) //游戏结束,不能按 return ; String colorName=start? "黑棋" : "白棋" ; //判断是什么颜色的棋子 xindex=(e.getX()-MARGIN+GRID_SPAN/ 2 )/GRID_SPAN; //得到棋子x坐标 yindex=(e.getY()-MARGIN+GRID_SPAN/ 2 )/GRID_SPAN; //得到棋子y坐标 board[xindex][yindex]=colorName; //以棋子x坐标y坐标做索引将棋子的颜色添加到board中 if (xindex< 0 ||xindex>ROWS||yindex< 0 ||yindex>COLS) { //棋子在棋盘外不能下, return ; } else if (findchess( xindex, yindex)) { //所下位置已有棋子,不能下 return ; } Chess po= new Chess(xindex,yindex,start?Color.black:Color.WHITE); //对棋子对象进行初始化 chessList[chessCount++]=po; //将棋子对象添加到棋子数组中 repaint(); //重画图型 if (win( xindex,yindex,start)) { //判断是否胜利 String msg=String.format( "恭喜 %s赢了" ,colorName); JOptionPane.showMessageDialog( this , msg); //gameOver=true; GameOver= true ; } else if (chessCount==(COLS+ 1 )*(ROWS+ 1 )) { //判断是否全部下满 String msg=String.format( "恭喜 %s赢了" ,colorName); JOptionPane.showMessageDialog( this , msg); GameOver= true ; } start=!start; //改变棋子先下棋状态 } |
函数paintComponent来对棋盘和棋子进行画图,对棋子进行绘图时,将最后一个棋子设为红色;
代码如下;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
protected void paintComponent(Graphics g) { //画棋盘和棋子 super .paintComponent(g); for ( int i= 0 ;i<=ROWS;i++) { //画横线 g.drawLine(MARGIN, MARGIN+i*GRID_SPAN, MARGIN+COLS*GRID_SPAN, MARGIN+i*GRID_SPAN); } for ( int j= 0 ;j<=COLS;j++) { //画竖线 g.drawLine(MARGIN+j*GRID_SPAN, MARGIN, MARGIN+j*GRID_SPAN, MARGIN+ROWS*GRID_SPAN); } for ( int i= 0 ;i<chessCount;i++) { //画棋子 int xpos=chessList[i].getX()*GRID_SPAN+MARGIN; //得到棋子x坐标 int ypos=chessList[i].getY()*GRID_SPAN+MARGIN; //得到棋子y坐标 g.setColor(chessList[i].getColor()); //设置棋子颜色 g.fillOval(xpos-Chess.DIAMETER/ 2 , ypos-Chess.DIAMETER/ 2 , Chess.DIAMETER, Chess.DIAMETER); //画棋子 if (i==chessCount- 1 ){ g.setColor(Color.red); //标记最后一个棋子为红色 g.drawRect(xpos-Chess.DIAMETER/ 2 , ypos-Chess.DIAMETER/ 2 , Chess.DIAMETER, Chess.DIAMETER); } }
} |
最后就是判断棋子输赢的函数,用字符串数组保存的棋子的颜色来进行判断所在行和列有没有五个棋子相连,判断撇和捺行的棋子有没有五个相连的,如果有则某位棋子胜利;
代码如下;
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 |
private boolean win( int x, int y, boolean start) { //对棋子输赢的判断 String str=start? "黑棋" : "白棋" ; //棋子所在行和列是否有五子相连的情况 for ( int i= 0 ;i< 16 ;i++){ if ((board[x][i].equals(str)&&board[x][i+ 1 ].equals(str)&&board[x][i+ 2 ].equals(str)&&board[x][i+ 3 ].equals(str)&&board[x][i+ 4 ].equals(str))||(board[i][y].equals(str)&&board[i+ 1 ][y].equals(str)&&board[i+ 2 ][y].equals(str)&&board[i+ 3 ][y].equals(str)&&board[i+ 4 ][y].equals(str))) return true ; } //棋子所在撇行是否有五子相连的情况 if (x+y>= 4 &&x+y<= 30 ){ int i=(x+y<= 19 )?x+y:x+y- 20 ; if (x+y<= 19 ){ for ( int k= 0 ;k<=i- 4 ;k++){ if (board[k][i-k].equals(str)&&board[k+ 1 ][i-k- 1 ].equals(str)&&board[k+ 2 ][i-k- 2 ].equals(str)&&board[k+ 3 ][i-k- 3 ].equals(str)&&board[k+ 4 ][i-k- 4 ].equals(str)) return true ; } } else { for ( int k=i;k<= 15 ;k++){ if (board[k][ 20 -k].equals(str)&&board[k+ 1 ][ 20 -k- 1 ].equals(str)&&board[k+ 2 ][ 20 -k- 2 ].equals(str)&&board[k+ 3 ][ 20 -k- 3 ].equals(str)&&board[k+ 4 ][ 20 -k- 4 ].equals(str)) return true ; } } } //棋子所在捺行是否有五子相连的情况 if (y-x<= 15 &&x-y<= 15 ){ int i=(x<y)?y-x:x-y; if (x<y){ for ( int k= 0 ;k<= 19 - 4 -i;k++){ if (board[k][i+k].equals(str)&&board[k+ 1 ][i+k+ 1 ].equals(str)&&board[k+ 2 ][i+k+ 2 ].equals(str)&&board[k+ 3 ][i+k+ 3 ].equals(str)&&board[k+ 4 ][i+k+ 4 ].equals(str)) return true ; } } else { for ( int k=i;k<= 15 ;k++){ if (board[k][i+k].equals(str)&&board[k+ 1 ][i+k+ 1 ].equals(str)&&board[k+ 2 ][i+k+ 2 ].equals(str)&&board[k+ 3 ][i+k+ 3 ].equals(str)&&board[k+ 4 ][i+k+ 4 ].equals(str)) return true ; } } } return false ;
} |
最后我就将完整的棋盘类代码贴出来,写五子棋代码时参考了很多其他人的想法,有相同的请不要见怪;
棋盘类完整代码如下:
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 |
import java.awt.*; import java.awt.event.*;
import javax.swing.*; /* * 五子棋的棋盘类 */
public class ChessBord extends JPanel implements MouseListener{ //继承面板类和鼠标事件接口 public static int MARGIN= 30 ; //定义边距 public static int ROWS= 15 ; //定义行数 public static int COLS= 15 ; //定义列数 public static int GRID_SPAN= 35 ; //网格间距 Chess[] chessList= new Chess[(ROWS+ 1 )*(COLS+ 1 )]; //定义一个棋子数组 String[][] board= new String[MARGIN* 2 +GRID_SPAN*COLS][MARGIN* 2 +GRID_SPAN*COLS]; //声明一个字符串数组,用来判断输赢 int chessCount; //棋子数目 int xindex,yindex; //棋子的坐标索引 boolean start= true ; //开始默认黑子先下 boolean GameOver= false ; //定义是否游戏结束 public ChessBord() { //棋盘类构造函数 setBackground(Color.LIGHT_GRAY); //设置背景颜色 addMouseListener( this ); //将棋盘类添加到鼠标事件监听器 addMouseMotionListener( new MouseMotionListener() { //匿名内部类
@Override public void mouseMoved(MouseEvent e) { //根据鼠标的移动所在的坐标来设置鼠标光标形状 int x1=(e.getX()-MARGIN+GRID_SPAN/ 2 )/GRID_SPAN; //对鼠标光标的x坐标进行转换 int y1=(e.getY()-MARGIN+GRID_SPAN/ 2 )/GRID_SPAN; //对鼠标光标的y坐标进行转换 if (x1< 0 ||x1>ROWS||y1< 0 ||y1>COLS||GameOver||findchess(x1, y1)) { setCursor( new Cursor(Cursor.DEFAULT_CURSOR)); //设置鼠标光标为默认形状 } else { setCursor( new Cursor(Cursor.HAND_CURSOR)); //设置鼠标光标为手型 }
} @Override public void mouseDragged(MouseEvent e) {
} }); for ( int i= 0 ;i<MARGIN* 2 +GRID_SPAN*COLS;i++) { //对board[][]赋初值 for ( int j = 0 ; j < MARGIN* 2 +GRID_SPAN*COLS; j++) { board[i][j]= "0" ; } } }
@Override public void mouseClicked(MouseEvent e) { // TODO Auto-generated method stub
}
@Override public void mousePressed(MouseEvent e) { //鼠标点击事件 if (GameOver) //游戏结束,不能按 return ; String colorName=start? "黑棋" : "白棋" ; //判断是什么颜色的棋子 xindex=(e.getX()-MARGIN+GRID_SPAN/ 2 )/GRID_SPAN; //得到棋子x坐标 yindex=(e.getY()-MARGIN+GRID_SPAN/ 2 )/GRID_SPAN; //得到棋子y坐标 board[xindex][yindex]=colorName; //以棋子x坐标y坐标做索引将棋子的颜色添加到board中 if (xindex< 0 ||xindex>ROWS||yindex< 0 ||yindex>COLS) { //棋子在棋盘外不能下, return ; } else if (findchess( xindex, yindex)) { //所下位置已有棋子,不能下 return ; } Chess po= new Chess(xindex,yindex,start?Color.black:Color.WHITE); //对棋子对象进行初始化 chessList[chessCount++]=po; //将棋子对象添加到棋子数组中 repaint(); //重画图型 if (win( xindex,yindex,start)) { //判断是否胜利 String msg=String.format( "恭喜 %s赢了" ,colorName); JOptionPane.showMessageDialog( this , msg); //gameOver=true; GameOver= true ; } else if (chessCount==(COLS+ 1 )*(ROWS+ 1 )) { //判断是否全部下满 String msg=String.format( "恭喜 %s赢了" ,colorName); JOptionPane.showMessageDialog( this , msg); GameOver= true ; } start=!start; //改变棋子先下棋状态 }
@Override public void mouseReleased(MouseEvent e) {
}
@Override public void mouseEntered(MouseEvent e) {
}
@Override public void mouseExited(MouseEvent e) {
}
@Override protected void paintComponent(Graphics g) { //画棋盘和棋子 super .paintComponent(g); for ( int i= 0 ;i<=ROWS;i++) { //画横线 g.drawLine(MARGIN, MARGIN+i*GRID_SPAN, MARGIN+COLS*GRID_SPAN, MARGIN+i*GRID_SPAN); } for ( int j= 0 ;j<=COLS;j++) { //画竖线 g.drawLine(MARGIN+j*GRID_SPAN, MARGIN, MARGIN+j*GRID_SPAN, MARGIN+ROWS*GRID_SPAN); } for ( int i= 0 ;i<chessCount;i++) { //画棋子 int xpos=chessList[i].getX()*GRID_SPAN+MARGIN; //得到棋子x坐标 int ypos=chessList[i].getY()*GRID_SPAN+MARGIN; //得到棋子y坐标 g.setColor(chessList[i].getColor()); //设置棋子颜色 g.fillOval(xpos-Chess.DIAMETER/ 2 , ypos-Chess.DIAMETER/ 2 , Chess.DIAMETER, Chess.DIAMETER); //画棋子 if (i==chessCount- 1 ){ g.setColor(Color.red); //标记最后一个棋子为红色 g.drawRect(xpos-Chess.DIAMETER/ 2 , ypos-Chess.DIAMETER/ 2 , Chess.DIAMETER, Chess.DIAMETER); } }
} private boolean findchess( int index, int yindex) { //查找所在位置是否有棋子 for (Chess c : chessList) { if (c!= null &&c.getX()==xindex&&c.getY()==yindex) return true ; } return false ; } private boolean win( int x, int y, boolean start) { //对棋子输赢的判断 String str=start? "黑棋" : "白棋" ; //棋子所在行和列是否有五子相连的情况 for ( int i= 0 ;i< 16 ;i++){ if ((board[x][i].equals(str)&&board[x][i+ 1 ].equals(str)&&board[x][i+ 2 ].equals(str)&&board[x][i+ 3 ].equals(str)&&board[x][i+ 4 ].equals(str))||(board[i][y].equals(str)&&board[i+ 1 ][y].equals(str)&&board[i+ 2 ][y].equals(str)&&board[i+ 3 ][y].equals(str)&&board[i+ 4 ][y].equals(str))) return true ; } //棋子所在撇行是否有五子相连的情况 if (x+y>= 4 &&x+y<= 30 ){ int i=(x+y<= 19 )?x+y:x+y- 20 ; if (x+y<= 19 ){ for ( int k= 0 ;k<=i- 4 ;k++){ if (board[k][i-k].equals(str)&&board[k+ 1 ][i-k- 1 ].equals(str)&&board[k+ 2 ][i-k- 2 ].equals(str)&&board[k+ 3 ][i-k- 3 ].equals(str)&&board[k+ 4 ][i-k- 4 ].equals(str)) return true ; } } else { for ( int k=i;k<= 15 ;k++){ if (board[k][ 20 -k].equals(str)&&board[k+ 1 ][ 20 -k- 1 ].equals(str)&&board[k+ 2 ][ 20 -k- 2 ].equals(str)&&board[k+ 3 ][ 20 -k- 3 ].equals(str)&&board[k+ 4 ][ 20 -k- 4 ].equals(str)) return true ; } } } //棋子所在捺行是否有五子相连的情况 if (y-x<= 15 &&x-y<= 15 ){ int i=(x<y)?y-x:x-y; if (x<y){ for ( int k= 0 ;k<= 19 - 4 -i;k++){ if (board[k][i+k].equals(str)&&board[k+ 1 ][i+k+ 1 ].equals(str)&&board[k+ 2 ][i+k+ 2 ].equals(str)&&board[k+ 3 ][i+k+ 3 ].equals(str)&&board[k+ 4 ][i+k+ 4 ].equals(str)) return true ; } } else { for ( int k=i;k<= 15 ;k++){ if (board[k][i+k].equals(str)&&board[k+ 1 ][i+k+ 1 ].equals(str)&&board[k+ 2 ][i+k+ 2 ].equals(str)&&board[k+ 3 ][i+k+ 3 ].equals(str)&&board[k+ 4 ][i+k+ 4 ].equals(str)) return true ; } } } return false ;
} public void goback() { //悔棋函数 if (chessCount== 0 ) { return ; } chessList[chessCount- 1 ]= null ; chessCount--; if (chessCount> 0 ) { xindex=chessList[chessCount- 1 ].getX(); yindex=chessList[chessCount- 1 ].getY(); } start=!start; repaint(); } public void restartGame() { //重新开始函数 for ( int i= 0 ;i<chessList.length;i++) //设置为初始状态 chessList[i]= null ; for ( int i= 0 ;i<MARGIN* 2 +GRID_SPAN*COLS;i++) { for ( int j = 0 ; j < MARGIN* 2 +GRID_SPAN*COLS; j++) { board[i][j]= "0" ; } } start= true ; GameOver= false ; chessCount= 0 ; repaint(); }
public Dimension getPreferredSize(){ //画矩形 return new Dimension(MARGIN* 2 +GRID_SPAN*COLS,MARGIN* 2 +GRID_SPAN*ROWS); }
} |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
原文链接:https://blog.csdn.net/weixin_41946004/article/details/88066504