首页 > 编程语言 >洛谷P2670扫雷游戏(Java)

洛谷P2670扫雷游戏(Java)

时间:2024-12-04 13:33:09浏览次数:11  
标签:P2670 字符 ch 洛谷 地雷 int char 数组 Java

三.P2670 [NOIP2015 普及组] 扫雷游戏

题目背景

NOIP2015 普及组 T2

题目描述

扫雷游戏是一款十分经典的单机小游戏。在 n 行 m列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格)。玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有多少个是地雷格。游戏的目标是在不翻出任何地雷格的条件下,找出所有的非地雷格。

现在给出 n行 m列的雷区中的地雷分布,要求计算出每个非地雷格周围的地雷格数。

注:一个格子的周围格子包括其上、下、左、右、左上、右上、左下、右下八个方向上与之直接相邻的格子。

输入格式

第一行是用一个空格隔开的两个整数 n和 m,分别表示雷区的行数和列数。

接下来 n 行,每行 m个字符,描述了雷区中的地雷分布情况。字符 * 表示相应格子是地雷格,字符 ? 表示相应格子是非地雷格。相邻字符之间无分隔符。

输出格式

输出文件包含 n行,每行 m 个字符,描述整个雷区。用 *表示地雷格,用周围的地雷个数表示非地雷格。相邻字符之间无分隔符。

样例 #1

样例输入 #1

3 3
*??
???
?*?

样例输出 #1

*10
221
1*1

样例 #2

样例输入 #2

2 3
?*?
*??

样例输出 #2

2*1
*21

算法思路

输出的结果需要地雷(也就是*原样输出),而?地方则输出地雷数。中间的数算 上、下、左、右、左上、右上、左下、右下八个方向 的地雷数当然好算,但是边界的数该如何解决呢?

我的思路是将输入的原数组周围在套上一层。我这边是都补的字符 0 (自己画的,理解就好),那么三行三列的数组就变成了五行五列,同样的两行三列变成了四行五列。总结:就是将行和列都 +2 就可以了。这样边界问题就可以很轻松的解决了。每个格子都有八个方向了。当遇到 0 时直接不管就行。

image-20241201223950076
// 为了加上虚拟边界,创建大小为 (n+2) x (m+2) 的 ch 数组
char[][] ch = new char[n + 2][m + 2]; // 边界填充的数组
char[][] res = new char[n][m]; // 存储计算结果的数组

读取输入数据,并填充到 ch[1] 到 ch[n] 中

//这里不能这样写,困扰我好久,一直报ArrayIndexOutOfBoundsException,原因是toCharArray方法将字符串转化为字符数组时是从下标为0开始的,而不是1。
        for (int i = 1; i <= n; i++) {
            String line = scan.nextLine();
            ch[i] = line.toCharArray();
        }

首先我们来说明下toCharArray

toCharArray() 是 Java 中 String 类的一个方法,用于将字符串转换为字符数组(char[])。它的返回值是一个包含字符串中所有字符的数组,每个字符都被存储在数组的相应位置。

当自动字符串转字符时是从下标0开始的,但是我们的下标为0 的是虚拟数组的边界。这样就导致有个位置的数组是空的。

ArrayIndexOutOfBoundsException 是 Java 中的一种运行时异常,表示数组下标越界异常。当你尝试访问数组中不存在的索引时,就会抛出这个异常。

如图,就会有三个位置为null,导致异常。

image-20241201235337491
//改成逐一赋值,就没问题了。
        for (int i = 1; i <= n; i++) {  // 从 1 到 n 填充数据
            String line = scan.nextLine(); // 读取输入的一行
            for (int j = 0; j < m; j++) {
                ch[i][j + 1] = line.charAt(j);  // 将字符逐个赋值到 ch[i][j+1]
            }
        }

默默吐槽一句,java真不适合写算法。

代码

import java.util.Arrays;
import java.util.Scanner;

public class P2670 {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt(); // 行数
        int m = scan.nextInt(); // 列数
        scan.nextLine();  // 消耗掉换行符

        // 为了加上虚拟边界,创建大小为 (n+2) x (m+2) 的 ch 数组
        char[][] ch = new char[n + 2][m + 2]; // 边界填充的数组
        char[][] res = new char[n][m]; // 存储计算结果的数组

        // 初始化二维数组,将所有元素填充为 '0'
        for (int i = 0; i < n + 2; i++) {
            Arrays.fill(ch[i], '0');
//            也可以写两个循环
//            for (int j = 0; j < n + 2; j++) {
//                ch[i][j] = '0';
//            }

        }

        // 读取输入数据,并填充到 ch[1] 到 ch[n] 中
        for (int i = 1; i <= n; i++) {  // 从 1 到 n 填充数据
            String line = scan.nextLine(); // 读取输入的一行
            for (int j = 0; j < m; j++) {
                ch[i][j + 1] = line.charAt(j);  // 将字符逐个赋值到 ch[i][j+1]
            }
        }

        // 计算每个位置周围的星号数
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                int count = 0;
                if (ch[i][j] == '*') {
                    res[i - 1][j - 1] = '*'; // 如果当前位置是星号,直接赋值
                } else {
                    // 遍历当前位置周围的 3x3 区域
                    for (int k = i - 1; k <= i + 1; k++) {
                        for (int l = j - 1; l <= j + 1; l++) {
                            if (ch[k][l] == '*') {
                                count++; // 计算周围星号的数量
                            }
                        }
                    }
                    res[i - 1][j - 1] = (char) (count + '0'); // 将数量转换为字符并存储
                }
            }
        }

        // 输出结果
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                System.out.print(res[i][j]); // 打印每个字符,不换行
            }
            System.out.println(); // 每行输出后换行
        }
    }
}

嘿嘿嘿!!!!

image-20241201235803212

标签:P2670,字符,ch,洛谷,地雷,int,char,数组,Java
From: https://blog.csdn.net/qq_65201998/article/details/144177589

相关文章

  • javabean重写equals和hashcode方法的作用
    Javabean重写equals()方法主要是为了实现自定义的对象比较。这个方法在Java集合框架和双列集合中扮演了关键角色;HashMap和HashSet底层原理是哈希表结构,依赖hashcode方法和equals方法保证键的唯一没有重写equals和hashcode方法:实体类比较的是地址值,map集合是根据地址值判断......
  • 【JavaScript】下拉框的实现
    什么是下拉框鼠标放到黑色盒子上才会显示下拉框中的内容,红色盒子是显示文本内容。蓝色盒子对外隐藏,鼠标放上去会将黑色盒子高度扩大。JavaScript获取元素的高度使用querySelector或者querySelectorAll获取元素,使用循环进行重复元素的选择,对元素的height属性进行修改。......
  • 网络编程(JavaEE)
    前言:    熟悉了网络的基本概念之后,接下来就需要针对网络进行一系列的编程,其中可能涉及到新的一些编程操作,需要我们进一步探索!网络编程套接字:    套接字其实是socket的翻译。    操作系统给应用程序(传输层给应用层)提供的API,起了个名字就叫socket......
  • HTML5期末考核大作业,个人网站—— 程序员个人简历模板下载HTML+CSS+JavaScript (2)
    ......
  • 全网最全情景,深入浅出解析JavaScript数组去重:数值与引用类型的全面攻略
    目录全网最全情景,深入浅出解析JavaScript数组去重:数值与引用类型的全面攻略一、引言:我们为什么需要关注数组去重?二、数值类去重1、使用Set去重2、遍历+includes()3、使用filter()和indexOf()4、使用reduce()5、嵌套数组去重:结合flat()三、引用类去重——去除......
  • 深入理解Java内存模型与线程
    Java内存模型(JMM)是为了屏蔽底层硬件和操作系统的差异,使得Java程序在各种平台上都能获得一致的内存访问效果。随着多线程的普及,理解JMM以及Java线程的实现至关重要。本文将详细解析Java内存模型、线程实现及其状态转换。1.硬件的效率与一致性由于计算机的处理器与内存速度差......
  • java: 不兼容的类型: java.lang.Long无法转换为java.lang.String
     1、异常提示: java:不兼容的类型:java.lang.Long无法转换为java.lang.String 2、原因分析: 长整型(Long)的数据无法转换为字符串型(String)的数据,请检查数据类型是否一致。 3、解决办法: 将被操作的变量的数据类型统一了,常见的解决办法有4中: 比如被操作的变量名为......
  • python、JAVA等多种语言演示免费获取股票数据(实时数据、历史数据、CDMA、KDJ等指标数
    ​近一两年来,股票量化分析逐渐受到广泛关注。而作为这一领域的初学者,首先需要面对的挑战就是如何获取全面且准确的股票数据。因为无论是实时交易数据、历史交易记录、财务数据还是基本面信息,这些数据都是我们进行量化分析时不可或缺的宝贵资源。我们的核心任务是从这些数据......
  • (免费源码)计算机毕业设计必学必看 万套实战教程 java、python、php、node.js、c#、APP
                   摘 要在网络信息的时代,众多的软件被开发出来,给业主带来了很大的选择余地,而且人们越来越追求更个性的需求。在这种时代背景下,智慧小区管理系统只能以业主为导向,以产品的持续创新作为智慧小区管理系统最重要的竞争手段。系统采用了B/S结构,将......
  • (免费源码)计算机毕业设计必学必看 万套实战教程 java、python、php、node.js、c#、APP
    摘要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对在线考试等问题,对如何通过计算机在线考试进行研究分析,然后开发设计出在线考试系统已解决问......