Java实现简易五子棋小游戏
本文实例为大家分享了Java实现简易五子棋小游戏的具体代码,供大家参考,具体内容如下
五子棋是一个简单小游戏,首先我们先想想五子棋都有什么东西,棋子,棋盘;
首先我们可以定义一个棋子类,棋子类里有棋子的坐标,半径和颜色;还有棋子的构造函数;
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; } }
接下来我们定义一个主框架,在主框架里有面板对象和三个按钮对象,分别是重新开始游戏按钮,悔棋按钮和退出游戏按钮;还设置一个按钮事件类,用来监听三个按钮,并作出相应的动作;
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);//设置为可见 } }
最后一个类是棋盘类,我们要对棋盘的边距,网格的距离进行赋值,设定棋盘的初始状态,如默认黑子先下,定义一个棋子类数组,来保存棋子对象,再定义一个字符串二维数组函数来保存的颜色,用来判断输赢,用匿名内部类来处理当棋子在面板上移动时的一些状态;
代码如下:
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"; } } }
我们再对下棋时鼠标按下时的动作事件类进行解析,当在网格上下棋时,判断是否在棋盘内和判断网格上有没有棋子,当棋子在棋盘内并且网格上没有棋子,我们就开始画棋子,将棋子对象和颜色保存,接下来判断是否胜利,判断棋盘是否下满,如果没有继续下棋;
代码如下;
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来对棋盘和棋子进行画图,对棋子进行绘图时,将最后一个棋子设为红色;
代码如下;
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 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; }
最后我就将完整的棋盘类代码贴出来,写五子棋代码时参考了很多其他人的想法,有相同的请不要见怪;
棋盘类完整代码如下:
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/880665
相关文章
- 这篇文章主要介绍了如何利用java语言实现经典《复杂迷宫》游戏,文中采用了swing技术进行了界面化处理,感兴趣的小伙伴可以动手试一试...2022-02-01
java 运行报错has been compiled by a more recent version of the Java Runtime
java 运行报错has been compiled by a more recent version of the Java Runtime (class file version 54.0)...2021-04-01- 这篇文章主要介绍了在java中获取List集合中最大的日期时间操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
- 这篇文章主要介绍了教你怎么用Java获取国家法定节假日,文中有非常详细的代码示例,对正在学习java的小伙伴们有非常好的帮助,需要的朋友可以参考下...2021-04-23
- 这篇文章主要介绍了Java如何发起http请求的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-31
- 说起C#和Java这两门语言(语法,数据类型 等),个人以为,大概有90%以上的相似,甚至可以认为几乎一样。但是在工作中,我也发现了一些细微的差别...2020-06-25
- 这篇文章主要介绍了解决Java处理HTTP请求超时的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-29
- 这篇文章主要介绍了java 判断两个时间段是否重叠的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
- 这篇文章主要介绍了超简洁java实现双色球若干注随机号码生成(实例代码),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-04-02
- 这篇文章主要介绍了Java生成随机姓名、性别和年龄的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-10-01
java 画pdf用itext调整表格宽度、自定义各个列宽的方法
这篇文章主要介绍了java 画pdf用itext调整表格宽度、自定义各个列宽的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-31- 这篇文章主要介绍了java正则表达式判断前端参数修改表中另一个字段的值,需要的朋友可以参考下...2021-05-07
Java使用ScriptEngine动态执行代码(附Java几种动态执行代码比较)
这篇文章主要介绍了Java使用ScriptEngine动态执行代码,并且分享Java几种动态执行代码比较,需要的朋友可以参考下...2021-04-15- 这篇文章主要介绍了Java开发实现人机猜拳游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-03
- 这篇文章主要介绍了Java List集合返回值去掉中括号('[ ]')的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-29
Java中lombok的@Builder注解的解析与简单使用详解
这篇文章主要介绍了Java中lombok的@Builder注解的解析与简单使用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-01-06- 下面小编就为大家带来一篇java中String类型变量的赋值问题介绍。小编觉得挺不错的。现在分享给大家,给大家一个参考。...2016-03-28
Java 8 Stream 的终极技巧——Collectors 功能与操作方法详解
这篇文章主要介绍了Java 8 Stream Collectors 功能与操作方法,结合实例形式详细分析了Java 8 Stream Collectors 功能、操作方法及相关注意事项,需要的朋友可以参考下...2020-05-20- 这篇文章主要介绍了Java线程池中的各个参数如何合理设置操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-06-19
- 在Java中,我们可以利用多线程来最大化地压榨CPU多核计算的能力,下面这篇文章主要给大家介绍了关于java中多线程与线程池基本使用的相关资料,需要的朋友可以参考下...2021-09-13