Java课程设计之推箱子

  推箱子游戏是一个比较古老的游戏,深受广大游戏爱好者的欢迎,它在带来乐趣的同时也能培养我们的反应力以及严谨的思维能力。

  游戏规则是要求角色将地图中所有放置的箱子推到指定目标位置,只有合理安排移动次序和位置 ,才能顺利完成任务。

  项目任务是用java语言设计并实现一个推箱子游戏,旨在培养学生面向对象编程思维方式,开发小型桌面应用程序的能力。

  系统功能模块设计

  其中系统可以分为初始化模块,绘制地图模块,移动箱子模块、移动小人模块,音乐播放模块,功能控制模块。

程序设计

主要分为四个类:BattleField类,Music类,Window类和Gameload类。

1. Battlefield类:内含BattleField构造方法,paint方法。其中paint方法重写了Graphics类中的paint方法,承载了绘制地图的作用,对内置的box、field、hero、target和wall等图片进行图像绘制。BattleField方法承载着初始化图片的作用,从相应的位置提取图片并存储到相应的图片存储单元中。

2. Music类:内置run方法和play方法。其中run方法调用了play方法使得其能够在调用run方法的时候进行音乐的播放。Play方法读取文件、存储到相应的存储单元中,最后通过player对象实现音乐文件的播放。

3. Window类:作为主方法,其中包含了了GUI界面的设计。建立了多个JPanel作为容器存储相关的JButton、JTextField和JLabel,以及相应的监视器,来确定在组件响应的时候所执行的操作,包括按钮监听,键盘监听等监视器。

4. Gameload类:初始化地图,通过读取地图文件来绘制地图。包含了moveLeft、moveRight、moveUp和moveDown等方法,以及判断游戏是否结束的isEnd方法。

项目文件位于GitHub上,在此处仅粘贴相关代码。

GitHub仓库链接

Music.java

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.*;

class Play0 extends Thread {
    Player player;
    String music;

    public Play0(String file) {
        this.music = file;
    }

    public void run() {
        try {
            play();
        } catch (FileNotFoundException | JavaLayerException e) {
            e.printStackTrace();
        }
    }
    public void play() throws FileNotFoundException, JavaLayerException {
        BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(music));
        player = new Player(buffer);
        player.play();
    }
}

Window.java

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;

public class Window extends JFrame {
    private Gameload Gameload;
    private BattleField canvas;int sum=1;//设置关卡数目
    JFrame frame=new JFrame();
    public Window()
    {

        Play0 pl=new Play0("music.mp3");
        pl.start();//打开时就开始播放音乐
        Gameload=new Gameload(sum);
        canvas=new BattleField(Gameload);


        frame.setLayout(new BorderLayout());
        frame.add(canvas,BorderLayout.CENTER);
        frame.setSize(700,690);//设置窗口大小

        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JButton exit=new JButton("退出");//设置退出游戏按钮
        exit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
                pl.stop();
                exit.setFocusable(false);
            }
        });//设置窗口关闭
        JButton next=new JButton("下一关");//设置下一关按钮

        JButton refresh=new JButton("重新开始");//设置重新开始按钮
        refresh.addActionListener(new ActionListener() {//按下”重新开始“按钮的监视器
            @Override
            public void actionPerformed(ActionEvent e) {
                Gameload.init(sum);
                canvas.repaint();
                refresh.setFocusable(false);
            }
        });
        JButton musicstop=new JButton("关闭音乐");//设置关闭音乐的按钮

        JPanel buttons=new JPanel();//新建一个JPanel 容纳所有的按钮
        JPanel lbadtxt=new JPanel(new BorderLayout());//显示相关字体和文本框
        JPanel txtandfield=new JPanel();//新建



        JTextField mission=new JTextField(2);
        mission.setEditable(false);
        JLabel missions=new JLabel("关卡数");
        mission.setText(String.valueOf(sum));//显示相关的关卡数
        txtandfield.add(missions);
        txtandfield.add(mission);

        JLabel titles=new JLabel("<html>狼<br>狼<br>追<br>羊<br>羊<br>",JLabel.CENTER);//设置标题按钮
        Font f=new Font("微软雅黑",Font.BOLD,40);//设置字体
        titles.setFont(f);
        titles.setForeground(Color.red);

        lbadtxt.add(titles,BorderLayout.CENTER);
        lbadtxt.add(txtandfield,BorderLayout.NORTH);


        buttons.add(exit);//设置按钮控件,并放置在button panel里
        buttons.add(next);
        buttons.add(refresh);
        buttons.add(musicstop);



        next.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                sum++;//关卡数控件


                if(sum<=2){
                    mission.setText(String.valueOf(sum));//显示相关的关卡数
                Gameload.init(sum);
                canvas.repaint();
                    next.setFocusable(false);

                }
                else{
                    JOptionPane.showMessageDialog(null, "关卡数超出,程序退出", "ERROR",
                            JOptionPane.ERROR_MESSAGE);
                    System.exit(0);

                }
                next.setFocusable(false);
            }
        });//控件

        musicstop.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                pl.stop();
                musicstop.setFocusable(false);
            }
        });



        frame.add(buttons,BorderLayout.SOUTH);//放在界面的南部(即下部)

        frame.add(lbadtxt,BorderLayout.EAST);//放在界面的东部(即右部)


        frame.addKeyListener(new KeyListener(){//创建监视器
            public void keyPressed(KeyEvent event) {
                if(event.getKeyCode()==KeyEvent.VK_UP)
                {
                    Gameload.moveUp();//监控键盘,如果按下方向上键,则执行向上走的方法

                }else if(event.getKeyCode()==KeyEvent.VK_DOWN)
                {
                    Gameload.moveDown();

                }else if(event.getKeyCode()==KeyEvent.VK_LEFT)
                {
                    Gameload.moveLeft();

                }else if(event.getKeyCode()==KeyEvent.VK_RIGHT)
                {
                    Gameload.moveRight();
                }
                canvas.repaint();
                if(Gameload.isEnd()) {
                    JOptionPane.showMessageDialog(null, "游戏结束");
                    System.exit(0);

                }
            }
            public void keyReleased(KeyEvent event) {
            }
            public void keyTyped(KeyEvent event) {
            }

        });


        frame.setVisible(true);
        frame.setFocusable(true);
    }
    public static void main(String[] args) {
        Window show=new Window();

    }
}

Gameload.Java

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class Gameload {
    private boolean exist=true;
    // 游戏角色的坐标位置
    private int x;
    private int y;
    // 游戏为20x20的地图
    private String field[][] = new String[20][20];
    // 记录推箱子的目标位置
    private String target[][] = new String[20][20];
    public void init(int num) {
        try {


            BufferedReader reader = new BufferedReader(new FileReader("field" + String.valueOf(num) + ".txt"));
            // 读取文件的一行
            String line = reader.readLine();
            int j = 0;
            while (line != null) {
                // 以空格为分隔符号,分割一行数据;
                String strs[] = line.split(" ");
                for (int i = 0; i < 20; i++) {//初次设计的是20*20矩阵 以后根据要求重新编辑文件
                    field[i][j] = strs[i];
                    if (strs[i].equals("T")) {
                        // 记录目标位置
                        target[i][j] = "T";
                    } else {
                        // 非目标位置记为O
                        target[i][j] = "O";
                    }
                    // 记录角色的初始位置
                    if (strs[i].equals("H")) {
                        this.x = i;
                        this.y = j;
                    }
                }
                line = reader.readLine();
                j++;
            }
            reader.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Gameload(int num) {
        // 从field文件加载地图信息
        try {
            BufferedReader reader = new BufferedReader(new FileReader("field" + String.valueOf(num) + ".txt"));
            // 读取文件的一行
            String line = reader.readLine();
            int j = 0;
            while (line != null) {
                // 以空格为分隔符号,分割一行数据;
                String strs[] = line.split(" ");
                for (int i = 0; i < 20; i++) {//初次设计的是20*20矩阵 以后根据要求重新编辑文件
                    field[i][j] = strs[i];
                    if (strs[i].equals("T")) {
                        // 记录目标位置
                        target[i][j] = "T";
                    } else {
                        // 非目标位置记为O
                        target[i][j] = "O";
                    }
                    // 记录角色的初始位置
                    if (strs[i].equals("H")) {
                        this.x = i;
                        this.y = j;
                    }
                }
                line = reader.readLine();
                j++;
            }
            reader.close();
        }
         catch (Exception e) {
            e.printStackTrace();
        }
    }
    //角色向左移动
    public void moveLeft() {
        int a = x;
        int b = y;
        if (!field[a - 1][b].equals("W")) {//判断二维数组前一位是否为墙壁
            if (field[a - 1][b].equals("B")) {
                if (!field[a - 2][b].equals("B") && !field[a - 2][b].equals("W")) {
                    if (target[a][b].equals("T")) {//如果任务位置为目标位置
                        field[a - 1][b] = "H";//将人物向左平移一格
                        field[a][b] = "T";//将目标位置定在原来人物位置上
                        field[a - 2][b] = "B";
                        x = a - 1;//将人物位置x坐标平移一位
                    } else {//否则将人物向左平移
                        field[a - 1][b] = "H";
                        field[a][b] = "E";//将背景赋值为
                        field[a - 2][b] = "B";//将箱子向左平移两个
                        x = a - 1;
                    }
                }
            } else {//如果人物位置的左边不为墙壁位置
                if (target[a][b].equals("T")) {
                    field[a - 1][b] = "H";//当位置为目标位置时,将H向左移动
                    field[a][b] = "T";//将位置设置为T
                    x = a - 1;//向左位置设置
                } else {
                    field[a - 1][b] = "H";//不为目标位置时,将H向左移动
                    field[a][b] = "E";//将位置设置为背景
                    x = a - 1;//向左位置设置
                }
            }
        }
    }
    //角色向右移动
    public void moveRight() {
        int a = x;
        int b = y;
        if (!field[a + 1][b].equals("W")) {
            if (field[a + 1][b].equals("B")) {
                if (!field[a + 2][b].equals("B") && !field[a + 2][b].equals("W")) {
                    if (target[a][b].equals("T")) {
                        field[a + 1][b] = "H";
                        field[a][b] = "T";
                        field[a + 2][b] = "B";
                        x = a + 1;
                    } else {
                        field[a + 1][b] = "H";
                        field[a][b] = "E";
                        field[a + 2][b] = "B";
                        x = a + 1;
                    }
                }
            } else {
                if (target[a][b].equals("T")) {
                    field[a + 1][b] = "H";
                    field[a][b] = "T";
                    x = a + 1;
                } else {
                    field[a + 1][b] = "H";
                    field[a][b] = "E";
                    x = a + 1;
                }
            }
        }
    }
    //角色向上移动
    public void moveUp() {
        int a = x;
        int b = y;
        if (!field[a][b - 1].equals("W")) {
            if (field[a][b - 1].equals("B")) {
                if (!field[a][b - 2].equals("B") && !field[a][b - 2].equals("W")) {
                    if (target[a][b].equals("T")) {
                        field[a][b - 1] = "H";
                        field[a][b] = "T";
                        field[a][b - 2] = "B";
                        y = b - 1;
                    } else {
                        field[a][b - 1] = "H";
                        field[a][b] = "E";
                        field[a][b - 2] = "B";
                        y = b - 1;
                    }
                }
            } else {
                if (target[a][b].equals("T")) {
                    field[a][b - 1] = "H";
                    field[a][b] = "T";
                    y = b - 1;
                } else {
                    field[a][b - 1] = "H";
                    field[a][b] = "E";
                    y = b - 1;
                }
            }
        }
    }
    //角色向下移动
    public void moveDown() {
        int a = x;
        int b = y;
        if (!field[a][b + 1].equals("W")) {
            if (field[a][b + 1].equals("B")) {
                if (!field[a][b + 2].equals("B") && !field[a][b + 2].equals("W")) {
                    if (target[a][b].equals("T")) {
                        field[a][b + 1] = "H";
                        field[a][b] = "T";
                        field[a][b + 2] = "B";
                        y = b - 1;
                    } else {
                        field[a][b + 1] = "H";
                        field[a][b] = "E";
                        field[a][b + 2] = "B";
                        y = b + 1;
                    }
                }
            } else {
                if (target[a][b].equals("T")) {
                    field[a][b + 1] = "H";
                    field[a][b] = "T";
                    y = b + 1;
                } else {
                    field[a][b + 1] = "H";
                    field[a][b] = "E";
                    y = b + 1;
                }
            }
        }
    }
    //判断游戏是否结束
    public boolean isEnd() {
        for (int i = 0; i < 20; i++)
            for (int j = 0; j < 20; j++) {
                if (field[i][j].equals("T"))
                    return false;
            }
        return true;
    }
    public String[][] getfield() {
        return field;
    }

}

Battlefield.java

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

//游戏使用的场地初始化,即战场
public class BattleField extends JPanel {
    private BufferedImage box;
    private BufferedImage field;
    private BufferedImage hero;
    private BufferedImage target;
    private BufferedImage wall;
    private Gameload gl;
    public Graphics g;
    public BattleField(Gameload gl){
        this.gl=gl;

        try{
            box= ImageIO.read(new File("box.png"));
            field=ImageIO.read(new File("field.png"));
            hero=ImageIO.read(new File("hero.png"));
            target=ImageIO.read(new File("target.png"));
            wall=ImageIO.read(new File("wall.png"));
        }catch(IOException e){
            e.printStackTrace();
        }
    }
    public void paint(Graphics g){
        this.g=g;

        BufferedImage image=null;
        for(int j=0;j<20;j++)
            for(int i=0;i<20;i++)
            {
                if(gl.getfield()[i][j].equals("B"))
                {
                    image=box;//将图像设置为box
                }else if(gl.getfield()[i][j].equals("E"))
                {
                    image=field;//将图像设置为底图
                }else if(gl.getfield()[i][j].equals("H")) {
                    image = hero;//将图像设置为人物
                }
                else if(gl.getfield()[i][j].equals("W")) {
                    image = wall;//将图像设置为墙面
                }
                else if (gl.getfield()[i][j].equals("T")){
                    image=target;//将图像设置为目标位置
                        }

                g.drawImage(image, 0+i*image.getWidth(), 0+j*image.getHeight(),null);
            }
    }

}

学习不易,请勿随意转载。

猜你喜欢

转载自blog.csdn.net/m0_49684834/article/details/128073098
今日推荐