Java实现推箱子小游戏(idea+mySQL)

就是我们学校实训有个推箱子的小游戏,一开始只是完成任务,然后……【想法越来越多,我的第一个小游戏就诞生了,虽然可能就我一个人玩了,但是很高兴能和你分享制作的过程!】
完整的白嫖代码以及资料可以通过下面的百度云连接获取
(大家可以根据源码和看文章中对各个板块的说明这样更加清晰一点)

链接:https://pan.baidu.com/s/18LGcssj8ms-A7WgPNH3bwQ 提取码:yncd
复制这段内容后打开百度网盘手机App,操作更方便哦

游戏部分功能及部分地图展示

一、游戏设定

1.玩法

把箱子推到指定的地方,这里我把箱子替换成了礼物,需要把礼物搬运到指定的地点,就能进入下一关。

2.剧情

小熊要给小兔子过生日,在每一年都会准备不同的礼物,当所有礼物都送达的时候,小熊就会给小兔子送上这一年的生日祝福!小兔子也能按时长大一岁。

二、需求分析

1.用户登录界面

玩家凭借用户名和密码登录,没有账号时可以选择注册

2.游戏界面

(1)窗体标题栏


玩家登入成功后就会在窗体的标题栏上显示用户昵称

(2)窗体菜单栏


玩家可以在通过菜单栏的点击实现相应的功能

(3)主要按钮


玩家可以点击按钮实现相应的功能

(4)主面版


玩家可以通过键盘,实现小熊位置的移动,箱子的推动,所有箱子推到指定位置(就是小熊爪印的时候)就会自动进入下一关,在右侧的版面,有关卡的提示功能,记录步骤,送达礼物,用时,实现所有玩家的排行(前三名),并在右下角有当前的时间显示。

三、数据库设计

1.用MySQL设计存储玩家信息的表

这里我们用到的是mySQL
创建数据库-> mygame
创建数据表-> user

2.为了后续方便操作,我们可以使用idea的Database功能


填写用户名和密码一般就可以连接成功了,但是MySQL(8.0)好像是要配置时区的

四、需要提前创建的一些接口类

工程总览

1.class GameUtil【负责实现图面的读取】

package yuixiangzi;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;public class GameUtil {// 工具类最好将构造器私有化。private GameUtil() {}public static Image getImage(String path) {BufferedImage bi = null;try {URL u = GameUtil.class.getClassLoader().getResource(path);bi = ImageIO.read(GameUtil.class.getResourceAsStream(path));} catch (IOException e) {e.printStackTrace();}return bi;}
}

2.class SetImage【这是我对文件夹中的图片进行的处理】

package yuixiangzi;import java.awt.*;public class SetImage {private SetImage() {}public static Image[] GetImage(int year) {Image img1 = GameUtil.getImage("/pic/1.png");Image img2 = GameUtil.getImage("/pic/2.png");Image img3 = GameUtil.getImage("/pic/3.png");Image img4 = GameUtil.getImage("/pic/4.png");Image img5 = GameUtil.getImage("/pic/5.png");Image img6 = GameUtil.getImage("/pic/6.png");Image img7 = GameUtil.getImage("/pic/7.png");Image img8 = GameUtil.getImage("/pic/8.png");Image img9 = GameUtil.getImage("/pic/9.png");Image img10 = GameUtil.getImage("/pic/10.png");Image img11 = GameUtil.getImage("/pic/11.png");Image img12 = GameUtil.getImage("/pic/12.png");Image img13= GameUtil.getImage("/pic/13.png");Image img14 = GameUtil.getImage("/pic/14.png");Image img15 = GameUtil.getImage("/pic/001.png");Image img16 = GameUtil.getImage("/pic/002.png");Image img17 = GameUtil.getImage("/pic/003.png");Image img18 = GameUtil.getImage("/pic/004.png");Image img19 = GameUtil.getImage("/pic/005.png");Image img20 = GameUtil.getImage("/pic/006.png");Image img21 = GameUtil.getImage("/pic/007.png");Image img22 = GameUtil.getImage("/pic/008.png");Image img23 = GameUtil.getImage("/pic/009.png");Image img24 = GameUtil.getImage("/pic/010.png");Image img25 = GameUtil.getImage("/pic/011.png");Image img26 = GameUtil.getImage("/pic/012.png");Image img27 = GameUtil.getImage("/pic/013.png");Image img28 = GameUtil.getImage("/pic/014.png");Image img29 = GameUtil.getImage("/pic/015.png");Image img30 = GameUtil.getImage("/pic/016.png");Image img31 = GameUtil.getImage("/pic/017.png");Image img32 = GameUtil.getImage("/pic/018.png");Image img33 = GameUtil.getImage("/pic/019.png");Image img34 = GameUtil.getImage("/pic/020.png");Image img35 = GameUtil.getImage("/pic/021.png");Image img36 = GameUtil.getImage("/pic/022.png");Image img37 = GameUtil.getImage("/pic/023.png");Image img38 = GameUtil.getImage("/pic/024.png");Image img39 = GameUtil.getImage("/pic/025.png");Image img40 = GameUtil.getImage("/pic/026.png");Image img41 = GameUtil.getImage("/pic/027.png");Image img42 = GameUtil.getImage("/pic/028.png");Image img43 = GameUtil.getImage("/pic/029.png");Image img44 = GameUtil.getImage("/pic/030.png");Image img45 = GameUtil.getImage("/pic/031.png");Image img46 = GameUtil.getImage("/pic/032.png");Image img47 = GameUtil.getImage("/pic/033.png");Image img48 = GameUtil.getImage("/pic/034.png");Image img49 = GameUtil.getImage("/pic/035.png");Image img50 = GameUtil.getImage("/pic/036.png");Image img51 = GameUtil.getImage("/pic/037.png");Image img52 = GameUtil.getImage("/pic/038.png");Image img53 = GameUtil.getImage("/pic/039.png");Image img54 = GameUtil.getImage("/pic/040.png");Image img55 = GameUtil.getImage("/pic/041.png");Image img56 = GameUtil.getImage("/pic/042.png");Image img57 = GameUtil.getImage("/pic/043.png");Image img58 = GameUtil.getImage("/pic/044.png");Image img59 = GameUtil.getImage("/pic/045.png");Image img60 = GameUtil.getImage("/pic/046.png");Image img61 = GameUtil.getImage("/pic/047.png");Image img62 = GameUtil.getImage("/pic/048.png");Image img63 = GameUtil.getImage("/pic/049.png");Image img64 = GameUtil.getImage("/pic/050.png");Image img65 = GameUtil.getImage("/pic/051.png");Image img66 = GameUtil.getImage("/pic/052.png");Image img67 = GameUtil.getImage("/pic/053.png");Image img68 = GameUtil.getImage("/pic/054.png");Image img69 = GameUtil.getImage("/pic/055.png");Image img70 = GameUtil.getImage("/pic/056.png");Image img71 = GameUtil.getImage("/pic/057.png");Image img72 = GameUtil.getImage("/pic/058.png");Image img73 = GameUtil.getImage("/pic/059.png");Image img74 = GameUtil.getImage("/pic/060.png");Image img75 = GameUtil.getImage("/pic/061.png");Image img76 = GameUtil.getImage("/pic/062.png");Image img77 = GameUtil.getImage("/pic/063.png");Image img78 = GameUtil.getImage("/pic/064.png");Image img79 = GameUtil.getImage("/pic/065.png");Image img80 = GameUtil.getImage("/pic/066.png");Image img81 = GameUtil.getImage("/pic/067.png");Image img82 = GameUtil.getImage("/pic/068.png");Image img83 = GameUtil.getImage("/pic/069.png");//imag40 6 7 3不变其他自己配置 00命名的记得加14Image[] maping = new Image[10];if(year%7==1){maping = new Image[]{img34, img36, img40, img6, img7, img3, img3, img3, img3, img5,};}else if(year%7==2){maping = new Image[]{img35, img64, img40, img6, img7, img3, img3, img3, img3, img60,};}else if(year%7==3){maping = new Image[]{img68, img71, img40, img6, img7, img3, img3, img3, img3, img69,};}else if(year%7==4){maping = new Image[]{img41, img50, img40, img49, img58,img37, img37, img37, img37, img42,};}else if(year%7==5){maping = new Image[]{img13, img23, img40, img6, img7,img3, img3, img3, img3, img66,};}else if(year%7==6){maping = new Image[]{img46,img56, img40, img6, img7,img3, img3, img3, img3, img65,};}else{maping = new Image[]{img54,img42, img40, img6, img7,img3, img3, img3, img3, img2,};}return maping;}
}

3.class JDBCUtils【数据库连接工具类】

package yuixiangzi;import java.io.FileReader;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;//JDBC工具了
public class JDBCUtils {private static String url;private static String user;private static String password;private static String driver;static {try {Properties pro=new Properties();pro.load(new FileReader("src\\jdbc.properties"));url = pro.getProperty("url");user=pro.getProperty("user");password = pro.getProperty("password");driver = pro.getProperty("driver");Class.forName(driver);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}}public static Connection getConnection() throws SQLException{return DriverManager.getConnection(url,user,password);}public static void close(Statement stmt,Connection conn){if(stmt !=null){try{stmt.close();}catch (SQLException e){e.printStackTrace();}}if(conn !=null){try{conn.close();}catch (SQLException e){e.printStackTrace();}}}public static void close(ResultSet rs,Statement stmt, Connection conn){if(rs !=null){try{rs.close();}catch (SQLException e){e.printStackTrace();}}if(stmt !=null){try{stmt.close();}catch (SQLException e){e.printStackTrace();}}if(conn !=null){try{conn.close();}catch (SQLException e){e.printStackTrace();}}}
}

4.jdbc.properties【方便更改数据库】


特别特别要注意,不要多打空格!!!(当初连数据库的时候就是因为这里多打了空格找了好久的原因QVQ)

url=jdbc:mysql:///mygame
user=root
password=root
driver=com.mysql.cj.jdbc.Driver

五、登入窗口实现

1.界面外观设计

我就是喜欢这样可可爱爱(花里胡哨)的设计!谁说程序员就不可以粉粉嫩嫩的嘛!

class MyGameLogin extends JFrame {String username = null;String password = null;public MyGameLogin() {super("时光登入口");String path = "/pic/10.png";//设置窗体图标try {Image image = ImageIO.read(getClass().getResource(path));setIconImage(image);} catch (IOException e) {e.printStackTrace();}setSize(400, 400);Container C = getContentPane();C.setLayout(null);C.setBackground(new Color(255, 228, 196));JLabel lblTitle = new JLabel("时光登入口");lblTitle.setForeground(new Color(255, 140, 0));lblTitle.setFont(new Font("幼圆", Font.BOLD, 35));lblTitle.setBounds(100, 35, 200, 35);add(lblTitle);JLabel lblLogin = new JLabel("玩家名:");lblLogin.setForeground(new Color(244, 164, 96));lblLogin.setFont(new Font("幼圆", Font.BOLD, 20));lblLogin.setBounds(70, 160, 100, 35);add(lblLogin);JLabel lblLogin1 = new JLabel("密码:");lblLogin1.setForeground(new Color(244, 164, 96));lblLogin1.setFont(new Font("幼圆", Font.BOLD, 20));lblLogin1.setBounds(70, 220, 100, 35);add(lblLogin1);JButton btnLogin;btnLogin = new JButton("注册");btnLogin.setForeground(new Color(255, 127, 80));btnLogin.setBackground(new Color(255, 222, 173));btnLogin.setBounds(230, 270, 80, 30);C.add(btnLogin);JPasswordField passWord = new JPasswordField();passWord.setForeground(new Color(255, 140, 0));passWord.setBounds(170, 220, 140, 35);C.add(passWord);JTextField userName = new JTextField();userName.setForeground(new Color(255, 140, 0));userName.setBounds(170, 160, 140, 35);C.add(userName);JButton btnLogin1;btnLogin1 = new JButton("登入");btnLogin1.setForeground(new Color(255, 127, 80));btnLogin1.setBackground(new Color(255, 222, 173));btnLogin1.setBounds(100, 270, 80, 30);C.add(btnLogin1);setVisible(true);setLocationRelativeTo(null);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}Image imagetx = GameUtil.getImage("/pic/1.png");Image imagexx = GameUtil.getImage("/pic/3.png");Image imageLove = GameUtil.getImage("/pic/13.png");Image imageFlower1 = GameUtil.getImage("/pic/003.png");Image imageFlower2 = GameUtil.getImage("/pic/009.png");Image imageFlower3 = GameUtil.getImage("/pic/005.png");Image imageFlower4 = GameUtil.getImage("/pic/012.png");public void paint(Graphics g) {super.paint(g);g.drawImage(imageFlower1, 90, 150, null);g.drawImage(imageFlower3, 120, 150, null);g.drawImage(imagetx, 150, 150, null);g.drawImage(imageLove, 180, 150, null);g.drawImage(imagexx, 210, 150, null);g.drawImage(imageFlower2, 240, 150, null);g.drawImage(imageFlower4, 270, 150, null);}
}

2.登录功能实现

(1)登录按钮监听

按下登录按钮后,开始判断用户名和密码是否不为空,如果不为空,则进行查询语句的判断。

btnLogin1.addActionListener(new AbstractAction() {@Override/*[为什么这里不能判断是否为空]如果这个遗留问题不解决,那么后面的注册插入数据库的操作有没有办法执行*/public void actionPerformed(ActionEvent e) {username = userName.getText();password = new String(passWord.getPassword());System.out.println("test:" + username);System.out.println("test:" + password);if (StringUtils.isNullOrEmpty(username)) {JOptionPane.showMessageDialog(null, "小兔子:真是的!你连名字都不告诉我");}if (StringUtils.isNullOrEmpty(password)) {JOptionPane.showMessageDialog(null, "咦?你忘记了我们之间的暗号!不是不是小兔子乖乖,把门开开啦!");}if (!StringUtils.isNullOrEmpty(username) && !StringUtils.isNullOrEmpty(password)) {//【这里执行查找语句】if (login()) {JOptionPane.showMessageDialog(null, "小兔子:你好!" + username + "又见面了!");dispose();long startTime =  System.currentTimeMillis();System.out.println(startTime);int[] result= null;result=select(username);select(username);new myGame(startTime,username,result[0],result[1],result[2]);} else {JOptionPane.showMessageDialog(null, "小兔子:我好像不认识你哦!");}}}});

(2)查询数据库判断该用户密码是否正确

 public boolean login() {if (username == null || password == null) {return false;}Connection conn = null;PreparedStatement pstmt = null;ResultSet rs = null;try {conn = JDBCUtils.getConnection();String sql = "select* from user where id= ? and password = ? ";pstmt = conn.prepareStatement(sql);pstmt.setString(1,username);pstmt.setString(2,password);rs = pstmt.executeQuery();return rs.next();} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.close(rs, pstmt, conn);}return false;}

(3)用户登录后查询保存的游戏信息

public int[] select(String username){Connection conn = null;PreparedStatement pstmt = null;ResultSet rs = null;int[] result= null;try {int grift,level,step;conn = JDBCUtils.getConnection();String sql = "select grift,lever,step from user where id= ? ";pstmt = conn.prepareStatement(sql);pstmt.setString(1,username);rs = pstmt.executeQuery();result=new int[3];while (rs.next()){grift=rs.getInt("grift");level=rs.getInt("lever");step=rs.getInt("step");result[0]=grift;result[1]=level;result[2]=step;}return result;} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.close(rs, pstmt, conn);}return result;}

3.注册功能的实现

(1)注册按钮的监听

btnLogin.addActionListener(new AbstractAction() {@Overridepublic void actionPerformed(ActionEvent e) {username = userName.getText();password = new String(passWord.getPassword());//[这里执行插入语句]if (!StringUtils.isNullOrEmpty(username) && !StringUtils.isNullOrEmpty(password)) {JOptionPane.showMessageDialog(null, "小兔子:你好!" + username + "很高兴和你做朋友");insert(username,password);dispose();long startTime =  System.currentTimeMillis();System.out.println(startTime);new myGame(startTime,username,0,1,0);}else {JOptionPane.showMessageDialog(null, "小兔子:我好像不认识你哦!");}}});

(2)插入用户信息功能的实现

 //这是插入语句public void insert(String userName,String passWord) {Connection conn = null;PreparedStatement pstmt = null;try {conn = JDBCUtils.getConnection();String sql = "insert into user values (?,?,0,1,0)";pstmt = conn.prepareStatement(sql);pstmt.setString(1, userName);pstmt.setString(2, passWord);int count = pstmt.executeUpdate();if (count > 0) {System.out.println("注册成功");} else {System.out.println("插入失败");}} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.close(pstmt, conn);}}

六、游戏版面的实现

1.实现游戏地图的导入及图形的显示

(1)游戏地图的读取

每一关有又相应的由int map[20][20]的二维数组组成,我们只需要读取响应的数字,然后放置相应名字的图片在面板上就好了。

class ReadMap{private int map[][];//人物位置private int mx,my;//游戏关卡编号private int level;public ReadMap(int level){this.level=level;//文件路径String sfilename ="src\\maps\\"+level+".map";String content="";//文件字符流读取文件src\maps\0.maptry{FileReader fr = new FileReader(sfilename);BufferedReader br = new BufferedReader(fr);String temp = "";//一行一行地读取文件,如果读到文件的末尾返回nullwhile ((temp = br.readLine())!=null){content += temp;}//转化成字节数组byte b[] = content.getBytes();map = new int[20][20];int c =0;for(int i=0;i<20;i++){for(int j=0;j<20;j++){map[i][j]=b[c]-48;c++;//返回人物的位置if(map[i][j]==5){mx=i;my=j;}}}}catch (FileNotFoundException e){e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}public  int[][] getMap(){return map;}public int getMx() {return mx;}public int getMy() {return my;}
}

2.游戏显示界面实现

(1)设计总的组件

//设置按钮JButton btnBack, btnNext, btnPrev, btnSelect, btnReset,//撤销一步,下一关,上一关,选择关卡,重新游戏btnMusic,//选择音乐btnLook;//查看当前排名JComboBox cbMusic;//下拉链表框,选择音乐JMenuBar menuBar;//菜单条JMenu menuOption, mnuSet, mnuHelp;//菜单条选项,关卡选择,音乐设置,帮助JMenuItem miReset, miPrev, miNext, miSelect, miExit, miBack;JMenuItem miMusic1, miMusic2;//帮助信息JMenuItem miHelp;//只有50关//定义一个数组存放音乐//创建MyPanel类MyPanel mainPanel;

(2)设计窗体

     //设置窗体图标try {Image image = ImageIO.read(this.getClass().getResource(path));this.setIconImage(image);} catch (IOException e) {e.printStackTrace();}Color bgColor = new Color(230, 230, 250);//设置窗体大小setSize(800, 840);//设置窗体颜色Container C = getContentPane();C.setLayout(null);C.setBackground(new Color(255, 240, 245));//将标题设置JLabel lblTitle = new JLabel("Happy Birthday !", JLabel.CENTER);lblTitle.setForeground(new Color(205, 92, 92));lblTitle.setFont(new Font("幼圆", Font.BOLD, 30));lblTitle.setBounds(100, 20, 500, 30);add(lblTitle);//设置主面板大小和背景颜色mainPanel = new MyPanel();mainPanel.setBounds(10, 90, 760, 600);mainPanel.setBackground(bgColor);C.add(mainPanel);createButton(C);//设置窗体可见setVisible(true);setLocationRelativeTo(null);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}

(3)设计按钮、音乐下拉选择框和下方标签

//创建按钮函数public void createButton(Container C) {//设置显示文字btnReset = new JButton("重新游戏");btnBack = new JButton("赖皮一下");btnNext = new JButton("跳过这关");btnPrev = new JButton("回溯一关");btnLook = new JButton("保存当前进度");btnSelect = new JButton("选择关卡");btnMusic = new JButton("关闭音乐");cbMusic = new JComboBox(sMusic);//设置按钮监听btnBack.addActionListener(this);btnMusic.addActionListener(this);btnNext.addActionListener(this);btnPrev.addActionListener(this);btnBack.addActionListener(this);btnLook.addActionListener(this);btnReset.addActionListener(this);btnSelect.addActionListener(this);//设置绝对位置btnReset.setBounds(10, 50, 95, 30);btnMusic.setBounds(110, 50, 95, 30);btnSelect.setBounds(210, 50, 95, 30);btnBack.setBounds(310, 50, 95, 30);btnPrev.setBounds(410, 50, 95, 30);btnNext.setBounds(510, 50, 95, 30);btnLook.setBounds(610, 50, 160, 30);btnReset.setBackground(new Color(255, 174, 185));btnMusic.setBackground(new Color(255, 174, 185));btnSelect.setBackground(new Color(255, 174, 185));btnBack.setBackground(new Color(255, 174, 185));btnPrev.setBackground(new Color(255, 174, 185));btnNext.setBackground(new Color(255, 174, 185));btnLook.setBackground(new Color(255, 174, 185));cbMusic.addItemListener(this);C.add(btnReset);C.add(btnMusic);C.add(btnSelect);C.add(btnLook);C.add(btnPrev);C.add(btnNext);C.add(btnBack);JLabel lblMusic = new JLabel("选择音乐");lblMusic.setBounds(610, 700, 160, 30);JLabel lblText1 = new JLabel("小熊:今天是小兔子的生日,我要赶紧把礼物给她送过去!");lblText1.setForeground(new Color(205, 92, 92));lblText1.setBounds(10, 700, 460, 30);C.add(lblText1);JLabel lblText2 = new JLabel("小熊:你问我是什么礼物?这是秘密!是小兔子喜欢的……");lblText2.setForeground(new Color(205, 92, 92));lblText2.setBounds(10, 730, 460, 30);C.add(lblText2);C.add(lblMusic);cbMusic.setBounds(610, 730, 160, 30);C.add(cbMusic);}

(4)设计菜单选项

public void createMenus() {//选项子菜单menuOption = new JMenu("选项(O)");menuOption.setMnemonic('O');//设置热键miReset = new JMenuItem("重置");miPrev = new JMenuItem("上一关");miNext = new JMenuItem("下一关");miSelect = new JMenuItem("选择");miExit = new JMenuItem("退出");miBack = new JMenuItem("撤销一步");menuOption.add(miReset);menuOption.add(miPrev);menuOption.add(miNext);menuOption.add(miSelect);menuOption.add(miBack);menuOption.addSeparator();//添加分隔条menuOption.add(miExit);//音乐子菜单mnuSet = new JMenu("设置(S)");mnuSet.setMnemonic('S');//设置热键miMusic1 = new JMenuItem(sMusic[0]);miMusic2 = new JMenuItem(sMusic[1]);ButtonGroup bg = new ButtonGroup();bg.add(miMusic1);bg.add(miMusic2);//帮助子菜单//默认选第一首setMenuState(0);mnuSet.add(miMusic1);mnuSet.add(miMusic2);mnuHelp = new JMenu("帮助(H)");mnuHelp.setMnemonic('H');miHelp = new JMenuItem("关于我们……");mnuHelp.add(miHelp);//监听miReset.addActionListener(this);miPrev.addActionListener(this);miNext.addActionListener(this);miBack.addActionListener(this);miSelect.addActionListener(this);miExit.addActionListener(this);miMusic1.addActionListener(this);miMusic2.addActionListener(this);miHelp.addActionListener(this);menuBar = new JMenuBar();menuBar.add(menuOption);menuBar.add(mnuSet);menuBar.add(mnuHelp);setJMenuBar(menuBar);}

(5)一些面板显示文字以及图片的实现

    public void paint(Graphics g) {Image[] maping = SetImage.GetImage(level);super.paint(g);for (int i = 0; i < 20; i++) {for (int j = 0; j < 20; j++) {g.drawImage(maping[tempmap[j][i]], i * 30, j * 30, null);}}g.drawImage(img11, 580, 30, null);g.drawImage(imagetx, 620, 550, null);g.drawImage(imagetx, 650, 550, null);g.drawImage(imagetx, 680, 550, null);g.drawImage(imagetx, 710, 550, null);g.drawImage(imageff, 595, 280, null);g.drawImage(imageff, 625, 280, null);g.drawImage(imageff, 700, 280, null);g.drawImage(imageff, 730, 280, null);g.setColor(new Color(233,150,122));g.setFont(new Font("幼圆", Font.BOLD, 20));g.drawString("小兔几" + level + "岁啦", 625, 30);nowlever=level;g.setColor(new Color(250,128,114));g.setFont(new Font("幼圆", Font.BOLD, 14));g.drawString("小熊熊在努力派送礼物", 605, 220);g.setColor(new Color(255,160,122));g.drawString("已经走了:" +nowstep + "步啦", 605, 240);g.setFont(new Font("幼圆", Font.BOLD, 16));g.setColor(new Color(205,92,92));g.drawString("排行榜", 655, 300);g.setFont(new Font("幼圆", Font.BOLD, 14));g.setColor(new Color(255,99,71));//[排行榜实现 6.22]要有查询操作 返回一个字符数组(排序)
//            g.drawString("第一名:"+id1+" "+"礼物:"+lw1+"步骤"+bz1);order();for(int i=0;i<sites.size();i++){g.drawString(sites.get(i),605,330+i*30);}sites.clear();g.setFont(new Font("幼圆", Font.BOLD, 14));g.setColor(new Color(255,165,0));g.drawString("已经送去:" + nowgrift + "礼物", 605, 260);long usedTimem = (endTime-startTime)/60000;long usedTimes =(endTime-startTime)%60000/1000;Date date = new Date();g.setColor(new Color(255,140,0));if(usedTimem>=0||usedTimes>=0)g.drawString("用时:" +usedTimem+ "分钟"+usedTimes+"秒", 605, 280);g.drawString(date.toString(), 600, 590);}

(6)关于版面中的order函数实现排行榜功能

//实现排行榜功能取前三名public void order(){Connection conn = null;PreparedStatement pstmt = null;ResultSet rs = null;try {conn = JDBCUtils.getConnection();String sql = "select grift,step,id from user order by grift desc,step asc limit 3 ";pstmt = conn.prepareStatement(sql);rs = pstmt.executeQuery();String s="";int fc=1;while(rs.next()){s="第"+fc+"名:"+rs.getNString("id");sites.add(s);s="礼物:"+rs.getInt("grift")+" "+"步骤"+rs.getInt("step");sites.add(s);s="";fc++;}System.out.println(sites);} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.close(rs, pstmt, conn);}}

3.完善具体的功能

在之前的代码中已经完善了监听

(1)帮助功能的实现

 if (e.getSource() == miHelp) {String str = "游戏简介:快帮小熊把礼物送到指定的位置吧\n";str += "版本信息:lcy制作,希望每一个小朋友都可以收到生日祝福!\n";JOptionPane.showMessageDialog(this, str, "帮助", JOptionPane.INFORMATION_MESSAGE);}

(2)退出功能的实现

 else if (e.getSource() == miExit) {System.exit(0);}

关于setLevel()函数实现关卡

  //设置关卡public void setLevel(int level) {if (level == 0) {this.level = 1;} else if (level == 50) {this.level = 50;} else if (level > 1) {//选择关卡this.level = level;} else {this.level = level + this.level;}//要在关卡范围之内if (this.level <= 0) {this.level = 1;} else if (this.level >= 50) {this.level = 50;}readFile(this.level);//清空step.clear();//设置焦点requestFocus();}public void setLevel() {readFile(this.level);//清空上一关保存在堆栈中的所有步骤step.clear();//设置焦点requestFocus();}

(3)下一关功能的实现

 else if (e.getSource() == btnNext || e.getSource() == miNext) {mainPanel.setLevel(1);}

(4)上一关功能的实现

 else if (e.getSource() == btnPrev || e.getSource() == miPrev) {mainPanel.setLevel(-1);}

(5)输入数字实现关卡跳转

 else if (e.getSource() == btnSelect || e.getSource() == miSelect) {String slevel = JOptionPane.showInputDialog(this, "请输入你想祝福的年龄(1~50)", "时光直通车", JOptionPane.OK_CANCEL_OPTION);if (slevel != null) {try {int level = Integer.parseInt(slevel);if (level <= 0 || level >= 50) {JOptionPane.showMessageDialog(this, "小兔子说:要输入1~50之间的数字");return;}System.out.println("test:" + level);mainPanel.setLevel(level);} catch (Exception ex) {JOptionPane.showMessageDialog(this, "哎呀!是数字,请输入1~50之间的数字");return;}}}

关于goBack()函数实现撤退一步拿向左退一步举例

我们需要用一个栈存储每一步(上下左右)每一步的两种情况(推到了箱子,没有推到箱子)

 public void goBack() {//判断堆栈是否为空if (step.isEmpty()) {JOptionPane.showMessageDialog(null, "小熊已经回到出发点了!");return;}//1没有退箱子 11推了箱子int n = step.pop();//取出栈顶元素switch (n) {case 1:case 11:backLeft(n);}requestFocus();}

当我们每次从栈中取出上一步的时候就要开始进行判断
1.如果上一步没有推箱子,原来人的位置就会变成空地
2.如果上一步推了箱子,那么原来人的位置就会变成箱子,而箱子的位置就会变成空地

 public void backLeft(int step) {if (step == 1) { //没有推箱子tempmap[mx][my + 1] = 6;//原来站人的地方,现在变成草地if (map[mx][my] == 4 || map[mx][my] == 9)tempmap[mx][my] = 4;elsetempmap[mx][my] = 2;my++;} else {//推了箱子tempmap[mx][my + 1] = 6;//原来站人的地方,现在放箱子if (map[mx][my] == 4 || map[mx][my] == 9) {tempmap[mx][my] = 9;} else {tempmap[mx][my] = 3;}//原来放箱子的地方,现在变成空地if (map[mx][my - 1] == 4 || map[mx][my - 1] == 9) {tempmap[mx][my - 1] = 4;} else {tempmap[mx][my - 1] = 2;}my++;}//重画界面repaint();}

(6)实现赖皮一步的功能

else if (e.getSource() == btnBack || e.getSource() == miBack) {mainPanel.goBack();mainPanel.requestFocus();}

关于sound函数实现音乐的控制

读取音乐文件,注意如果你想要自己喜欢的音乐请使用mid格式的音乐!

class Sound {String path = new String("src\\music\\");//默认背景音乐String file = new String("1.mid");Sequence seq;Sequencer midi;//判断是否在播放音乐boolean sign;public Sound() {loadSound();}//播放背景音乐的函数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 ( Exception ex ) {ex.printStackTrace();}sign = true;}void mystop() {midi.stop();midi.close();sign = false;}//判断是否在播放背景音乐boolean isplay() {return sign;}//设置在下拉框中选择的背景音乐文件名称void setMusic(String e) {file = e;}
}

(7)实现音乐的开关功能

else if (e.getSource() == btnMusic) {String title = btnMusic.getText();if (title.equals("关闭音乐")) {if (sound.isplay()) {sound.mystop();}//设置按钮标题btnMusic.setText("打开音乐");} else {btnMusic.setText("关闭音乐");sound.loadSound();}}

(8)实现音乐的选择功能

     else if (e.getSource() == miMusic1) {cbMusic.setSelectedIndex(0);} else if (e.getSource() == miMusic2) {cbMusic.setSelectedIndex(1);}

(9)实现重新选择功能

 else if (e.getSource() == btnReset || e.getSource() == miReset) {//重来mainPanel.setLevel();}

关于save函数实现将当前进度存入数据库

public void save(int gift,int level,int step,String username) {Connection conn = null;PreparedStatement pstmt = null;try {conn = JDBCUtils.getConnection();String sql = "update user set grift = ?, lever = ? , step = ? where id = ?";pstmt = conn.prepareStatement(sql);pstmt.setInt(1, gift);pstmt.setInt(2, level);pstmt.setInt(3,step);pstmt.setString(4,username);int count = pstmt.executeUpdate();if (count > 0) {System.out.println("保存:"+step+" "+gift+" "+level+" "+username);System.out.println("保存成功");} else {System.out.println("保存失败");}} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.close(pstmt, conn);}}

(10)实现保存的当前进度功能

 else if (e.getSource() == btnLook) {JOptionPane.showMessageDialog(this, "咔嚓!时光定格,已经记录下了当前状态期待与你下次的会面");System.out.println("test:"+level);save(nowgrift,nowlever,nowstep,username);}

七、玩家交互代码实现

1.键盘动态交互

(1)实现键盘的监听

public MyPanel() {//监听键盘事件this.addKeyListener(this);setSize(600, 600);readFile(level);}

(2)读取键盘输入做出响应

 public void keyTyped(KeyEvent e) {}@Overridepublic void keyPressed(KeyEvent e) {System.out.println(e.getKeyCode());nowstep++;//方向键左键if (e.getKeyCode() == 37) {goLeft();}//方向键向上else if (e.getKeyCode() == 38) {goUp();}//方向键向右else if (e.getKeyCode() == 39) {goRight();} //方向键向下else if (e.getKeyCode() == 40) {goDown();}if (isWin()) {//这是我设置的通关剧情,你们也可以自行输入了!!String zf[] = {"很开心一年前你诞生在这个世界!","现在的你软糯糯的像夏天里的棉花糖","听说你会啃胡萝卜了,我准备在这个春天给你种下胡萝卜的种子","我的胡萝卜丰收了!所以今年的礼物是胡萝卜","送你一罐蜂蜜,但是要小心蛀牙哦",};nowgrift += needGift;endTime =  System.currentTimeMillis();System.out.println(endTime);JOptionPane.showMessageDialog(null, "小熊:祝你" + level + "岁生日快乐!" + zf[level - 1]);setLevel(1);}}@Overridepublic void keyReleased(KeyEvent e) {}

(3)判断箱子是否推到位

        public boolean isWin() {boolean isok = true;for (int i = 0; i < 20; i++) {for (int j = 0; j < 20; j++) {if ((map[i][j] == 4 || map[i][j] == 9) && tempmap[i][j] != 9) {isok = false;break;}}if (!isok)break;}return isok;}

2.推箱子过程的实现

拿向上推箱子举例,在这段代码中我们其实也完成了当前步骤的入栈,用于实现之后的撤销一步的功能

public void goUp() {//如果向上推到箱子了(人的前面有箱子)if (tempmap[mx - 1][my] == 3 || tempmap[mx - 1][my] == 9) {//判断箱子的上面是什么,如果是目的地或者是空地就可以推动箱子if (tempmap[mx - 2][my] == 2 || tempmap[mx - 2][my] == 4) {//如果箱子推到是是空地if (tempmap[mx - 2][my] == 2) {//交换空地和箱子的位置tempmap[mx - 2][my] = 3;//箱子前面tempmap[mx - 1][my] = 8;//人前面}//如果推到的是目的地else {//改变箱子的状态tempmap[mx - 2][my] = 9;tempmap[mx - 1][my] = 8;}//要与原始地图作对比才可以对原来人的位置进行判断if (map[mx][my] == 4 || map[mx][my] == 9) {tempmap[mx][my] = 4;}//如果推到的是目的地else {tempmap[mx][my] = 2;}//改变人物的三视图状态(暂时还没有找到三视图)mx--;//改变人物的位置step.push(22);}}//如果人的前面是空地else if (tempmap[mx - 1][my] == 2 || tempmap[mx - 1][my] == 4 || tempmap[mx - 1][my] == 5) {tempmap[mx - 1][my] = 8;if (map[mx][my] == 4 || map[mx][my] == 9) {tempmap[mx][my] = 4;}//如果推到的是目的地else {tempmap[mx][my] = 2;}mx--;step.push(2);}repaint();}

制作所遇到的困难和解决方法

1.再制作窗口图标时,无法正常更改窗体做上角的图标。
解决办法,将原先的语句用try-catch异常处理包起来,于是发现是路径设置出现问题(input==null),修改正确 的路径就可以正常显示了。

try{Image image = ImageIO.read(this.getClass().getResource(path));this.setIconImage(image);}catch (IOException e){e.printStackTrace();}

2.登录注册时候,玩家输入是否为空时,我用了判断是否为(null),是否为(“”)都不能完成我想要的功能:输入为空的时候不能注册,最后改为StringUtils.isNullOrEmpty(username),成功解决

 if (StringUtils.isNullOrEmpty(username)) {JOptionPane.showMessageDialog(null, "小兔子:真是的!你连名字都不告诉我");}if (StringUtils.isNullOrEmpty(password)) {JOptionPane.showMessageDialog(null, "咦?你忘记了我们之间的暗号!不是不是小兔子乖乖,把门开开啦!");
}

Java实现推箱子小游戏相关推荐

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

    Java实现推箱子小游戏 一.整体框架 二.游戏效果图 三.推箱子四大类 1. GameFrame类 2. Map类 3. MapFactory类 4. Sound类 四.游戏分析 1.游戏操作 2. ...

  2. JAVA简易推箱子小游戏制作

    以下是代码: Run.java public class Run {public static void main(String[] args) {// TODO Auto-generated met ...

  3. 【基于Swing+Java的推箱子小游戏的设计与实现(效果+源代码+论文+答辩PPT)墙裂推荐!!超级好玩儿!带背景音乐~~】

    快速阅读目录 (一)效果 (1)游戏静态截图 (2)动态游戏示例 (二)源代码示例 (三)说明 (一)效果 (可以通过上下左右键来控制箱子的移动) (1)游戏静态截图 初始化游戏界面: 选项: < ...

  4. 基于Java Swing JFream 组件的趣味推箱子小游戏

    一 需求分析 设计一个经典的推箱子小游戏,在窗体里有墙,箱子,胜利的标志,和工人,用户可以通过键盘上的"上"."下"."左"."右 ...

  5. [源码和文档分享]基于Java Swing JFream 组件的趣味推箱子小游戏

    一 需求分析 设计一个经典的推箱子小游戏,在窗体里有墙,箱子,胜利的标志,和工人,用户可以通过键盘上的"上"."下"."左"."右 ...

  6. java实现二维数组推箱子小游戏

    推箱子小游戏 import java.util.Scanner;public class 推箱子 {public static void main(String[] args) {int x =3, ...

  7. 手把手教你使用Python实现推箱子小游戏(附完整源码)

    文章目录 项目介绍 项目规则 项目接口文档 项目实现过程 前置方法编写 move核心方法编写 项目收尾 项目完善 项目整体源码 项目缺陷分析 项目收获与反思 项目介绍 我们这个项目是一个基于Pytho ...

  8. android开发--推箱子小游戏(二)

    一.前言 迎来第二章的更新啦:使用ListView实现关卡的选择. 本章的内容有点小复杂,毕竟涉及使用了安卓开发中最难用也是最常用的控件之一:ListView 本章可以说是复杂但是单一吧.主要是想大家 ...

  9. [新手必备]Unity推箱子小游戏C#代码详解(第一篇-代码部分)

    完整项目请参考博客:https://blog.csdn.net/qq_41676090/article/details/96300302 本文为推箱子小游戏C#代码详解第一篇的代码部分,主要讲解 Sy ...

  10. c++ 小游戏_C/C++编程笔记:C语言写推箱子小游戏,大一学习C语言练手项目

    C语言,作为大多数人的第一门编程语言,重要性不言而喻,很多编程习惯,逻辑方式在此时就已经形成了.这个是我在大一学习 C语言 后写的推箱子小游戏,自己的逻辑能力得到了提升,在这里同大家分享这个推箱子小游 ...

最新文章

  1. 夏瑞、陈程杰报告—科研神器TBtools 从“结识”到“结伴”(下午3点腾讯会议)...
  2. WINCE6.0系统调用
  3. 【机器学习PAI实践七】文本分析算法实现新闻自动分类
  4. css 图片换行_这个开源库教你写高级的CSS
  5. 直播|百度AI开发者大会深度学习直播课程表
  6. git 检查更新文件_Git通过差异比对快速打包待更新文件(SQL)
  7. 最早单机的计算机操作系统,川农《计算机操作系统(本科)》19年12月在线作业【满分答案】...
  8. vue 里面引入高德地图
  9. 索尼发布工业设备用SWIR图像传感器 采用5微米像素尺寸
  10. 所有win7机器都必须要做的一个优化!作用:让系统流畅,减少卡顿
  11. 使用CSS来美化你的javafx滚动条
  12. MySQL用命令行运行sql文件
  13. 广度优先搜索(啊哈算法)
  14. PDF文件有密码怎么解除?
  15. Android常用的工具方法
  16. LeetCode刷题之旅正式开始
  17. AutoGPT保姆级安装使用教程
  18. 区块链学习笔记4——BTC实现
  19. 中标麒麟+QT+达梦数据库
  20. 通过BACnet物联网关实现楼宇自动化的物联网解决方案

热门文章

  1. 联想ThinkPad笔记本Fn键关闭与启用方法
  2. 草莓电吉他音源 Orange Tree Samples Evolution Strawberry Kontakt
  3. e470c拆机图解全拆 thinkpad_e470c拆机图解全拆 thinkpad_THINKPAD e470硬盘拆解教程是?...
  4. Springboot中Aspect实现切面(以记录日志为例)
  5. 多线程下载王者荣耀高清壁纸
  6. OSChina 周日乱弹 —— 会后空翻算个屁,咱这卖艺卖身吃鱼干
  7. UberAir飞行汽车:一键乘坐飞机会变成现实吗
  8. win10自带邮箱无法登录QQ邮箱
  9. 平安保险的万能险怎么样?
  10. 【开集识别论文解读】C2AE: Class Conditioned Auto-Encoder for Open-set Recognition——CVPR2019