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小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~