做了一个像微软扫雷一样的游戏,基本玩法一致;
缺点:界面不太美观,功能也不是很强大
图片和音效都是没办法上传
话不多说,贴代码了
entity
Boom
package com.game.minesweeper.entity;
import com.game.minesweeper.util.Util;
public class Boom extends Entity {
public Boom(int x, int y) {
super(x, y, 28, 28, Util.getImage("img/boom.png"), 1);
}
}
BoomList
package com.game.minesweeper.entity;
import java.util.Random;
import java.util.Vector;
public class BoomList extends Vector<Boom> {
static BoomList list;
// 保存炸弹位置地图
public static boolean[][] map;
public static BoomList getList(int x, int width, int hight) {
if (list == null) {
list = new BoomList();
map = new boolean[width][hight];
setBoom(x, width, hight);
}
return list;
}
// 随机设置count个地雷位置并加入list中
public static void setBoom(int count, int width, int hight) {
Random r = new Random();
int c = 0;
for (int i = 0; i < count; i++) {
boolean flag = true;// 循环随机条件
// 初次循环
int x = r.nextInt(width);
int y = r.nextInt(hight);
if (list.size() != 0) {
// 如果是空列表直接添加。不是空列表就找空白位置
while (flag) {
// 重新随机位置
x = r.nextInt(width);
y = r.nextInt(hight);
// 判断是否与列表中某个重合
boolean flag1 = true;
for (int j = 0; j < list.size(); j++) {
if (x == list.get(j).x && y == list.get(j).y) {
flag1 = false;
}
}
if (flag1) {
flag = false;
}
}
}
// 加入列表中
list.add(new Boom(x, y));
map[x][y] = true;
}
}
}
Entity
package com.game.minesweeper.entity;
import java.awt.Graphics;
import java.awt.Image;
public class Entity {
// 坐标和高宽
public int x;
public int y;
int width;
int hight;
Image img;
// 为了不遮住线条,设置一个变量来改变位置
int offset;
public Entity(int x, int y, int width, int hight, Image img, int offset) {
this.x = x;
this.y = y;
this.width = width;
this.hight = hight;
this.img = img;
this.offset = offset;
}
public void drawSelf(Graphics g) {
g.drawImage(img, x * 30 + offset, y * 30 + offset, width, hight, null);
}
}
Number
package com.game.minesweeper.entity;
import java.awt.Graphics;
import java.awt.Image;
public class Entity {
// 坐标和高宽
public int x;
public int y;
int width;
int hight;
Image img;
// 为了不遮住线条,设置一个变量来改变位置
int offset;
public Entity(int x, int y, int width, int hight, Image img, int offset) {
this.x = x;
this.y = y;
this.width = width;
this.hight = hight;
this.img = img;
this.offset = offset;
}
public void drawSelf(Graphics g) {
g.drawImage(img, x * 30 + offset, y * 30 + offset, width, hight, null);
}
}
NumList
package com.game.minesweeper.entity;
import java.util.ArrayList;
public class NumberList extends ArrayList<Number> {
static NumberList list;
BoomList blist;
public static boolean[][] bMap;
public static boolean[][] map;
// 懒汉模式
public static NumberList getList(int x, int width, int hight, BoomList blist) {
if (list == null) {
blist = BoomList.getList(x, width, hight);
bMap = new boolean[width][hight];
map = new boolean[width][hight];
// 拿到炸弹图
bMap = blist.map;
list = new NumberList();
// 表示数字
setNumber(width, hight);
}
return list;
}
private static void setNumber(int width, int hight) {
for (int i = 0; i < width; i++) {
for (int j = 0; j < hight; j++) {
if (bMap[i][j]) {
// 此处是一个炸弹
continue;
}
// count是附近炸弹数
int count = 0;
// 防越界处理
if (i - 1 >= 0 && j - 1 >= 0) {
if (bMap[i - 1][j - 1])
count++;
}
if (i - 1 >= 0) {
if (bMap[i - 1][j])
count++;
}
if (i - 1 >= 0 && j + 1 < hight) {
if (bMap[i - 1][j + 1])
count++;
}
if (j - 1 >= 0) {
if (bMap[i][j - 1])
count++;
}
if (j + 1 < hight) {
if (bMap[i][j + 1])
count++;
}
if (i + 1 < width && j - 1 >= 0) {
if (bMap[i + 1][j - 1])
count++;
}
if (i + 1 < width) {
if (bMap[i + 1][j])
count++;
}
if (i + 1 < width && j + 1 < hight) {
if (bMap[i + 1][j + 1])
count++;
}
if (count > 0) {
list.add(new Number(i, j, count));
map[i][j] = true;
}
}
}
}
}
Plank
package com.game.minesweeper.entity;
import com.game.minesweeper.util.Util;
public class Plank extends Entity {
// 标记变量,如果已经被标记,则为true,否则为false
public boolean flag = false;
public Plank(int x, int y) {
super(x, y, 28, 28, Util.getImage("img/plank.png"), 1);
}
}
PlankList
package com.game.minesweeper.entity;
import java.util.Vector;
public class PlankList extends Vector<Plank> {
static PlankList list;
public static boolean[][] map;
public static PlankList getList(int width, int hight) {
if (list == null) {
map = new boolean[width][hight];
list = new PlankList();
setPlank(width, hight);
}
return list;
}
// 全添加
private static void setPlank(int width, int hight) {
for (int i = 0; i < width; i++) {
for (int j = 0; j < hight; j++) {
list.add(new Plank(i, j));
}
}
}
}
Sign
package com.game.minesweeper.entity;
import com.game.minesweeper.util.Util;
public class Sign extends Entity {
public Sign(int x, int y) {
super(x, y, 28, 28, Util.getImage("img/sign.png"), 1);
}
}
SignList
package com.game.minesweeper.entity;
import java.util.Vector;
public class SignList extends Vector<Entity> {
static SignList list;
public static SignList getList() {
if (list == null) {
list = new SignList();
}
return list;
}
}
ui
GameFrame
package com.game.minesweeper.ui;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Calendar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import com.game.minesweeper.entity.BoomList;
import com.game.minesweeper.entity.NumberList;
import com.game.minesweeper.entity.Plank;
import com.game.minesweeper.entity.PlankList;
import com.game.minesweeper.entity.Sign;
import com.game.minesweeper.entity.SignList;
import com.game.minesweeper.util.Util;
public class GameFrame extends MyFrame {
JPanel jp;
BoomList boomList;
PlankList plankList;
SignList signList;
NumberList numList;
boolean[][] bMap;
boolean[][] nMap;
boolean[][] pMap;
int width;// 宽格数
int hight;// 高格数
int count;// 地雷数
int grade = 0;// 成绩
boolean timeFlag;
Calendar calendar1 = Calendar.getInstance();
public GameFrame(String mode, int count, int width, int hight) {
super(mode, width * 30 + 50, hight * 30 + 60);
this.count = count;
this.width = width;
this.hight = hight;
}
public void setData() {
jp = new JPanel() {
public void paint(Graphics g) {
Image img = createImage(width * 30 + 51, hight * 30 + 61);
Graphics gg = img.getGraphics();
// 设置背景色
gg.setColor(Color.getHSBColor(250, 20, 200));
gg.fillRect(0, 0, getWidth(), getHeight());
gg.setColor(Color.black);
// 布线:竖线
for (int i = 0; i < width + 1; i++) {
for (int j = 1; j < hight + 1; j++) {
gg.drawLine(i * 30, j, i * 30, j * 30);
}
}
// 布线:横线
for (int i = 0; i < hight + 1; i++) {
for (int j = 0; j < width + 1; j++) {
gg.drawLine(j, i * 30, j * 30, i * 30);
}
}
// 画炸弹
boomList = BoomList.getList(count, width, hight);
for (int i = 0; i < boomList.size(); i++) {
boomList.get(i).drawSelf(gg);
}
// 画数字
numList = NumberList.getList(count, width, hight, boomList);
for (int i = 0; i < numList.size(); i++) {
numList.get(i).drawSelf(gg);
}
// 画遮板
plankList = PlankList.getList(width, hight);
for (int i = 0; i < plankList.size(); i++) {
plankList.get(i).drawSelf(gg);
}
// 画标记
signList = SignList.getList();
for (int i = 0; i < signList.size(); i++) {
signList.get(i).drawSelf(gg);
}
g.drawImage(img, 20, 40, null);
}
};
new Thread() {
public void run() {
while (true) {
Util.sleep(10);
repaint();
}
}
}.start();
new Thread() {
public void run() {
timeFlag = true;
while (timeFlag) {
Util.sleep(10);
System.out.println(timer());
setTitle("扫雷 - " + timer() + "秒");
}
}
}.start();
}
@Override
public void paint(Graphics g) {
jp.paint(g);
}
public void addComent() {
this.add(jp);
}
public void addLinstener() {
this.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
// 获取位置
int x = e.getX();
int y = e.getY();
for (int i = 0; i < plankList.size(); i++) {
Plank p = plankList.get(i);
if (p.x * 30 + 20 < x && p.x * 30 + 50 > x && p.y * 30 + 40 < y && p.y * 30 + 70 > y) {
// 判断鼠标左键时
int x1 = p.x;
int y1 = p.y;
if (e.getButton() == e.BUTTON1) {
// 消除这块遮板
dfs(x1, y1);
if (bMap[x1][y1])
gameOver();
}
// 判断鼠标右键时
if (e.getButton() == e.BUTTON3) {
// 如果还没标记的就打上标记,如果标对的加分
p.flag = !p.flag;
if (p.flag) {
signList.add(new Sign(x1, y1));
if (bMap[x1][y1]) {
grade++;
if (count == grade) {
win();
}
}
} else {
for (int j = 0; j < signList.size(); j++) {
Sign s = (Sign) signList.get(j);
if (s.x == x1 && s.y == y1) {
signList.remove(j);
if (bMap[x1][y1])
grade--;
}
}
}
}
}
}
}
});
}
protected void win() {
JOptionPane.showMessageDialog(null, "恭喜过关,时间:" + timer() + "秒", "过关", 1);
}
public void dfs(int x, int y) {
bMap = boomList.map;
nMap = numList.map;
pMap = plankList.map;
// 如果此处有遮板且有数字,先去掉遮板
if (!pMap[x][y] && nMap[x][y]) {
for (int i = 0; i < plankList.size(); i++) {
if (plankList.get(i).x == x && plankList.get(i).y == y) {
plankList.remove(i);
// 更新地图
pMap[x][y] = true;
break;
}
}
}
// 如果此处没有遮板且没有数字,去掉遮板后开始宽搜
else if (!pMap[x][y] && !nMap[x][y]) {
for (int i = 0; i < plankList.size(); i++) {
if (plankList.get(i).x == x && plankList.get(i).y == y) {
plankList.remove(i);
// 更新地图
pMap[x][y] = true;
break;
}
}
// 防止越界
if (x - 1 >= 0)
dfs(x - 1, y);
if (x + 1 < width)
dfs(x + 1, y);
if (y - 1 >= 0)
dfs(x, y - 1);
if (y + 1 < hight)
dfs(x, y + 1);
}
}
private void gameOver() {
plankList.removeAllElements();
new MusicPlayTool("sound/boom.wav", false).startMusic();
timeFlag = false;
JOptionPane.showMessageDialog(null, "失败,成绩:" + grade, "失败", 1);
}
public int timer() {
Calendar calendar2 = Calendar.getInstance();
// 计算时间
int time = (calendar2.get(Calendar.HOUR) - calendar1.get(Calendar.HOUR)) * 360
+ (calendar2.get(Calendar.MINUTE) - calendar1.get(Calendar.MINUTE)) * 60
+ calendar2.get(Calendar.SECOND) - calendar1.get(Calendar.SECOND);
return time;
}
}
MainFrame
package com.game.minesweeper.ui;
public class MainFrame {
public static void main(String[] args) {
SelectFrame sf = new SelectFrame();
}
}
MyFrame
package com.game.minesweeper.ui;
import java.awt.LayoutManager;
import javax.swing.JFrame;
/*
* 默认设置无标题,大小为500*500,布局为null
*/
public abstract class MyFrame extends JFrame {
public MyFrame(String title, int width, int height, LayoutManager manager) {
// 设置标题
setTitle(title);
// 设置大小
setSize(width, height);
// 设置默认关闭操作
setDefaultCloseOperation(3);
// 设置相对位置
setLocationRelativeTo(null);
// 设置布局
setLayout(manager);
// 设置初值或者加载其他项目
setData();
// 添加组件
addComent();
// 设置可视化
setVisible(true);
// 添加监听器
addLinstener();
}
public abstract void setData();
// 重写只有标题的构造函数
public MyFrame(String title) {
this(title, 500, 500, null);
}
// 重写只有大小的构造函数
public MyFrame(int width, int height) {
this(null, width, height, null);
}
// 重写只有布局的构造函数
public MyFrame(LayoutManager manager) {
this(null, 500, 500, manager);
}
// 重写没有设置布局的构造函数
public MyFrame(String title, int width, int height) {
this(title, width, height, null);
}
// 重写没有标题的构造函数
public MyFrame(int width, int height, LayoutManager manager) {
this(null, width, height, manager);
}
// 重写没有设置大小的构造函数
public MyFrame(String title, LayoutManager manager) {
this(title, 500, 500, manager);
}
// 重写默认构造函数
public MyFrame() {
this(null, 500, 500, null);
}
// 添加组件的抽象方法
public abstract void addComent();
// 添加监听器的抽象方法
public abstract void addLinstener();
}
SelectFrame
package com.game.minesweeper.ui;
import java.awt.event.MouseAdapter;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class SelectFrame extends MyFrame {
public SelectFrame() {
}
@Override
public void setData() {
// TODO 自动生成的方法存根
}
public void addComent() {
JLabel jlb1 = new JLabel("9×9,10颗雷");
jlb1.setBounds(100, 160, 100, 20);
JButton jb1 = new JButton("简单");
jb1.setBounds(100, 100, 60, 50);
jb1.addMouseListener(new MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
GameFrame gf = new GameFrame("简单", 10, 9, 9);
}
});
this.add(jb1);
this.add(jlb1);
JLabel jlb2 = new JLabel("16×16,40颗雷");
jlb2.setBounds(100, 260, 100, 20);
JButton jb2 = new JButton("中等");
jb2.setBounds(100, 200, 60, 50);
jb2.addMouseListener(new MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
GameFrame gf = new GameFrame("中等", 40, 16, 16);
}
});
this.add(jb2);
this.add(jlb2);
JLabel jlb3 = new JLabel("30×16,99颗雷");
jlb3.setBounds(100, 360, 100, 20);
JButton jb3 = new JButton("困难");
jb3.setBounds(100, 300, 60, 50);
jb3.addMouseListener(new MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
GameFrame gf = new GameFrame("困难", 99, 30, 16);
}
});
this.add(jb3);
this.add(jlb3);
JTextField jtf1 = new JTextField();
JTextField jtf2 = new JTextField();
JTextField jtf3 = new JTextField();
jtf1.setBounds(240, 160, 100, 30);
jtf2.setBounds(240, 240, 100, 30);
jtf3.setBounds(240, 320, 100, 30);
JLabel jlb4 = new JLabel("地雷数量");
JLabel jlb5 = new JLabel("长度格数");
JLabel jlb6 = new JLabel("宽度格数");
jlb4.setBounds(240, 200, 100, 20);
jlb5.setBounds(240, 280, 100, 20);
jlb6.setBounds(240, 280, 100, 20);
JButton jb4 = new JButton("自定义");
jb4.setBounds(240, 100, 100, 50);
jb4.addMouseListener(new MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
GameFrame gf = new GameFrame("自定义", Integer.parseInt(jtf1.getText()), Integer.parseInt(jtf2.getText()),
Integer.parseInt(jtf3.getText()));
}
});
this.add(jb4);
this.add(jtf1);
this.add(jtf2);
this.add(jtf3);
this.add(jlb4);
this.add(jlb5);
this.add(jlb6);
}
@Override
public void addLinstener() {
// TODO 自动生成的方法存根
}
}
util
工具包
MusicPalyTool
package com.game.minesweeper.util;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
public class MusicPlayTool implements Runnable {
private String filename;
SourceDataLine auline = null;
public MusicPlayTool(String wavfile, boolean isLoop) {
filename = wavfile;
this.isLoop = isLoop;
// 开启自己
new Thread(this).start();
}
boolean isLoop = true;
public void run() {
do {
File soundFile = new File(filename);
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
} catch (Exception e1) {
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat();
// FloatControl
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format); // 打开
} catch (Exception e) {
e.printStackTrace();
return;
}
auline.start(); // 开始播放
int nBytesRead = 0;
byte[] abData = new byte[512];
try {
while (nBytesRead != -1) {
nBytesRead = audioInputStream
.read(abData, 0, abData.length);
if (nBytesRead >= 0)
auline.write(abData, 0, nBytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
auline.close();
}
} while (isLoop);
}
public void stopMusic() {
isLoop = false;
if (auline != null) {
auline.stop();
}
}
public void startMusic() {
if (auline != null)
auline.start();
}
}
Util
package com.game.minesweeper.util;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Util {
// 获取图片,返回Image
public static Image getImage(String path) {
return new ImageIcon(path).getImage();
}
// 休眠
public static void sleep(long time) {
// while (!Mario.isLive || !GameFrame.GameIsRun) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
// try {
//
// Thread.sleep(time);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
}
这是一个自制的扫雷游戏,玩法与微软扫雷相同,但界面和功能还有待改进。虽然无法展示图片和音效,但代码已列出,包括entity模块的Boom、Entity、Number等类,ui模块的GameFrame、MainFrame等类,以及util模块的MusicPalyTool和Util工具包。
537

被折叠的 条评论
为什么被折叠?



