【数据结构课设】扫雷 (java实现)

目录

一、问题描述

二、逻辑结构设计

三、存储结构设计

三、主要操作设计

四、技术难点与解决方法

五、实现与展示

六、详细代码

七、游戏内图片


一、问题描述

设计实现经典扫雷游戏,要求如下:

(1) 分初级、中级和高级三个级别,扫雷英雄榜存储每个级别的最好成绩,即挖出所有地雷

且用时最少者。

(2) 选择级别后出现相对应级别的扫雷区域,用户使用鼠标左键单击雷区中任一方块便启动

计时器。

(3) 单击方块,若所揭方块下有雷,则 Game Over;若所揭方块下无雷,则显示一个数字,

该数字代表方块周围 8 个方块中共有多少颗雷。如果数字为 0,则程序自动揭开方块周

围方块,直到找到非 0 数字的方块。

(4) 用户可以右键单击标记雷,无论用户标记是否正确,程序都将显示剩余雷数少一。

(5) 胜利后,用时少于排行榜最末成绩,则弹窗提示保存成绩

[测试数据]

参照原版设计:win7 或者 winXP 系统下自带扫雷游戏,或者扫雷游戏网页版 -

Minesweeper

[实现提示]

可能用到数组、排序、递归等。

二、逻辑结构设计

 图2.1扫雷操作流程图

  首先GameStart类中进行程序,调用MineSweeping的构造方法来绘制窗口与基本组件,然后在MineSweeping类中调用GamePanel来绘制雷区,绘制雷区时用了两层for循环遍历,并用if方法判断地雷是否被埋在重复的位置。绘制完毕后便可以开始游戏。

  用户点击任意格子后会先进行判断,若为雷,游戏失败。若为数字,不会翻开周围的格子。若为空,则会递归调用翻开周围3*3的格子。

  若游戏失败,则结束游戏,用户可以点击顶部的笑脸重新开始游戏。若胜利,则输入名称,并生成一个Hero对象存入到ArrayList当中,排序并显示英雄榜。

三、存储结构设计

  该课程设计的类主要包含两个大部分。一个是绘制扫雷地图与组件的类,另一个是存储获胜用户信息的类。在绘制扫雷地图中,包括GamePanel、GameUtils、MineSweeping类等。在存储用户信息及英雄榜排名中,包括Hero、HeroDialog。

 图3.1绘制地图uml类图

  (1)GameStart是整个游戏开始的入口,从这里开始运行程序。

  (2)其中GameUtils存储了绘制扫雷地图时所需要的变量,比如地图的宽、高,地的偏移量、地雷的数量等。并将这些变量全部设置为静态变量,以此能在不同类中很好的调用。

  (3) GamePanel绘制雷区的部分,利用randomBomb()和writeNumber()来随机生成地雷与数字,open()与subOpen()来绘制地雷翻开的动作。因为雷区是一个矩阵,因此将地雷与按钮存储到一个二维数组当中,同时在此类中判断游戏是否胜利。

 (4)MineSweeping绘制了地图其他组件,将笑脸,倒计时,剩余雷数以及排行榜添加到窗口当中。并对调用GamePanel类,将扫雷地图进行组装,最后实现出扫雷的效果。

 图3.2 排行榜制作uml类图

  (5)当用户在VistoryDialog中输入名称后,用Hero类来new一个对象,因为考虑到后续的插入操作,在这里使用数组的效率会更高一些,因此将这些对象存入到ArrayList当中

三、主要操作设计

  扫雷窗口与雷区生成后,顶部有三个按钮,分别是难度选择,重新开始游戏以及查看排行榜。在游戏进行的任何时候都可以进行难度选择,或是重新开始游戏。用户点击任意格子后会先进行判断,若为雷或数字,不会翻开周围的格子。若为空,则会递归调用翻开周围3*3的格子。数字代表周围3*3的地区有N个雷。若点到雷,游戏失败,若将除了雷以外的其他格子都翻开的话,则游戏成功。输入名称,显示排行榜。

四、技术难点与解决方法

技术难点:

①扫雷时翻开的操作比较难以实现,其一是要判断点开格子下面是否可以继续翻开其他周围的格子,其二是要如何实现翻开其周围的格子

②计时操作难以实现,其要求每秒都要改变秒数。其次在每次重新开局以及选择难度后倒计时都要重置,这一点也难以实现。

解决方法:

①首先用一个if语句进行判断,如果格子下面是数字或地雷的话,则不用继续翻开周围的格子。若格子下面为空,则利用递归算法遍历其周围3*3的格子,若还为空,则继续调用遍历。

②计时操作必须根据用户点下去的一瞬间开始计时。在这里必须要让计时操作与主程序分开开来,因此使用到了Java里面的多线程操作,将计时放到与主程序不一样的线程里面进行操作。这样就可以使计时操作与主程序同步进行。同时在Open()添加一个boolean类型的变量,记录按钮是否被点击,如果被点击,则开始计时。

五、实现与展示

图5.1游戏主要界面

游戏开始的主界面,顶部菜单显示五个部分,分别为计时、难度选择、重新开始按键、排行榜查看以及剩余雷(旗子)数显示。

图5.2难度选择

难度选择可以切换到不同的难度界面。初级是标准的9*9一共10个雷,中级是标准的16*16一共140个雷,高级是标准的16*40一共99个雷

图5.3中级与高级界面

图5.4游戏成功与失败展示

当游戏成功时,会跳出一个对话框,要求用户输入姓名。输入姓名后点击确定会录入到英雄榜当中,并进行排名显示英雄榜。当游戏失败时,点击确定按钮后可以选择顶部笑脸按钮以重新开始游戏。

​​​​​​​

 

图5.5游戏排行榜展示

排行榜会显示用户的昵称以及扫雷所花费的时间,并按照升序从上到下依次排列。

六、详细代码

public class GameStart {

    public static void main(String[] args) {
        /*
        GameStart是整个游戏开始的入口,从这里开始运行程序。
         */
        new MineSweeping();//调用MineSweeping绘制窗口框架与基本组件
    }
}
import javax.swing.*;

public class Btn extends JButton {
    public int i,j;
}


import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.*;
import java.awt.event.MouseEvent;

public class GamePanel extends JPanel {

    /*
    GamePanel绘制雷区的部分,利用randomBomb()和writeNumber()来随机生成地雷与数字,
    open()与subOpen()来绘制地雷翻开的动作。因为雷区是一个矩阵,因此将地雷与按钮存储到一个二维数组当中,同时在此类中判断游戏是否胜利。
     */

    int count = 0;

    public GamePanel() {
        GameUtils.NUM_FLAGS = GameUtils.NUM_MINES;
        GameUtils.label = new JLabel[GameUtils.MAP_H][GameUtils.MAP_W];  // 用于存储图案
        GameUtils.isBomb = new boolean[GameUtils.MAP_H][GameUtils.MAP_W];  // 用于存储是否有地雷(true-有地雷,false-没有地雷)
        GameUtils.buttons = new Btn[GameUtils.MAP_H][GameUtils.MAP_W];//绘制按钮
        GameUtils.state = new int[GameUtils.MAP_H][GameUtils.MAP_W];  //      用于存储方格状态(0-未点击,1-已点击,2-未点击但周围有雷,3-插旗字)
        MineSweeping.setMineNum(GameUtils.NUM_FLAGS);//调用该方法实现棋子数的修改
        setLayout(null);
        initLable();
        randomBomb();
        writeNumber();
        drawBtn();
    }

    // 将地图底部初始化为一个个小格子,方便后续填充图片
    public void initLable() {
        for (int i = 0; i < GameUtils.MAP_H; i++) {
            for (int j = 0; j < GameUtils.MAP_W; j++) {
                JLabel l = new JLabel("", JLabel.CENTER);
                l.setBounds(j * GameUtils.DELL_LENGTH,
                        i * GameUtils.DELL_LENGTH,
                        GameUtils.DELL_LENGTH,
                        GameUtils.DELL_LENGTH);//设置大小和位置
                l.setBorder(BorderFactory.createLineBorder(Color.GRAY));    // 绘制方格边框
                l.setOpaque(true);
                l.setBackground(Color.lightGray);
                this.add(l);

                GameUtils.label[i][j] = l;//将lable标签放入一个个格子中整齐排布
                GameUtils.label[i][j].setVisible(false);//可见性
            }
        }
    }

    //绘制地雷
    private void randomBomb() {
        for (int i = 0; i < GameUtils.NUM_MINES; i++) {
            int rRow = (int) (Math.random() * GameUtils.MAP_H);
            int rCol = (int) (Math.random() * GameUtils.MAP_W);
            // 避免雷埋在相同的位置
            if (GameUtils.isBomb[rRow][rCol]) {
                i--;
            }
            GameUtils.label[rRow][rCol].setIcon(GameUtils.bomb);//设置图片
            GameUtils.isBomb[rRow][rCol] = true;
        }
    }

    // 绘制数字
    private void writeNumber() {
        for (int i = 0; i < GameUtils.MAP_H; i++) {
            for (int j = 0; j < GameUtils.MAP_W; j++) {//前两村遍历宽和高
                if (GameUtils.isBomb[i][j]) {
                    continue;//当前想绘制数字的点是否有雷如果没有雷继续遍历下一个格子
                }
                int bombCount = 0;
                /* 寻找以自己为中心的九个格子中的地雷数 */
                for (int k = -1; (k + i < GameUtils.MAP_H) && (k < 2); k++) {
                    //从这个格子周围3*3遍历
                    if (k + i < 0) {
                        continue;//判断是否越界
                    }
                    for (int c = -1; (c + j < GameUtils.MAP_W) && (c < 2); c++) {
                        if (c + j < 0) {
                            continue;//判断是否越界
                        }
                        if (GameUtils.isBomb[k + i][c + j]) {
                            bombCount++;//若有雷数字加一
                        }
                    }
                    if (bombCount > 0) {
                        GameUtils.state[i][j] = 2;//游戏=2意味这这个格子是数字
                        GameUtils.label[i][j].setText(String.valueOf(bombCount));//设置数字的图案
                    }
                }
            }
        }
    }

    // 绘制按钮
    private void drawBtn() {
        for (int i = 0; i < GameUtils.MAP_H; i++) {
            for (int j = 0; j < GameUtils.MAP_W; j++) {
                //把按钮赋坐标值 把每一个btn按钮添加鼠标点击事件
                Btn btn = new Btn();
                btn.i = i;
                btn.j = j;
                btn.setBounds(j * GameUtils.DELL_LENGTH, i * GameUtils.DELL_LENGTH, GameUtils.DELL_LENGTH, GameUtils.DELL_LENGTH);
                //设置大小和位置
                this.add(btn);
                GameUtils.buttons[i][j] = btn;
                btn.addMouseListener(new MouseInputAdapter() {
                    @Override
                    public void mouseClicked(MouseEvent e) {
                        /* 左键点击翻开 */
                        if (e.getButton() == MouseEvent.BUTTON1) {
                            open(btn);
                        }
                        /* 右键点击插旗 */
                        if (e.getButton() == MouseEvent.BUTTON3) {
                            placeFlag(btn);
                        }
                    }
                });
            }
        }
    }

    // 打开这个雷区
    private void open(Btn b) {
        // 如果踩雷
        if (GameUtils.isBomb[b.i][b.j]) {
            for (int k = 0; k < GameUtils.MAP_H; k++) {
                for (int t = 0; t < GameUtils.MAP_W; t++) {
                    GameUtils.buttons[k][t].setVisible(false);
                    GameUtils.label[k][t].setVisible(true);
                    //把每一个格子都翻开
                }
            }
            GameUtils.gameSate = -1;
            JOptionPane.showMessageDialog(null, "您失败了", "游戏结束", JOptionPane.PLAIN_MESSAGE);
        } else {
            if (!GameUtils.isClick) {
                MineSweeping.TimeClock timeClock = new MineSweeping.TimeClock();//点击一瞬间不是地雷就开始计时
                timeClock.start();
                GameUtils.isClick = true;
            }
            subOpen(b);
            isVictory();
        }
    }

    // 递归打开周边雷区
    private void subOpen(Btn button) {
        //不能打开的情况
        if (GameUtils.isBomb[button.i][button.j] || GameUtils.state[button.i][button.j] == 1 || GameUtils.state[button.i][button.j] == 3) {
            return;
        }
        /* 周围有雷的,只打开它 */
        if (GameUtils.state[button.i][button.j] == 2) {
            button.setVisible(false);
            GameUtils.label[button.i][button.j].setVisible(true);
            GameUtils.state[button.i][button.j] = 1;
            count ++;
            return;
        }
        /* 打开当前这个按钮 */
        button.setVisible(false);
        GameUtils.label[button.i][button.j].setVisible(true);
        GameUtils.state[button.i][button.j] = 1;
        count ++;
        /* 递归检测周边八个按钮 */
        for (int r = -1; (r + button.i < GameUtils.MAP_H) && (r < 2); ++r) {
            if (r + button.i < 0) continue;
            for (int c = -1; (c + button.j < GameUtils.MAP_W) && (c < 2); ++c) {
                if (c + button.j < 0) {
                    continue;
                }
                if (r == 0 && c == 0) {
                    continue;
                }
                Btn newBtn = GameUtils.buttons[r + button.i][c + button.j];
                subOpen(newBtn);
            }
        }
    }

    // 绘制插旗
    private void placeFlag(Btn b) {
        // 插过旗的,再点一次取消
        if (GameUtils.state[b.i][b.j] == 3) {
            if (GameUtils.label[b.i][b.j].getText() == "[0-9]") GameUtils.state[b.i][b.j] = 2;
            else GameUtils.state[b.i][b.j] = 0;
            b.setIcon(GameUtils.transparency);
            ++GameUtils.NUM_FLAGS;
            MineSweeping.setMineNum(GameUtils.NUM_FLAGS);
        } else if (GameUtils.NUM_FLAGS > 0) {  // 剩余旗子数量等于0时则不能再插旗
            b.setIcon(GameUtils.flag);
            GameUtils.state[b.i][b.j] = 3;
            --GameUtils.NUM_FLAGS;
            MineSweeping.setMineNum(GameUtils.NUM_FLAGS);
        }
        if(GameUtils.NUM_FLAGS == 0){
            boolean flagstate = true;
            for(int i = 0;i < GameUtils.MAP_H; ++i){
                for(int j = 0; j < GameUtils.MAP_W; ++j){
                    if (GameUtils.state[i][j] != 3 && GameUtils.isBomb[i][j]) flagstate = false;
                }
            }
        }
    }

    // 失败显示所有地雷
    public void showBomb() {
        for (int r = 0; r < GameUtils.MAP_H; ++r) {
            for (int c = 0; c < GameUtils.MAP_W; ++c) {
                GameUtils.buttons[r][c].setVisible(false);
                GameUtils.label[r][c].setVisible(true);
            }
        }
    }

    public void isVictory() {
        if (count + GameUtils.NUM_MINES == GameUtils.MAP_W * GameUtils.MAP_H) {
            GameUtils.gameSate = 1;
            new VictoryDialog(GameUtils.GAME_TIME);
        }
    }
}


import javax.swing.*;
import java.util.ArrayList;

public class GameUtils {

    /*
    GameUtils存储了绘制扫雷地图时所需要的变量,比如地图的宽、高,地的偏移量、地雷的数量等。并将这些变量全部设置为静态变量,以此能在不同类中很好的调用。
     */

    // 窗口的相关参数
    static int MAP_W = 9;
    static int MAP_H = 9;
    static final int DELL_LENGTH = 20;
    static final int OFFSET = 40;
    static int GAME_TIME = 0;

    // 游戏的相关状态
    static JLabel[][] label;
    static boolean[][] isBomb;
    static Btn[][] buttons;
    static int[][] state;//定义格子的状态 0-未点击,1-已点击,2-未点击但周围有雷,3-插旗字
    static int gameSate;
    static boolean isClick = false;

    static ArrayList<Hero> heroesList = new ArrayList<>();

    // 地雷与棋子的数量
    static int NUM_MINES = 10;
    static int NUM_FLAGS = 10;

    // 游戏的相关图片
    static ImageIcon flag = new ImageIcon("src/experimentFinal1/images/flag.jpg");
    static ImageIcon bomb = new ImageIcon("src/experimentFinal1/images/bomb.jpg");
    static ImageIcon transparency = new ImageIcon("src/experimentFinal1/images/transparency.png");
    static ImageIcon face = new ImageIcon("src/experimentFinal1/images/face.jpg");

    public static void addHero() {
        heroesList.add(new Hero("张三", 45));
        heroesList.add(new Hero("李四", 60));
        heroesList.add(new Hero("王五", 30));
        heroesList.add(new Hero("赵六", 51));
        heroesList.add(new Hero("狗蛋", 33));
    }
}
import java.io.Serializable;

// 该对象想要序列化或反序列化你需要实现Serializable接口,此接口为标记接口,不需要重写方法
public class Hero implements Serializable {

    private String name = "";
    private int time = 0;

    public Hero(String name, int time) {
        this.name = name;
        this.time = time;
    }

    public String getName() {
        return name;
    }

    public int getTime() {
        return time;
    }
}
package experimentFinal1;

import javax.swing.*;

public class HeroesDialog extends JFrame {

    public HeroesDialog() /*throws IOException, ClassNotFoundException*/ {
        this.setVisible(true);
        this.setSize(200, 200);
        this.setLocationRelativeTo(null);

        insertSort();

        String[] heroes = new String[GameUtils.heroesList.size()];
        for (int i = 0; i < GameUtils.heroesList.size(); i++) {
            heroes[i] = GameUtils.heroesList.get(i).getName()
                    + "                                   "
                    + GameUtils.heroesList.get(i).getTime();
        }

        JLabel label = new JLabel();
        label.setText("英雄排行榜");
        JList<String> list = new JList<>(heroes);
        JPanel panel = new JPanel();
        panel.add(label);
        panel.add(new JScrollPane(list));
        this.add(panel);
    }

    private void insertSort() {
        for (int i = 1; i < GameUtils.heroesList.size(); i++) {
            for (int j = i; j > 0; j--) {
                if (GameUtils.heroesList.get(j - 1).getTime() > GameUtils.heroesList.get(j).getTime()) {
                    Hero temp = GameUtils.heroesList.get(j - 1);
                    GameUtils.heroesList.set(j - 1, GameUtils.heroesList.get(j));
                    GameUtils.heroesList.set(j, temp);
                } else {
                    break;
                }
            }
        }
    }
}
package experimentFinal1;

public class LevelSelect {

    public LevelSelect(String item) {
        switch (item) {
            case "初级":
                GameUtils.NUM_MINES = 10;
                GameUtils.MAP_W = 9;
                GameUtils.MAP_H = 9;
                break;
            case "中级":
                GameUtils.NUM_MINES = 40;
                GameUtils.MAP_W = 16;
                GameUtils.MAP_H = 16;
                break;
            case "高级":
                GameUtils.NUM_MINES =99;
                GameUtils.MAP_W = 30;
                GameUtils.MAP_H = 16;
                break;
            default:
        }
    }
}
package experimentFinal1;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

public class MineSweeping {
    /*
    将一些小组件绘制完成 绘制整体的窗口大小 把雷区放进来
     */

    private static int mineNum = 0;
    private static boolean isChanged = false;  //判断游戏对局是否改变
    private static boolean isRestart = false;  //判断游戏是否重开
    private static boolean isAdd = false;
    private static JLabel label1, label2;
    private static GamePanel gp;

    public MineSweeping() {
        if (!isAdd) {
            GameUtils.addHero();
            isAdd = true;
        }
        isRestart = false;
        isChanged = false;
        GameUtils.isClick = false;//判断是否点击
        // 绘制窗口
        JFrame jFrame = new JFrame("扫雷");
        jFrame.setBounds(600,
                200,
                GameUtils.OFFSET * 2 + GameUtils.MAP_W * GameUtils.DELL_LENGTH,
                GameUtils.OFFSET * 2 + GameUtils.MAP_H * GameUtils.DELL_LENGTH);
        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        jFrame.setLocationRelativeTo(null);   //让图形界面窗口居中显示
        jFrame.setLayout(null);

        // 绘制倒计时
        label1 = new JLabel("0");
        label1.setBounds(10, 0, 120, 20);
        jFrame.add(label1);

        // 绘制剩余旗子数
        label2 = new JLabel("" + mineNum);
        label2.setBounds(jFrame.getWidth() - (int)(  GameUtils.OFFSET),
                0,
                100,
                20);//设置棋子数字的大小和位置
        jFrame.add(label2);
        // 绘制重置按钮
        JButton restartBt = new JButton(GameUtils.face);
        restartBt.setBounds(GameUtils.OFFSET + (GameUtils.MAP_W * GameUtils.DELL_LENGTH / 2) - 15,
                0,
                30,
                30);
        restartBt.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                jFrame.dispose();
                isRestart = true;
                GameUtils.isClick = false;
                new MineSweeping();
            }
        });//设置重开的鼠标点击时间
        jFrame.add(restartBt);

        JButton heroBt = new JButton("英雄榜");
        heroBt.setBounds(GameUtils.OFFSET + (GameUtils.MAP_W * GameUtils.DELL_LENGTH / 2) + 20,
                0,
                50,
                20);
        heroBt.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                new HeroesDialog();
            }
        });//设置英雄榜点击事件
        jFrame.add(heroBt);

        // 难度等级选择绘制
        JComboBox comboBox = new JComboBox();
        comboBox.addItem("难度选择");
        comboBox.addItem("初级");
        comboBox.addItem("中级");
        comboBox.addItem("高级");
        comboBox.setBounds(GameUtils.OFFSET - 10, 0, 80, 20);
        jFrame.add(comboBox);

        // 绘制雷区
        gp = new GamePanel();
        gp.setBounds(GameUtils.OFFSET,
                GameUtils.OFFSET,
                GameUtils.MAP_W * GameUtils.DELL_LENGTH,
                GameUtils.MAP_H * GameUtils.DELL_LENGTH);
        //绘制雷区的大小和位置
        jFrame.add(gp);
        jFrame.setVisible(true);

        comboBox.addItemListener(new ItemListener() {
            //选择难度的按钮事件
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (!isChanged) {
                    jFrame.dispose();
                    new LevelSelect((String) comboBox.getSelectedItem());
                    isRestart = true;
                    GameUtils.isClick = false;
                    isChanged = true;
                    new MineSweeping();
                } else {
                    isChanged = false;
                }
            }
        });
    }

    // 修改旗子数
    public static void setMineNum(int i) {
        mineNum = i;
        label2.setText("剩余:" + mineNum);
    }

    // 多线程绘制倒计时
    public static class TimeClock extends Thread {

        long startTime = System.currentTimeMillis() / 1000;

        @Override
        public void run() {
            while (true) {
                long endTime = System.currentTimeMillis() / 1000;
                label1.setText("" + (endTime - startTime));
                if (isRestart || GameUtils.gameSate == -1 || GameUtils.gameSate == 1) {
                    if (isRestart) {
                        isRestart = false;
                    }
                    GameUtils.GAME_TIME = (int) (endTime - startTime);
                    GameUtils.gameSate = 0;
                    break;
                }
            }
        }
    }
}
package experimentFinal1;

import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.event.MouseEvent;

public class VictoryDialog extends JDialog {

    public VictoryDialog(int time) {
        this.setVisible(true);
        this.setSize(200, 200);
        this.setLocationRelativeTo(null);

        JPanel panel = new JPanel();
        panel.setLayout(null);

        JLabel label1 = new JLabel("扫雷成功!共用时" + time + "s");
        JLabel label2 = new JLabel("敢问英雄大名是");
        label1.setBounds(40, 0, 150, 30);
        label2.setBounds(50, 30, 100, 30);
        panel.add(label1);
        panel.add(label2);

        JTextField textField = new JTextField();
        textField.setBounds(0, 60, 200, 30);
        panel.add(textField);

        JButton addBtn = new JButton("确定");
        addBtn.setBounds(60, 120, 70, 20);
        panel.add(addBtn);

        addBtn.addMouseListener(new MouseInputAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    dispose();
                    String name = textField.getText();
                    Hero hero = new Hero(name, time);
                    GameUtils.heroesList.add(hero);
                    new HeroesDialog();
                }
            }
        });
        this.add(panel);
    }
}

七、游戏内图片

 

  • 10
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
数据结构是指在学习数据结构程时,通过计并实现一个扫雷游戏来加深对数据结构的理解和应用。扫雷游戏是一种经典的益智类游戏,在一个由格子组成的雷区中,玩家需要根据数字提示来逐步揭开格子,避开雷块,最终将所有非雷格子都揭开。下面我将简要介绍一下如何用C语言来实现扫雷游戏。 首先,我们需要定义一个二维数组来表示雷区,其中每个元素代表一个格子,可以使用字符数组或整型数组来表示。字符数组可以包含两个字符,用来表示格子状态,如"#"代表未揭开,"*"代表雷块,数字字符代表周围雷块的数量。整型数组可以将数字的相应值存储在对应的位置上。 接下来,我们需要实现格子的揭开功能。当玩家选择一个格子时,我们需要判断该格子是否为雷块。如果是雷块,则游戏结束;如果不是雷块,则需要计算周围雷块的数量,并将该格子状态更新为数字字符。如果周围无雷块,则需要递归地揭开周围的未揭开格子。 此外,还需要实现游戏的初始化功能,将雷块随机地分布在雷区中。可以使用rand函数生成随机数,并将生成的数与雷块的概率阈值进行比较,从而确定是否为雷块。 最后,还可以增加计时功能、计分功能、游戏界面等附加功能,来提升游戏体验。 总之,数据结构扫雷游戏可以通过定义二维数组来表示雷区,实现格子的揭开和雷块的随机分布等功能,以加深对数据结构的理解和应用。通过C语言的实现,可以让我们更好地掌握数据结构知识,提升编程能力。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天的命名词

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值