扫雷游戏的规则就不多说了
然后的话跟大部分人一样我也是运用二维数组来进行存储雷的信息,不过使用的是二进制数来表示雷的个数 是否插旗 和是否是雷
二维数组存储的表示这个信息 0b 0000 00 0
0001 代表有一个雷
00: 00 打开
01 插旗
10 打开
0:1 是雷
0 不是雷
首先是埋雷 埋雷的话是用随机函数来随机生成坐标X Y,然后的话主要判断方式是通过位运算来判断是否为雷,因为用的是二进制数
然后的话 输出的值是通过二进制转化成十进制的数,而我们所需要的的是 1 2 3 4 这种,所以还要让二进制的数向右位移三位,因为最后三位数并不影响雷的个数输出(这里的雷的个数是雷周围的值,也就是旁边有几个雷,以自己为中心的九宫格)。
因为是面向对象的想法 所以首先Point类,这个类是数组的下标X Y以及状态State 0b0000000
Point()
public class Point {
private int x;//行
private int y;//列
private int state;// 0b1111(表示附近雷的数量)11(表示棋子状态 00 没打开 10插旗 01 打开)1(1为雷 0不为雷)
public Point(){}
public Point(int x,int y,int state)
{
this.x = x;
this.y = y;
this.state=state;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
}
获取扫雷页面,而获取到扫雷页面的时候也已经赋值好了,也就是地雷状态这些,suoyi,然后的话运用的是对象数组。
MineMaps()
import java.util.Random;
public class MineMaps {
private int rows; //行
private int cols; //列
private int minecount; //雷的数量
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public int getCols() {
return cols;
}
public void setCols(int cols) {
this.cols = cols;
}
public int getMinecount() {
return minecount;
}
public void setMinecount(int minecount) {
this.minecount = minecount;
}
public MineMaps(){}
public MineMaps(int rows,int cols,int minecount){
this.rows = rows;
this.cols = cols;
this.minecount = minecount;
}
public Point[][] getMineMaps(){
Point[][] mineBoard=new Point[rows][cols];
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
mineBoard[i][j]=new Point(i,j,0);
}
}
return burnMine(mineBoard);
}
public Point[][] burnMine(Point [][] mineBoard)
{
Random rd=new Random();
for(int i=0;i<minecount;)
{
int x=rd.nextInt(rows);
int y=rd.nextInt(cols);
if((mineBoard[x][y].getState()&0b1)==0)
{
//没有雷
//埋雷
mineBoard[x][y].setState(mineBoard[x][y].getState()|0b1);
if(x-1>=0)
{
if(y-1>=0)//左上
{
mineBoard[x-1][y-1].setState(mineBoard[x-1][y-1].getState()+0b0001000);
}
if(y+1<cols) //右上
{
mineBoard[x-1][y+1].setState(mineBoard[x-1][y+1].getState()+0b0001000);
}
//正上方
mineBoard[x-1][y].setState(mineBoard[x-1][y].getState()+0b0001000);
}
if(x+1<rows)
{
if(y-1>=0)//左下
{
mineBoard[x+1][y-1].setState(mineBoard[x+1][y-1].getState()+0b0001000);
}
if(y+1<cols) //右下
{
mineBoard[x+1][y+1].setState(mineBoard[x+1][y+1].getState()+0b0001000);
}
//正下方
mineBoard[x+1][y].setState(mineBoard[x+1][y].getState()+0b0001000);
}
if(y-1>=0) //x最左边时
{
mineBoard[x][y-1].setState(mineBoard[x][y-1].getState()+0b0001000);
}
if(y+1<cols) //x在最右边时
{
mineBoard[x][y+1].setState(mineBoard[x][y+1].getState()+0b0001000);
}
i++;
}
}
return mineBoard;
}
}
ClearMineGame类
这个类中包含了几个功能,整个游戏进行都在这里,分为开始选择难度,输入坐标打开格子,如果是地雷直接游戏结束,如果是空白则直接向周围的格子寻找是不是空白,如果是就打开然后一直递归,直到空白周围有数字为止,然后的话还有插旗和删旗的功能,当插旗数与地雷数一样,游戏取得胜利,不过我这里的代码其实还有点问题,就是删旗和判断游戏胜利那个地方,等明天再解决了。
import java.util.Scanner;
public class ClearMineGame {
private MineMaps mineMap;
private int pointCount;
private Point[][] minePoints;
Scanner sc = new Scanner(System.in);
static int f=0;
public void init() {
System.out.println("***************欢迎进行扫雷*************");
System.out.println("**************请选择游戏难度 2.中等 3.困难*************");
int choice = sc.nextInt();
switch (choice) {
case 2:
mineMap = new MineMaps(16, 16, 40);
pointCount = 16 * 16;
break;
case 3:
mineMap = new MineMaps(16, 30, 99);
pointCount = 16 * 30;
break;
default:
mineMap = new MineMaps(9, 9, 10);
pointCount = 9 * 9;
break;
}
minePoints = mineMap.getMineMaps();
playGame();
}
private void playGame() {
showMineBoard();
boolean isOver = false;
System.out.println("请输入坐标");
int x = sc.nextInt();
int y = sc.nextInt();
Point point = minePoints[x - 1][y - 1];
System.out.println("请选择操作1.打开 2.插旗 3.拔旗");
int choice=0;
do{
choice=sc.nextInt();
switch(choice)
{
case 1:
isOver=openPoint(point);
break;
case 2:
insertFlag(point);
break;
case 3:
deletFlag(point);
break;
default:
System.out.println("没有此选项,请重新输入");
break;
}
}while(choice<1||choice>3);
if(isOver==true)
{
showMineBoard();
System.out.println("游戏结束....");
}else{
playGame();
}
}
private boolean openPoint(Point point)
{//1.判断是否为雷
//2.不是雷 如果点击空白点 级联打开
if((point.getState()&0b1)==0b1)
{
for(int i=0;i<minePoints.length;i++)
{
for(int j=0;j<minePoints[0].length;j++)
{
minePoints[i][j].setState(minePoints[i][j].getState()|0b010);//游戏结束 所有格子全部打开
}
}
return true;
}else{
openwhitePoint(point);
if(pointCount==0&&(f==mineMap.getMinecount()))
{
System.out.println("恭喜通关!");
}
}
return false;
}
private void openwhitePoint(Point point)
{
if(((point.getState()&0b1)==0b1)||((point.getState()&0b110)==0b100)||(point.getState()&0b110)==0b010)
{
return ;
}
minePoints[point.getX()][point.getY()].setState(point.getState()|0b010);
pointCount--;
if(point.getState()>>3==0)
{
if(point.getX()-1>0)
{
if(point.getY()-1>0) //左上
{
openwhitePoint(minePoints[point.getX()-1][point.getY()-1]);
}
if(point.getY()+1<minePoints[0].length) //右上
{
openwhitePoint(minePoints[point.getX()-1][point.getY()+1]);
}
openwhitePoint(minePoints[point.getX()-1][point.getY()]);
}
if(point.getX()+1<minePoints.length)
{
if(point.getY()-1>0)//左下
{
openwhitePoint(minePoints[point.getX()+1][point.getY()-1]);
}
if(point.getY()+1<minePoints[0].length)//右下
{
openwhitePoint(minePoints[point.getX()+1][point.getY()+1]);
}
openwhitePoint(minePoints[point.getX()+1][point.getY()]);
}
if(point.getY()-1>=0)
{
openwhitePoint(minePoints[point.getX()][point.getY()-1]);
}
if(point.getY()+1<minePoints[0].length)
{
openwhitePoint(minePoints[point.getX()][point.getY()+1]);
}
}
}
private void insertFlag(Point point)
{
if((point.getState()&0b110)==0b010)
{
System.out.println("已经打开!");
return;
}
if((point.getState()&0b110)==0b100)
{
System.out.println("已经是插过的旗子了!");
return ;
}
minePoints[point.getX()][point.getY()].setState(point.getState()|0b100);
f++;
pointCount--;
}
private void deletFlag(Point point)
{
if((point.getState()&0b110)==0b100)
{
minePoints[point.getX()][point.getY()].setState(minePoints[point.getX()][point.getY()].getState()&0b000);
}
}
public void showMineBoard() {
// 输出列下标
System.out.print("\t");
for (int i = 1; i <= minePoints[0].length; i++) {
System.out.print(i + "\t");
}
System.out.println();
// 输出*
System.out.print("\t");
for (int i = 0; i < minePoints[0].length; i++) {
System.out.print("*\t");
}
System.out.println();
for (int i = 0; i < minePoints.length; i++) {
System.out.print((i + 1) + "*\t");
for (int j = 0; j < minePoints[0].length; j++) {
// 判断是否打开
if ((minePoints[i][j].getState() & 0b110) == 0) // 未打开
{
System.out.print("M\t");
} else if ((minePoints[i][j].getState() & 0b100) == 0b100) {
// 10 表示插旗 xxxx10x & 0b110
System.out.print("F\t");
} else {
if ((minePoints[i][j].getState() & 0b1) == 0b1) // 判断是否为雷
{
System.out.print("N\t");
} else {
if (minePoints[i][j].getState() >> 3 == 0) // 使用位运算来判断
{
System.out.print("\t"); // 值为0的话 就设置为空
} else {
System.out.print((minePoints[i][j].getState() >> 3) + "\t"); // 二进制数向右移动三位
// 0b0001000
// 0b0010000
/*
* 0b0011000
*/
}
}
}
}
System.out.println();
}
}
}
public class Start {
public static void main(String[] args) {
ClearMineGame s=new ClearMineGame();
s.init();
}
}