·【尚学堂Java开发扫雷游戏项目】1个半小时做出java扫雷小游戏_java小游戏_Java游戏开发_Java练手项目_java项目实战_java初级项目_哔哩哔哩_bilibili
前言:
- 记录的是大致的写代码过程
- 为了视觉上更清晰,下面只是放出了完成该功能的核心代码,把每个功能的代码拼装起来,才是完整的项目代码
- 项目中导入的图片,是缩小过它们的尺寸的
package com.study;
import javax.swing.*;
/**
* 绘制
*/
public class GameWin extends JFrame {
void launch(){//绘制窗口
this.setVisible(true);//窗口是否可见
this.setSize(500,500);//窗口大小
this.setLocationRelativeTo(null);//窗口位置居中显示
this.setTitle("扫雷游戏");//窗口标题
this.setDefaultCloseOperation(EXIT_ON_CLOSE);//窗口关闭方式
}
public static void main(String[] args) {
GameWin gameWin=new GameWin();
gameWin.launch();//调用方法绘制窗口
}
}
运行结果:
package com.study;
import javax.swing.*;
import java.awt.*;
/**
* 绘制
*/
public class GameWin extends JFrame {
MapBottom mapBottom=new MapBottom();
public void paint(Graphics g){//绘制组件
mapBottom.paintSelf(g);
}
}
package com.study;
import java.awt.*;
/**
* 底层地图
* 绘制游戏相关组件
*/
public class MapBottom {
//绘制方法
void paintSelf(Graphics g){
for(int i=0;i<500;i=i+50){//每隔50像素画一条线
g.setColor(Color.red);
//通过画线,组成网格,代表雷区
//横坐标x1和x2相等,是竖线
//纵坐标y1和y2相等,是横线
g.drawLine(0,i,500,i);//横线
g.drawLine(i,0,i,500);//竖线
}
}
}
运行结果:
画草图处理变量间的数据关系,整理成公式
package com.study;
/**
* 工具类
* 存放静态参数
* 工具方法
*/
public class GameUtil {
//地图的宽
static int MAP_W=11;
//地图的高
static int MAP_H=11;
//雷区偏移量
static int OFFSET=45;
//格子边长
static int SQUARE_LENGTH=50;
}
package com.study;
import javax.swing.*;
import java.awt.*;
/**
* 绘制
*/
public class GameWin extends JFrame {
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.setSize(width,height);//窗口大小
}
}
package com.study;
import java.awt.*;
/**
* 底层地图
* 绘制游戏相关组件
*/
public class MapBottom {
//绘制方法
void paintSelf(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);
}
}
}
运行结果:
package com.study;
import java.awt.*;
/**
* 工具类
* 存放静态参数
* 工具方法
*/
public class GameUtil {
//底层元素 -1:雷 0:空 1-8:雷数
static int[][] DATA_BOTTOM=new int[MAP_W+2][MAP_H+2];
//载入图片
static Image lei=Toolkit.getDefaultToolkit().getImage("imgs/lei.png");
}
package com.study;
import java.awt.*;
/**
* 底层地图
* 绘制游戏相关组件
*/
public class MapBottom {
//绘制方法
void paintSelf(Graphics g){
//画雷格
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,//+1是为了露出红线
GameUtil.OFFSET*3+(j-1)*GameUtil.SQUARE_LENGTH+1,
GameUtil.SQUARE_LENGTH-2,
GameUtil.SQUARE_LENGTH-2,
null);
}
}
}
}
运行结果:
package com.study;
/**
* 初始化地雷
*/
public class BottomRay {
//存放坐标
int[] rays=new int[GameUtil.RAY_MAX*2];
//地雷坐标
int x,y;
{
for(int i=0;i
package com.study;
import java.awt.*;
/**
* 工具类
* 存放静态参数
* 工具方法
*/
public class GameUtil {
//地雷个数
static int RAY_MAX=5;
}
package com.study;
import java.awt.*;
/**
* 底层地图
* 绘制游戏相关组件
*/
public class MapBottom {
BottomRay bottomRay=new BottomRay();
//绘制方法
void paintSelf(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,//+1是为了露出红线
GameUtil.OFFSET * 3 + (j - 1) * GameUtil.SQUARE_LENGTH + 1,
GameUtil.SQUARE_LENGTH - 2,
GameUtil.SQUARE_LENGTH - 2,
null);
}
}
}
}
}
运行结果:
package com.study;
/**
* 初始化地雷
*/
public class BottomRay {
//是否可以放置 T:可以;F:不可以
boolean isPlace=true;
{
for(int i=0;i
package com.study;
import java.awt.*;
public class GameUtil {
//地雷个数
static int RAY_MAX=121;
}
package com.study;
import javax.swing.*;
import java.awt.*;
/**
* 绘制
*/
public class GameWin extends JFrame {
void launch(){//绘制窗口
while(true){//让窗口实时刷新
repaint();
try {
Thread.sleep(40);//每隔40毫秒刷新一次
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果:
package com.study;
/**
* 底层数据类
*/
public class BottomNum {
{
for(int i=1;i<=GameUtil.MAP_W;i++){
for(int j=1;j<=GameUtil.MAP_H;j++){
//如果遍历整个雷区时,遍历到了雷,就进一步遍历该雷周围3*3区域的雷数
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]++;
}
}
}
}
}
}
}
}
package com.study;
import java.awt.*;
/**
* 工具类
* 存放静态参数
* 工具方法
*/
public class 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("imgs/nums/"+i+".png");
}
}
}
package com.study;
import java.awt.*;
/**
* 底层地图
* 绘制游戏相关组件
*/
public class MapBottom {
BottomNum bottomNum=new BottomNum();
//绘制方法
void paintSelf(Graphics g){
//画地雷
for(int i=1;i<=GameUtil.MAP_W;i++){
//雷数
if(GameUtil.DATA_BOTTOM[i][j]>=0) {
g.drawImage(GameUtil.images[GameUtil.DATA_BOTTOM[i][j]],
GameUtil.OFFSET + (i - 1) * GameUtil.SQUARE_LENGTH + 15,//+15是为了让图片更居中
GameUtil.OFFSET * 3 + (j - 1) * GameUtil.SQUARE_LENGTH + 5,
null);
}
}
}
}
}
运行结果:
package com.study;
import java.awt.*;
/**
* 工具类
* 存放静态参数
* 工具方法
*/
public class GameUtil {
//项层元素 -1:无覆盖 0:覆盖 1:插旗 2:差错旗
static int[][] DATA_TOP=new int[MAP_W+2][MAP_H+2];
//载入图片
static Image top=Toolkit.getDefaultToolkit().getImage("imgs/top.png");
static Image flag=Toolkit.getDefaultToolkit().getImage("imgs/flag.png");
static Image noflag=Toolkit.getDefaultToolkit().getImage("imgs/noflag.png");
}
package com.study;
import javax.swing.*;
import java.awt.*;
/**
* 绘制
*/
public class GameWin extends JFrame {
MapTop mapTop=new MapTop();
public void paint(Graphics g){//绘制组件
mapTop.paintSelf(g);
}
}
package com.study;
import java.awt.*;
/**
* 顶层地图类
* 绘制顶层组件
* 判断逻辑
*/
public class MapTop {
//绘制方法
void paintSelf(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);
}
}
}
}
}
运行结果:
- 用于解决窗口不断闪动问题
- 闪动原因:在不停地绘制窗口,底层组件和顶层组件是分开被绘制进窗口,所以会交叉出现,造成闪动
- 解决办法:新建一个画布,把底层组件和顶层组件都绘制好在画布上,再把画布绘制进窗口
package com.study;
import javax.swing.*;
import java.awt.*;
/**
* 绘制
*/
public class GameWin extends JFrame {
//新建画布,用于组合底层组件和顶层组件
Image offScreenImage=null;
public void paint(Graphics g){//绘制组件
offScreenImage=this.createImage(width,height);//初始化画布
Graphics gImage=offScreenImage.getGraphics();//新建画笔
gImage.setColor(Color.orange);//背景颜色
gImage.fillRect(0,0,width,height);//填充
mapBottom.paintSelf(gImage);//调用画笔
mapTop.paintSelf(gImage);//调用画笔
g.drawImage(offScreenImage,0,0,null);//将画布绘制进窗口
}
}
运行结果:
package com.study;
import java.awt.*;
/**
* 工具类
* 存放静态参数
* 工具方法
*/
public class GameUtil {
//鼠标相关
//鼠标点击处的坐标
static int MOUSE_X;
static int MOUSE_Y;
//鼠标左右键的状态
static boolean LEFT=false;
static boolean RIGHT=false;
}
package com.study;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* 绘制
*/
public class GameWin extends JFrame {
void launch(){//绘制窗口
//鼠标事件
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;
}
}
});
}
}
package com.study;
import java.awt.*;
/**
* 顶层地图类
* 绘制顶层组件
* 判断逻辑
*/
public class MapTop {
//判断逻辑
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 paintSelf(Graphics g){
logic();//调用上面的逻辑方法
}
}
运行结果:
格子区域的数据分析:
package com.study;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* 绘制
*/
public class GameWin extends JFrame {
void launch(){//绘制窗口
//鼠标事件
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;
}
}
});
}
}
package com.study;
import java.awt.*;
/**
* 顶层地图类
* 绘制顶层组件
* 判断逻辑
*/
public class MapTop {
//格子位置
int temp_x;
int temp_y;
//判断逻辑
void logic(){
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;//释放右键
}
}
}
}
运行结果:
package com.study;
import java.awt.*;
/**
* 顶层地图类
* 绘制顶层组件
* 判断逻辑
*/
public class MapTop {
//判断逻辑
void logic(){
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);
}
}
}
//打开空格
//此处用递归,递归打开点击处的空格周围相邻的所有空格
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);//调用方法本身,是递归明显的特征
}
}
}
}
}
}
}
运行结果:
package com.study;
import java.awt.*;
/**
* 顶层地图类
* 绘制顶层组件
* 判断逻辑
*/
public class MapTop {
//判断逻辑
void logic(){
if(temp_x>=1 && temp_x<=GameUtil.MAP_W
&& temp_y>=1 && temp_y<=GameUtil.MAP_H) {
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;
}
GameUtil.RIGHT = false;//释放右键
}
}
}
}
运行结果:
package com.study;
import java.awt.*;
/**
* 顶层地图类
* 绘制顶层组件
* 判断逻辑
*/
public class MapTop {
//判断逻辑
void logic(){
if(temp_x>=1 && temp_x<=GameUtil.MAP_W
&& temp_y>=1 && temp_y<=GameUtil.MAP_H) {
if (GameUtil.RIGHT) {
//数字翻开
else if(GameUtil.DATA_TOP[temp_x][temp_y]==-1){
numOpen(temp_x,temp_y);
}
}
}
}
//数字翻开
void numOpen(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);//调用方法本身,是递归明显的特征
}
}
}
}
}
}
}
运行结果:
package com.study;
import java.awt.*;
/**
* 顶层地图类
* 绘制顶层组件
* 判断逻辑
*/
public class MapTop {
//判断逻辑
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("fail");
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;
}
}
}
}
}
运行结果:
package com.study;
import java.awt.*;
/**
* 顶层地图类
* 绘制顶层组件
* 判断逻辑
*/
public class MapTop {
//判断逻辑
void logic(){
victory();
}
//胜利判断 t:胜利;f:未胜利
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("success");
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;
}
}
运行结果:
package com.study;
import java.awt.*;
/**
* 工具类
* 存放静态参数
* 工具方法
*/
public class GameUtil {
//游戏状态 0:游戏中;1:胜利;2:失败
static int state=0;
//载入图片
static Image face=Toolkit.getDefaultToolkit().getImage("imgs/face.png");
static Image over=Toolkit.getDefaultToolkit().getImage("imgs/over.png");
static Image win=Toolkit.getDefaultToolkit().getImage("imgs/win.png");
}
package com.study;
import java.awt.*;
/**
* 底层地图
* 绘制游戏相关组件
*/
public class MapBottom {
//绘制方法
void paintSelf(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;
default:
}
}
}
package com.study;
import java.awt.*;
/**
* 顶层地图类
* 绘制顶层组件
* 判断逻辑
*/
public class 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; }
}
}
return false;
}
//胜利判断 t:胜利;f:未胜利
boolean victory(){
if(count==GameUtil.RAY_MAX){
GameUtil.state=1;
}
}
}
运行结果:
package com.study;
/**
* 底层数据类
*/
public class BottomNum {
void newNum(){
for(int i=1;i<=GameUtil.MAP_W;i++){
//...
}
}
}
package com.study;
/**
* 初始化地雷
*/
public class BottomRay {
//生成雷
void newRay(){
for(int i=0;i
package com.study;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* 绘制
*/
public class GameWin extends JFrame {
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
&& e.getY()
package com.study;
import java.awt.*;
/**
* 底层地图
* 绘制游戏相关组件
*/
public class MapBottom {
{
//游戏初始化界面
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();
}
}
package com.study;
import java.awt.*;
/**
* 顶层地图类
* 绘制顶层组件
* 判断逻辑
*/
public class MapTop {
//格子位置
int temp_x;
int temp_y;
//重置游戏
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;
}
}
}
}
运行结果:
package com.study;
import java.awt.*;
/**
* 工具类
* 存放静态参数
* 工具方法
*/
public class GameUtil {
//倒计时
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);
}
}
package com.study;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* 绘制
*/
public class GameWin extends JFrame {
void launch(){//绘制窗口
GameUtil.START_TIME=System.currentTimeMillis();
//鼠标事件
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
switch (GameUtil.state){
case 0:
case 1:
case 2://在任何状态下,点击中间的图案都可以重置游戏
if(e.getButton()==1){
if(e.getX()>GameUtil.OFFSET+GameUtil.SQUARE_LENGTH*(GameUtil.MAP_W/2)
&& e.getX()GameUtil.OFFSET
&& e.getY()
package com.study;
import java.awt.*;
/**
* 底层地图
* 绘制游戏相关组件
*/
public class MapBottom {
//绘制方法
void paintSelf(Graphics g){
//绘制数字,剩余雷数
GameUtil.drawWord(g,""+(GameUtil.RAY_MAX-GameUtil.FLAG_NUM),
GameUtil.OFFSET,
2*GameUtil.OFFSET,
30,
Color.red);
//绘制数字,倒计时
GameUtil.drawWord(g,""+(GameUtil.END_TIME-GameUtil.START_TIME)/1000,
GameUtil.OFFSET+GameUtil.SQUARE_LENGTH*(GameUtil.MAP_W-1),
2*GameUtil.OFFSET,
30,
Color.red);
switch (GameUtil.state){
case 0:
GameUtil.END_TIME=System.currentTimeMillis();//实时刷新
}
}
}
package com.study;
import java.awt.*;
/**
* 顶层地图类
* 绘制顶层组件
* 判断逻辑
*/
public class MapTop {
//判断逻辑
void logic(){
if(temp_x>=1 && temp_x<=GameUtil.MAP_W
&& temp_y>=1 && temp_y<=GameUtil.MAP_H) {
if (GameUtil.RIGHT) {
//覆盖则插旗
if(GameUtil.DATA_TOP[temp_x][temp_y]==0){
GameUtil.FLAG_NUM++;
}
//插旗则取消
else if(GameUtil.DATA_TOP[temp_x][temp_y]==1){
GameUtil.FLAG_NUM--;
}
}
}
}
//失败判定,true:失败;false:未失败
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;
}
}
}
}
}
//打开空格
//此处用递归,递归打开点击处的空格周围相邻的所有空格
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--;//释放旗子
}
}
}
}
}
}
}
运行结果:
package com.study;
/**
* 初始化地雷
*/
public class BottomRay {
//存放坐标,改成static,初始化为最大值,后续可防止数组越界
static int[] rays=new int[GameUtil.RAY_MAX*2];
}
package com.study;
import java.awt.*;
/**
* 难度选择类
*/
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;
default:
}
}
}
package com.study;
import java.awt.*;
/**
* 工具类
* 存放静态参数
* 工具方法
*/
public class GameUtil {
//游戏状态 0:游戏中;1:胜利;2:失败 3:难度选择
static int state=3;
//游戏难度 1:简单2:普通 3:困难
static int level;
}
package com.study;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* 绘制
*/
public class GameWin extends JFrame {
GameSelect gameSelect=new GameSelect();
//是否开始 f:未开始 t:开始
boolean begin=false;
void launch(){//绘制窗口
if(GameUtil.state==3){
this.setSize(500,500);//游戏难度选择窗口大小
}else{
this.setSize(width,height);//游戏界面窗口大小
}
//鼠标事件
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
switch (GameUtil.state){
case 0:
case 1:
case 2:
//在游戏重置时点击鼠标中间的滚轮可以再次选择难度
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;
default:
}
}
});
while(true){
begin();//时时刻刻在调用
}
}
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();
}
}
public void paint(Graphics g) {//绘制组件
if (GameUtil.state == 3) {
//难度选择窗口的背景颜色
g.setColor(Color.white);
g.fillRect(0,0,500,500);
gameSelect.paintSelf(g);
} else {
//...
}
}
}
运行结果: