扫雷游戏

这是一个自制的扫雷游戏,玩法与微软扫雷相同,但界面和功能还有待改进。虽然无法展示图片和音效,但代码已列出,包括entity模块的Boom、Entity、Number等类,ui模块的GameFrame、MainFrame等类,以及util模块的MusicPalyTool和Util工具包。

做了一个像微软扫雷一样的游戏,基本玩法一致;
缺点:界面不太美观,功能也不是很强大
图片和音效都是没办法上传
话不多说,贴代码了

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

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值