發(fā)布時(shí)間:2023-11-27 01:23:13 瀏覽量:145次
摘要:本程序共封裝了五個(gè)類,分別是主類GameWin類,繪制底層地圖和繪制頂層地圖的類MapBottom類和MapTop類,繪制底層數(shù)字的類BottomNum類,以及初始化地雷的BottomRay類和工具GameUtil類,用于存靜態(tài)參數(shù)和方法。
本文分享自華為云社區(qū)《Java實(shí)現(xiàn)掃雷小游戲【完整版】-云社區(qū)-華為云》,作者:橙子!。
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);
//鼠標(biāo)事件
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,任何時(shí)候都監(jiān)聽(tīng)鼠標(biāo)事件
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.OFFSET
&& e.getY()<GameUtil.OFFSET+GameUtil.SQUARE_LENGTH){
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();
//設(shè)置背景顏色
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();
}
}
//底層地圖:繪制游戲相關(guān)組件
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);
//畫(huà)豎線
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);
}
//畫(huà)橫線
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);
}
//數(shù)字
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);
}
}
}
//繪制數(shù)字,剩余雷數(shù),倒計(jì)時(shí)
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:
}
}
}
頂層地圖類:繪制頂層組件
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){
//覆蓋,則翻開(kāi)
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();
}
//數(shù)字翻開(kāi)
void numOpen(int x,int y){
//記錄旗數(shù)
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;
}
//必須在雷區(qū)當(dāng)中
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;
}
//底層不是雷,頂層是旗,顯示差錯(cuò)旗
if(GameUtil.DATA_BOTTOM[i][j]!=-1&&GameUtil.DATA_TOP[i][j]==1){
GameUtil.DATA_TOP[i][j]=2;
}
}
}
}
//勝利判斷 t 表示勝利 f 未勝利
boolean victory(){
//統(tǒng)計(jì)未打開(kāi)格子數(shù)
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++) {
//未翻開(kāi),變成旗
if(GameUtil.DATA_TOP[i][j]==0){
GameUtil.DATA_TOP[i][j]=1;
}
}
}
return true;
}
return false;
}
//打開(kāi)空格
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;
//必須在雷區(qū)當(dāng)中
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);
}
//差錯(cuò)旗
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);
}
}
}
}
}
//底層數(shù)字類
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]++;
}
}
}
}
}
}
}
}
//初始化地雷類
package com.sxt;
public class BottomRay {
//存放坐標(biāo)
int[] rays = new int[GameUtil.RAY_MAX*2];
//地雷坐標(biāo)
int x,y;
//是否放置 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
//判斷坐標(biāo)是否存在
for (int j = 0; j < i ; j=j+2) {
if(x==rays[j] && y==rays[j+1]){
i=i-2;
isPlace = false;
break;
}
}
//將坐標(biāo)放入數(shù)組
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;
}
}
}
//工具類:存放靜態(tài)參數(shù),工具方法
package com.sxt;
import java.awt.*;
public class GameUtil {
//地雷個(gè)數(shù)
static int RAY_MAX = 5;
//地圖的寬
static int MAP_W = 11;
//地圖的高
static int MAP_H = 11;
//雷區(qū)偏移量
static int OFFSET = 45;
//格子邊長(zhǎng)
static int SQUARE_LENGTH = 50;
//插旗數(shù)量
static int FLAG_NUM = 0;
//鼠標(biāo)相關(guān)
//坐標(biāo)
static int MOUSE_X;
static int MOUSE_Y;
//狀態(tài)
static boolean LEFT = false;
static boolean RIGHT = false;
//游戲狀態(tài) 0 表示游戲中 1 勝利 2 失敗
static int state = 0;
//倒計(jì)時(shí)
static long START_TIME;
static long END_TIME;
//底層元素 -1 雷 0 空 1-8 表示對(duì)應(yīng)數(shù)字
static int[][] DATA_BOTTOM = new int[MAP_W+2][MAP_H+2];
//頂層元素 -1 無(wú)覆蓋 0 覆蓋 1 插旗 2 差錯(cuò)旗
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編寫(xiě)掃雷小游戲時(shí)遇到了很多問(wèn)題,在解決問(wèn)題時(shí),確實(shí)對(duì)java的面向?qū)ο缶幊逃辛烁由钊氲睦斫?。雖然GUI現(xiàn)在并沒(méi)有很大的市場(chǎng),甚至好多初學(xué)者已經(jīng)放棄了學(xué)習(xí)GUI,但是利用GUI編程的過(guò)程對(duì)于培養(yǎng)編程興趣,深入理解Java編程有很大的作用。
本程序共封裝了五個(gè)類,分別是主類GameWin類,繪制底層地圖和繪制頂層地圖的類MapBottom類和MapTop類,繪制底層數(shù)字的類BottomNum類,以及初始化地雷的BottomRay類和工具GameUtil類,用于存靜態(tài)參數(shù)和方法。
游戲的設(shè)計(jì)類似windows掃雷,用戶在圖形化用戶界面內(nèi)利用鼠標(biāo)監(jiān)聽(tīng)事件標(biāo)記雷區(qū),左上角表示剩余雷的數(shù)量,右上角動(dòng)態(tài)顯示使用的時(shí)間。用戶可選擇中間組件按鈕重新游戲。為了解決程序窗口閃動(dòng)的問(wèn)題,本程序采用了雙緩沖技術(shù)。
請(qǐng)大家指正!
點(diǎn)擊下方,第一時(shí)間了解華為云新鮮技術(shù)~
華為云博客_大數(shù)據(jù)博客_AI博客_云計(jì)算博客_開(kāi)發(fā)者中心-華為云
熱門(mén)資訊
探討游戲引擎的文章,介紹了10款游戲引擎及其代表作品,涵蓋了RAGE Engine、Naughty Dog Game Engine、The Dead Engine、Cry Engine、Avalanche Engine、Anvil Engine、IW Engine、Frostbite Engine、Creation引擎、Unreal Engine等引擎。借此分析引出了游戲設(shè)計(jì)領(lǐng)域和數(shù)字藝術(shù)教育的重要性,歡迎點(diǎn)擊咨詢報(bào)名。
2. 手機(jī)游戲如何開(kāi)發(fā)(如何制作傳奇手游,都需要準(zhǔn)備些什么?)
?如何制作傳奇手游,都需要準(zhǔn)備些什么?提到傳奇手游相信大家都不陌生,他是許多80、90后的回憶;從起初的端游到現(xiàn)在的手游,說(shuō)明時(shí)代在進(jìn)步游戲在更新,更趨于方便化移動(dòng)化。而如果我們想要制作一款傳奇手游的
3. B站視頻剪輯軟件「必剪」:免費(fèi)、炫酷特效,小白必備工具
B站視頻剪輯軟件「必剪」,完全免費(fèi)、一鍵制作炫酷特效,適合新手小白??靵?lái)試試!
4. Steam值得入手的武俠游戲盤(pán)點(diǎn),各具特色的快意江湖
游戲中玩家將面臨武俠人生的掙扎抉擇,戰(zhàn)或降?殺或放?每個(gè)抉定都將觸發(fā)更多愛(ài)恨糾葛的精彩奇遇?!短烀嬗肪哂卸嗑€劇情多結(jié)局,不限主線發(fā)展,高自由...
5. Bigtime加密游戲經(jīng)濟(jì)體系揭秘,不同玩家角色的經(jīng)濟(jì)活動(dòng)
Bigtime加密游戲經(jīng)濟(jì)模型分析,探討游戲經(jīng)濟(jì)特點(diǎn),幫助玩家更全面了解這款GameFi產(chǎn)品。
6. 3D動(dòng)畫(huà)軟件你知道幾個(gè)?3ds Max、Blender、Maya、Houdini大比拼
當(dāng)提到3D動(dòng)畫(huà)軟件或動(dòng)畫(huà)工具時(shí),指的是數(shù)字內(nèi)容創(chuàng)建工具。它是用于造型、建模以及繪制3D美術(shù)動(dòng)畫(huà)的軟件程序。但是,在3D動(dòng)畫(huà)軟件中還包含了其他類型的...
7. 3D動(dòng)漫建模全過(guò)程,不是一般人能學(xué)的會(huì)的,會(huì)的多不是人?
步驟01:面部,頸部,身體在一起這次我不準(zhǔn)備設(shè)計(jì)圖片,我從雕刻進(jìn)入。這一次,它將是一種純粹關(guān)注建模而非整體繪畫(huà)的形式。像往常一樣,我從Sphere創(chuàng)建它...
8. 如何自己開(kāi)發(fā)一款游戲(游戲開(kāi)發(fā)入門(mén)必看:五大獨(dú)立游戲開(kāi)發(fā)技巧)
?游戲開(kāi)發(fā)入門(mén)必看:五大獨(dú)立游戲開(kāi)發(fā)技巧無(wú)論您是剛剛起步開(kāi)發(fā)自己的第一款游戲,還是已經(jīng)制作了幾款游戲,本篇文章中的5大獨(dú)立游戲開(kāi)發(fā)技巧都可以幫助您更好地設(shè)計(jì)下一款游戲。無(wú)論你對(duì)游戲有著什么樣的概念,都
9. 開(kāi)發(fā)三昧游戲叫什么(三昧動(dòng)漫)
?三昧動(dòng)漫對(duì)于著名ARPG游戲《巫師》系列,最近CD Projekt 的高層回應(yīng)并不會(huì)推出《巫師4》。因?yàn)椤段讕煛废盗性诓邉澋臅r(shí)候一直定位在“三部曲”的故事框架,所以在游戲的出品上不可能出現(xiàn)《巫師4》
10. 3D打印技巧揭秘!Cura設(shè)置讓你的模型更堅(jiān)固
想讓你的3D打印模型更堅(jiān)固?不妨嘗試一下Cura參數(shù)設(shè)置和設(shè)計(jì)技巧,讓你輕松掌握!
最新文章
同學(xué)您好!