JavaSE简易版扫雷小游戏

描述:用户输入二维雷区的高和宽,输入确定地雷数,随机在地雷区生成地雷。用户输入横竖坐标进行挖雷,挖到地雷游戏以失败结束,并让用户选择是否再次游戏;没挖到雷,显示该区域8个方向地雷数。如果8个方向都没有地雷,即地雷数为0,自动挖开周围区域,如果周围区域挖开后地雷数任为0继续自动挖开周围区域直到地雷数不为0为止。当剩下未挖开区域为地雷即游戏成功结束。

最终实现效果:

 思路

1.用二维数组表示扫雷的区域,其中长宽我们可以自己定义,埋雷的数量也可以自定义,但是为了游戏的可玩性,设计雷数量小于扫雷整个区域格子的34%。

2.因为挖开的格子要显示周围埋雷的数量,所以整个扫雷区域的数组用int类型,并且定义当某个格子为-1时,则为雷。

3.游戏结束的条件---》成功或者失败就会结束游戏。成功的条件为挖开所有安全的格子并且不踩雷,失败的条件为踩雷。踩雷很好判断,即判断选中的格子在二维数组中的值为不为-1,-1则为踩雷。要判断成功的条件,还得定义一个变量表示未挖的格子数,当它为0时即为成功。

4.需要一个布尔型的二维数组表示每个格子是否挖开与否。

具体实现

变量定义:

 private static int[][] mineField;  // 雷区二维数组
 private static boolean[][] revealed; // 表示每个位置是否被挖开,true表示挖开,false表示未挖开
 private static int rows;  // 表示行
 private static int cols; // 表示列
 private static int mineCount; // 表示雷区总数
 private static int cellsLeft; // 表示未挖开的安全的格子数

游戏菜单:

 public static void menu(){
        Scanner scanner = new Scanner(System.in);
        System.out.println("**************挖地雷游戏开始**************");
        System.out.print("请输入雷区的高度:");
        rows = scanner.nextInt();
        System.out.print("请输入雷区的宽度:");
        cols = scanner.nextInt();
        // 计算最大允许的地雷数量
        int maxMines = (int) (rows * cols * 0.34);
        System.out.print("请输入地雷数(小于" + maxMines + "个):");
        mineCount = scanner.nextInt();
        // 检查地雷数量是否超过限制
        while (mineCount >= maxMines || mineCount <= 0) {
            System.out.print("地雷数不能超过最大限制且必须大于0,请重新输入地雷数(小于" + maxMines + "个):");
            mineCount = scanner.nextInt();
        }
        cellsLeft = rows * cols - mineCount;  // 初始化为挖开的安全的格子数
        System.out.println("地雷已经埋好,挖雷开始!");
    }

main:

public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        boolean playAgain; // 是否再次游戏
        do {
            menu();
            initializeGame();  // 初始化游戏
            boolean gameLost = false;  // 标识是否踩雷的状态  默认为没有踩雷
            while (cellsLeft > 0 && !gameLost) {  // 当未挖开的安全格子数大于0 或者 没有踩雷
                printField(); // 打印图形
                int x, y;
                do {
                    System.out.print("请输入挖雷的x坐标(0-" + (rows - 1) + "):");
                    x = scanner.nextInt();
                    System.out.print("请输入挖雷的y坐标(0-" + (cols - 1) + "):");
                    y = scanner.nextInt();
                    if (x < 0 || x >= rows || y < 0 || y >= cols) {
                        System.out.println("输入超出范围,请重新输入!");
                    } else if (revealed[x][y]) {
                        System.out.println("这个位置已经挖过了,请重新输入!");
                    }
                } while (x < 0 || x >= rows || y < 0 || y >= cols || revealed[x][y]);

                System.out.println("你挖雷的坐标是("+ x + "," + y + ")!");
                if (mineField[x][y] == -1) {
                    revealed[x][y] = true;
                    printField();
                    System.out.println("你踩到地雷了!游戏失败!");
                    gameLost = true;
                } else {
                    revealCell(x, y);  // 递归挖格子
                }
            }

            if (!gameLost) {
                System.out.println("恭喜你,游戏成功!");
            }

            System.out.print("你想再玩一次吗?(输入true继续,输入false结束):");
            playAgain = scanner.nextBoolean();
        } while (playAgain);

        scanner.close();
    }

初始化游戏:initializeGame(); 方法中包括初始化了扫雷区域二维数组的长宽,以及记录是否被挖开的布尔型数组的长宽。调用placeMines()方法随机设置了地雷。调用calculateNumbers()方法计算每个非地雷格子周围的地雷数。

具体如下:

  private static void initializeGame() {
        mineField = new int[rows][cols];
        revealed = new boolean[rows][cols];

        placeMines();  // 放地雷
        calculateNumbers(); // 计算每个非地雷格子周围的地雷数
    }

    private static void placeMines() {
        Random random = new Random();
        int minesPlaced = 0;

        while (minesPlaced < mineCount) {
            int x = random.nextInt(rows);
            int y = random.nextInt(cols);

            if (mineField[x][y] != -1) {  // 必须要当前格子没有放雷才行,否则重复放入了
                mineField[x][y] = -1;
                minesPlaced++;
            }
        }
    }


    private static void calculateNumbers() {
        // 遍历整个雷区,对于每个非地雷格子,检查其周围八个方向的格子 --> 如果周围有地雷,则计数并更新该格子的值。
        for (int x = 0; x < rows; x++) {
            for (int y = 0; y < cols; y++) {
                if (mineField[x][y] == -1) continue;

                int mineCount = 0;
                for (int dx = -1; dx <= 1; dx++) {
                    for (int dy = -1; dy <= 1; dy++) {
                        int nx = x + dx;
                        int ny = y + dy;
                        if (nx >= 0 && nx < rows && ny >= 0 && ny < cols && mineField[nx][ny] == -1) {
                            mineCount++;
                        }
                    }
                }
                mineField[x][y] = mineCount;
            }
        }
    }

其中dx和dy都表示偏移量,表示该格子周围的八个格子。这八个格子中有埋雷的格子就让mineCount++,最终得到该格子的值。

初始化游戏完毕后开始选择要挖的格子,格子的x坐标和y坐标不能超过整个扫雷区域的宽和长,并且不能是挖过的格子,否则重新输入有效的x和y:

 do {
                    System.out.print("请输入挖雷的x坐标(0-" + (rows - 1) + "):");
                    x = scanner.nextInt();
                    System.out.print("请输入挖雷的y坐标(0-" + (cols - 1) + "):");
                    y = scanner.nextInt();
                    if (x < 0 || x >= rows || y < 0 || y >= cols) {
                        System.out.println("输入超出范围,请重新输入!");
                    } else if (revealed[x][y]) {
                        System.out.println("这个位置已经挖过了,请重新输入!");
                    }
                } while (x < 0 || x >= rows || y < 0 || y >= cols || revealed[x][y]);

输入有效的x和y后,判断当前挖开的格子是否埋雷,即判断 mineField[x][y] == -1,如果为true则游戏失败,如果不为true则递归挖开格子,直到格子周围埋雷数量大于0。

递归挖开格子的方法为:

    private static void revealCell(int x, int y) {
        if (x < 0 || x >= rows || y < 0 || y >= cols || revealed[x][y]) { // 结束条件
            return;
        }

        revealed[x][y] = true;
        cellsLeft--;

        if (mineField[x][y] == 0) {
            for (int dx = -1; dx <= 1; dx++) {
                for (int dy = -1; dy <= 1; dy++) {
                    revealCell(x + dx, y + dy);
                }
            }
        }
    }

打印图形的方法printField():

    private static void printField() {
        for (int x = 0; x < rows; x++) {
            for (int y = 0; y < cols; y++) {
                if (revealed[x][y]) {
                    if (mineField[x][y] == -1) {
                        System.out.print("* ");
                    } else {
                        System.out.print(mineField[x][y] + " ");
                    }
                } else {
                    System.out.print("\u25A0 ");
                }
            }
            System.out.println();
        }
    }

整体代码

import java.util.Random;
import java.util.Scanner;

public class Game {
    private static int[][] mineField;  // 雷区二维数组
    private static boolean[][] revealed; // 表示每个位置是否被挖开,true表示挖开,false表示未挖开
    private static int rows;  // 表示行
    private static int cols; // 表示列
    private static int mineCount; // 表示雷区总数
    private static int cellsLeft; // 表示未挖开的安全的格子数

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        boolean playAgain; // 是否再次游戏
        do {
            menu();
            initializeGame();  // 初始化游戏
            boolean gameLost = false;  // 标识是否踩雷的状态  默认为没有踩雷
            while (cellsLeft > 0 && !gameLost) {  // 当未挖开的安全格子数大于0 或者 没有踩雷
                printField(); // 打印图形
                int x, y;
                do {
                    System.out.print("请输入挖雷的x坐标(0-" + (rows - 1) + "):");
                    x = scanner.nextInt();
                    System.out.print("请输入挖雷的y坐标(0-" + (cols - 1) + "):");
                    y = scanner.nextInt();
                    if (x < 0 || x >= rows || y < 0 || y >= cols) {
                        System.out.println("输入超出范围,请重新输入!");
                    } else if (revealed[x][y]) {
                        System.out.println("这个位置已经挖过了,请重新输入!");
                    }
                } while (x < 0 || x >= rows || y < 0 || y >= cols || revealed[x][y]);

                System.out.println("你挖雷的坐标是("+ x + "," + y + ")!");
                if (mineField[x][y] == -1) {
                    revealed[x][y] = true;
                    printField();
                    System.out.println("你踩到地雷了!游戏失败!");
                    gameLost = true;
                } else {
                    revealCell(x, y);  // 递归挖格子
                }
            }

            if (!gameLost) {
                System.out.println("恭喜你,游戏成功!");
            }

            System.out.print("你想再玩一次吗?(输入true继续,输入false结束):");
            playAgain = scanner.nextBoolean();
        } while (playAgain);

        scanner.close();
    }


    public static void menu(){
        Scanner scanner = new Scanner(System.in);
        System.out.println("**************挖地雷游戏开始**************");
        System.out.print("请输入雷区的高度:");
        rows = scanner.nextInt();
        System.out.print("请输入雷区的宽度:");
        cols = scanner.nextInt();
        // 计算最大允许的地雷数量
        int maxMines = (int) (rows * cols * 0.34);
        System.out.print("请输入地雷数(小于" + maxMines + "个):");
        mineCount = scanner.nextInt();
        // 检查地雷数量是否超过限制
        while (mineCount >= maxMines || mineCount <= 0) {
            System.out.print("地雷数不能超过最大限制且必须大于0,请重新输入地雷数(小于" + maxMines + "个):");
            mineCount = scanner.nextInt();
        }
        cellsLeft = rows * cols - mineCount;  // 初始化为挖开的安全的格子数
        System.out.println("地雷已经埋好,挖雷开始!");
    }
    // 初始化游戏的方法
    private static void initializeGame() {
        mineField = new int[rows][cols];
        revealed = new boolean[rows][cols];

        placeMines();  // 放地雷
        calculateNumbers(); // 计算每个非地雷格子周围的地雷数
    }

    private static void placeMines() {
        Random random = new Random();
        int minesPlaced = 0;

        while (minesPlaced < mineCount) {
            int x = random.nextInt(rows);
            int y = random.nextInt(cols);

            if (mineField[x][y] != -1) {  // 必须要当前格子没有放雷才行,否则重复放入了
                mineField[x][y] = -1;
                minesPlaced++;
            }
        }
    }


    private static void calculateNumbers() {
        // 遍历整个雷区,对于每个非地雷格子,检查其周围八个方向的格子 --> 如果周围有地雷,则计数并更新该格子的值。
        for (int x = 0; x < rows; x++) {
            for (int y = 0; y < cols; y++) {
                if (mineField[x][y] == -1) continue;

                int mineCount = 0;
                for (int dx = -1; dx <= 1; dx++) {
                    for (int dy = -1; dy <= 1; dy++) {
                        int nx = x + dx;
                        int ny = y + dy;
                        if (nx >= 0 && nx < rows && ny >= 0 && ny < cols && mineField[nx][ny] == -1) {
                            mineCount++;
                        }
                    }
                }
                mineField[x][y] = mineCount;
            }
        }
    }

    private static void revealCell(int x, int y) {
        if (x < 0 || x >= rows || y < 0 || y >= cols || revealed[x][y]) { // 结束条件
            return;
        }

        revealed[x][y] = true;
        cellsLeft--;

        if (mineField[x][y] == 0) {
            for (int dx = -1; dx <= 1; dx++) {
                for (int dy = -1; dy <= 1; dy++) {
                    revealCell(x + dx, y + dy);
                }
            }
        }
    }

    private static void printField() {
        for (int x = 0; x < rows; x++) {
            for (int y = 0; y < cols; y++) {
                if (revealed[x][y]) {
                    if (mineField[x][y] == -1) {
                        System.out.print("* ");
                    } else {
                        System.out.print(mineField[x][y] + " ");
                    }
                } else {
                    System.out.print("\u25A0 ");
                }
            }
            System.out.println();
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/766606.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

去中心化社会的崛起:探索区块链对社会结构的影响

随着区块链技术的发展和应用&#xff0c;我们正逐步迈向一个去中心化的社会结构。本文将深入探讨区块链技术如何影响社会结构&#xff0c;从经济、政治到文化等多个方面进行探索和分析&#xff0c;揭示其可能带来的革命性变革。 1. 区块链技术的基本原理回顾 1.1 分布式账本与…

放大器的输入电容Cin对放大电路的影响

1、OPA859构成的放大电路的设计 图中OPA859的增益G设定为1.16 &#xff0c;OPA859的增益带宽积GBP 900M , 放大器的带宽BW GBP / Acl 900 / 1.16 775.86M。 图&#xff1a;OPA859放大电路 由于需要在放大电路上加带宽的限制&#xff0c;所以在OPA859放大电路上有个低通限…

Elasticsearch基础(二):阿里云Elasticsearch快速入门

文章目录 阿里云Elasticsearch快速入门 一、资源领取 二、访问实例 三、创建索引 四、插入数据 五、搜索数据 1、全文搜索 2、按查询条件搜索 六、删除数据 阿里云Elasticsearch快速入门 一、资源领取 这里资源领取只针对新用户&#xff0c;如果是老用户按需购买&am…

vue3.0(十六)axios详解以及完整封装方法

文章目录 axios简介1. promise2. axios特性3. 安装4. 请求方法5. 请求方法别名6. 浏览器支持情况7. 并发请求 Axios的config的配置信息1.浏览器控制台相关的请求信息&#xff1a;2.配置方法3.默认配置4.配置的优先级5.axios请求响应结果 Axios的拦截器1.请求拦截2.响应拦截3.移…

太阳辐射系统日光全光谱模拟太阳光模拟器

太阳光模拟器是一种用于评估太阳能电池性能的重要设备。它能够模拟太阳光的特性&#xff0c;通过测试电池的短路电流、开路电压、填充因子和光电转化效率等关键指标&#xff0c;来评估电池的性能优劣。 设备型号&#xff1a;KYF-GC004品牌制造商&#xff1a;科迎法电气太阳光模…

bigNumber的部分使用方法与属性

场景&#xff1a;最近做IoT项目的时候碰到一个问题&#xff0c;涉及到双精度浮点型的数据范围的校验问题。业务上其实有三种类型&#xff1a;int、float和double类型三种。他们的范围分别是&#xff1a; //int int: [-2147483648, 2147483647],//float float: [-3402823466385…

idea xml ctrl+/ 注释格式不对齐

处理前 处理后 解决办法 取消这两个勾选

【C++题解】1456. 淘淘捡西瓜

问题&#xff1a;1456. 淘淘捡西瓜 类型&#xff1a;贪心 题目描述&#xff1a; 地上有一排西瓜&#xff0c;每个西瓜都有自己的重量。淘淘有一个包&#xff0c;包的容量是固定的&#xff0c;淘淘希望尽可能在包里装更多的西瓜&#xff08;当然要装整个的&#xff0c;不能切开…

Go语言--运算符

算术运算符 关系运算符 不能写0<a<10&#xff0c;要判断必须0<a&&a<10。因为int和bool不兼容 逻辑运算符 位运算符 赋值运算符 其他 运算符的优先级

数字化精益生产系统--RD研发管理系统

R&D研发管理系统是一种用于管理和监督科学研究和技术开发的软件系统&#xff0c;其设计和应用旨在提高企业研发活动的效率、质量和速度。以下是对R&D研发管理系统的功能设计&#xff1a;

Promethuse-监控 Etcd

一、思路 Prometheus监控Etcd集群&#xff0c;是没有对应的exporter&#xff0c;而 由CoreOS公司开发的Operator&#xff0c;用来扩展 Kubernetes API&#xff0c;特定的应用程序控制器&#xff0c;它用来创建、配置和管理复杂的有状态应用&#xff0c;如数据库、缓存和监控系…

PCL 点云最小图割(前景、背景点云提取)

点云最小图割 一、概述1.1 概念1.2 算法原理二、代码示例三、运行结果🙋 结果预览 一、概述 1.1 概念 最小图割算法(pcl::MinCutSegmentation):是一种基于图论的对象分割方法,主要用于点云数据的处理和分析。该算法将点云数据表示为一个图结构,其中点云中的点作为图的节…

每日一题——Python实现PAT乙级1100 校庆(举一反三+思想解读+逐步优化)五千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 代码结构和逻辑 时间复杂度分析 空间复杂度分析 总结 我要更强 方法一…

中控室监控台在水处理行业的作用

随着工业化和城市化的快速推进&#xff0c;水处理行业的重要性日益凸显。作为确保水质安全、提高水资源利用效率的关键环节&#xff0c;水处理厂需要高效、稳定地运行。在这个过程中&#xff0c;中控室监控台发挥着不可或缺的作用。本文将从以下几个方面&#xff0c;详细阐述中…

Docker精华篇 - 常用命令大全,入门到精通!

大家好,我是CodeQi! 我们都知道 Docker 的重要性,以及 Docker 如何在软件开发生命周期中发挥重要作用 。 说实话,学习 Docker 很有趣,至少在我看来是这样。 一旦掌握了基础知识,这并不难。 困难的是记住所有这些命令。 因此,在这篇文章中,我收集了所有命令,或者更…

UG NX二次开发(C#)-根据草图创建拉伸特征(UFun+NXOpen)

文章目录 1、前言2、在UG NX中创建草图,然后创建拉伸特征3、基于UFun函数的实现4、基于NXOpen的实现代码1、前言 UG NX是基于特征的三维建模软件,其中拉伸特征是一个很重要的特征,有读者问如何根据草图创建拉伸特征,我在这篇博客中讲述一下草图创建拉伸特征的UG NX二次开发…

分享六款免费u盘数据恢复工具,U盘恢复工具集合【工具篇】

U盘里面的数据丢失了怎么找回&#xff1f;随着数字化时代的深入发展&#xff0c;U盘已成为我们日常生活中不可或缺的数据存储工具。然而&#xff0c;由于各种原因&#xff0c;如误删除、格式化、病毒攻击等&#xff0c;U盘中的数据可能会丢失&#xff0c;给用户带来极大的困扰。…

stm32中IIC通讯协议

参考资料&#xff1a;大部分均引用b站江协科技课程、GPT及网络资料 什么是IIC&#xff08;i2C&#xff09;通讯协议&#xff1f; 关键字&#xff1a;SCL、SDA、半双工、同步、串行。 IIC&#xff08;Inter-Integrated Circuit&#xff09;&#xff0c;也称为I2C&#xff08;In…

力扣双指针算法题目:双数之和,三数之和,四数之和

目录 一&#xff1a;双数之和 1.题目&#xff1a; 2.思路解析 3.代码 二&#xff1a;三数之和 1.题目 2.思路解析 3&#xff0c;代码 三&#xff1a;四数字之和 1.题目 2.思路解析 3.代码 一&#xff1a;双数之和 1.题目&#xff1a; 输入一个递增排序的数组和一…

思维导图插件--jsMind的使用

vue引入jsmind&#xff08;右键菜单&#xff09;_jsmind.menu.js-CSDN博客 第一版 vue-JsMind思维导图实现&#xff08;包含鼠标右键自定义菜单&#xff09;_jsmind 右键菜单-CSDN博客 // 新增节点addNode() {console.log(this.get_selected_nodeid());this.get_selected_…