小言_互联网的博客

【Java】推箱子小游戏(带背景音乐)完整代码

448人阅读  评论(0)


文章比较长,请耐心看完。

一、整体框架

该程序由四个类组成,GameFrame类(程序主体)、Map类(地图基础设置)、MapFactory类(地图构图)、Sound类(添加音乐),下面是程序结构图。

注意音乐格式要转MIDI序列(直接改文件后缀名不可行,如果想更换背景音乐,建议下载widi进行格式转换)

二、游戏效果图

游戏画面没有设置的很炫酷,因为绿色比较护眼。
正在看这篇博客的你,让眼睛休息一下吧!

图片音乐素材及游戏源码链接:
https://pan.baidu.com/wap/init?surl=PvUnMYBukB7A_2K-uNhzxw
.

提取码:5k71

言归正传,我们来看游戏代码

代码直接复制粘贴就能运行(素材包放在项目src目录下)

二、推箱子四大类

GameFrame类

package 推箱子;

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.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class GameFrame extends JFrame implements ActionListener ,MouseListener,KeyListener{
   

	/**
	 * 序列化ID,相当于身份认证,
	 * 主要用于程序的版本控制,保持不同版本的兼容性,
	 * 在程序版本升级时避免程序报出版本不一致的错误。
	 */
	private static final long serialVersionUID = 1L;
	
	private int grade = 0;//定义关卡数
	private int row = 7,column = 7,leftX = 0,leftY = 0;
	//row,column表示人物坐标;leftX,leftY记载左上角图片位置
	private int mapRow = 0,mapColumn = 0;//地图的行列数
	private int width = 0,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("推箱子游戏带音乐版");
		//1.窗体设置
		setSize(600,600);//窗体大小
		setVisible(true);//窗体可见
		setResizable(false);//窗体大小不可被用户改变
		setLocation(680,200);//窗体位置
		setBackground(Color.green);//窗体背景颜色
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗体结束程序
		
		//2.cont容器设置
		Container cont = getContentPane();
		/**
		 * 因为JFrame是一个框架,所以JFrame不能通过add方法直接添加组件,
		 * 创建一个content pane容器,方便向框架内添加组件
		 */
		cont.setLayout(null);//清空默认的流式布局管理器
		cont.setBackground(Color.green);//容器背景颜色
		getPic();//获取图片
		width = this.getWidth();
		height = this.getHeight();
		this.setFocusable(true);//设置组件可以被选中
		initMap();
		this.addKeyListener(this);
		this.addMouseListener(this);
		//播放音乐
		Sound sound = new Sound();
		sound.loadSound();//加载音乐
	}
	
	//初始化地图
	public void initMap(){
   
		map = getMap(grade);//获取每个地图的关卡数
		list.clear();//清除列表
		byte[][] temp = map;
		
		//创建地图
		for(int i=0;i<temp.length;i++)
		{
   
			for(int j=0;j<temp[0].length;j++){
   
				System.out.print(temp[i][j]+" ");		
				}
			System.out.println();
		}	
		
		getMapSizeAndPosition();
		getManPosition();
	}
	
	//获取人物当前位置
	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]==MANUP||map[i][j]==MANLEFT||map[i][j]==MANRIGHT){
   
					row = i;
					column = j;
					break;
				}			
			}
		}
	}
	
	
	//获取游戏区域大小及显示游戏的左上角位置
	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 getPic(){
   
		pic = new Image[14];
		for(int i=0;i<=13;i++){
   
			pic[i] = Toolkit.getDefaultToolkit().getImage
					("E:\\kkkkk\\\\推箱子\\\\src\\\\img/pic"+i+".png");
		}
	}
	
	//人走过变草地
	public byte grassOrEnd(byte man){
   
		byte result = GRASS;
		if(man == MANLEFTONEND || man == MANRIGHTONEND || man == MANUPONEND || man == MANDOWNONEND){
   
			result = END;
		}
		
		return result;
	}

	private void moveUp(){
   
		if(map[row-1][column]==WALL)
			return;
		byte tempBox;
		byte tempMan;
		
		if(map[row-1][column]==BOX||map[row-1][column]==BOXONEND){
   		//如果向上一格是箱子
			if(map[row-2][column]==GRASS||map[row-2][column]==END){
        //如果向上第二格是过道或者终点
				Map currentMap = new Map(row,column,map);
				list.add(currentMap);//用于撤回操作
				tempBox = map[row-2][column]==END?BOXONEND:BOX;
				tempMan = map[row-1][column]==BOXONEND?MANUPONEND:MANUP;
				map[row][column] = grassOrEnd(map[row][column]);
				map[row-2][column] = tempBox;
				map[row-1][column] = tempMan;
				row--;
			}
		}else{
   //如果向上一格是过道或者终点
			Map currentMap = new Map(row,column,map);
			list.add(currentMap);//用于撤回操作
			tempMan = map[row-1][column]==GRASS?MANUP:MANUPONEND;
			map[row][column] = grassOrEnd(map[row][column]);
			map[row-1][column] = tempMan;
			row--;
		}
		
	}
	
	private void moveDown(){
   
	
		if(map[row+1][column]==WALL)
			return ;
		
		byte tempBox;
		byte tempMan;
		
		if(map[row+1][column]==BOX||map[row+1][column]==BOXONEND){
   
			if(map[row+2][column]==END||map[row+2][column]==GRASS){
   
				Map currentMap = new Map(row,column,map);
				list.add(currentMap);//用于撤回操作
				tempBox = map[row+2][column] == END?BOXONEND:BOX;
				tempMan = map[row+1][column] == BOXONEND?MANDOWNONEND:MANDOWN;
				map[row][column] = grassOrEnd(map[row][column]);
				map[row+2][column] = tempBox;
				map[row+1][column] = tempMan;
				row++;
			}
		}else{
   
			Map currentMap = new Map(row,column,map);
			list.add(currentMap);//用于撤回操作
			tempMan = map[row+1][column]==GRASS?MANDOWN:MANDOWNONEND;
			map[row][column] = grassOrEnd(map[row][column]);
			map[row+1][column] = tempMan;
			row++;
		}
		
	}
	
	private void moveLeft(){
   
		
		if(map[row][column-1]==WALL)
			return ;
		
		byte tempBox;
		byte tempMan;
		
		if(map[row][column-1]==BOX||map[row][column-1]==BOXONEND){
   
			if(map[row][column-2]==END||map[row][column-2]==GRASS){
   
				Map currentMap = new Map(row,column,map);
				list.add(currentMap);//用于撤回操作
				tempBox = map[row][column-2] == END?BOXONEND:BOX;
				tempMan = map[row][column-1] == BOXONEND?MANLEFTONEND:MANLEFT;
				map[row][column] = grassOrEnd(map[row][column]);
				map[row][column-2] = tempBox;
				map[row][column-1] = tempMan;
				column--;
			}
		}else{
   
			Map currentMap = new Map(row,column,map);
			list.add(currentMap);//用于撤回操作
			tempMan = map[row][column-1]==GRASS?MANLEFT:MANLEFTONEND;
			map[row][column] = grassOrEnd(map[row][column]);
			map[row][column-1] = tempMan;
			column--;
		}
		
	}
	
	private void moveRight(){
   
		
		if(map[row][column+1]==WALL)
			return ;
		
		byte tempBox;
		byte tempMan;
		
		if(map[row][column+1]==BOX||map[row][column+1]==BOXONEND){
   
			
			if(map[row][column+2]==END||map[row][column+2]==GRASS){
   
				
				Map currentMap = new Map(row,column,map);
				list.add(currentMap);//用于撤回操作
				tempBox = map[row][column+2] == END?BOXONEND:BOX;
				tempMan = map[row][column+1] == BOXONEND?MANRIGHTONEND:MANRIGHT;
				map[row][column] = grassOrEnd(map[row][column]);
				map[row][column+2] = tempBox;
				map[row][column+1] = tempMan;
				column++;
			}
		}else{
   
			Map currentMap = new Map(row,column,map);
			list.add(currentMap);//用于撤回操作
			tempMan = map[row][column+1]==GRASS?MANRIGHT:MANRIGHTONEND;
			map[row][column] = grassOrEnd(map[row][column]);
			map[row][column+1] = tempMan;
			column++;
		}
		
	}
	
	//判断游戏是否结束
	public boolean isFinished(){
   
		
		for(int i=0;i<mapRow;i++) {
   
			for(int j=0;j<mapColumn;j++){
   
	//		System.out.println("值是"+map[i][j]+",END 的值是"+END+",他们相等吗?:"+(map[i][j]==END));
				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;
	}
	
	
	@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();
		}
		if(e.getKeyCode() == KeyEvent.VK_A){
   //上一关
			acceptKey = true;
			priorGrade();
			return ;
		}
		if(e.getKeyCode() == KeyEvent.VK_D){
   //下一关
			acceptKey = true;
			nextGrade();
			return ;
		}
		if(e.getKeyCode() == KeyEvent.VK_B){
   //撤回
			undo();
		}
		
		repaint();
		
		if(isFinished()){
   
			//禁用按键
			acceptKey = false;
			if(grade==10){
   JOptionPane.showMessageDialog(this, "恭喜通过最后一关");}
			else{
   
				String msg = "恭喜你通过第"+(grade+1)+"关!!!\n是否要进入下一关?";
				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();
				}
			}
		}
		
	}
	
	//画图
	public void paint(Graphics g){
   
		//System.out.println("我被调用了");
		for(int i=0;i<mapRow;i++) {
   
			for(int j=0;j<mapColumn;j++){
   
				if(map[i][j]!=0){
   
//					System.out.println("这个位置 不是0,它的值是"+map[i][j]);
//					g.drawRect(10, 30, getWidth()/2-50, getHeight()/2-50);
					g.drawImage(pic[map[i][j]],leftX+j*30,leftY+i*30,30,30,this);
			}
		}
	}
		g.setColor(Color.black);
		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 int getGrade(){
   
		return grade;
	}
	
	public byte[][] getMap(int grade){
   		
		return MapFactory.getMap(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 priorGrade(){
   
		grade--;
		acceptKey = true;
		if(grade<0)
			grade = 0;
		initMap();
		clearPaint(this.getGraphics());
		repaint();
	}
	
	public void nextGrade(){
   
		if(grade>=MapFactory.getCount()-1){
   
			DisplayToast("恭喜你完成所有关卡");
			acceptKey = false;
		}else{
   
			grade++;
			initMap();
			clearPaint(this.getGraphics());
			repaint();
			acceptKey = true;
		}
	}
	
	private void clearPaint(Graphics g) {
   
	 g.clearRect(0, 0, width+leftX, height+leftY);
	}

	@Override
	public void keyReleased(KeyEvent e) {
   
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseClicked(MouseEvent e) {
   
		// TODO Auto-generated method stub
		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 actionPerformed(ActionEvent e) {
   
		// TODO Auto-generated method stub
		
	}
	
	
	public static void main(String[] args){
   
		GameFrame a = new GameFrame();
	}
	
}


Map类

package 推箱子;

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;
	}
	
	//人物X坐标
	public int getManX(){
   
		return manX;
	}
	
	//人物Y坐标
	public int getManY(){
   
		return manY;
	}
	
	//地图数组
	public byte[][] getMap(){
   
		return map;
	}
	
	//关卡
	public int getGrade(){
   
		return grade;
	}
	
}


MapFactory类

package 推箱子;



public class MapFactory {
   //地图数据类
	
	static byte map[][][] = {
   
		{
   
			{
   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}
		},
		{
   
			{
   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}
		},
		{
   
			{
   1,1,1,1,1,0,0,0,0},
			{
   1,9,9,9,1,1,0,0,0},
			{
   1,9,2,9,9,1,0,0,0},
			{
   1,1,9,2,9,1,1,1,1},
			{
   0,1,1,1,5,4,9,9,1},
			{
   0,0,1,9,9,4,1,9,1},
			{
   0,0,1,9,9,9,9,9,1},
			{
   0,0,1,1,1,1,1,1,1}			
		},
		{
   
			{
   0,0,1,1,1,1},
			{
   0,1,1,9,9,1},
			{
   1,1,9,2,9,1},
			{
   1,4,2,9,5,1},
			{
   1,2,4,9,1,1},
			{
   1,4,9,1,1,0},
			{
   1,1,1,1,0,0}
		},
		
		{
   
			{
   1,1,1,1,1,1},
			{
   1,9,5,9,9,1},
			{
   1,9,2,9,9,1},
			{
   1,2,9,1,1,1},
			{
   1,4,9,4,1,0},
			{
   1,1,1,1,1,0}
		},
		{
   
			{
   0,0,0,1,1,1,1,0,0},
			{
   0,0,1,1,9,9,1,1,0},
			{
   1,1,1,9,5,2,4,1,1},
			{
   1,9,9,9,9,2,4,9,1},
			{
   1,9,9,9,1,2,4,9,1},
			{
   1,1,1,1,1,9,1,9,1},
			{
   0,0,0,0,1,9,9,9,1},
			{
   0,0,0,0,1,1,1,1,1}
		},
		
		
		{
   
			{
   0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0},//19行
			{
   0,0,0,0,1,9,9,9,1,0,0,0,0,0,0,0,0,0,0},
			{
   0,0,0,0,1,2,9,9,1,0,0,0,0,0,0,0,0,0,0},
			{
   0,0,1,1,1,9,9,2,1,1,0,0,0,0,0,0,0,0,0},
			{
   0,0,1,9,9,2,9,2,9,1,0,0,0,0,0,0,0,0,0},
			{
   1,1,1,9,1,9,1,1,9,1,0,0,0,1,1,1,1,1,1},
			{
   1,9,9,9,1,9,1,1,9,1,1,1,1,1,9,9,4,4,1},
			{
   1,9,2,9,9,2,9,9,9,9,9,9,9,9,9,9,4,4,1},
			{
   1,1,1,1,1,9,1,1,1,9,1,5,1,1,9,9,4,4,1},
			{
   0,0,0,0,1,9,9,9,9,9,1,1,1,1,1,1,1,1,1},
			{
   0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0}
		},
		{
   
			{
   1,1,1,1,1,1,1,1,1,1,1,1,0,0},//14行
			{
   1,4,4,9,9,1,9,9,9,9,9,1,1,1},
			{
   1,4,4,9,9,1,9,2,9,9,2,9,9,1},
			{
   1,4,4,9,9,1,2,1,1,1,1,9,9,1},
			{
   1,4,4,9,9,9,9,5,9,1,1,9,9,1},
			{
   1,4,4,9,9,1,9,1,9,9,2,9,1,1},
			{
   1,1,1,1,1,1,9,1,1,2,9,2,9,1},
			{
   0,0,1,9,2,9,9,2,9,2,9,2,9,1},
			{
   0,0,1,9,9,9,9,1,9,9,9,9,9,1},
			{
   0,0,1,1,1,1,1,1,1,1,1,1,1,1}
		},
		{
   
			{
   0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0},//17行
			{
   0,0,0,0,0,0,0,0,1,9,9,9,9,9,5,1,0},
			{
   0,0,0,0,0,0,0,0,1,9,2,1,2,9,1,1,0},
			{
   0,0,0,0,0,0,0,0,1,9,2,9,9,2,1,0,0},
			{
   0,0,0,0,0,0,0,0,1,1,2,9,2,9,1,0,0},
			{
   1,1,1,1,1,1,1,1,1,9,2,9,1,9,1,1,1},
			{
   1,4,4,4,4,9,9,1,1,9,2,9,9,2,9,9,1},
			{
   1,1,4,4,4,9,9,9,9,2,9,9,2,9,9,9,1},
			{
   1,4,4,4,4,9,9,1,1,1,1,1,1,1,1,1,1},
			{
   1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0}	
		},
		{
   
			{
   0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0},//19行
			{
   0,0,0,0,0,1,1,1,1,0,1,9,9,1,0,0,0,0,0},
			{
   0,0,0,1,1,1,9,5,1,1,1,2,9,1,0,0,0,0,0},
			{
   0,0,1,1,9,9,9,9,9,9,2,9,9,1,0,0,0,0,0},
			{
   0,1,1,9,9,2,9,2,2,1,1,9,1,1,0,0,0,0,0},
			{
   0,1,9,9,1,2,1,1,9,9,9,9,9,1,0,0,0,0,0},
			{
   0,1,9,1,9,2,9,2,2,9,1,9,1,1,1,0,0,0,0},
			{
   0,1,9,9,9,2,9,1,9,9,1,9,2,9,1,1,1,1,1},
			{
   1,1,1,1,9,9,9,9,1,9,9,2,2,9,1,9,9,9,1},
			{
   1,1,1,1,9,1,1,9,2,9,9,9,9,9,9,9,9,9,1},
			{
   1,4,9,9,9,9,1,1,1,9,9,1,1,1,1,1,1,1,1},
			{
   1,4,4,9,4,4,1,0,1,1,1,1,0,0,0,0,0,0,0},
			{
   1,4,4,4,1,4,1,0,0,0,0,0,0,0,0,0,0,0,0},
			{
   1,4,4,4,4,4,1,0,0,0,0,0,0,0,0,0,0,0,0},
			{
   1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0}
			
		}
		
	};
	static int count = map.length;
	
	
	public static byte[][] getMap(int grade){
   
		byte[][] temp;
		if(grade>=0&&grade<count) {
   
			temp = map[grade];
		}else {
   
			temp = map[0];
		}
		int row = temp.length;
		int column = temp[0].length;
		byte[][] result = new byte[row][column];//备份关卡版本
		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;
	}

}

Sound类

package 推箱子;

import javax.sound.midi.*;

import java.io.File;
import java.io.IOException;

public class Sound {
   

	String path = new String("E:/kkkkk/推箱子/src/img/");
	String file = new String("nor.mid");
	Sequence seq;
	Sequencer midi;
	boolean sign;
	
	//加载音乐
	public void loadSound(){
   
		try {
   
			seq = MidiSystem.getSequence(new File(path+file));
			midi = MidiSystem.getSequencer();
			midi.open();
			midi.setSequence(seq);
			midi.start();
			midi.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
			
		} catch (InvalidMidiDataException | IOException e) {
   
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MidiUnavailableException e) {
   
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		sign = true;
	}
	
	//public Sound(){
   
		
	//}
	

	
	void mystop(){
   
		midi.stop();
		midi.close();
		sign=false;
	}
	boolean isplay(){
   
		return sign;
	}
	void setMusic(String e){
   
		file=e;
	}
	
}

四、游戏分析

游戏操作

键盘上下左右键控制人物的移动,按A回到上一关,按D直接进入下一关。

数组解读

很多人对这个庞大的数组很好奇,其实呢,它们非常简单,下面我来解读一下。
0(墙外的空余区域);1(墙);2(箱子);3(箱子位于目标点上);
4(目标点);5(人物向下);9(空地);

五、wav格式音乐代码

由于mid格式比较少见,一般的软件无法实现该格式的转换,所以我们使用javax.sound实现简单的音频播放(只支持AU,RA,WAV格式),相比而言比较大众化。可以自己挑选喜欢的音乐作为背景音乐。
更新后代码如下(只修改GameFrame类和Sound类)

GameFrame类

package 推箱子;

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.util.ArrayList;
import java.util.concurrent.TimeUnit;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class GameFrame extends JFrame implements ActionListener ,MouseListener,KeyListener{
   

	/**
	 * 序列化ID,相当于身份认证,
	 * 主要用于程序的版本控制,保持不同版本的兼容性,
	 * 在程序版本升级时避免程序报出版本不一致的错误。
	 */
	private static final long serialVersionUID = 1L;
	
	private int grade = 0;//定义关卡数
	private int row = 7,column = 7,leftX = 0,leftY = 0;
	//row,column表示人物坐标;leftX,leftY记载左上角图片位置
	private int mapRow = 0,mapColumn = 0;//地图的行列数
	private int width = 0,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("推箱子游戏带音乐版");
		//1.窗体设置
		setSize(600,600);//窗体大小
		setVisible(true);//窗体可见
		setResizable(false);//窗体大小不可被用户改变
		setLocation(680,200);//窗体位置
		setBackground(Color.green);//窗体背景颜色
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗体结束程序
		
		//2.cont容器设置
		Container cont = getContentPane();
		/**
		 * 因为JFrame是一个框架,所以JFrame不能通过add方法直接添加组件,
		 * 创建一个content pane容器,方便向框架内添加组件
		 */
		cont.setLayout(null);//清空默认的流式布局管理器
		cont.setBackground(Color.green);//容器背景颜色
		getPic();//获取图片
		width = this.getWidth();
		height = this.getHeight();
		this.setFocusable(true);//设置组件可以被选中
		initMap();
		this.addKeyListener(this);
		this.addMouseListener(this);

	}
	
	//初始化地图
	public void initMap(){
   
		map = getMap(grade);//获取每个地图的关卡数
		list.clear();//清除列表
		byte[][] temp = map;
		
		//创建地图
		for(int i=0;i<temp.length;i++)
		{
   
			for(int j=0;j<temp[0].length;j++){
   
				System.out.print(temp[i][j]+" ");		
				}
			System.out.println();
		}	
		
		getMapSizeAndPosition();
		getManPosition();
	}
	
	//获取人物当前位置
	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]==MANUP||map[i][j]==MANLEFT||map[i][j]==MANRIGHT){
   
					row = i;
					column = j;
					break;
				}			
			}
		}
	}
	
	
	//获取游戏区域大小及显示游戏的左上角位置
	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 getPic(){
   
		pic = new Image[14];
		for(int i=0;i<=13;i++){
   
			pic[i] = Toolkit.getDefaultToolkit().getImage
					("E:\\kkkkk\\\\推箱子\\\\src\\\\img/pic"+i+".png");
		}
	}
	
	//人走过变草地
	public byte grassOrEnd(byte man){
   
		byte result = GRASS;
		if(man == MANLEFTONEND || man == MANRIGHTONEND || man == MANUPONEND || man == MANDOWNONEND){
   
			result = END;
		}
		
		return result;
	}

	private void moveUp(){
   
		if(map[row-1][column]==WALL)
			return;
		byte tempBox;
		byte tempMan;
		
		if(map[row-1][column]==BOX||map[row-1][column]==BOXONEND){
   		//如果向上一格是箱子
			if(map[row-2][column]==GRASS||map[row-2][column]==END){
        //如果向上第二格是过道或者终点
				Map currentMap = new Map(row,column,map);
				list.add(currentMap);//用于撤回操作
				tempBox = map[row-2][column]==END?BOXONEND:BOX;
				tempMan = map[row-1][column]==BOXONEND?MANUPONEND:MANUP;
				map[row][column] = grassOrEnd(map[row][column]);
				map[row-2][column] = tempBox;
				map[row-1][column] = tempMan;
				row--;
			}
		}else{
   //如果向上一格是过道或者终点
			Map currentMap = new Map(row,column,map);
			list.add(currentMap);//用于撤回操作
			tempMan = map[row-1][column]==GRASS?MANUP:MANUPONEND;
			map[row][column] = grassOrEnd(map[row][column]);
			map[row-1][column] = tempMan;
			row--;
		}
		
	}
	
	private void moveDown(){
   
	
		if(map[row+1][column]==WALL)
			return ;
		
		byte tempBox;
		byte tempMan;
		
		if(map[row+1][column]==BOX||map[row+1][column]==BOXONEND){
   
			if(map[row+2][column]==END||map[row+2][column]==GRASS){
   
				Map currentMap = new Map(row,column,map);
				list.add(currentMap);//用于撤回操作
				tempBox = map[row+2][column] == END?BOXONEND:BOX;
				tempMan = map[row+1][column] == BOXONEND?MANDOWNONEND:MANDOWN;
				map[row][column] = grassOrEnd(map[row][column]);
				map[row+2][column] = tempBox;
				map[row+1][column] = tempMan;
				row++;
			}
		}else{
   
			Map currentMap = new Map(row,column,map);
			list.add(currentMap);//用于撤回操作
			tempMan = map[row+1][column]==GRASS?MANDOWN:MANDOWNONEND;
			map[row][column] = grassOrEnd(map[row][column]);
			map[row+1][column] = tempMan;
			row++;
		}
		
	}
	
	private void moveLeft(){
   
		
		if(map[row][column-1]==WALL)
			return ;
		
		byte tempBox;
		byte tempMan;
		
		if(map[row][column-1]==BOX||map[row][column-1]==BOXONEND){
   
			if(map[row][column-2]==END||map[row][column-2]==GRASS){
   
				Map currentMap = new Map(row,column,map);
				list.add(currentMap);//用于撤回操作
				tempBox = map[row][column-2] == END?BOXONEND:BOX;
				tempMan = map[row][column-1] == BOXONEND?MANLEFTONEND:MANLEFT;
				map[row][column] = grassOrEnd(map[row][column]);
				map[row][column-2] = tempBox;
				map[row][column-1] = tempMan;
				column--;
			}
		}else{
   
			Map currentMap = new Map(row,column,map);
			list.add(currentMap);//用于撤回操作
			tempMan = map[row][column-1]==GRASS?MANLEFT:MANLEFTONEND;
			map[row][column] = grassOrEnd(map[row][column]);
			map[row][column-1] = tempMan;
			column--;
		}
		
	}
	
	private void moveRight(){
   
		
		if(map[row][column+1]==WALL)
			return ;
		
		byte tempBox;
		byte tempMan;
		
		if(map[row][column+1]==BOX||map[row][column+1]==BOXONEND){
   
			
			if(map[row][column+2]==END||map[row][column+2]==GRASS){
   
				
				Map currentMap = new Map(row,column,map);
				list.add(currentMap);//用于撤回操作
				tempBox = map[row][column+2] == END?BOXONEND:BOX;
				tempMan = map[row][column+1] == BOXONEND?MANRIGHTONEND:MANRIGHT;
				map[row][column] = grassOrEnd(map[row][column]);
				map[row][column+2] = tempBox;
				map[row][column+1] = tempMan;
				column++;
			}
		}else{
   
			Map currentMap = new Map(row,column,map);
			list.add(currentMap);//用于撤回操作
			tempMan = map[row][column+1]==GRASS?MANRIGHT:MANRIGHTONEND;
			map[row][column] = grassOrEnd(map[row][column]);
			map[row][column+1] = tempMan;
			column++;
		}
		
	}
	
	//判断游戏是否结束
	public boolean isFinished(){
   
		
		for(int i=0;i<mapRow;i++) {
   
			for(int j=0;j<mapColumn;j++){
   
	//		System.out.println("值是"+map[i][j]+",END 的值是"+END+",他们相等吗?:"+(map[i][j]==END));
				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;
	}
	
	
	@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();
		}
		if(e.getKeyCode() == KeyEvent.VK_A){
   //上一关
			acceptKey = true;
			priorGrade();
			return ;
		}
		if(e.getKeyCode() == KeyEvent.VK_D){
   //下一关
			acceptKey = true;
			nextGrade();
			return ;
		}
		if(e.getKeyCode() == KeyEvent.VK_B){
   //撤回
			undo();
		}
		
		repaint();
		
		if(isFinished()){
   
			//禁用按键
			acceptKey = false;
			if(grade==10){
   JOptionPane.showMessageDialog(this, "恭喜通过最后一关");}
			else{
   
				String msg = "恭喜你通过第"+(grade+1)+"关!!!\n是否要进入下一关?";
				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();
				}
			}
		}
		
	}
	
	//画图
	public void paint(Graphics g){
   
		//System.out.println("我被调用了");
		for(int i=0;i<mapRow;i++) {
   
			for(int j=0;j<mapColumn;j++){
   
				if(map[i][j]!=0){
   
//					System.out.println("这个位置 不是0,它的值是"+map[i][j]);
//					g.drawRect(10, 30, getWidth()/2-50, getHeight()/2-50);
					g.drawImage(pic[map[i][j]],leftX+j*30,leftY+i*30,30,30,this);
			}
		}
	}
		g.setColor(Color.black);
		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 int getGrade(){
   
		return grade;
	}
	
	public byte[][] getMap(int grade){
   		
		return MapFactory.getMap(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 priorGrade(){
   
		grade--;
		acceptKey = true;
		if(grade<0)
			grade = 0;
		initMap();
		clearPaint(this.getGraphics());
		repaint();
	}
	
	public void nextGrade(){
   
		if(grade>=MapFactory.getCount()-1){
   
			DisplayToast("恭喜你完成所有关卡");
			acceptKey = false;
		}else{
   
			grade++;
			initMap();
			clearPaint(this.getGraphics());
			repaint();
			acceptKey = true;
		}
	}
	
	private void clearPaint(Graphics g) {
   
	 g.clearRect(0, 0, width+leftX, height+leftY);
	}

	@Override
	public void keyReleased(KeyEvent e) {
   
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseClicked(MouseEvent e) {
   
		// TODO Auto-generated method stub
		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 actionPerformed(ActionEvent e) {
   
		// TODO Auto-generated method stub
		
	}
	
	//主方法
	public static void main(String[] args) throws InterruptedException{
   
		GameFrame a = new GameFrame();
		Sound player = new Sound("E:/kkkkk/推箱子/src/img/XiongDi.wav");   //创建音乐播放器
        
        player.start(true);//以开始以循环的形式播放,player(false)为不循环播放
        
        TimeUnit.SECONDS.sleep(5);
        
        player.stop();                        //暂停播放音频
        
        TimeUnit.SECONDS.sleep(4);
        
        player.continues();                //继续开始播放音频
	}
	
}


Sound类

package 推箱子;






/**
*
* Description: 简易音频播放器(只支持AU,RA,WAV)
* 			   在不使用JMF的情况下快速实现音频播放
* 
*/
import javax.sound.sampled.*;
import java.io.*;
import java.util.concurrent.TimeUnit;
 
public class Sound {
   
	private String musicPath; //音频文件
	private volatile boolean run = true;  //记录音频是否播放
	private Thread mainThread;   //播放音频的任务线程
	
	private AudioInputStream audioStream;
	private AudioFormat audioFormat;
	private SourceDataLine sourceDataLine;
	
	public Sound(String musicPath) {
   
		this.musicPath = musicPath;
		prefetch();
	}
	
	//数据准备
	private void prefetch(){
   
		try{
   
		//获取音频输入流
	    audioStream = AudioSystem.getAudioInputStream(new File(musicPath));
		//获取音频的编码对象
		audioFormat = audioStream.getFormat();
		//包装音频信息
		DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class,
				audioFormat,AudioSystem.NOT_SPECIFIED);
		//使用包装音频信息后的Info类创建源数据行,充当混频器的源
		sourceDataLine = (SourceDataLine)AudioSystem.getLine(dataLineInfo);
		
		sourceDataLine.open(audioFormat);
		sourceDataLine.start();
		
		}catch(UnsupportedAudioFileException ex){
   
			ex.printStackTrace();
		}catch(LineUnavailableException ex){
   
			ex.printStackTrace();
		}catch(IOException ex){
   
			ex.printStackTrace();
		}
		
	}
	//析构函数:关闭音频读取流和数据行
	protected void finalize() throws Throwable{
   
		super.finalize();
		sourceDataLine.drain();
		sourceDataLine.close();
		audioStream.close();
	}
	
	//播放音频:通过loop参数设置是否循环播放
	private void playMusic(boolean loop)throws InterruptedException {
   
		try{
   
				if(loop){
   
					while(true){
   
						playMusic();
					}
				}else{
   
					playMusic();
					//清空数据行并关闭
					sourceDataLine.drain();
					sourceDataLine.close();
					audioStream.close();
				}
			
		}catch(IOException ex){
   
			ex.printStackTrace();
		}
		
		
	}
	private void playMusic(){
   
		try{
   
			synchronized(this){
   
				run = true;
			}
			//通过数据行读取音频数据流,发送到混音器;
			//数据流传输过程:AudioInputStream -> SourceDataLine;
			audioStream = AudioSystem.getAudioInputStream(new File(musicPath));
			int count;
			byte tempBuff[] = new byte[1024];
			
				while((count = audioStream.read(tempBuff,0,tempBuff.length)) != -1){
   
					synchronized(this){
   
					while(!run)
						wait();
					}
					sourceDataLine.write(tempBuff,0,count);
							
			}
 
		}catch(UnsupportedAudioFileException ex){
   
			ex.printStackTrace();
		}catch(IOException ex){
   
			ex.printStackTrace();
		}catch(InterruptedException ex){
   
			ex.printStackTrace();
		}
		
	}
	
	
	//暂停播放音频
	private void stopMusic(){
   
		synchronized(this){
   
			run = false;
			notifyAll();
		}
	}
	//继续播放音乐
	private void continueMusic(){
   
		synchronized(this){
   
			 run = true;
			 notifyAll();
		}
	}
	
	
	//外部调用控制方法:生成音频主线程;
	public void start(boolean loop){
   
		mainThread = new Thread(new Runnable(){
   
			public void run(){
   
				try {
   
					playMusic(loop);
				} catch (InterruptedException e) {
   
					e.printStackTrace();
				}
			}
		});
		mainThread.start();
	}
	
	//外部调用控制方法:暂停音频线程
	public void stop(){
   
		new Thread(new Runnable(){
   
			public void run(){
   
				stopMusic();
				
			}
		}).start();
	}
	//外部调用控制方法:继续音频线程
	public void continues(){
   
		new Thread(new Runnable(){
   
			public void run(){
   
				continueMusic();
			}
		}).start();
	}

  
 }

修改后就可以自己修改喜欢的背景音乐了


转载:https://blog.csdn.net/weixin_48701521/article/details/108050872
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场