刷洛谷题单第二天,今天第一道题还是挺简单的,但是又被现实给了一级大逼兜子,做这题关键还是想熟悉Java的快速输入。还有做这道题很容易出现RE错误,下面总结了常见的RE错误导致情况(点击跳转下文)
我的上篇文章详细讲关于Java最快速输入输出法(关于StreamTokenizer和PrintWriter的应用)但是,StreamTokenizer有个不足就是,不能输入特殊符号,而今天做的洛谷这道题P2670 [NOIP2015 普及组] 扫雷游戏需要输入“*”和“?”,所以肯定得另外找过一个块输法了,这里就有另一个块输工具:BufferedReader。
BufferedReader实例化以及使用模板:
public class Main {
// 用BufferedReader才能读特殊字符
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException { // 注意这里一定要抛出异常
// 输入数字:
String[] dimensions = in.readLine().split(" "); // 例如,输入2 3
int n = Integer.parseInt(dimensions[0]); // 2
int m = Integer.parseInt(dimensions[1]); // 3
// ...代码
// 输入字符串:
String str = in.readLine();
// 循环输入字符串:
String line;
while ((line = in.readLine()) != null) {
// 当你输入一个空行并按下回车时,程序将停止读取
if (line.isEmpty()) {
break;
}
System.out.println(line);
}
// ...代码
}
}
什么就是BufferedReader常用的输入数字和字符串的方法,大家会发现,输入数字的时候要利用String类的split方法分割然后用Integer类转换才能得到,看上去有点麻烦,而BufferedReader中恰好有一个直接返回int型的方法:read();这不可以直接输入吗?哈哈,本人就是踩了这个坑,没了解方法内部具体实现情况,只看返回值来使用,导致一开始数据怎么都输入不进去。
BufferedReader中的read();方法确实是返回int型,但是,它返回的是输入字符的ASCII码值。所以,想要输入数字,只能用上面实例中的代码,防止踩坑啊。
扫雷游戏题解:
思路:
我的思路是:定义一个int型的二维数组作为雷区结果集minefield (最后根据这个集合来输出),遍历ch字符二维数组,当遇到一个雷,首先给雷区数组minefield 的这个位置设置一个最小值(Integer自带的MIN_VALUE,是个很小的负数),然后扫描它的八个方向,满足没有造成数组越界情况时,给雷区数组周围的位子都自增1,这样结束之后,在结果集minefield 中,非雷区就会标记周围雷区情况,代码如下:
代码:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
public class Main {
// 用BufferedReader才能读特殊字符
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static void main(String[] args) throws IOException {
String[] dimensions = in.readLine().split(" ");
int n = Integer.parseInt(dimensions[0]); // 行数
int m = Integer.parseInt(dimensions[1]); // 列数
char[][] ch = new char[n][m];
int[][] minefield = new int[n][m];
for(int i = 0; i < n; i++) {
String str = in.readLine();
ch[i] = str.toCharArray();
}
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(ch[i][j] == '*') {
minefield [i][j] = Integer.MIN_VALUE;
// 注意是否越界条件,否则在洛谷提交中会出现RE错误
if((i - 1) >= 0) {
minefield [i - 1][j]++;
}
if((i - 1) >= 0 && (j + 1) <= m - 1) {
minefield [i - 1][j + 1]++;
}
if((j + 1) <= m - 1) {
minefield [i][j +1]++;
}
if((i + 1) <= n - 1 && (j + 1) <= m - 1) {
minefield [i + 1][j + 1]++;
}
if((i + 1) <= n - 1) {
minefield [i + 1][j]++;
}
if((i + 1) <= n - 1 && (j - 1) >= 0) {
minefield [i + 1][j - 1]++;
}
if((j - 1) >= 0) {
minefield [i][j - 1]++;
}
if((i - 1) >= 0 && (j - 1) >= 0) {
minefield [i - 1][j - 1]++;
}
}
}
}
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(minefield [i][j] < 0) {
out.print('*');
}else {
out.print(minefield [i][j]);
}
}
out.println();
}
out.close();
}
}
运行结果图:
这题难就难在八个方向的判断这里,很容易出现数组越界错误,当出现数组越界错误时,洛谷会出现一个叫“RE”的错误,RE:运行时错误。
RE错误常见的情况:
- 数组越界:尝试访问数组超出其定义范围的元素。
- 空指针解引用:试图通过空指针访问对象或内存。
- 除以零:在整数或浮点数除法中,除数为零。
- 栈溢出:通常由于无限递归或过大的局部变量/数组分配导致。
- 内存溢出:尝试分配超过可用内存的空间。
- 访问非法地址:试图读取或写入不属于程序的内存地址。
- 使用未初始化的变量:在某些情况下,使用未初始化的变量可能导致运行时错误。
- 浮点数异常:如除以零、溢出、下溢或非法的浮点操作。