zoukankan      html  css  js  c++  java
  • 推箱子

    难点

    逻辑判断当前地图的状态(注意数组越界问题), 根据这个状态, 对数组的值进行修改, 然后调用 repaint() -> paint() 来将图形绘制出来.

    举一反三

    实际上, 步骤1,2 完全可以用在 连连看中. 而且连连看不需要撤销功能, 所以不需要保存之前的图形的样子.

    而连连看的主程序在实现逻辑上会有区别, 另外, 连连看在鼠标事件中会有应用, 点了哪个图片等等.

    步骤:

    1. 创建初始化界面(地图) {可共用} MapFactory.java

    package com.leon.movebox;
    
    public class MapFactory {
        /**
         * 
         */
        static byte map[][][] = {
            /*
             *  0 表示空白, 什么都不用画, 不参与到游戏中
             *  WALL = 1, BOX = 2, BOXONEND = 3, END = 4,
             *  MANDOWN = 5, MANLEFT = 6, MANRIGHT = 7, MANUP = 8, 
             *  GRASS = 9, MANDOWNONEND = 10, MANLEFTONEND = 11, MANRIGHTONEND = 12,
             *  MANUPONEND = 13;
             * */
            {
                // map[0]
                {0, 0, 1, 1, 1, 0, 0, 0},
                {0, 0, 1, 4, 1, 0, 0, 0},
                {0, 0, 1, 9, 1, 1, 1, 1},
                {1, 1, 1, 2, 9, 2, 4, 1},
                {1, 4, 9, 2, 5, 1, 1, 1},
                {1, 1, 1, 1, 2, 1, 0, 0},
                {0, 0, 0, 1, 4, 1, 0, 0},
                {0, 0, 0, 1, 1, 1, 0, 0},
            },
            {
                // map[1]
                {1, 1, 1, 1, 1, 0, 0, 0, 0},
                {1, 9, 9, 5, 1, 0, 0, 0, 0},
                {1, 9, 2, 2, 1, 0, 1, 1, 1},
                {1, 9, 2, 9, 1, 0, 1, 4, 1},
                {1, 1, 1, 9, 1, 1, 1, 4, 1},
                {0, 1, 1, 9, 9, 9, 9, 4, 1},
                {0, 1, 9, 9, 9, 1, 9, 9, 1},
                {0, 1, 9, 9, 9, 1, 1, 1, 1},
                {0, 1, 1, 1, 1, 1, 0, 0, 0},
            },
        };
        // count 当前有多少关
        static int count = map.length;
        public static byte[][] getMap(int grade) {
            byte temp[][];
            if (grade >= 0 && grade < count)
                // 指针, 并非真正 copy
                temp = map[grade];
            else
                temp = map[0];
            int row = temp.length;
            int column = temp[0].length;
            byte[][] result = new byte[row][column];
            // 真正 copy
            for (int i = 0; i < row; i++)
                for (int j = 0; j < column; j++)
                    result[i][j] = temp[i][j];
            return result;
        }
        public static int getCount() {
            return count;
        }
    }

    2. 初始化声音 {可共用} Sound.java

    package com.leon.movebox;
    
    import java.io.File;
    import java.io.IOException;
    
    import javax.sound.midi.InvalidMidiDataException;
    import javax.sound.midi.MidiSystem;
    import javax.sound.midi.MidiUnavailableException;
    import javax.sound.midi.Sequence;
    import javax.sound.midi.Sequencer;
    
    public class Sound {
        
        private String path = new String("musics/");
        private String file = new String("nor.mid");
        private Sequence seq;
        private Sequencer midi;
        private boolean sign;
        
        public void loadSound() {
            try {
                // 打开 MIDI 文件
                seq = MidiSystem.getSequence(new File(path+file));
                // 建立音频序列
                midi = MidiSystem.getSequencer();
                // 打开音频序列
                midi.open();
                // 读取即将播放的音频序列
                midi.setSequence(seq);
                // 播放音乐
                midi.start();
                midi.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
                
            } catch (Exception e) {
                e.printStackTrace();
            }
            sign = true;
        }
        
        public void mystop() {
            midi.stop();
            midi.close();
            sign = false;
        }
        
        public boolean isPlay() {
            return sign;
        }
        
        public void setMusic(String e) {
            file = e;
        }
        
    }

    3. 记录当前的地图的状态

    package com.leon.movebox;
    
    /**
     * save the currently map status
     * @author Leon
     *
     */
    public class Map {
        int manX = 0;
        int manY = 0;
        byte map[][];
        int grade;
        
        public Map(int manX, int manY, byte[][] map) {
            this.manX = manX;
            this.manY = manY;
            int row = map.length;
            int column = map[0].length;
            byte temp[][] = new byte[row][column];
            for (int i = 0; i < row; i++)
                for (int j = 0; j < column; j++)
                    temp[i][j] = map[i][j];
            this.map = temp;
        }
        
        public Map(int manX, int manY, byte[][] map, int grade) {
            this(manX, manY, map);
            this.grade = grade;
        }
        
        public int getManX() {
            return manX;
        }
        
        public int getManY() {
            return manY;
        }
        
        public byte[][] getMap() {
            return this.map;
        }
        
        public int getGrade() {
            return grade;
        }
    }

    4. 主程序(还需要再调整, 当前有 Bug) (设计到 上, 下, 左, 右 移动, 即根据当前的状态更改数组的状态, 进而更改图片)

    package com.leon.movebox;
    
    import java.awt.Color;
    import java.awt.Container;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.Toolkit;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    
    import javax.sound.midi.InvalidMidiDataException;
    import javax.sound.midi.MidiSystem;
    import javax.sound.midi.MidiUnavailableException;
    import javax.sound.midi.Sequence;
    import javax.sound.midi.Sequencer;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    
    public class GameFrame extends JFrame implements ActionListener, MouseListener, KeyListener{
    
        // 游戏关卡
        // row, column 记载人的行号和列号
        // leftX, leftY 记载图片左上角的位置
        private int grade = 0;    
        private int row = 7; 
        private int column = 7;
        private int leftX = 0;
        private int leftY = 0;
        private int mapRow = 0;
        private int mapColumn = 0;
        // 记载屏幕的宽 和 高
        private int width = 0;
        private int height = 0;
        private boolean acceptKey = true;
        private Image pic[] = null;
        private byte[][] map = null;
        // 为了悔棋, 回退步骤
        private ArrayList list = new ArrayList();
        Sound sound;
        final byte WALL = 1, BOX = 2, BOXONEND = 3, END = 4,
            MANDOWN = 5, MANLEFT = 6, MANRIGHT = 7, MANUP = 8, 
            GRASS = 9, MANDOWNONEND = 10, MANLEFTONEND = 11, MANRIGHTONEND = 12,
            MANUPONEND = 13;
                
        public GameFrame() {
            super("推箱子游戏音乐版");
            setSize(600, 600);
            setVisible(true);
            setResizable(false);
            setLocation(300, 20);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            Container cont = getContentPane();
            cont.setLayout(null);
            cont.setBackground(Color.black);
            getPic();
            width = this.getWidth();
            height = this.getHeight();
            this.setFocusable(true);
            initMap();
            this.addKeyListener(this);
            this.addMouseListener(this);
            sound = new Sound();
            sound.loadSound();
        }
        
        public void initMap() {
            map = getMap(grade);
            list.clear();
            getMapSizeAndPosition();
            getManPosition();
        }
        
        public void getMapSizeAndPosition() {
            mapRow = map.length;
            mapColumn = map[0].length;
            // 找到起始图片位置, 相当于留出边界
            leftX = (width - map[0].length * 30) / 2;
            leftY = (height - map.length * 30) / 2;
            System.out.println(leftX);
            System.out.println(leftY);
            System.out.println(mapRow);
            System.out.println(mapColumn);
        }
        
        public void getManPosition() {
            for (int i = 0; i < map.length; i++) 
                for (int j = 0; j < map[0].length; j++)
                    if (map[i][j] == MANDOWN || map[i][j] == MANDOWNONEND
                        || map[i][j] == MANUP || map[i][j] == MANUPONEND
                        || map[i][j] == MANLEFT || map[i][j] == MANLEFTONEND
                        || map[i][j] == MANRIGHT || map[i][j] == MANRIGHTONEND) {
                        row = i;
                        column = j;
                        break;
                    }
        }    
        
        // 初始化地图
        public byte[][] getMap(int grade) {
            return MapFactory.getMap(grade);
        }
        
        // 加载图片
        public void getPic() {
            pic = new Image[14];
            for (int i = 0; i < 13; i++) {
                pic[i] = Toolkit.getDefaultToolkit().getImage("images/pic" + i + ".JPG");
            }
        }
        
        // 判断人所在的位置, 是grass 还是 end
        public byte grassOrEnd(byte man) {
            byte result = GRASS;
            if (man == MANDOWNONEND || man == MANLEFTONEND
                || man == MANRIGHTONEND || man == MANUPONEND)
                result = END;
            return result;
        }
        
        // 这个函数命名成 paint, 就会自动调用
        public void paint(Graphics g) {
            for (int i = 0; i < mapRow; i++)
                for (int j = 0; j < mapColumn; j++) {
                    // 画出地图, i 代表行数, j 代表列数
                    if (map[i][j] != 0)
                        g.drawImage(pic[map[i][j]], leftX + j*30, leftY + i*30, this);
                }
    //        g.setColor(Color.RED);
    //        g.setFont(new Font("楷体_2312", Font.BOLD, 30));
    //        g.drawString("现在是第", 150, 140);
    //        g.drawString(String.valueOf(grade+1), 310, 140);
    //        g.drawString("关", 360, 140);
        }
        
        public int getManX() {
            return row;
        }
        
        public int getManY() {
            return column;
        }
        
        public boolean isFinished() {
            for (int i = 0; i < mapRow; i++)
                for (int j = 0; j < mapColumn; j++)
                    if (map[i][j] == END || map[i][j] == MANDOWNONEND
                        || map[i][j] == MANUPONEND || map[i][j] == MANLEFTONEND
                        || map[i][j] == MANRIGHTONEND)
                        return false;
            return true;
        }
    
        private void moveUp() {
            // 上一步 p1 为 wall
            if (map[row-1][column] == WALL)
                return;
            // 如果 p1 是 BOX, BOXONEND, 须考虑 p2
            if (map[row-1][column] == BOX || map[row-1][column] == BOXONEND) {
                if (map[row-2][column] == END || map[row-2][column] == GRASS) {
                    Map currMap = new Map(row, column, map);
                    list.add(currMap);
                    byte boxTemp = map[row-2][column] == END? BOXONEND: BOX;
                    byte manTemp = map[row-1][column] == BOX? MANUP: MANUPONEND;
                    // 箱子变成 temp, 箱子往前一步
                    map[row-2][column] = boxTemp;
                    // 人变成MANUP, 往上走一步
                    map[row-1][column] = manTemp;
                    // 人刚才站的地方编程 GRASS 或者 END
                    map[row][column] = grassOrEnd(map[row][column]);
                    // 人离开后, 修改人的坐标
                    row--;
                }
            } else {
                // 上一位是 GRASS, END 无需考虑 p2, 其他情况不用处理
                if (map[row-1][column] == GRASS || map[row-1][column] == END) {
                    Map currMap = new Map(row, column, map);
                    list.add(currMap);
                    byte temp = map[row-1][column] == END?MANUPONEND: MANUP;
                    // 人变成 temp, 人往上走一步
                    map[row-1][column] = temp;
                    // 人刚才站的地方编程 GRASS 或者 END
                    map[row][column] = grassOrEnd(map[row][column]);
                    // 人离开后修改人的坐标
                    row--;
                }
            }
        }
        
        private void moveDown() {
            // 下一步 p1 为 wall
            if (map[row+1][column] == WALL)
                return;
            // 如果 p1 是 BOX, BOXONEND, 须考虑 p2
            if (map[row+1][column] == BOX || map[row+1][column] == BOXONEND) {
                if (map[row+2][column] == END || map[row+2][column] == GRASS) {
                    Map currMap = new Map(row, column, map);
                    list.add(currMap);
                    byte boxTemp = map[row+2][column] == END? BOXONEND: BOX;
                    byte manTemp = map[row+1][column] == BOX? MANUP: MANUPONEND;
                    // 箱子变成 temp, 箱子往前一步
                    map[row+2][column] = boxTemp;
                    // 人变成MANUP, 往下走一步
                    map[row+1][column] = manTemp;
                    // 人刚才站的地方编程 GRASS 或者 END
                    map[row][column] = grassOrEnd(map[row][column]);
                    // 人离开后, 修改人的坐标
                    row--;
                }
            } else {
                // 下一位是 GRASS, END 无需考虑 p2, 其他情况不用处理
                if (map[row+1][column] == GRASS || map[row+1][column] == END) {
                    Map currMap = new Map(row, column, map);
                    list.add(currMap);
                    byte temp = map[row+1][column] == END?MANUPONEND: MANUP;
                    // 人变成 temp, 人往下走一步
                    map[row+1][column] = temp;
                    // 人刚才站的地方编程 GRASS 或者 END
                    map[row][column] = grassOrEnd(map[row][column]);
                    // 人离开后修改人的坐标
                    row--;
                }
            }
        }
        
        private void moveLeft() {
            // 左一步 p1 为 wall
                    if (map[row][column-1] == WALL)
                        return;
                    // 如果 p1 是 BOX, BOXONEND, 须考虑 p2
                    if (map[row][column-1] == BOX || map[row][column-1] == BOXONEND) {
                        if (map[row][column-2] == END || map[row][column-2] == GRASS) {
                            Map currMap = new Map(row, column, map);
                            list.add(currMap);
                            byte boxTemp = map[row][column-2] == END? BOXONEND: BOX;
                            byte manTemp = map[row][column-1] == BOX? MANUP: MANUPONEND;
                            // 箱子变成 temp, 箱子往前一步
                            map[row][column-2] = boxTemp;
                            // 人变成MANUP, 往下走一步
                            map[row][column-1] = manTemp;
                            // 人刚才站的地方编程 GRASS 或者 END
                            map[row][column] = grassOrEnd(map[row][column]);
                            // 人离开后, 修改人的坐标
                            row--;
                        }
                    } else {
                        // 下一位是 GRASS, END 无需考虑 p2, 其他情况不用处理
                        if (map[row][column-1] == GRASS || map[row][column-1] == END) {
                            Map currMap = new Map(row, column, map);
                            list.add(currMap);
                            byte temp = map[row][column-1] == END?MANUPONEND: MANUP;
                            // 人变成 temp, 人往下走一步
                            map[row][column-1] = temp;
                            // 人刚才站的地方编程 GRASS 或者 END
                            map[row][column] = grassOrEnd(map[row][column]);
                            // 人离开后修改人的坐标
                            row--;
                        }
                    }
        }
        
        private void moveRight() {
            // 左一步 p1 为 wall
                    if (map[row][column+1] == WALL)
                        return;
                    // 如果 p1 是 BOX, BOXONEND, 须考虑 p2
                    if (map[row][column+1] == BOX || map[row][column+1] == BOXONEND) {
                        if (map[row][column+2] == END || map[row][column+2] == GRASS) {
                            Map currMap = new Map(row, column, map);
                            list.add(currMap);
                            byte boxTemp = map[row][column+2] == END? BOXONEND: BOX;
                            byte manTemp = map[row][column+1] == BOX? MANUP: MANUPONEND;
                            // 箱子变成 temp, 箱子往前一步
                            map[row][column+2] = boxTemp;
                            // 人变成MANUP, 往下走一步
                            map[row][column+1] = manTemp;
                            // 人刚才站的地方编程 GRASS 或者 END
                            map[row][column] = grassOrEnd(map[row][column]);
                            // 人离开后, 修改人的坐标
                            row--;
                        }
                    } else {
                        // 下一位是 GRASS, END 无需考虑 p2, 其他情况不用处理
                        if (map[row][column+1] == GRASS || map[row][column+1] == END) {
                            Map currMap = new Map(row, column, map);
                            list.add(currMap);
                            byte temp = map[row][column+1] == END?MANUPONEND: MANUP;
                            // 人变成 temp, 人往下走一步
                            map[row][column+1] = temp;
                            // 人刚才站的地方编程 GRASS 或者 END
                            map[row][column] = grassOrEnd(map[row][column]);
                            // 人离开后修改人的坐标
                            row--;
                        }
                    }
        }
        
        public int getGrade() {
            return grade;
        }
        
        public void displayToast(String str) {
            JOptionPane.showMessageDialog(null, str, "提示", JOptionPane.ERROR_MESSAGE);
        }
        
        public void undo() {
            if (acceptKey) {
                // 撤销
                if (list.size() > 0) {
                    // 若要撤销, 必须走过
                    Map priorMap = (Map) list.get(list.size() - 1);
                    map = priorMap.getMap();
                    row = priorMap.getManX();
                    column = priorMap.getManY();
                    repaint();
                    list.remove(list.size() - 1);
                } else
                    displayToast("不能再撤销!");
            } else {
                displayToast("此关已经完成, 不能撤销!");
            }
        }
        
        public void nextGrade() {
            if (grade >= MapFactory.getCount() - 1) {
                displayToast("恭喜你完成所有关卡");
                acceptKey = false;
            } else {
                grade++;
                initMap();
                repaint();
                acceptKey = true;
            }
        }
        
        public void priorGrade() {
            grade--;
            acceptKey = true;
            if (grade < 0)
                grade = 0;
            initMap();
            repaint();
        }
        
        @Override
        public void mouseClicked(MouseEvent e) {
            // 右键撤销移动
            if (e.getButton() == MouseEvent.BUTTON3) {
                undo();
            }    
            
        }
    
        @Override
        public void mousePressed(MouseEvent e) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void mouseReleased(MouseEvent e) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void mouseEntered(MouseEvent e) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void mouseExited(MouseEvent e) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void keyTyped(KeyEvent e) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_UP ) {
                moveUp();
            }
            if (e.getKeyCode() == KeyEvent.VK_DOWN ) {
                moveDown();
            }
            if (e.getKeyCode() == KeyEvent.VK_LEFT ) {
                moveLeft();
            }
            if (e.getKeyCode() == KeyEvent.VK_RIGHT ) {
                moveRight();
            }
            repaint();
            if (isFinished()) {
                acceptKey = false;
                if (grade == 2) {
                    JOptionPane.showMessageDialog(this, "恭喜通过最后一关");
                } else {
                    // 提示进入下一关
                    String msg = "恭喜您通过第" + grade + "关!!!
     是否进入下一关?";
                    int type = JOptionPane.YES_NO_OPTION;
                    String title = "过关";
                    int choice = 0;
                    choice = JOptionPane.showConfirmDialog(null, msg, title, type);
                    if (choice == 1)
                        System.exit(0);
                    else if (choice == 0) {
                        acceptKey = true;
                        nextGrade();
                    }
                }
            }
        }
    
        @Override
        public void keyReleased(KeyEvent e) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            
        }
    
        public static void main(String[] args) {
            new GameFrame();
    
        }
    }
  • 相关阅读:
    caffe-ubuntu1604-gtx850m-i7-4710hq----bvlc_reference_caffenet.caffemodel
    anaconda2下面安装opencv2.4.13.4完成----解决默认安装的问题----Thefunction is not implemented. Rebuild the library with Windows, GTK+ 2.x orCarbon support. If you are on Ubuntu or Debian, install libgtk2.0‑dev and pkg
    caffe-ubuntu1604-gtx850m-i7-4710hq----VGG_ILSVRC_16_layers.caffemodel
    caffe-ubuntu1604-gtx850m-i7-4710hq----bvlc_reference_caffenet.caffemodel
    matlab中文显示乱码:控制台上的,编辑器的,图片中的
    模式识别,计算机视觉领域,期刊
    matlab2017b linux版分享
    国内开源镜像站点汇总
    condarc文件
    conda清华源 pip 清华源ubuntu 清华镜像 R代理以及包的安装
  • 原文地址:https://www.cnblogs.com/moveofgod/p/12636644.html
Copyright © 2011-2022 走看看