扫雷游戏的核心数据就是存储每个格子状态的地图,使用二维数组可以很直观地对应行列结构的游戏面板,每个数组元素对应一个格子的相关信息,包括是否为地雷、周围地雷数量、是否被翻开等状态。

基础数据结构设计
首先我们需要定义两个二维数组,一个用来存储真实的地图数据,包含地雷位置和周围地雷数量,另一个用来存储玩家看到的面板状态,记录每个格子是否被翻开、是否被标记。
我们可以先定义游戏的基础参数,比如地图的行数、列数,以及地雷的总数:
// 游戏基础参数 int row = 9; // 地图行数 int col = 9; // 地图列数 int mineCount = 10; // 地雷总数 // 真实地图数组,存储每个格子的真实信息 // 0-8表示周围地雷数量,9表示当前格子是地雷 int[][] realMap = new int[row][col]; // 显示面板数组,存储玩家看到的格子状态 // 0表示未翻开,1表示已翻开,2表示标记为地雷 int[][] showMap = new int[row][col];
地图初始化与地雷布置
初始化阶段需要先把两个数组的所有元素都置为初始值,然后随机在真实地图中布置指定数量的地雷。布置地雷时要确保不会重复放在同一个位置。
import java.util.Random;
public class Minesweeper {
// 之前的参数定义省略
// 初始化地图方法
public static void initMap() {
// 初始化真实地图和显示地图为0
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
realMap[i][j] = 0;
showMap[i][j] = 0;
}
}
// 随机布置地雷
Random random = new Random();
int placedMine = 0;
while (placedMine < mineCount) {
int r = random.nextInt(row);
int c = random.nextInt(col);
// 如果该位置不是地雷,就放置地雷
if (realMap[r][c] != 9) {
realMap[r][c] = 9;
placedMine++;
}
}
}
}
计算周围地雷数量
地雷布置完成后,需要遍历真实地图的每个非地雷格子,计算它周围8个相邻格子中地雷的总数,把这个数量存到对应的数组元素中。
// 计算周围地雷数量的方法
public static void calculateMineCount() {
// 遍历真实地图的每个格子
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
// 如果当前格子是地雷,跳过
if (realMap[i][j] == 9) {
continue;
}
int count = 0;
// 遍历周围8个相邻格子
for (int x = Math.max(0, i - 1); x <= Math.min(row - 1, i + 1); x++) {
for (int y = Math.max(0, j - 1); y <= Math.min(col - 1, j + 1); y++) {
// 排除当前格子本身
if (x == i && y == j) {
continue;
}
// 如果相邻格子是地雷,计数加1
if (realMap[x][y] == 9) {
count++;
}
}
}
// 把周围地雷数量存入真实地图
realMap[i][j] = count;
}
}
}
控制台交互逻辑实现
交互部分需要接收用户的输入,包括要操作的行、列,以及操作类型(翻开或者标记),然后根据操作更新显示面板的状态,同时判断游戏是否结束。
import java.util.Scanner;
// 处理用户操作的方法
public static void handleOperation() {
Scanner scanner = new Scanner(System.in);
while (true) {
// 先打印当前显示面板
printShowMap();
System.out.println("请输入操作(格式:行 列 操作类型,操作类型0表示翻开,1表示标记):");
int inputRow = scanner.nextInt();
int inputCol = scanner.nextInt();
int opType = scanner.nextInt();
// 校验输入是否合法
if (inputRow < 0 || inputRow >= row || inputCol < 0 || inputCol >= col) {
System.out.println("输入的位置不合法,请重新输入");
continue;
}
// 处理翻开操作
if (opType == 0) {
// 如果翻开的格子是地雷,游戏结束
if (realMap[inputRow][inputCol] == 9) {
System.out.println("你踩到地雷了,游戏结束!");
// 打印真实地图让玩家看到所有地雷位置
printRealMap();
break;
} else {
// 翻开当前格子
showMap[inputRow][inputCol] = 1;
// 如果周围地雷数量为0,可以扩展翻开周围格子,这里简化为只翻开当前格子
}
} else if (opType == 1) {
// 处理标记操作,切换标记状态
if (showMap[inputRow][inputCol] == 2) {
showMap[inputRow][inputCol] = 0;
} else {
showMap[inputRow][inputCol] = 2;
}
}
// 判断游戏是否胜利:所有非地雷格子都被翻开
boolean win = true;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
// 如果非地雷格子没有被翻开,说明还没胜利
if (realMap[i][j] != 9 && showMap[i][j] != 1) {
win = false;
break;
}
}
if (!win) {
break;
}
}
if (win) {
System.out.println("恭喜你,扫雷成功!");
printRealMap();
break;
}
}
}
// 打印显示面板的方法
public static void printShowMap() {
System.out.println("当前游戏面板:");
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (showMap[i][j] == 0) {
System.out.print("* ");
} else if (showMap[i][j] == 1) {
System.out.print(realMap[i][j] + " ");
} else if (showMap[i][j] == 2) {
System.out.print("F ");
}
}
System.out.println();
}
}
// 打印真实地图的方法
public static void printRealMap() {
System.out.println("真实地图:");
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (realMap[i][j] == 9) {
System.out.print("X ");
} else {
System.out.print(realMap[i][j] + " ");
}
}
System.out.println();
}
}
完整流程串联
最后我们把所有方法串联起来,加上主函数就可以运行整个扫雷游戏了:
public class Minesweeper {
static int row = 9;
static int col = 9;
static int mineCount = 10;
static int[][] realMap = new int[row][col];
static int[][] showMap = new int[row][col];
public static void main(String[] args) {
// 初始化地图
initMap();
// 计算周围地雷数量
calculateMineCount();
// 开始处理用户交互
handleOperation();
}
// 之前的initMap、calculateMineCount、handleOperation、printShowMap、printRealMap方法都放在这里
}
以上就是一个基于二维数组的控制台扫雷游戏的基础实现逻辑,你可以根据需求扩展功能,比如添加翻开空格时自动扩展相邻无雷区域、统计游戏用时、调整地图大小和地雷数量等,进一步熟悉二维数组的使用方式。