您的位置:首页 > 编程语言 > Java开发

扫雷JavaSE+控制台

2017-08-10 09:53 92 查看
本文章主要面向于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 + "]";

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息