Java Swing实现扫雷源码
作者:掉队洋先生 发布时间:2023-11-10 08:16:20
标签:Java,Swing,扫雷
本文实例为大家分享了Java Swing实现扫雷源码的具体代码,供大家参考,具体内容如下
先来看下效果
运行时只需要创建一个GameWindow的对象即可,可使用有参构造函数自定义雷区行列数及 * 个数,也可使用无参构造函数设置默认值(小旗和 * 的图标自己去找吧,我就不在这里放了)
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.LinkedList;
public class GameWindow{
private static Font labelFont = new Font("隶书",Font.BOLD,45);
private static Font buttonFont = new Font("隶书",Font.CENTER_BASELINE,20);
private static Icon flag = new ImageIcon("src/images/小旗.jpg");//小旗图标
private static Icon bomb = new ImageIcon("src/images/ * .png");// * 图标
private static int labelWeight = 30;//小方块(雷区)宽度
private static int labelHeigth = 30;//小方块(雷区)高度
private static int labelSpace = 1;//小方块(雷区)间距
private static int scoreHeight = 50;//积分区域高度
private static int[] x8 = {-1,-1,-1,0,0,1,1,1};//原坐标周围 8 个坐标的 x 值变化
private static int[] y8 = {-1,0,1,-1,1,-1,0,1};//原坐标周围 8 个坐标的 y 值变化
private static int[] x4 = {0,0,1,-1};//原坐标周围 4 个坐标的 x 值变化
private static int[] y4 = {1,-1,0,0};//原坐标周围 4 个坐标的 x 值变化
private JFrame frame;
private int[][] data;//存储和 * 位置有关数据,值为-1时表示 *
private JLabel[][] labels;
private JPanel mainPanel;//雷区主面板
private JPanel scorePanel;//积分区域面板
private JLabel areaLabel;//未扫雷区个数标签
private JLabel bombLabel;//剩余地雷数标签
private int width;//窗体宽度
private int height;//窗体高度
private int row;//行数
private int column;//列数
private int bombNum;// * 个数
private int remainArea;//未扫雷区个数
private int remainBomb;//剩余地雷数
public GameWindow(int row,int column,int bombNum){
frame = new JFrame("扫雷-洋仔小游戏");
this.row = row;
this.column = column;
this.bombNum = bombNum;
mainPanel = new JPanel();
init();
}
public GameWindow(){
this(10,10,20);
}
private void setWidthAndHeight(){
width = labelWeight * column + (column + 1) * labelSpace;
height = scoreHeight + labelHeigth * row + (row + 1) * labelSpace;
}
private void setBomb(){
if(bombNum > row * column)
throw new RuntimeException(" * 数设置过多!");
data = new int[row][column];
int count = 0;
while (count < bombNum){
int r = (int)(Math.random() * row);
int c = (int)(Math.random() * column);
System.out.println("r = " + r + "\tc = " + c);
if(data[r][c] == -1)
continue;
data[r][c] = -1;
for(int i = 0; i < 8; i ++){
int x = r + x8[i];
int y = c + y8[i];
if(x < 0 || x >= row || y < 0 || y >= column || data[x][y] == -1)
continue;
data[r + x8[i]][c + y8[i]] ++;
}
count ++;
System.out.println(count);
}
}
private class ButtonListener extends MouseAdapter {
private JButton button;
private int r;
private int w;
private GameWindow window;
private boolean disabled = true;
public ButtonListener(JButton button,int r,int w,GameWindow window){
this.button = button;
this.r = r;
this.w = w;
this.window = window;
}
@Override
public void mouseClicked(MouseEvent mouseEvent) {
synchronized (window){
if(!button.isEnabled())
return;
if(mouseEvent.getButton() == MouseEvent.BUTTON3){
if(disabled) {
button.setIcon(flag);
data[r][w] -= 20;
remainBomb --;
remainArea --;
}
else {
button.setIcon(null);
data[r][w] += 20;
remainBomb ++;
remainArea ++;
}
disabled = !disabled;
bombLabel.setText("" + remainBomb);
areaLabel.setText("" + remainArea);
return;
}
if(!disabled)
return;
int cnt = 1;
button.setVisible(false);
if(data[r][w] == -1){
gameOver();
// System.out.println("\n点到 * ,全体按钮已禁用");
return;
}
LinkedList<int[]> stack = new LinkedList<>();
stack.push(new int[]{r,w});
data[r][w] = -1;
while (stack.size() > 0){
int[] source = stack.pop();
for(int i = 0; i < 4; i ++){
int x = source[0] + x4[i];
int y = source[1] + y4[i];
if(x < 0 || x >= row || y < 0 || y >= column || data[x][y] < 0)
continue;
if(data[x][y] == 0)
stack.push(new int[]{x,y});
labels[x][y].getLabelFor().setVisible(false);
cnt ++;
data[x][y] = -1;
}
}
remainArea -= cnt;
areaLabel.setText("" + remainArea);
if(remainArea == remainBomb){
gameOver();
}
}
}
}
private void gameOver(){
for(JLabel[] ls : labels){
for(JLabel l : ls){
JButton button = (JButton) l.getLabelFor();
button.setEnabled(false);
}
}
}
private void init(){
setWidthAndHeight();
frame.setBounds(380,100,width + 9,height + 32);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLayout(null);
mainPanel.setBackground(Color.GRAY);
mainPanel.setBounds(1,scoreHeight + 1,width,height);
mainPanel.setLayout(null);
scorePanel = new JPanel();
scorePanel.setBounds(0,0,width,scoreHeight);
scorePanel.setLayout(new GridLayout(1,3,0,0));
areaLabel = new JLabel();
areaLabel.setFont(labelFont);
areaLabel.setHorizontalAlignment(JLabel.CENTER);
scorePanel.add(areaLabel);
JLabel buttonLabel = new JLabel();
scorePanel.add(buttonLabel);
JButton resetButton = new JButton("重开");
resetButton.setFont(buttonFont);
resetButton.setFocusPainted(false);
resetButton.setBounds(width/ 24,10,width / 4,30);
resetButton.addActionListener((event)->{
frame.setVisible(false);
mainPanel.removeAll();
resetGame();
});
buttonLabel.add(resetButton);
bombLabel = new JLabel();
bombLabel.setFont(labelFont);
bombLabel.setHorizontalAlignment(JLabel.CENTER);
scorePanel.add(bombLabel);
frame.add(scorePanel);
frame.add(mainPanel);
resetGame();
}
public void resetGame(){
setBomb();
remainArea = row * column;
remainBomb = bombNum;
labels = new JLabel[row][column];
System.gc();
for(int i = 0; i < row; i ++){
for(int j = 0; j < column; j ++){
labels[i][j] = new JLabel();
//设置元素居中
labels[i][j].setHorizontalAlignment(JLabel.CENTER);
if(data[i][j] == -1) {
labels[i][j].setIcon(bomb);
}
else if(data[i][j] > 0)
labels[i][j].setText("" + data[i][j]);
int y = (i + 1) * labelSpace + i * labelWeight;
int x = (j + 1) * labelSpace + j * labelHeigth;
labels[i][j].setBounds(x,y,labelWeight,labelHeigth);
JButton button = new JButton();
button.addMouseListener(new ButtonListener(button,i,j,this));
button.setBounds(0,0,labelWeight,labelHeigth);
labels[i][j].setLayout(null);
labels[i][j].add(button);
labels[i][j].setLabelFor(button);
mainPanel.add(labels[i][j]);
}
}
areaLabel.setText("" + remainArea);
bombLabel.setText("" + remainBomb);
frame.setVisible(true);
}
}
来源:https://blog.csdn.net/qq_46121425/article/details/122775637


猜你喜欢
- 本文实例为大家分享了Android Scroller的使用方法,供大家参考,具体内容如下1、scrollTo和ScrollByView类定义
- Java中四种访问权限总结一、Java中有四种访问权限, 其中三种有访问权限修饰符,分别为private、public、prot
- 一,网络编程中两个主要的问题一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输。在TCP/IP协议中I
- mybatis 3 | 参考文档MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几
- /// <summary>/// 获取本机在局域网的IP地址/// </summary>/// <return
- 有的时候,我们需要对一堆数据进行统计分析后生成HTML或Excel格式报表。本来这并不是一件很难的事,但确是件比较麻烦的事情。最令人头痛的是
- 本文实例讲述了Android编程使用WebView实现文件下载功能的两种方法。分享给大家供大家参考,具体如下:在应用中,通常会使用到文件下载
- Android canvas drawBitmap方法详解及实例之前自己在自定义view,用到canvas.drawBitmap
- APP中可能会遇到一种需求,就是将当前所在位置的坐标传到服务器上,今天我提供三种途径去获取经纬度坐标信息,第一种是通过Android API
- 半路开始看的朋友可以回顾一下前几篇java并发编程专题(一)----线程基础知识java并发编程专题(二)----如何创建并运行java线程
- scheduleAtFixedRate(task,time,period)task-所要安排的任务 time-首次执行任务的时间 perio
- PPT中的动画效果可分为已有内置动画以及自定义动画。设置内置动画,只需直接指定动画效果类型即可。本文主要介绍如何实现自定义动画,即自定义形状
- 1,验证传入路径是否为正确的路径名(Windows系统,其他系统未使用)Java代码 // 验证字符串是否为正确路径名的正则表达式 
- TCPTCP协议是面向连接、保证高可靠性(数据无丢失、数据无失序、数据无错误、数据无重复到达)传输层协议。TCP通过三次握手建立连接,通讯完
- 专业的Android app开发人员会关注一些成熟的项目管理技术,以成功构建Android app,并让这个app在Google Play
- 获取手机唯一标识 拼接的方式获取手机唯一标识第一种方式是获取IMEI,但是有的手机如果不是正品的话,就获取不到所以通过这一种方式还是会出现有
- 背景Springboot 默认把异常的处理集中到一个ModelAndView中了,但项目的实际过程中,这样做,并不能满足我们的要求。具体的自
- Java调用Oracle存储过程详解步骤:1、编写Oracle存储过程2、编写数据库获取连接工具类3、编写简单应用调用存储过程实现:1、Or
- 效果图片重写DataGridView的OnRowPostPaint方法或者直接在DataGridView的RowPostPaint事件里写,
- 一、前言前面我们介绍了运算符的一部分运算符,现在我们把剩余的他介绍完全来二、运算符赋值运算符所谓赋值,就是一个等于号连接的两个如int a=