java小游戏-扫雷游戏

java小游戏-ava小游戏-扫雷游戏

  • 1 窗口绘制
  • 2 雷区绘制
  • 3 界面规划
  • 4 底层地图
  • 5 地雷生成
  • 6 地雷重合
  • 7 数字生成
  • 8 顶层绘制
  • 9 双缓存技术
  • 10 鼠标事件
  • 11 左键翻开
  • 12 递归翻开
  • 13 右键插旗
  • 14 右键翻开
  • 15 失败判定
  • 16 胜利判断
  • 17 游戏状态
  • 18 游戏重置
  • 19 数字添加
  • 20 游戏难度选择

连接视频

1 窗口绘制

创建GameWin类

public class GameWin extends JFrame {

    //设置窗口
    void launch(){
        //设置窗口是否可见
        this.setVisible(true);
        //设置窗口大小
        this.setSize(500,500);
        //设置窗口位置(居中显示)
        this.setLocationRelativeTo(null);
        //设置窗体标题
        this.setTitle("扫雷游戏");
        //关闭窗口
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        GameWin gameWin = new GameWin();
        gameWin.launch();
    }

}

2 雷区绘制

创建MapBottom类

/**
 * 底层地图
 * 绘制游戏相关组件
 */
public class MapBottom {

    //绘制自己
    void printSelf(Graphics g){
        for (int i = 0; i < 500; i=i+50) {
            g.setColor(Color.red);
            g.drawLine(0,i,500,i);
            g.drawLine(i,0,i,500);
        }
    }

}

在GameWin类引用

private MapBottom mapBottom = new MapBottom();

//绘制区
@Override
public void paint(Graphics g) {
    mapBottom.printSelf(g);
}

3 界面规划

java小游戏-扫雷游戏_第1张图片

创建GameUtil类

/**
 * 游戏工具类
 * 存放静态参数
 * 工具方法
 */
public class GameUtil {
    //地图的宽
    static int MAP_W = 11;
    //地图的高
    static int MAP_H = 11;
    //雷区偏移量
    static int OFFSET = 45;
    //格子边长
    static int SQUARE_LENGTH = 50;
	
}

在MapBottom类修改printSelf方法

//绘制自己
void printSelf(Graphics g) {
   g.setColor(Color.red);
   //画竖线
   for (int i = 0; i <= GameUtil.MAP_W; i++) {
       g.drawLine(GameUtil.OFFSET + i * GameUtil.SQUARE_LENGTH,
               3 * GameUtil.OFFSET,
               GameUtil.OFFSET + i * GameUtil.SQUARE_LENGTH,
               3 * GameUtil.OFFSET + GameUtil.MAP_H * GameUtil.SQUARE_LENGTH);
   }

   //画横线
   for (int i = 0; i <= GameUtil.MAP_H; i++) {
       g.drawLine(GameUtil.OFFSET,
               3 * GameUtil.OFFSET + i * GameUtil.SQUARE_LENGTH,
               GameUtil.OFFSET + GameUtil.MAP_W * GameUtil.SQUARE_LENGTH,
               3 * GameUtil.OFFSET + i * GameUtil.SQUARE_LENGTH);
   }
}

在GameWin添加参数

int width = 2 * GameUtil.OFFSET + GameUtil.MAP_W * GameUtil.SQUARE_LENGTH;
int height = 4 * GameUtil.OFFSET + GameUtil.MAP_H * GameUtil.SQUARE_LENGTH;

void launch(){
    //设置窗口是否可见
    this.setVisible(true);
    //设置窗口大小
    this.setSize(width,height);
    //设置窗口位置(居中显示)
    this.setLocationRelativeTo(null);
    //设置窗体标题
    this.setTitle("扫雷游戏");
    //关闭窗口
    this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}

4 底层地图

先载入图片到项目中

在GameUtil类添加图片引用

//底层的元素 -1 雷 0 空 1-8 表示对应的数字
static int[][] DATA_BOTTOM = new int[MAP_W + 2][MAP_H + 2];

//载入游戏图片
static Image lei = Toolkit.getDefaultToolkit().getImage("img/lei.png");

在MapBottom类修改printSelf方法

void printSelf(Graphics g) {
     g.setColor(Color.red);
     //画竖线
     for (int i = 0; i <= GameUtil.MAP_W; i++) {
         g.drawLine(GameUtil.OFFSET + i * GameUtil.SQUARE_LENGTH,
                 3 * GameUtil.OFFSET,
                 GameUtil.OFFSET + i * GameUtil.SQUARE_LENGTH,
                 3 * GameUtil.OFFSET + GameUtil.MAP_H * GameUtil.SQUARE_LENGTH);
     }

     //画横线
     for (int i = 0; i <= GameUtil.MAP_H; i++) {
         g.drawLine(GameUtil.OFFSET,
                 3 * GameUtil.OFFSET + i * GameUtil.SQUARE_LENGTH,
                 GameUtil.OFFSET + GameUtil.MAP_W * GameUtil.SQUARE_LENGTH,
                 3 * GameUtil.OFFSET + i * GameUtil.SQUARE_LENGTH);
     }

     //绘制雷
     for (int i = 1; i <= GameUtil.MAP_W; i++) {
         for (int j = 1; j <= GameUtil.MAP_H; j++) {
             g.drawImage(GameUtil.lei,
                     GameUtil.OFFSET + (i - 1) * GameUtil.SQUARE_LENGTH + 1,
                     GameUtil.OFFSET * 3 + (j - 1) * GameUtil.SQUARE_LENGTH + 1,
                     GameUtil.SQUARE_LENGTH - 2,
                     GameUtil.SQUARE_LENGTH - 2,
                     null);
         }
     }
 }

5 地雷生成

在GameUtil类添加常量

//定义地雷的个数
static int RAY_MAX = 5;

创建BottomRay类

/**
 * 初始化地雷
 */
public class BottomRay {

    //存放坐标
    int[] rays = new int[GameUtil.RAY_MAX * 2];
    //地雷坐标
    int x, y;

    {
        for (int i = 0; i < GameUtil.RAY_MAX * 2; i = i + 2) {
            x = (int) (Math.random() * GameUtil.MAP_W + 1);//随机数:1-12
            y = (int) (Math.random() * GameUtil.MAP_H + 1);//随机数:1-12
            rays[i] = x;
            rays[i + 1] = y;
        }

        for (int i = 0; i < GameUtil.RAY_MAX * 2; i = i + 2) {
            GameUtil.DATA_BOTTOM[rays[i]][rays[i + 1]] = -1;
        }
    }

}

在MapBottom类修改printSelf方法,并且引用BottomRay类

BottomRay bottomRay = new BottomRay();

//绘制自己
void printSelf(Graphics g) {
   ...

    //绘制雷
    for (int i = 1; i <= GameUtil.MAP_W; i++) {
        for (int j = 1; j <= GameUtil.MAP_H; j++) {
            if(GameUtil.DATA_BOTTOM[i][j] == -1){
                g.drawImage(GameUtil.lei,
                        GameUtil.OFFSET + (i - 1) * GameUtil.SQUARE_LENGTH + 1,
                        GameUtil.OFFSET * 3 + (j - 1) * GameUtil.SQUARE_LENGTH + 1,
                        GameUtil.SQUARE_LENGTH - 2,
                        GameUtil.SQUARE_LENGTH - 2,
                        null);
            }
        }
    }
}

6 地雷重合

在GameUtil类修改地雷数量

//定义地雷的个数
static int RAY_MAX = 121;

在BottomRay类重绘地雷

//是否放置 true 表示可以放置 false 不可放置
boolean isPlace = true;

{
    for (int i = 0; i < GameUtil.RAY_MAX * 2; i = i + 2) {
        x = (int) (Math.random() * GameUtil.MAP_W + 1);//随机数:1-12
        y = (int) (Math.random() * GameUtil.MAP_H + 1);//随机数:1-12

        //判断坐标是否存在
        for (int j = 0; j < i; j = j+2) {
            if(x==rays[j] && y == rays[j+1]){
                i = i-2;
                isPlace = false;
                break;
            }
        }
        //将坐标放入数组
        if(isPlace){
            rays[i] = x;
            rays[i + 1] = y;
        }
        isPlace =true;
    }

    for (int i = 0; i < GameUtil.RAY_MAX * 2; i = i + 2) {
        GameUtil.DATA_BOTTOM[rays[i]][rays[i + 1]] = -1;
    }
}

在GameWin类添加死循环,绘制界面

void launch(){
    //设置窗口是否可见
    this.setVisible(true);
    //设置窗口大小
    this.setSize(width,height);
    //设置窗口位置(居中显示)
    this.setLocationRelativeTo(null);
    //设置窗体标题
    this.setTitle("扫雷游戏");
    //关闭窗口
    this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

    while (true) {
        //游戏中才调用
        repaint();
        try {
            Thread.sleep(40);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

7 数字生成

java小游戏-扫雷游戏_第2张图片

java小游戏-扫雷游戏_第3张图片

在GameUtil类定义数字图片

static int RAY_MAX = 5;

static Image[] images = new Image[9];

static {
    for (int i = 1; i <= 8; i++) {
        images[i] = Toolkit.getDefaultToolkit().getImage("img/" + i + ".png");
    }
}

创建BottomNum类

/**
 * 底层数字类
 */
public class BottomNum {

    {
        for (int i = 1; i <= GameUtil.MAP_W; i++) {
            for (int j = 1; j < GameUtil.MAP_H; j++) {
                if (GameUtil.DATA_BOTTOM[i][j] == -1) {
                    for (int k = i - 1; k <= i + 1; k++) {
                        for (int l = j - 1; l <= j + 1; l++) {
                            if (GameUtil.DATA_BOTTOM[k][l] >= 0) {
                                GameUtil.DATA_BOTTOM[k][l]++;
                            }
                        }
                    }
                }
            }
        }
    }

}

在MapBottom类添加绘制

BottomNum bottomNum = new BottomNum();

void printSelf(Graphics g) {
     ...

     //绘制雷
     for (int i = 1; i <= GameUtil.MAP_W; i++) {
         for (int j = 1; j <= GameUtil.MAP_H; j++) {
             //雷
             if (GameUtil.DATA_BOTTOM[i][j] == -1) {
                 g.drawImage(GameUtil.lei,
                         GameUtil.OFFSET + (i - 1) * GameUtil.SQUARE_LENGTH + 1,
                         GameUtil.OFFSET * 3 + (j - 1) * GameUtil.SQUARE_LENGTH + 1,
                         GameUtil.SQUARE_LENGTH - 2,
                         GameUtil.SQUARE_LENGTH - 2,
                         null);
             }
             //数字
             if (GameUtil.DATA_BOTTOM[i][j] >= 0) {
                 g.drawImage(GameUtil.images[GameUtil.DATA_BOTTOM[i][j]],
                         GameUtil.OFFSET + (i - 1) * GameUtil.SQUARE_LENGTH + 15,
                         GameUtil.OFFSET * 3 + (j - 1) * GameUtil.SQUARE_LENGTH + 5,
                         null);
             }
         }
     }
 }

8 顶层绘制

在GameUtil类添加参数

 //顶层的元素 -1 无覆盖 0 覆盖 1 插旗 2 差错旗
static int[][] DATA_TOP = new int[MAP_W + 2][MAP_H + 2];

static Image top = Toolkit.getDefaultToolkit().getImage("img/top.gif");
static Image flag = Toolkit.getDefaultToolkit().getImage("img/flag.gif");
static Image noflag = Toolkit.getDefaultToolkit().getImage("img/noflag.png");

创建MapTop类

/**
 * 顶层地图类
 * 绘制顶层组件
 * 判断逻辑
 */
public class MapTop {

    //绘制方法
    void printSelf(Graphics g) {
        for (int i = 1; i <= GameUtil.MAP_W; i++) {
            for (int j = 1; j <= GameUtil.MAP_H; j++) {
                //覆盖
                if (GameUtil.DATA_TOP[i][j] == 0) {
                    g.drawImage(GameUtil.top,
                            GameUtil.OFFSET + (i - 1) * GameUtil.SQUARE_LENGTH + 1,
                            GameUtil.OFFSET * 3 + (j - 1) * GameUtil.SQUARE_LENGTH + 1,
                            GameUtil.SQUARE_LENGTH - 2,
                            GameUtil.SQUARE_LENGTH - 2,
                            null);
                }
                //插旗
                if (GameUtil.DATA_TOP[i][j] == 1) {
                    g.drawImage(GameUtil.flag,
                            GameUtil.OFFSET + (i - 1) * GameUtil.SQUARE_LENGTH + 1,
                            GameUtil.OFFSET * 3 + (j - 1) * GameUtil.SQUARE_LENGTH + 1,
                            GameUtil.SQUARE_LENGTH - 2,
                            GameUtil.SQUARE_LENGTH - 2,
                            null);
                }
                //差错旗
                if (GameUtil.DATA_TOP[i][j] == 2) {
                    g.drawImage(GameUtil.noflag,
                            GameUtil.OFFSET + (i - 1) * GameUtil.SQUARE_LENGTH + 1,
                            GameUtil.OFFSET * 3 + (j - 1) * GameUtil.SQUARE_LENGTH + 1,
                            GameUtil.SQUARE_LENGTH - 2,
                            GameUtil.SQUARE_LENGTH - 2,
                            null);
                }

            }
        }
    }

}

在GameWin类引用MapTop类【放在MapBottom对象下面】

private MapTop mapTop = new MapTop();

@Override
public void paint(Graphics g) {
    mapBottom.printSelf(g);
    mapTop.printSelf(g);
}

9 双缓存技术

在GameWin类添加画布

//创建画布
Image offScreenImage = null;

@Override
public void paint(Graphics g) {
    offScreenImage = this.createImage(width, height);
    Graphics graphics = offScreenImage.getGraphics();
    //设置背景颜色
    graphics.setColor(Color.orange);
    //填充
    graphics.fillRect(0,0,width,height);
    mapBottom.printSelf(graphics);
    mapTop.printSelf(graphics);

    g.drawImage(offScreenImage, 0, 0, null);
}

10 鼠标事件

在GameUtil类添加参数

//鼠标相关参数
//坐标
static int MOUSE_X;
static int MOUSE_Y;
//状态
static boolean LEFT = false;
static boolean RIGHT = false;

在GameWin类的launch方法添加鼠标事件监听

void launch() {
     ...
     //关闭窗口
     this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

     //鼠标事件
     this.addMouseListener(new MouseAdapter() {
         @Override
         public void mouseClicked(MouseEvent e) {//鼠标点击事件
             super.mouseClicked(e);
             if(e.getButton() == 1){//鼠标左键点击
                 GameUtil.MOUSE_X = e.getX();
                 GameUtil.MOUSE_Y = e.getY();
                 GameUtil.LEFT = true;
             }
             if (e.getButton() == 3) {//鼠标右键点击
                 GameUtil.MOUSE_X = e.getX();
                 GameUtil.MOUSE_Y = e.getY();
                 GameUtil.RIGHT = true;
             }
         }
     });

     while (true) {
         ...
 }

在MapTop类添加logic方法

//判断鼠标逻辑
void logic(){
    if (GameUtil.LEFT) {
        System.out.println(GameUtil.MOUSE_X);
        System.out.println(GameUtil.MOUSE_Y);
        GameUtil.LEFT = false;
    }
    if (GameUtil.RIGHT) {
        System.out.println(GameUtil.MOUSE_X);
        System.out.println(GameUtil.MOUSE_Y);
        GameUtil.RIGHT = false;
    }
}

//绘制方法
void printSelf(Graphics g) {
    logic();
    ...

11 左键翻开

java小游戏-扫雷游戏_第4张图片

在MapTop类添加临时参数,修改logic方法

//格子位置
int temp_x;
int temp_y;

void logic() {
    //30/60 = 0  +1 = 1  || -30 / 60 = 0 + 1 = 1
    temp_x = 0;
    temp_y = 0;
    if (GameUtil.MOUSE_X > GameUtil.OFFSET && GameUtil.MOUSE_Y > 3 * GameUtil.OFFSET) {
        temp_x = (GameUtil.MOUSE_X - GameUtil.OFFSET) / GameUtil.SQUARE_LENGTH + 1;
        temp_y = (GameUtil.MOUSE_Y - GameUtil.OFFSET * 3) / GameUtil.SQUARE_LENGTH + 1;
    }
    
    if (temp_x >= 1 && temp_x <= GameUtil.MAP_W
            && temp_y >= 1 && temp_y <= GameUtil.MAP_H) {
        if (GameUtil.LEFT) {
         	//覆盖,则翻开	
            if (GameUtil.DATA_TOP[temp_x][temp_y] == 0) {
                GameUtil.DATA_TOP[temp_x][temp_y] = -1;
            }
            GameUtil.LEFT = false;
        }
        if (GameUtil.RIGHT) {
            System.out.println(GameUtil.MOUSE_X);
            System.out.println(GameUtil.MOUSE_Y);
            GameUtil.RIGHT = false;
        }
    }
}

12 递归翻开

在MapTop类添加spaceOpen方法,修改logic方法

void logic() {
    //30/60 = 0  +1 = 1  || -30 / 60 = 0 + 1 = 1
    temp_x = 0;
    temp_y = 0;
    if (GameUtil.MOUSE_X > GameUtil.OFFSET && GameUtil.MOUSE_Y > 3 * GameUtil.OFFSET) {
        temp_x = (GameUtil.MOUSE_X - GameUtil.OFFSET) / GameUtil.SQUARE_LENGTH + 1;
        temp_y = (GameUtil.MOUSE_Y - GameUtil.OFFSET * 3) / GameUtil.SQUARE_LENGTH + 1;
    }

    if (temp_x >= 1 && temp_x <= GameUtil.MAP_W
            && temp_y >= 1 && temp_y <= GameUtil.MAP_H) {
        if (GameUtil.LEFT) {
        	 //覆盖,则翻开
            if (GameUtil.DATA_TOP[temp_x][temp_y] == 0) {
                GameUtil.DATA_TOP[temp_x][temp_y] = -1;
            }
            spaceOpen(temp_x, temp_y);
            GameUtil.LEFT = false;
        }
        if (GameUtil.RIGHT) {
            System.out.println(GameUtil.MOUSE_X);
            System.out.println(GameUtil.MOUSE_Y);
            GameUtil.RIGHT = false;
        }
    }
}

//打开空格
void spaceOpen(int x, int y) {
    if (GameUtil.DATA_BOTTOM[x][y] == 0) {
        for (int i = x - 1; i <= x + 1; i++) {
            for (int j = y - 1; j <= y + 1; j++) {
                //覆盖,才递归
                if (GameUtil.DATA_TOP[i][j] != -1) {
                    GameUtil.DATA_TOP[i][j] = -1;//打开格子
                    //必须在雷区当中
                    if (i >= 1 && j >= 1
                            && i <= GameUtil.MAP_W && j <= GameUtil.MAP_H) {
                        spaceOpen(i, j);
                    }
                }
            }
        }
    }
}

13 右键插旗

在MapTop类修改logic方法

void logic() {
    	.....
         if (GameUtil.RIGHT) {
             //覆盖,则插旗
             if (GameUtil.DATA_TOP[temp_x][temp_y] == 0) {
                 GameUtil.DATA_TOP[temp_x][temp_y] = 1;
             }else if (GameUtil.DATA_TOP[temp_x][temp_y] == 1) { //插旗则取消
                 GameUtil.DATA_TOP[temp_x][temp_y] = 0;
             }
             spaceOpen(temp_x, temp_y);

             GameUtil.RIGHT = false;
         }
     }
 }

14 右键翻开

在MapTop类修改logic方法,添加numberOpen方法

void logic() {
    ....
        if (GameUtil.RIGHT) {
            //覆盖,则插旗
            if (GameUtil.DATA_TOP[temp_x][temp_y] == 0) {
                GameUtil.DATA_TOP[temp_x][temp_y] = 1;
            }else if (GameUtil.DATA_TOP[temp_x][temp_y] == 1) { //插旗则取消
                GameUtil.DATA_TOP[temp_x][temp_y] = 0;
            }else if(GameUtil.DATA_TOP[temp_x][temp_y] == -1){
                numberOpen(temp_x, temp_y);
            }
            GameUtil.RIGHT = false;
        }
    }
}

//数字翻开
void numberOpen(int x, int y) {
    //记录旗数
    int count = 0;
    if(GameUtil.DATA_BOTTOM[x][y] > 0){
        for (int i = x - 1; i <= x + 1; i++) {
            for (int j = y - 1; j <= y + 1; j++) {
                if (GameUtil.DATA_TOP[i][j] == 1) {
                    count++;
                }
            }
        }
    }
    if (count == GameUtil.DATA_BOTTOM[x][y]) {
        for (int i = x - 1; i <= x + 1; i++) {
            for (int j = y - 1; j <= y + 1; j++) {
                if(GameUtil.DATA_TOP[i][j] != 1){
                    GameUtil.DATA_TOP[i][j] = -1;//翻开
                }
                //必须在雷区当中
                if (i >= 1 && j >= 1
                        && i <= GameUtil.MAP_W && j <= GameUtil.MAP_H) {
                    spaceOpen(i, j);
                }
            }
        }
    }
}

15 失败判定

在MapTop类添加boom()和seeBoom()方法

void logic() {
    ....
    boom();
}

//数字翻开

//失败判定 true 表示失败 false 表示未失败
boolean boom(){
    for (int i = 1; i <= GameUtil.MAP_W ; i++) {
        for (int j = 1; j <= GameUtil.MAP_H; j++) {
            if(GameUtil.DATA_BOTTOM[i][j] == -1
                && GameUtil.DATA_TOP[i][j] == -1){
                System.out.println("ovar1");
                seeBoom();
                return true;
            }
        }
    }
    return false;
}

//失败显示所有雷
void seeBoom(){
    for (int i = 1; i <= GameUtil.MAP_W ; i++) {
        for (int j = 1; j <= GameUtil.MAP_H; j++) {
            //底层是雷 顶层未插旗
            if(GameUtil.DATA_BOTTOM[i][j] == -1
                    &&  GameUtil.DATA_TOP[i][j] != 1){
                GameUtil.DATA_TOP[i][j] = -1;
            }
            //底层不是雷 顶层是旗,显示差错旗
            if(GameUtil.DATA_BOTTOM[i][j] != -1
                    &&  GameUtil.DATA_TOP[i][j] == 1){
                GameUtil.DATA_TOP[i][j] = 2;
            }
        }
    }
}

16 胜利判断

在MapTop类添加victory()方法

void logic() {
    ....
    boom();
    victory();
}

//胜利判断 true 表示胜利 false 表示未胜利
boolean victory() {
    //统计未打开格子数
    int count = 0;
    for (int i = 1; i <= GameUtil.MAP_W; i++) {
        for (int j = 1; j <= GameUtil.MAP_H; j++) {
            //顶层不是打开
            if (GameUtil.DATA_TOP[i][j] != -1) {
                count++;
            }
        }
    }
    //判断地雷的个数
    if (count == GameUtil.RAY_MAX) {
        System.out.println("胜利");
        for (int i = 1; i <= GameUtil.MAP_W; i++) {
            for (int j = 1; j <= GameUtil.MAP_H; j++) {
                //未翻开,变成旗
                if (GameUtil.DATA_TOP[i][j] == 0) {
                    GameUtil.DATA_TOP[i][j] = 1;
                }
            }
        }
        return true;
    }
    return false;
}

17 游戏状态

在GameUtil类添加参数

//游戏状态 0 表示游戏中 1 胜利 2 失败
static int state = 0;

static Image face = Toolkit.getDefaultToolkit().getImage("img/face.png");
static Image over = Toolkit.getDefaultToolkit().getImage("img/over.png");
static Image win = Toolkit.getDefaultToolkit().getImage("img/win.png");

在MapBottom类添加绘制

void printSelf(Graphics g) {
    ...
    //游戏状态绘制
    switch (GameUtil.state) {
        case 0:
            g.drawImage(GameUtil.face,
                    GameUtil.OFFSET + GameUtil.SQUARE_LENGTH * (GameUtil.MAP_W / 2),
                    GameUtil.OFFSET,
                    null);
            break;
        case 1:
            g.drawImage(GameUtil.win,
                    GameUtil.OFFSET + GameUtil.SQUARE_LENGTH * (GameUtil.MAP_W / 2),
                    GameUtil.OFFSET,
                    null);
            break;
        case 2:
            g.drawImage(GameUtil.over,
                    GameUtil.OFFSET + GameUtil.SQUARE_LENGTH * (GameUtil.MAP_W / 2),
                    GameUtil.OFFSET,
                    null);
            break;
    }
}

在MapTop类添加游戏状态设值

//失败判定 true 表示失败 false 表示未失败
boolean boom() {
    for (int i = 1; i <= GameUtil.MAP_W; i++) {
        for (int j = 1; j <= GameUtil.MAP_H; j++) {
            if (GameUtil.DATA_BOTTOM[i][j] == -1
                    && GameUtil.DATA_TOP[i][j] == -1) {
                GameUtil.state = 2;
                seeBoom();
                return true;
            }
        }
    }
    return false;
}

//胜利判断 true 表示胜利 false 表示未胜利
 boolean victory() {
    ...
     //判断地雷的个数
     if (count == GameUtil.RAY_MAX) {
         GameUtil.state = 1;
         for (int i = 1; i <= GameUtil.MAP_W; i++) {
             for (int j = 1; j <= GameUtil.MAP_H; j++) {
                 //未翻开,变成旗
                 if (GameUtil.DATA_TOP[i][j] == 0) {
                     GameUtil.DATA_TOP[i][j] = 1;
                 }
             }
         }
         return true;
     }
     return false;
 }

18 游戏重置

修改BottomRay类

/**
 * 初始化地雷
 */
public class BottomRay {

    //存放坐标
    int[] rays = new int[GameUtil.RAY_MAX * 2];
    //地雷坐标
    int x, y;
    //是否放置 true 表示可以放置 false 不可放置
    boolean isPlace = true;

    //生成雷
    void newRay(){
        for (int i = 0; i < GameUtil.RAY_MAX * 2; i = i + 2) {
            x = (int) (Math.random() * GameUtil.MAP_W + 1);//随机数:1-12
            y = (int) (Math.random() * GameUtil.MAP_H + 1);//随机数:1-12

            //判断坐标是否存在
            for (int j = 0; j < i; j = j+2) {
                if(x==rays[j] && y == rays[j+1]){
                    i = i-2;
                    isPlace = false;
                    break;
                }
            }
            //将坐标放入数组
            if(isPlace){
                rays[i] = x;
                rays[i + 1] = y;
            }
            isPlace =true;
        }

        for (int i = 0; i < GameUtil.RAY_MAX * 2; i = i + 2) {
            GameUtil.DATA_BOTTOM[rays[i]][rays[i + 1]] = -1;
        }
    }

}

修改BottomNum类

/**
 * 底层数字类
 */
public class BottomNum {

    void newNum() {
        for (int i = 1; i <= GameUtil.MAP_W; i++) {
            for (int j = 1; j < GameUtil.MAP_H; j++) {
                if (GameUtil.DATA_BOTTOM[i][j] == -1) {
                    for (int k = i - 1; k <= i + 1; k++) {
                        for (int l = j - 1; l <= j + 1; l++) {
                            if (GameUtil.DATA_BOTTOM[k][l] >= 0) {
                                GameUtil.DATA_BOTTOM[k][l]++;
                            }
                        }
                    }
                }
            }
        }
    }

}

在MapBottom添加重置游戏方法

BottomRay bottomRay = new BottomRay();
BottomNum bottomNum = new BottomNum();
{
    bottomRay.newRay();
    bottomNum.newNum();
}

//重置游戏
void reGame(){
    for (int i = 1; i <= GameUtil.MAP_W; i++) {
        for (int j = 1; j <= GameUtil.MAP_H; j++) {
            GameUtil.DATA_BOTTOM[i][j] = 0;
        }
    }
    bottomRay.newRay();
    bottomNum.newNum();
}

在MapTop添加重置游戏方法

//重置游戏
void reGame(){
    for (int i = 1; i <= GameUtil.MAP_W; i++) {
        for (int j = 1; j <= GameUtil.MAP_H; j++) {
            GameUtil.DATA_TOP[i][j] = 0;
        }
    }
}

在GameWin类添加鼠标监听事件

void launch() {
   ....

    //鼠标事件
    this.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {//鼠标点击事件
            super.mouseClicked(e);

            switch (GameUtil.state) {
                case 0:
                    if (e.getButton() == 1) {//鼠标左键点击
                        GameUtil.MOUSE_X = e.getX();
                        GameUtil.MOUSE_Y = e.getY();
                        GameUtil.LEFT = true;
                    }
                    if (e.getButton() == 3) {//鼠标右键点击
                        GameUtil.MOUSE_X = e.getX();
                        GameUtil.MOUSE_Y = e.getY();
                        GameUtil.RIGHT = true;
                    }
                case 1:
                case 2:
                    if (e.getButton() == 1) {
                        if (e.getX() > GameUtil.OFFSET + GameUtil.SQUARE_LENGTH * (GameUtil.MAP_W / 2)
                                && e.getX() < GameUtil.OFFSET + GameUtil.SQUARE_LENGTH * (GameUtil.MAP_W / 2) + GameUtil.SQUARE_LENGTH
                                && e.getY() > GameUtil.SQUARE_LENGTH
                                && e.getY() < GameUtil.SQUARE_LENGTH + GameUtil.OFFSET) {
                            mapBottom.reGame();
                            mapTop.reGame();
                            GameUtil.state = 0;
                        }
                    }
                    break;
            }


        }
    });

   ...
}

19 数字添加

在GameUtil添加参数和方法

//插旗数量
static int FLAG_NUM = 0;

 //倒计时
static long start_time;
static long end_time;


 //绘制字符串
static void drawWord(Graphics g, String str, int x, int y, int size, Color color) {
    g.setColor(color);
    g.setFont(new Font("仿宋", Font.BOLD, size));
    g.drawString(str, x, y);
}

在MapBottom类修改相关参数

void printSelf(Graphics g) {
    ...
    //绘制数字 剩余雷数
    GameUtil.drawWord(g,
            (GameUtil.RAY_MAX - GameUtil.FLAG_NUM) + "",
            GameUtil.OFFSET,
            GameUtil.OFFSET * 2, 30, Color.red);
    //绘制,倒计时
    GameUtil.drawWord(g,
            (GameUtil.end_time - GameUtil.start_time) / 1000 + "",
            GameUtil.OFFSET + GameUtil.SQUARE_LENGTH * (GameUtil.MAP_W - 1),
            GameUtil.OFFSET * 2, 30, Color.red);

    //游戏状态绘制
    switch (GameUtil.state) {
        case 0:
            GameUtil.end_time = System.currentTimeMillis();
            g.drawImage(GameUtil.face,
                    GameUtil.OFFSET + GameUtil.SQUARE_LENGTH * (GameUtil.MAP_W / 2),
                    GameUtil.OFFSET,
                    null);
            break;
        ...
}

在MapTop类修改相关参数

 void logic() {
    ...
        if (GameUtil.RIGHT) {
            //覆盖,则插旗
            if (GameUtil.DATA_TOP[temp_x][temp_y] == 0) {
                GameUtil.DATA_TOP[temp_x][temp_y] = 1;
                GameUtil.FLAG_NUM++;
            } else if (GameUtil.DATA_TOP[temp_x][temp_y] == 1) { //插旗则取消
                GameUtil.DATA_TOP[temp_x][temp_y] = 0;
                GameUtil.FLAG_NUM--;
            } else if (GameUtil.DATA_TOP[temp_x][temp_y] == -1) {
                numberOpen(temp_x, temp_y);
            }
            GameUtil.RIGHT = false;
        }
    }
    boom();
    victory();
}

boolean boom() {
   if(GameUtil.FLAG_NUM == GameUtil.RAY_MAX){
       for (int i = 1; i <= GameUtil.MAP_W; i++) {
           for (int j = 1; j <= GameUtil.MAP_H; j++) {
               //格子未打开
               if(GameUtil.DATA_TOP[i][j] == 0){
                   GameUtil.DATA_TOP[i][j] = -1;
               }
           }
       }
   }
   for (int i = 1; i <= GameUtil.MAP_W; i++) {
       for (int j = 1; j <= GameUtil.MAP_H; j++) {
           if (GameUtil.DATA_BOTTOM[i][j] == -1
                   && GameUtil.DATA_TOP[i][j] == -1) {
               GameUtil.state = 2;
               seeBoom();
               return true;
           }
       }
   }
   return false;
}


void spaceOpen(int x, int y) {
   if (GameUtil.DATA_BOTTOM[x][y] == 0) {
       for (int i = x - 1; i <= x + 1; i++) {
           for (int j = y - 1; j <= y + 1; j++) {
               //覆盖,才递归
               if (GameUtil.DATA_TOP[i][j] != -1) {
                   if (GameUtil.DATA_TOP[i][j] == 1) {
                       GameUtil.FLAG_NUM--;
                   }
                   GameUtil.DATA_TOP[i][j] = -1;//打开格子
                   //必须在雷区当中
                   if (i >= 1 && j >= 1
                           && i <= GameUtil.MAP_W && j <= GameUtil.MAP_H) {
                       spaceOpen(i, j);
                   }
               }
           }
       }
   }
}

在GameWin类修改相关参数

void launch() {
    GameUtil.start_time = System.currentTimeMillis();
    //设置窗口是否可见
   ...

    //鼠标事件
    this.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {//鼠标点击事件
            super.mouseClicked(e);

            switch (GameUtil.state) {
                ...
                case 2:
                    if (e.getButton() == 1) {
                        if (e.getX() > GameUtil.OFFSET + GameUtil.SQUARE_LENGTH * (GameUtil.MAP_W / 2)
                                && e.getX() < GameUtil.OFFSET + GameUtil.SQUARE_LENGTH * (GameUtil.MAP_W / 2) + GameUtil.SQUARE_LENGTH
                                && e.getY() > GameUtil.SQUARE_LENGTH
                                && e.getY() < GameUtil.SQUARE_LENGTH + GameUtil.OFFSET) {
                            mapBottom.reGame();
                            mapTop.reGame();
                            GameUtil.FLAG_NUM = 0;
                            GameUtil.state = 0;
                            GameUtil.start_time = System.currentTimeMillis();
                        }
                    }
                    break;
            }
        }
    });

    ...
}

20 游戏难度选择

在GameUtil类添加修改参数

//定义地雷的个数
static int RAY_MAX = 100;
//地图的宽
static int MAP_W = 36;
//地图的高
static int MAP_H = 17;


//游戏状态 0 表示游戏中 1 胜利 2 失败 3 难度选择
static int state = 3;

//游戏难度
static int level;

创建GameSelect类

/**
 * 游戏选择难度类
 */
public class GameSelect {

    //判断鼠标是否点击到难度
    boolean hard() {
        if (GameUtil.MOUSE_X > 100 && GameUtil.MOUSE_X < 400) {
            if (GameUtil.MOUSE_Y > 50 && GameUtil.MOUSE_Y < 150) {
                GameUtil.level = 1;
                GameUtil.state = 0;
                return true;
            }
            if (GameUtil.MOUSE_Y > 200 && GameUtil.MOUSE_Y < 300) {
                GameUtil.level = 2;
                GameUtil.state = 0;
                return true;
            }
            if (GameUtil.MOUSE_Y > 350 && GameUtil.MOUSE_Y < 450) {
                GameUtil.level = 3;
                GameUtil.state = 0;
                return true;
            }
        }
        return false;
    }

    //绘制选择界面
    void paintSelf(Graphics g) {
        g.setColor(Color.black);

        g.drawRect(100, 50, 300, 100);
        GameUtil.drawWord(g, "简单", 220, 100, 30, Color.black);

        g.drawRect(100, 200, 300, 100);
        GameUtil.drawWord(g, "普通", 220, 250, 30, Color.black);

        g.drawRect(100, 350, 300, 100);
        GameUtil.drawWord(g, "困难", 220, 400, 30, Color.black);
    }

    void hard(int level) {
        switch (level) {
            case 1:
                GameUtil.RAY_MAX = 10;
                GameUtil.MAP_W = 9;
                GameUtil.MAP_H = 9;
                break;
            case 2:
                GameUtil.RAY_MAX = 40;
                GameUtil.MAP_W = 16;
                GameUtil.MAP_H = 16;
                break;
            case 3:
                GameUtil.RAY_MAX = 99;
                GameUtil.MAP_W = 30;
                GameUtil.MAP_H = 16;
                break;
        }
    }

}

在BottomRay类修改参数

//存放坐标
static int[] rays = new int[GameUtil.RAY_MAX * 2];

在GameWin类引用新对象

private GameSelect gameSelect = new GameSelect();

//是否开始,false 未开始 true 开始
boolean begin = false;

//设置窗口
void launch() {
    GameUtil.start_time = System.currentTimeMillis();
    //设置窗口是否可见
    this.setVisible(true);

    if (GameUtil.state == 3) {
        this.setSize(500,500);
    }else {
        //设置窗口大小
        this.setSize(width, height);
    }

    //设置窗口位置(居中显示)
    this.setLocationRelativeTo(null);
    //设置窗体标题
    this.setTitle("扫雷游戏");
    //关闭窗口
    this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

    //鼠标事件
    this.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {//鼠标点击事件
            super.mouseClicked(e);

            switch (GameUtil.state) {
                case 0:
                    if (e.getButton() == 1) {//鼠标左键点击
                        GameUtil.MOUSE_X = e.getX();
                        GameUtil.MOUSE_Y = e.getY();
                        GameUtil.LEFT = true;
                    }
                    if (e.getButton() == 3) {//鼠标右键点击
                        GameUtil.MOUSE_X = e.getX();
                        GameUtil.MOUSE_Y = e.getY();
                        GameUtil.RIGHT = true;
                    }
                case 1:
                case 2:
                    if (e.getButton() == 1) {
                        if (e.getX() > GameUtil.OFFSET + GameUtil.SQUARE_LENGTH * (GameUtil.MAP_W / 2)
                                && e.getX() < GameUtil.OFFSET + GameUtil.SQUARE_LENGTH * (GameUtil.MAP_W / 2) + GameUtil.SQUARE_LENGTH
                                && e.getY() > GameUtil.SQUARE_LENGTH
                                && e.getY() < GameUtil.SQUARE_LENGTH + GameUtil.OFFSET) {
                            mapBottom.reGame();
                            mapTop.reGame();
                            GameUtil.FLAG_NUM = 0;
                            GameUtil.state = 0;
                            GameUtil.start_time = System.currentTimeMillis();
                        }
                    }
                    if(e.getButton() == 2){//鼠标滚格
                        GameUtil.state = 3;
                        begin = true;
                    }
                    break;
                case 3:
                    if (e.getButton() == 1) {
                        GameUtil.MOUSE_X = e.getX();
                        GameUtil.MOUSE_Y = e.getY();
                        begin = gameSelect.hard();
                    }
                    break;
            }
        }
    });

    while (true) {
        //游戏中才调用
        repaint();
        begin();
        try {
            Thread.sleep(40);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

void begin(){
    if (begin) {
        begin = false;
        gameSelect.hard(GameUtil.level);
        dispose();
        GameWin gameWin = new GameWin();
        GameUtil.start_time = System.currentTimeMillis();
        GameUtil.FLAG_NUM = 0;
        mapBottom.reGame();
        mapTop.reGame();
        gameWin.launch();
    }
}

@Override
public void paint(Graphics g) {
    offScreenImage = this.createImage(width, height);
    Graphics graphics = offScreenImage.getGraphics();

    if(GameUtil.state == 3){
        graphics.setColor(Color.white);
        graphics.fillRect(0,0,500,500);
        gameSelect.paintSelf(graphics);
    }else {
        //设置背景颜色
        graphics.setColor(Color.orange);
        //填充
        graphics.fillRect(0, 0, width, height);
        mapBottom.printSelf(graphics);
        mapTop.printSelf(graphics);
    }

    g.drawImage(offScreenImage, 0, 0, null);
}

你可能感兴趣的:(java小游戏,java,游戏)