扫雷JavaSE+控制台

本文章主要面向于java初学者,练习方向为递归。

最近在整理javaSE的基础,突然有兴趣用javaSE写一个模拟扫雷的小程序。主要练习的是递归的使用。虽然在开发时要尽量回避使用递归,但是个人认为递归的练习依然非常的必要,递归能锻炼逻辑推理,对跟人的提高还是很有帮助的。常见的递归有,二叉树的代码实现、单链表的代码实现。

步入正题,扫雷的实现:

1、技术需要:二维数组、面向对象、Scanner读取控制台输入、递归、Math.random生成随机数。

2、实现步骤:

2.1、生成二维数组,存储地雷信息

2.2、随机生成地雷,存放到二维数组中

2.3、控制台上绘制扫雷,带坐标,方便操作

2.4、扫雷操作

2.4.1、选择输入的是地雷还是非地雷的坐标

2.4.2、判断输入坐标是否为地雷,并根据不同输入种类(地雷、非地雷)做出判断

2.4.3、根据输入点,利用递归想八个方向展开不断的扫描,注意出口和边界。

2.5、判断是否赢得游戏。赢得游戏标准是把所有地雷都找出来


以下是参考代码

package com.xdl.demo;


import java.util.Scanner;


public class MineSweeping {
private static Mine mine = null;// 记录赢的场数
private static int mineCount = 0;// 设置地雷的个数
private static int findMineCount = 0;// 记录已经找到的地雷的个数


public static void main(String[] args) {
mine = new Mine();
Scanner sc = new Scanner(System.in);
System.out.println("欢迎进入扫雷游戏。请选择游戏难度:1:低级;2:中级;3:高级");
int selNum = sc.nextInt();
Mine arr[][] = null;
a: while (true) {
switch (selNum) {
case 1:
// 创建矩阵的二维数组
arr = new Mine[9][9];
// 设置地雷个数10
mineCount = 10;
// 随机生成10个雷并随机放在二维数组中
arr = addMine(arr);
// 地雷信息存放到数组中
arr = addMineInfo(arr);
// 绘制
draw(arr);
// 扫雷开始
boolean outFalg = inXY(arr, sc);
// 结束游戏
if (outFalg) {
break a;
} else {
// 重新开始
break;
}
case 2:
// 创建矩阵的二维数组
arr = new Mine[16][16];
// 设置地雷个数40
mineCount = 40;
// 随机生成40个雷并随机放在二维数组中
arr = addMine(arr);
// 地雷信息存放到数组中
arr = addMineInfo(arr);
draw(arr);
// 扫雷开始
outFalg = inXY(arr, sc);
// 结束游戏
if (outFalg) {
break a;
} else {
// 重新开始
break;
}
case 3:
// 创建矩阵的二维数组
arr = new Mine[16][30];
// 设置地雷个数99
mineCount = 99;
// 随机生成99个雷并随机放在二维数组中
arr = addMine(arr);
// 地雷信息存放到数组中
arr = addMineInfo(arr);
draw(arr);
// 扫雷开始
outFalg = inXY(arr, sc);
// 结束游戏
if (outFalg) {
break a;
} else {
// 重新开始
break;
}
}


}


}


/**

* @param addMineArr矩阵的二维数组
* @return 放入地雷后的二维数组
*/
private static Mine[][] addMine(Mine[][] addMineArr) {
for (int i = 0; i < addMineArr.length; i++) {
for (int j = 0; j < addMineArr[0].length; j++) {
addMineArr[i][j] = new Mine(false, 0, 0);
}
}
for (int i = 0; i < mineCount;) {
int intRandom1 = (int) (addMineArr.length * Math.random());
int intRandom2 = (int) (addMineArr[0].length * Math.random());
// 判断当前位置是否是地雷
if (!addMineArr[intRandom1][intRandom2].isMine()) {
addMineArr[intRandom1][intRandom2].setMine(true);
i++;
}
}
return addMineArr;
}


/**
* 每个坐标点的地雷信息添加到数组中

* @param inArr矩阵数组
* @return 添加了每个坐标地雷信息的数组
*/
private static Mine[][] addMineInfo(Mine[][] inArr) {
// 周围地雷个数
for (int i = 0; i < inArr.length; i++) {
for (int j = 0; j < inArr[0].length; j++) {
int count = 0;
// 判断左上位置是否为地雷
if (i > 0 && j > 0) {
if (inArr[i - 1][j - 1].isMine()) {
count++;
}
}
// 判断正上位置是否为地雷
if (i > 0) {
if (inArr[i - 1][j].isMine()) {
count++;
}
}
// 判断右上位置是否为地雷
if (i > 0 && j < inArr.length - 1) {
if (inArr[i - 1][j + 1].isMine()) {
count++;
}
}
// 判断左边位置是否为地雷
if (j > 0) {
if (inArr[i][j - 1].isMine()) {
count++;
}
}
// 判断右边位置是否为地雷
if (j < inArr.length - 1) {
if (inArr[i][j + 1].isMine()) {
count++;
}
}
// 判断左下位置是否为地雷
if (i < inArr.length - 1 && j > 0) {
if (inArr[i + 1][j - 1].isMine()) {
count++;
}
}
// 判断正下位置是否为地雷
if (i < inArr.length - 1) {
if (inArr[i + 1][j].isMine()) {
count++;
}
}
// 判断右下位置是否为地雷
if (i < inArr.length - 1 && j < inArr.length - 1) {
if (inArr[i + 1][j + 1].isMine()) {
count++;
}
}
inArr[i][j].setOtherMineCount(count);
}
}
return inArr;
}


/**
* 打印所有信息

* @param arr
*            地雷信息
*/
private static void draw(Mine[][] arr) {
System.out.print("   ");
// 打印横向的标尺
for (int i = 0; i < arr[0].length; i++) {
if (i < 9) {
System.out.print(" " + (i + 1) + " ");
} else {
System.out.print((i + 1) + " ");
}
}
System.out.println();


for (int i = 0; i < arr.length; i++) {
// 打印纵向坐标
if (i < 9) {
System.out.print(" " + (i + 1));
} else {
System.out.print(i + 1);
}
System.out.print("|");
for (int j = 0; j < arr[0].length; j++) {
if (arr[i][j].isShowFalg() && (!arr[i][j].isMine())) {
System.out.print("-" + arr[i][j].getOtherMineCount() + "-");
} else if (arr[i][j].isMine() && arr[i][j].isShowFalg()) {
System.out.print("-" + "●" + "-");
} else {
System.out.print("-□-");
}
}
System.out.print("|");
System.out.println();
}
}


/**

* @param sc控制台输入流
* @param nineArr地雷信息
* @return true:退出游戏;false重新开始游戏、继续游戏
*/
private static boolean inXY(Mine[][] arr, Scanner sc) {
while (true) {
System.out.println("扫雷开始,若输入雷的坐标请输入M/m+横坐标+纵坐标,空格隔开;输入-1退出游戏");
System.out.println("若输入要点的坐标请输入P/p+横坐标+纵坐标,空格隔开;输入-1退出游戏");
String inSelect = sc.next();
int xVal = sc.nextInt() - 1;
// 横坐标非法检查
if (xVal < 0 || xVal >= arr.length) {
System.out.println("您输入的横坐标非法,请重新输入。");
continue;
}
if (xVal == -1) {
return true;
}
int yVal = sc.nextInt() - 1;
// 横坐标非法检查
if (yVal < 0 || yVal >= arr[0].length) {
System.out.println("您输入的纵坐标非法,请重新输入。");
continue;
}
if (yVal == -1) {
return true;
}
// 输入分类选项:M为地雷坐标、P:为非地雷坐标
if (inSelect.equalsIgnoreCase("M")) {
// 判断是否为地雷
if (checkWine(arr, xVal, yVal)) {
// 判断正确,找到地雷数+1
findMineCount++;
// 找到的地雷设置为显示
arr[xVal][yVal].setShowFalg(true);
System.out.println("输入正确,已找到地雷个数:" + findMineCount + "\t共有地雷:" + mineCount + "个。再接再厉。");
} else {
// 游戏输了,胜场-1
mine.setWinCount(mine.getWinCount() - 1);
System.out.println("输入错误,您已经输了!!!!重新开始游戏输入Y/y,退出游戏输入其他。");
if (sc.next().equalsIgnoreCase("Y")) {
return false;
} else {
return true;
}
}
} else if (inSelect.equalsIgnoreCase("P")) {
// 判断是否为地雷
if (checkWine(arr, xVal, yVal)) {
// 如果为地雷输了游戏,胜场-1
mine.setWinCount(mine.getWinCount() - 1);
System.out.println("踩到地雷,您已经输了!!!!重新开始游戏输入Y/y,退出游戏输入其他。");
// 菜单选择
if (sc.next().equalsIgnoreCase("Y")) {
return false;
} else {
return true;
}
}
// 判定输入信息,返回
// 输入点为基准扫描周围信息
arr = check(arr, xVal, yVal);
}
if (checkWin()) {
System.out.println(
"您已经赢得游戏,已找到地雷个数:" + findMineCount + "\t共有地雷:" + mineCount + "个。重新开始游戏输入Y/y,退出游戏输入其他。");
if (sc.next().equalsIgnoreCase("Y")) {
return false;
} else {
return true;
}
}
draw(arr);


}


}


/**

* @param arr
*            地雷现有信息
* @param xVal
*            输入的横坐标
* @param yVal
*            输入的纵坐标
* @return arr:数组最新信息添加
*/
private static Mine[][] check(Mine[][] arr, int xVal, int yVal) {
System.out.println(xVal + "\t" + yVal);
// 当前点设置为显示
arr[xVal][yVal].setShowFalg(true);
// 判断当前点是否为0,未0时显示周边的非雷位置的信息
if (arr[xVal][yVal].getOtherMineCount() == 0) {
// 把当前点是否已经判断标记设置为true
arr[xVal][yVal].setUsedFalg(true);
// 判断左上是否存在
if (xVal >= 1 && yVal >= 1) {
// 左上设置为显示
arr[xVal - 1][yVal - 1].setShowFalg(true);
// 判断下一个点是否已经经过判断
if (!arr[xVal - 1][yVal - 1].isUsedFalg()) {
// 判断左上是否为0,如果是0继续判断周围部分坐标信息
if (arr[xVal - 1][yVal - 1].getOtherMineCount() == 0) {
check(arr, xVal - 1, yVal - 1);
}


}
}


// 判断正上是否存在
if (xVal >= 1) {
// 正上设置为显示
arr[xVal - 1][yVal].setShowFalg(true);
// 判断下一个点是否已经经过判断
if (!arr[xVal - 1][yVal].isUsedFalg()) {
// 判断正上是否为0,如果是0继续判断周围部分坐标信息
if (arr[xVal - 1][yVal].getOtherMineCount() == 0) {
check(arr, xVal - 1, yVal);
}


}


}
// 判断右上是否存在
if (xVal >= 1 && yVal < arr[0].length - 1) {
// 右上设置为显示
arr[xVal - 1][yVal + 1].setShowFalg(true);
// 判断下一个点是否已经经过判断
if (!arr[xVal - 1][yVal + 1].isUsedFalg()) {


// 判断右上是否为0,如果是0继续判断周围部分坐标信息
if (arr[xVal - 1][yVal + 1].getOtherMineCount() == 0) {
check(arr, xVal - 1, yVal + 1);
}
}


}
// 判断左边是否存在
if (yVal >= 1) {
// 左边设置为显示
arr[xVal][yVal - 1].setShowFalg(true);
if (!arr[xVal][yVal - 1].isUsedFalg()) {
// 判断左边是否为0,如果是0继续判断周围部分坐标信息
if (arr[xVal][yVal - 1].getOtherMineCount() == 0) {
check(arr, xVal, yVal - 1);
}


}
}
// 判断右边是否存在
if (yVal < arr[0].length - 1) {
// 右边设置为显示
arr[xVal][yVal + 1].setShowFalg(true);
if (!arr[xVal][yVal + 1].isUsedFalg()) {


// 判断左上是否为0,如果是0继续判断周围部分坐标信息
if (arr[xVal][yVal + 1].getOtherMineCount() == 0) {
check(arr, xVal, yVal + 1);
}
}
}
// 判断左下是否存在
if (xVal < arr.length - 1 && yVal >= 1) {
// 当前坐标设置为显示
arr[xVal + 1][yVal - 1].setShowFalg(true);
if (!arr[xVal + 1][yVal - 1].isUsedFalg()) {
// 判断左上是否为0,如果是0继续判断周围部分坐标信息
if (arr[xVal + 1][yVal - 1].getOtherMineCount() == 0) {
check(arr, xVal + 1, yVal - 1);
}
}
}
// 判断正下是否存在
if (xVal < arr.length - 1) {
// 当前坐标设置为显示
arr[xVal + 1][yVal].setShowFalg(true);
if (!arr[xVal + 1][yVal].isUsedFalg()) {


// 判断左上是否为0,如果是0继续判断周围部分坐标信息
if (arr[xVal + 1][yVal].getOtherMineCount() == 0) {
check(arr, xVal + 1, yVal);
}
}
}
// 判断右下是否存在
if (xVal < arr.length - 1 && yVal < arr[0].length - 1) {
// 当前坐标设置为显示
arr[xVal + 1][yVal + 1].setShowFalg(true);
if (!arr[xVal + 1][yVal].isUsedFalg()) {
// 判断左上是否为0,如果是0继续判断周围部分坐标信息
if (arr[xVal + 1][yVal + 1].getOtherMineCount() == 0) {
check(arr, xVal + 1, yVal + 1);
}
}


}
}


return arr;
}


/**

* @param arr
*            地雷信息
* @param xVal
*            横坐标
* @param yVal
*            纵坐标
* @return true:是地雷;false:不是地雷
*/
private static boolean checkWine(Mine[][] arr, int xVal, int yVal) {
if (arr[xVal][yVal].isMine()) {
return true;
} else {
return false;
}
}


/**

* @return true:赢得游戏;false:没赢
*/
private static boolean checkWin() {
// 地雷个数与找到的地雷数相等
if (findMineCount == mineCount) {
// 胜场+1
mine.setWinCount(mine.getWinCount() + 1);
return true;
}
return false;
}


}


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

地雷的类

package com.xdl.demo;


public class Mine {
private boolean isMine;// 是否是地雷
private int otherMineCount;// 周围地雷个数
private int winCount;// 赢的局数
private boolean showFalg = false;// 是否显示
private boolean usedFalg = false;// 是否用此点判断过周围地雷--用于递归出口判断


public Mine() {
super();
}


public Mine(boolean isMine, int otherMineCount, int winCount) {
super();
this.isMine = isMine;
this.otherMineCount = otherMineCount;
this.winCount = winCount;
}


public boolean isMine() {
return isMine;
}


public void setMine(boolean isMine) {
this.isMine = isMine;
}


public int getOtherMineCount() {
return otherMineCount;
}


public void setOtherMineCount(int otherMineCount) {
this.otherMineCount = otherMineCount;
}


public int getWinCount() {
return winCount;
}


public void setWinCount(int winCount) {
this.winCount = winCount;
}


public boolean isShowFalg() {
return showFalg;
}


public void setShowFalg(boolean showFalg) {
this.showFalg = showFalg;
}


public boolean isUsedFalg() {
return usedFalg;
}


public void setUsedFalg(boolean usedFalg) {
this.usedFalg = usedFalg;
}


@Override
public String toString() {
return "Mine [isMine=" + isMine + ", otherMineCount=" + otherMineCount + ", winCount=" + winCount
+ ", showFalg=" + showFalg + ", usedFalg=" + usedFalg + "]";
}


}






JavaSE是Java平台的一个版本,它提供了一系列的API和工具,可以用于开发各种类型的应用程序。MySQL是一个开源关系型数据库管理系统,它提供了高效、稳定和可靠的数据存储和检索功能。JDBC是Java数据库连接技术,它允许通过Java代码连接和操作关系型数据库。 在一个JavaSE项目中,我们可以使用JDBC来连接MySQL数据库,并完成与数据库的交互。首先,我们需要导入JDBC相关的jar包,例如MySQL Connector/J,这个jar包提供了连接MySQL数据库所需的驱动程序。我们可以从MySQL官网下载并导入这个jar包。 接下来,在Java代码中,我们通过加载JDBC驱动程序,使用合适的URL、用户名和密码连接到MySQL数据库。这个URL包含了数据库的IP地址、端口号和数据库名称等信息。一旦连接成功,我们可以使用JDBC提供的API执行SQL语句,例如插入、更新和删除数据,或者查询数据库中的数据。 在JDBC项目中,我们可以使用PreparedStatement对象来预编译SQL语句,以提高执行效率和安全性。通过设置参数,我们可以动态地构建和执行SQL语句,避免了SQL注入等安全问题。 此外,我们还可以使用JDBC的事务操作来确保数据库的一致性和完整性。通过开始事务、执行SQL语句和提交或回滚事务,我们可以在多个数据库操作之间实现原子性和隔离性。 在开发JDBC项目时,我们还要注意资源的管理和释放,包括数据库连接、Statement和ResultSet等对象的关闭,以避免内存泄漏和性能问题。 总的来说,基于JavaSE的MySQL JDBC项目可以通过JDBC技术与MySQL数据库进行连接和交互。开发者可以使用JDBC提供的API执行各种数据库操作,并通过事务来确保数据的一致性。在项目开发过程中要注意合理管理和释放资源,以提高项目的性能和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值