开发五子棋小游戏2.0
📅 2026/7/27 6:38:23
👁️ 阅读次数
📝 编程学习
目录
效果展示
1、游戏界面
2、弹窗功能展示
功能改进
关键知识点
1】final关键字
2】将鼠标获取的坐标转化为行列值
3】保存已落的棋子实现不重复落子
代码展示
Data接口
MyFrame类继承JFrame类
Chess类
GoBangListener类实现MouseListener监听器
GoBangUI类
缺陷与不足
效果展示
1、游戏界面
2、弹窗功能展示
在正确区域落子
避免重复落子
功能改进
1、添加图片作为背景
2、创建接口定义行为规范,并使用final关键字修饰变量
3、结合变量思想优化设计棋盘的代码
4、解决无法固定在交叉点落子的问题
5、解决在区域外落子的问题
6、解决重复落子的问题
关键知识点
1】final关键字
final是最终的意思,可以修饰类、方法、变量
1)修饰类:该类被称为最终类,特点是不能被继承了
2)修饰方法:该类被称为最终方法,特点是不能再重写了
3)修饰变量:该变量只能赋值一次
2】将鼠标获取的坐标转化为行列值
先统一已知条件:
- 棋盘起点像素:(X,Y)
- 相邻交叉点像素间距:SIZE
- c:列号;r:行号
- 鼠标像素 (x,y)
- (px,py):交叉点像素坐标
若只需让整数向下取整,c = (x-X)/SIZE
推导:
第 r 行、第 c 列交叉点像素坐标公式(正向映射,绘图用):
{ px = X + c × SIZE
{py = Y + r × SIZE
现在需求: 已知鼠标像素 (x,y),求整数行列 c、r。
反向运算即可
而五子棋要求就近取整(即四舍五入),c = (x-X+SIZE/2)/SIZE
3】保存已落的棋子实现不重复落子
为了实现不重复落子,我们需要保存已落棋子的信息,并在每次落子前进行检查。以下是具体的实现步骤:
- 创建棋子类:创建一个类(如
Chess),设置三个属性:行(row)、列(col)、颜色(color)。 - 创建存储数组:在外部创建一个数组,数组的类型就是你创建的棋子类,用于存储所有已落棋子的信息。
- 落子时保存数据:在落子成功时,创建一个棋子对象,将当前棋子的行、列、颜色数据保存到对象中,然后将该对象存入数组中。
- 落子前检查重复:在落子前,得到行列值之后,先在数组中查找一遍是否有相同行列值的对象存在:
- 如果存在相同的行列值,说明该位置已有棋子,不能重复落子,直接
return或给出提示。 - 如果不存在,则允许落子,并执行后续的落子逻辑。
- 如果存在相同的行列值,说明该位置已有棋子,不能重复落子,直接
代码展示
Data接口
public interface Data { // interface 接口中的变量都是默认常量 并且可以使用接口名直接调用 // 任何一个类都可以实现多个接口 ,类实现接口之后,接口中定义的数据常量都可以直接使用 // 任何类都只能继承一个类 // final 修饰的变量必须初始化赋值 ,之后不能修改值 - 常量 final int X=50,Y=50,SIZE=40,ROW=15,COL=15; }MyFrame类继承JFrame类
import javax.swing.*; import java.awt.*; public class MyFrame2 extends JFrame implements Data{ @Override public void paint(Graphics g) { super.paint(g); //设置背景图片 ImageIcon img = new ImageIcon("D:\\谢智宁\\其他\\编程入门\\图片素材\\3865cd33e305922fcebd3c28aa422396 (1).jpeg"); g.drawImage(img.getImage(),0,0,900,900,null); //绘制棋盘图 Color col = new Color(246, 149, 56); g.setColor(col); g.fillRect(X-SIZE/2,Y-SIZE/2,COL*SIZE,ROW*SIZE); //画线 Color col1 = new Color(0,0,0); g.setColor(col1); for(int i=0;i<COL;i++){ g.drawLine(X,Y+i*SIZE,X+(COL-1)*SIZE,Y+i*SIZE); g.drawLine(X+i*SIZE,Y,X+i*SIZE,Y+(ROW-1)*SIZE); } //画点 g.setColor(Color.black); g.fillOval(X+3*SIZE-5,Y+3*SIZE-5,10,10); g.fillOval(X+11*SIZE-5,Y+11*SIZE-5,10,10); g.fillOval(X+3*SIZE-5,Y+11*SIZE-5,10,10); g.fillOval(X+11*SIZE-5,Y+3*SIZE-5,10,10); g.fillOval(X+7*SIZE-5,Y+7*SIZE-5,10,10); } }Chess类
import java.awt.*; public class Chess { int row; int col; Color color; }GoBangListener类实现MouseListener监听器
import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import static xzn0723.Data.*; public class GoBangListener2 implements MouseListener { Graphics g; int chessColor = 1; int size = 0; //创建一个数组存储棋子的位置、颜色 Chess[] cs = new Chess[225]; public void mouseClicked(MouseEvent e) { } public void mousePressed(MouseEvent e){ } public void mouseReleased(MouseEvent e){ //获取鼠标释放处的坐标值 int x = e.getX(); int y = e.getY(); //将坐标值通过算法转化为行列值 int c = (x-X+SIZE/2)/SIZE; int r = (y-Y+SIZE/2)/SIZE; //判断落子是否越界 if(x<X-SIZE/2||c>=COL||y<Y-SIZE/2||r>=ROW||c<0||r<0){ JOptionPane.showMessageDialog(null,"该区域无法落子!"); return; } //将行列值还原成坐标 int cx = c*SIZE+X; int ry = r*SIZE+Y; boolean a = false; for(int i=0;i<size;i++){ if(cs[i].col == c&&cs[i].row == r){ a = true; break; } } if(a==true){ JOptionPane.showMessageDialog(null,"无法重复落子!"); return; } //创建棋类对象,将棋子存储到数组中 Chess CS = new Chess(); CS.row = r; CS.col = c; cs[size]= CS; size++; //交替落子 if(chessColor == 1){ g.setColor(Color.black); chessColor = 2; }else if(chessColor == 2){ g.setColor(Color.white); chessColor = 1; } //绘制棋子 g.fillOval(cx-SIZE/2,ry-SIZE/2,SIZE,SIZE); } public void mouseEntered(MouseEvent e){ } public void mouseExited(MouseEvent e){ } }GoBangUI类
import java.awt.*; public class GoBangUI2 { public void showUI(){ MyFrame2 myFrame = new MyFrame2(); myFrame.setTitle("五子棋2.0"); myFrame.setSize(850,800); myFrame.setDefaultCloseOperation(3); myFrame.setLocationRelativeTo(null); myFrame.setPreferredSize(null); myFrame.setVisible(true); //将鼠标监听器绑定在窗体上 GoBangListener2 gbl = new GoBangListener2(); myFrame.addMouseListener(gbl); gbl.g = myFrame.getGraphics();//将窗体中的画笔的地址传给监听器中成员变量g,使得该变量也可以使用画笔的方法 } static void main() { GoBangUI2 gbui = new GoBangUI2(); gbui.showUI(); } }缺陷与不足
- 窗口拖动、被遮挡、最小化之后,所有棋子全部消失。
- 无法实现悔棋功能
- 无法自动判断输赢
下篇博客,我来改进上述不足之处~
编程学习
技术分享
实战经验