运用二进制知识写扫雷小游戏
前言
相信各位同学都玩过扫雷游戏,接下来我们来玩一玩扫雷code。我用的二进制知识表示雷的一些规则。以下是相关注释和代码。
扫雷类代码块
package Demo1;
import java.util.Random;
import java.util.Scanner;
/**
* 1.使用整形二维数组完成扫雷游戏1.是否为雷 2.周围雷的数量 3.状态:打开 未打开 插旗
* ob0 xxxx xx x ------
* 分成三组:
* 第一组:前四位 表示雷的数量 0001 表示一个雷 加一个雷的数量 0b00001000
* 第二组:中间两位 表示状态 00 未打开 10 插旗 01 打开
* 第三组:最后一位 表示雷 1 雷 0 没有雷
* 2.埋雷成功
* 2.1随机一个点 判断该点是否已经埋雷
* 已埋-》重新随机
* 未埋-》修改最后一位从0——》1
* 再以当前这个雷为中心,周围的八个点的雷数量+0b1000
* 0-->0b0 0000 00 0
* 1-->0b0 0000 00 1
* 8-->0b0 0001 00 0 -->1
* 16->0b0 0010 00 0 -->2
* 17->0b0 0010 00 1
* 24->0b0 0011 00 0 -->3
* 32->0b0 0100 00 0
* 25->0b0 0011 00 1
* @author 86151
*
*/
public class ClearMineGame {
int rows;//行长度
int cols;//列长度
int mineCount;//雷的数量
int pointCount;//未打开的棋子数量
int[][]mineBoard;
//构造函数
public ClearMineGame() {
init();//初始化操作
}
//初始化操作
public void init() {
Scanner sc=new Scanner(System.in);
int choice=0;
System.out.println("******************欢迎进入扫雷游戏社区*******************");
System.out.println("请选择游戏等级:1.初级 2.中级 3.高级");
choice=sc.nextInt();
switch (choice) {
case 2:
rows=16;
cols=16;
mineCount=40;
break;
case 3:
rows=16;
cols=30;
mineCount=100;
default:
rows=9;
cols=9;
mineCount=10;
break;
}
//创建二维数组
mineBoard=new int[rows][cols];
pointCount=rows*cols;
burnMine();
}
//开始游戏
public void startGame() {
int choice=0;
boolean flag=false;//标识游戏是否结束
Scanner sc=new Scanner(System.in);
showMineBoard2();
System.out.println("请输入坐标(x,y):");
int x=sc.nextInt()-1;
int y=sc.nextInt()-1;
do {
System.out.println("请选择:1.打开 2.插旗 3.拔旗");
choice=sc.nextInt();
switch (choice) {
case 1:
flag=openPoint(x,y);
break;
case 2:
insertFlag(x,y);
break;
case 3:
delFlag(x,y);
break;
default:
System.out.println("输入选项有误,请重新输入!");
break;
}
}while(choice<1||choice>3);
if(flag==false) {
startGame();
}else {
System.out.println("游戏结束。。。。。");
}
}
public void burnMine() {
Random rd=new Random();
for(int i=0;i<mineCount;) {
int x=rd.nextInt(rows);
int y=rd.nextInt(cols);
//判断是否为雷
if((mineBoard[x][y]&0b1)==1)
{
//是 重新循环
continue;
}
//不是 埋雷的操作
mineBoard[x][y]=mineBoard[x][y]|0b1;
//以雷为中心,周围8个点雷的数量+1
//上一行
if(x-1>=0) {
//左上角
if(y-1>=0) {
mineBoard[x-1][y-1]+=0b1000;
}
//右上角
if(y+1<cols) {
mineBoard[x-1][y+1]+=0b1000;
}
//正上方
mineBoard[x-1][y]+=0b1000;
}
//下一行
if(x+1<rows) {
//左下角
if(y-1>=0) {
mineBoard[x+1][y-1]+=0b1000;
}
//右下角
if (y+1<cols) {
mineBoard[x+1][y+1]+=0b1000;
}
//正下方
mineBoard[x+1][y]+=0b1000;
}
//同一行
//左边点
if (y-1>=0) {
mineBoard[x][y-1]+=0b1000;
}
//右边点
if (y+1<cols) {
mineBoard[x][y+1]+=0b1000;
}
i++;//当埋雷成功再i++
}
}
//拔旗
public void delFlag(int x,int y) {
if((mineBoard[x][y]&0b00000110)==0b100) {
mineBoard[x][y]=mineBoard[x][y]&0b01111001;
return;
}
System.out.println("没有插旗,不能进行拔旗操作!!");
}
//插旗
public void insertFlag(int x,int y) {
if((mineBoard[x][y]&0b00000110)==0b10) {
System.out.println("棋子已打开,不能插旗!!");
return;
}
if((mineBoard[x][y]&0b00000110)==0b100) {
System.out.println("棋子已插旗,不能重复插旗!!");
return;
}
mineBoard[x][y]=mineBoard[x][y]|0b100;
}
//打开棋子
public boolean openPoint(int x, int y) {
//1.判断是否为雷,结束游戏
if((mineBoard[x][y]&0b1)==0b1) {
//是雷 将所有的棋子打开
for(int i=0;i<rows;i++) {
for(int j=0;j<cols;j++) {
//全部设置为未打开然后再设置为打开
mineBoard[i][j]=(mineBoard[i][j]&0b01111001)|0b10;
}
}
showMineBoard2();//再次显示所有的棋子
return true;
}else {
//2.不是雷 数字 空白点(将周围的未打开且不是雷的点自动打开)
openWhitePoint(x,y);
//判断 剩余未打开的棋子数量==雷的数量 说明胜利 游戏结束
if(pointCount==mineCount) {
System.out.println("恭喜你,获胜了!!");
return true;
}
}
return false;
}
public void openWhitePoint(int x,int y) {
int state=mineBoard[x][y];
//1.是雷 2.已打开 3.插旗 不能去操作该点
if((state&0b1)==0b1||(state&0b110)==0b010||(state&0b110)==0b100){
return;
}
//设置为打开
mineBoard[x][y]=mineBoard[x][y]|0b10;
//未打开的点-1
pointCount--;
//判断当前这个点是否为空白点
if((mineBoard[x][y]>>3)==0) {
//说明是一个空白点,以空白点为中心,打开周围其他的点
//上一行
if(x-1>=0) {
//左上角
if(y-1>=0) {
openWhitePoint(x-1,y-1);
}
//右上角
if(y+1<cols) {
openWhitePoint(x-1,y+1);
}
//正上方
openWhitePoint(x-1,y);
}
//下一行
if(x+1<rows) {
//左下角
if(y-1>=0) {
openWhitePoint(x+1,y-1);
}
//右下角
if (y+1<cols) {
openWhitePoint(x+1,y+1);
}
//正下方
openWhitePoint(x+1,y);
}
//同一行
//左边点
if (y-1>=0) {
openWhitePoint(x,y-1);
}
//右边点
if (y+1<cols) {
openWhitePoint(x,y+1);
}
}
}
//显示棋盘,游戏中调用此方法
public void showMineBoard2() {
if(null==mineBoard) {
return;
}
showCol();
showXin();
//mineBoard[0][0]=0b00010101;
//mineBoard[0][1]=0b00010010;
for(int i=0;i<rows;i++) {
//输出行下标
System.out.print((i+1)+"*\t");
for(int j=0;j<cols;j++) {
//未打开00
if((mineBoard[i][j]&0b110)==0b0) {
System.out.print("N\t");
}
//插旗
else if ((mineBoard[i][j]&0b110)==0b100) {
System.out.print("F\t");
}else {//打开
if((mineBoard[i][j]&0b1)==1) {
System.out.print("M\t");
}
else {
if((mineBoard[i][j]>>3)==0) {
System.out.print(" \t");
}
else {
System.out.print((mineBoard[i][j]>>3)+"\t");
}
}
}
}
System.out.print("*"+(i+1));
System.out.println();
}
showXin();
showCol();
}
//显示列表号
public void showCol() {
for(int i=0;i<=cols;i++) {
if(i==0) {
System.out.print("\t");
}else {
System.out.print(i+"\t");
}
}
System.out.println();
}
//显示*
public void showXin() {
for(int i=0;i<=cols;i++) {
if(i==0) {
System.out.print("\t");
}else {
System.out.print("*\t");
}
}
System.out.println();
}
}
扫雷测试类代码块
package Demo1;
public class ClearMineGameTest {
public static void main(String[] args) {
ClearMineGame game=new ClearMineGame();
game.startGame();
}
}
如果有什么疑问或者缺陷不足,还请不吝赐教。谢谢!