教你使用Java实现扫雷小游戏(最新完整版)

网友投稿 273 2022-07-30


目录效果展示主类:GameWin类底层地图MapBottom类顶层地图MapTop类底层数字BottomNum类初始化地雷BottomRay类工具GameUtil类总结

大家好,我是orangemilk_,哈哈,学习java已经到一个阶段啦,今天我们使用GUI来写一个扫雷小游戏吧!

效果展示

主类:GameWin类

package com.sxt;

import javax.swing.*;

import java.awt.*;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

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;

Image offScreenImage = null;

MapBottom mapBottom = new MapBottom();

MapTop mapTop = new MapTop();

void launch(){

GameUtil.START_TIME=System.currentTimeMillis();

this.setVisible(true);

this.setSize(width,height);

this.setLocationRelativeTo(null);

this.setTitle("Java扫雷小游戏");

this.setDefaultCloseOperation(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;

}

//去掉break,任何时候都监听鼠标事件

case 1 :

case 2 :

if(e.getButton()==1){

if(e.getX()>GameUtil.OFFSET + GameUtil.SQUARE_LENGTH*(GameUtil.MAP_W/2)

&& e.getX()

&& e.getY()>GameUtil.OFFSET

&& e.getY()

mapBottom.reGame();

mapTop.reGame();

GameUtil.FLAG_NUM=0;

GameUtil.START_TIME=System.currentTimeMillis();

GameUtil.state=0;

}

}

break;

default:

}

}

});

while (true){

repaint();

try {

Thread.sleep(40);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

@Override

public void paint(Graphics g) {

offScreenImage = this.createImage(width,height);

Graphics gImage = offScreenImage.getGraphics();

//设置背景颜色

gImage.setColor(Color.lightGray);

gImage.fillRect(0,0,width,height);

mapBottom.paintSelf(gImage);

mapTop.paintSelf(gImage);

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

}

public static void main(String[] args) {

GameWin gameWin = new GameWin();

gameWin.launch();

}

}

底层地图MapBottom类

//底层地图:绘制游戏相关组件

package com.sxt;

import java.awt.*;

public class 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();

}

//绘制方法

void paintSelf(Graphics g){

g.setColor(Color.BLACK);

//画竖线

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++) {

//雷

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);

}

}

}

//绘制数字,剩余雷数,倒计时

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();

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:

}

}

}

顶层地图MapTop类

顶层地图类:绘制顶层组件

package com.sxt;

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;

}

}

}

//判断逻辑

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;

}

spaceOpen(temp_x,temp_y);

GameUtil.LEFT=false;

}

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){

numOpen(temp_x,temp_y);

}

GameUtil.RIGHT=false;

}

}

boom();

victory();

}

//数字翻开

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);

}

}

}

}

}

}

//失败判定 t 表示失败 f 未失败

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 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;

}

}

}

}

//胜利判断 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){

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;

}

//打开空格

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);

}

}

}

}

}

}

//绘制方法

void paintSelf(Graphics g){

logic();

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);

}

}

}

}

}

底层数字BottomNum类

//底层数字类

package com.sxt;

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]++;

}

}

}

}

}

}

}

}

初始化地雷BottomRay类

//初始化地雷类

package com.sxt;

public class BottomRay {

//存放坐标

int[] rays = new int[GameUtil.RAY_MAX*2];

//地雷坐标

int x,y;

http:// //是否放置 T 表示可以放置 F 不可放置

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;

}

}

}

工具GameUtil类

//工具类:存放静态参数,工具方法

package com.sxt;

import java.awt.*;

public class GameUtil {

//地雷个数

static int RAY_MAX = 5;

//地图的宽

static int MAP_W = 11;

//地图的高

static int MAP_H = 11;

//雷区偏移量

static int OFFSET = 45;

//格子边长

static int SQUARE_LENGTH = 50;

//插旗数量

static int FLAG_NUM = 0;

//鼠标相关

//坐标

static int MOUSE_X;

static int MOUSE_Y;

//状态

static boolean LEFT = false;

static boolean RIGHT = false;

//游戏状态 0 表示游戏中 1 胜利 2 失败

static int state = 0;

//倒计时

static long START_TIME;

static long END_TIME;

//底层元素 -1 雷 0 空 1-8 表示对应数字

static int[][] DATA_BOTTOM = new int[MAP_W+2][MAP_H+2];

//顶层元素 -1 无覆盖 0 覆盖 1 插旗 2 差错旗

static int[][] DATA_TOP = new int[MAP_W+2][MAP_H+2];

//载入图片

static Image lei = Toolkit.getDefaultToolkit().getImage("imgs/lei.png");

static Image top = Toolkit.getDefaultToolkit().getImage("imgs/top.gif");

static Image flag = Toolkit.getDefaultToolkit().getImage("imgs/flag.gif");

static Image noflag = Toolkit.getDefaultToolkit().getImage("imgs/noflag.png");

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");

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

static {

for (int i = 1; i <=8 ; i++) {

images[i] = Toolkit.getDefaultToolkit().getImage("imgs/num/"+i+".png");

}

}

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);

}

}

总结

在使用Java编写扫雷小游戏时遇到了很多问题,在解决问题时,确实对java的面向对象编程有了更加深入的理解。虽然GUI现在并没有很大的市场,甚至好多初学者已经放弃了学习GUI,但是利用GUI编程的过程对于培养编程兴趣,深入理解Java编程有很大的作用。本程序共封装了五个类,分别是主类GameWin类,绘制底层地图和绘制顶层地图的类MapBottom类和MapTop类,绘制底层数字的类BottomNum类,以及初始化地雷的BottomRay类和工具GameUtil类,用于存静态参数和方法。游戏的设计类似windows扫雷,用户在图形化用户界面内利用鼠标监听事件标记雷区,左上角表示剩余雷的数量,右上角动态显示使用的时间。用户可选择中间组件按钮重新游戏。为了解决程序窗口闪动的问题,本程序采用了双缓冲技术。

程序的总体界面布局:

项目结构:

程序测试:

&& e.getY()>GameUtil.OFFSET

&& e.getY()

mapBottom.reGame();

mapTop.reGame();

GameUtil.FLAG_NUM=0;

GameUtil.START_TIME=System.currentTimeMillis();

GameUtil.state=0;

}

}

break;

default:

}

}

});

while (true){

repaint();

try {

Thread.sleep(40);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

@Override

public void paint(Graphics g) {

offScreenImage = this.createImage(width,height);

Graphics gImage = offScreenImage.getGraphics();

//设置背景颜色

gImage.setColor(Color.lightGray);

gImage.fillRect(0,0,width,height);

mapBottom.paintSelf(gImage);

mapTop.paintSelf(gImage);

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

}

public static void main(String[] args) {

GameWin gameWin = new GameWin();

gameWin.launch();

}

}

底层地图MapBottom类

//底层地图:绘制游戏相关组件

package com.sxt;

import java.awt.*;

public class 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();

}

//绘制方法

void paintSelf(Graphics g){

g.setColor(Color.BLACK);

//画竖线

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++) {

//雷

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);

}

}

}

//绘制数字,剩余雷数,倒计时

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();

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:

}

}

}

顶层地图MapTop类

顶层地图类:绘制顶层组件

package com.sxt;

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;

}

}

}

//判断逻辑

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;

}

spaceOpen(temp_x,temp_y);

GameUtil.LEFT=false;

}

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){

numOpen(temp_x,temp_y);

}

GameUtil.RIGHT=false;

}

}

boom();

victory();

}

//数字翻开

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);

}

}

}

}

}

}

//失败判定 t 表示失败 f 未失败

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 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;

}

}

}

}

//胜利判断 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){

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;

}

//打开空格

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);

}

}

}

}

}

}

//绘制方法

void paintSelf(Graphics g){

logic();

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);

}

}

}

}

}

底层数字BottomNum类

//底层数字类

package com.sxt;

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]++;

}

}

}

}

}

}

}

}

初始化地雷BottomRay类

//初始化地雷类

package com.sxt;

public class BottomRay {

//存放坐标

int[] rays = new int[GameUtil.RAY_MAX*2];

//地雷坐标

int x,y;

http:// //是否放置 T 表示可以放置 F 不可放置

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;

}

}

}

工具GameUtil类

//工具类:存放静态参数,工具方法

package com.sxt;

import java.awt.*;

public class GameUtil {

//地雷个数

static int RAY_MAX = 5;

//地图的宽

static int MAP_W = 11;

//地图的高

static int MAP_H = 11;

//雷区偏移量

static int OFFSET = 45;

//格子边长

static int SQUARE_LENGTH = 50;

//插旗数量

static int FLAG_NUM = 0;

//鼠标相关

//坐标

static int MOUSE_X;

static int MOUSE_Y;

//状态

static boolean LEFT = false;

static boolean RIGHT = false;

//游戏状态 0 表示游戏中 1 胜利 2 失败

static int state = 0;

//倒计时

static long START_TIME;

static long END_TIME;

//底层元素 -1 雷 0 空 1-8 表示对应数字

static int[][] DATA_BOTTOM = new int[MAP_W+2][MAP_H+2];

//顶层元素 -1 无覆盖 0 覆盖 1 插旗 2 差错旗

static int[][] DATA_TOP = new int[MAP_W+2][MAP_H+2];

//载入图片

static Image lei = Toolkit.getDefaultToolkit().getImage("imgs/lei.png");

static Image top = Toolkit.getDefaultToolkit().getImage("imgs/top.gif");

static Image flag = Toolkit.getDefaultToolkit().getImage("imgs/flag.gif");

static Image noflag = Toolkit.getDefaultToolkit().getImage("imgs/noflag.png");

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");

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

static {

for (int i = 1; i <=8 ; i++) {

images[i] = Toolkit.getDefaultToolkit().getImage("imgs/num/"+i+".png");

}

}

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);

}

}

总结

在使用Java编写扫雷小游戏时遇到了很多问题,在解决问题时,确实对java的面向对象编程有了更加深入的理解。虽然GUI现在并没有很大的市场,甚至好多初学者已经放弃了学习GUI,但是利用GUI编程的过程对于培养编程兴趣,深入理解Java编程有很大的作用。本程序共封装了五个类,分别是主类GameWin类,绘制底层地图和绘制顶层地图的类MapBottom类和MapTop类,绘制底层数字的类BottomNum类,以及初始化地雷的BottomRay类和工具GameUtil类,用于存静态参数和方法。游戏的设计类似windows扫雷,用户在图形化用户界面内利用鼠标监听事件标记雷区,左上角表示剩余雷的数量,右上角动态显示使用的时间。用户可选择中间组件按钮重新游戏。为了解决程序窗口闪动的问题,本程序采用了双缓冲技术。

程序的总体界面布局:

项目结构:

程序测试:

mapBottom.reGame();

mapTop.reGame();

GameUtil.FLAG_NUM=0;

GameUtil.START_TIME=System.currentTimeMillis();

GameUtil.state=0;

}

}

break;

default:

}

}

});

while (true){

repaint();

try {

Thread.sleep(40);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

@Override

public void paint(Graphics g) {

offScreenImage = this.createImage(width,height);

Graphics gImage = offScreenImage.getGraphics();

//设置背景颜色

gImage.setColor(Color.lightGray);

gImage.fillRect(0,0,width,height);

mapBottom.paintSelf(gImage);

mapTop.paintSelf(gImage);

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

}

public static void main(String[] args) {

GameWin gameWin = new GameWin();

gameWin.launch();

}

}

底层地图MapBottom类

//底层地图:绘制游戏相关组件

package com.sxt;

import java.awt.*;

public class 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();

}

//绘制方法

void paintSelf(Graphics g){

g.setColor(Color.BLACK);

//画竖线

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++) {

//雷

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);

}

}

}

//绘制数字,剩余雷数,倒计时

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();

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:

}

}

}

顶层地图MapTop类

顶层地图类:绘制顶层组件

package com.sxt;

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;

}

}

}

//判断逻辑

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;

}

spaceOpen(temp_x,temp_y);

GameUtil.LEFT=false;

}

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){

numOpen(temp_x,temp_y);

}

GameUtil.RIGHT=false;

}

}

boom();

victory();

}

//数字翻开

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);

}

}

}

}

}

}

//失败判定 t 表示失败 f 未失败

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 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;

}

}

}

}

//胜利判断 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){

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;

}

//打开空格

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);

}

}

}

}

}

}

//绘制方法

void paintSelf(Graphics g){

logic();

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);

}

}

}

}

}

底层数字BottomNum类

//底层数字类

package com.sxt;

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]++;

}

}

}

}

}

}

}

}

初始化地雷BottomRay类

//初始化地雷类

package com.sxt;

public class BottomRay {

//存放坐标

int[] rays = new int[GameUtil.RAY_MAX*2];

//地雷坐标

int x,y;

http:// //是否放置 T 表示可以放置 F 不可放置

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;

}

}

}

工具GameUtil类

//工具类:存放静态参数,工具方法

package com.sxt;

import java.awt.*;

public class GameUtil {

//地雷个数

static int RAY_MAX = 5;

//地图的宽

static int MAP_W = 11;

//地图的高

static int MAP_H = 11;

//雷区偏移量

static int OFFSET = 45;

//格子边长

static int SQUARE_LENGTH = 50;

//插旗数量

static int FLAG_NUM = 0;

//鼠标相关

//坐标

static int MOUSE_X;

static int MOUSE_Y;

//状态

static boolean LEFT = false;

static boolean RIGHT = false;

//游戏状态 0 表示游戏中 1 胜利 2 失败

static int state = 0;

//倒计时

static long START_TIME;

static long END_TIME;

//底层元素 -1 雷 0 空 1-8 表示对应数字

static int[][] DATA_BOTTOM = new int[MAP_W+2][MAP_H+2];

//顶层元素 -1 无覆盖 0 覆盖 1 插旗 2 差错旗

static int[][] DATA_TOP = new int[MAP_W+2][MAP_H+2];

//载入图片

static Image lei = Toolkit.getDefaultToolkit().getImage("imgs/lei.png");

static Image top = Toolkit.getDefaultToolkit().getImage("imgs/top.gif");

static Image flag = Toolkit.getDefaultToolkit().getImage("imgs/flag.gif");

static Image noflag = Toolkit.getDefaultToolkit().getImage("imgs/noflag.png");

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");

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

static {

for (int i = 1; i <=8 ; i++) {

images[i] = Toolkit.getDefaultToolkit().getImage("imgs/num/"+i+".png");

}

}

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);

}

}

总结

在使用Java编写扫雷小游戏时遇到了很多问题,在解决问题时,确实对java的面向对象编程有了更加深入的理解。虽然GUI现在并没有很大的市场,甚至好多初学者已经放弃了学习GUI,但是利用GUI编程的过程对于培养编程兴趣,深入理解Java编程有很大的作用。本程序共封装了五个类,分别是主类GameWin类,绘制底层地图和绘制顶层地图的类MapBottom类和MapTop类,绘制底层数字的类BottomNum类,以及初始化地雷的BottomRay类和工具GameUtil类,用于存静态参数和方法。游戏的设计类似windows扫雷,用户在图形化用户界面内利用鼠标监听事件标记雷区,左上角表示剩余雷的数量,右上角动态显示使用的时间。用户可选择中间组件按钮重新游戏。为了解决程序窗口闪动的问题,本程序采用了双缓冲技术。

程序的总体界面布局:

项目结构:

程序测试:


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:基于Java实现经典蜘蛛纸牌游戏(经典蜘蛛纸牌手机版单机游戏2013)
下一篇:Java实现屏幕截图工具的代码分享(java实现截图功能)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~