(以下内容全部来自上述课程)
1.美化界面
private void initImage() {//路径分两种://1.绝对路径:从盘符开始写的路径 D:\\aaa\\bbb\\ccc.jpg//2.相对路径:从当前项目开始写的路径 aaa\\bbb\\ccc.jpg//添加图片的时候,就需要按照二维数组中管理的数据添加图片//外循环----把内循环的代码重复执行4次for (int i = 0; i < 4; i++) {//内循环----表示在一行中放4个图片for (int j = 0; j < 4; j++) {//获取二维数组中每个索引对应的数字int number = arr[i][j];//创建一个图片ImageIcon对象 参数:图片的路径(没加图片,意思一下得了)//这里的图片最好命名为数字ImageIcon icon = new ImageIcon("image\\background\\"+number+".jpg");//创建一个JLabel对象(管理容器)JLabel jLabel = new JLabel(icon);//设置图片的位置jLabel.setBounds(105*j+83,105*i+134,105,105);//给图片添加边框jLabel.setBorder(new BevelBorder(1));//把JLabel对象添加到界面中this.getContentPane().add(jLabel);//添加一次后number自增1,表示下一次加载后面一张图片}}//细节://先加载的图片在上方,后加载的图片在下方//添加背景图片ImageIcon background = new ImageIcon("image\\background\\background.jpg");JLabel backgroundJLabel = new JLabel(background);backgroundJLabel.setBounds(40,40,508,560);//把背景图片添加到界面中this.getContentPane().add(backgroundJLabel);}
2.上下移动
上移动:
向上移动实际上就是把空白方块下方的图片上移。
(新加代码,非完整)
public class GameJFrame extends javax.swing.JFrame implements KeyListener {//记录空白方块的位置int x = 0;int y = 0;private void initImage() {//清空原本已经出现的图片this.getContentPane().removeAll();}private void initJFrame() {//给整个界面添加键盘监听this.addKeyListener(this);}@Overridepublic void keyTyped(KeyEvent e) {}@Overridepublic void keyPressed(KeyEvent e) {}@Overridepublic void keyReleased(KeyEvent e) {//对应键盘上的上下左右键//获取键盘上的键码int keyCode = e.getKeyCode();System.out.println(keyCode);if (keyCode == 38) {System.out.println("上");if (x == 3) {//已经到底了,什么都不做return;}//逻辑://把空白方块下方的数字往上移动//x,y 表示空白方块//x+1,y 表示空白方块上的位置//把x+1,y位置上的数字赋值给x,y位置arr[x][y] = arr[x+1][y];arr[x+1][y] = 0;//空白方块的位置发生了改变x++;//重新初始化图片initImage();} else if (keyCode == 40) {if (x == 0) {//已经到底了,什么都不做return;}System.out.println("下");arr[x][y] = arr[x-1][y];arr[x-1][y] = 0;//空白方块的位置发生了改变x--;//重新初始化图片initImage();} else if (keyCode == 37) {if (y == 3) {//已经到底了,什么都不做return;}System.out.println("左");arr[x][y] = arr[x][y+1];arr[x][y+1] = 0;//空白方块的位置发生了改变y++;//重新初始化图片initImage();} else if (keyCode == 39) {if (y == 0) {//已经到底了,什么都不做return;}System.out.println("右");arr[x][y] = arr[x][y-1];arr[x][y-1] = 0;//空白方块的位置发生了改变y--;//重新初始化图片initImage();} else {System.out.println("其他");}}
}
3.查看完整图片的功能
按住A不松开,显示完整图片
松开A显示随机打乱的图片
(新加代码,非完整)
//定义一个变量,记录当前展示图片的路径String path = "";private void initImage() {//清空原本已经出现的图片this.getContentPane().removeAll();//..........//刷新界面this.getContentPane().repaint();}//监听上一步添加过了,直接用,修改方法即可//按下不松,一直触发@Overridepublic void keyPressed(KeyEvent e) {int code = e.getKeyCode();if (code == 65) {//把界面中的所有图片全部删除this.getContentPane().removeAll();//加载第一张完整的图片JLabel allJLabel = new JLabel(new ImageIcon(path+"all.jpg"));//设置图片的位置allJLabel.setBounds(83,134,420,420);//把图片添加到界面中this.getContentPane().add(allJLabel);//加载背景图片ImageIcon background = new ImageIcon("image\\background\\background.jpg");JLabel backgroundJLabel = new JLabel(background);backgroundJLabel.setBounds(40,40,508,560);//把背景图片添加到界面中this.getContentPane().add(backgroundJLabel);//刷新界面this.getContentPane().repaint();}}@Overridepublic void keyReleased(KeyEvent e) {//...........} else if( keyCode == 65){initImage();}}
}
4.作弊码
按一下W,直接胜利
keyReleased方法体中添加:
(新加代码,非完整)
else if (keyCode == 87) {arr = new int[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};initImage();
5.判断胜利
其实就是判断二维数组中的数字是否按照顺序进行排列
如果按照顺序进行排列的,那么显示胜利的图片
实现步骤:
- 定义一个正确的二维数组win
- 在加载图片之前,先判断一下二维数组中的数字跟win数组中是否相同
- 如果相同展示正确图标
- 如果不同则不展示正确图标
(新加代码,非完整)
//定义一个二维数组,存储正确的数据int[][] win = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};private void initImage() {
//....//判断游戏是否结束if (isWin()) {//显示胜利的图片ImageIcon winIcon = new ImageIcon("image\\win.jpg");JLabel winJLabel = new JLabel(winIcon);winJLabel.setBounds(203,283,197,73);this.getContentPane().add(winJLabel);}//........
}public void keyReleased(KeyEvent e) {//判断游戏是否胜利,如果胜利,此方法直接结束if (isWin()) {//1.返回结果//2.结束方法return;
//........}
}//判断游戏是否胜利public boolean isWin(){for (int i = 0; i < arr.length; i++) {for (int j = 0; j < arr[i].length; j++) {if (arr[i][j] != win[i][j]){return false;}}}return true;}
6.计步功能
//定义变量,记录步数int step = 0;private void initImage() {
//........
JLabel stepCount = new JLabel("步数:"+step);stepCount.setBounds(50,30,100,20);this.getContentPane().add(stepCount);//........
}// keyReleased 截止到现在的完整代码@Overridepublic void keyReleased(KeyEvent e) {//判断游戏是否胜利,如果胜利,此方法直接结束if (isWin()) {//1.返回结果//2.结束方法return;}//对应键盘上的上下左右键//获取键盘上的键码int keyCode = e.getKeyCode();System.out.println(keyCode);if (keyCode == 38) {System.out.println("上");if (x == 3) {//已经到底了,什么都不做return;}//逻辑://把空白方块下方的数字往上移动//x,y 表示空白方块//x+1,y 表示空白方块上的位置//把x+1,y位置上的数字赋值给x,y位置arr[x][y] = arr[x+1][y];arr[x+1][y] = 0;//空白方块的位置发生了改变x++;step++;//重新初始化图片initImage();} else if (keyCode == 40) {if (x == 0) {//已经到底了,什么都不做return;}System.out.println("下");arr[x][y] = arr[x-1][y];arr[x-1][y] = 0;//空白方块的位置发生了改变x--;step++;//重新初始化图片initImage();} else if (keyCode == 37) {if (y == 3) {//已经到底了,什么都不做return;}System.out.println("左");arr[x][y] = arr[x][y+1];arr[x][y+1] = 0;//空白方块的位置发生了改变y++;step++;//重新初始化图片initImage();} else if (keyCode == 39) {if (y == 0) {//已经到底了,什么都不做return;}System.out.println("右");arr[x][y] = arr[x][y-1];arr[x][y-1] = 0;//空白方块的位置发生了改变y--;step++;//重新初始化图片initImage();} else if( keyCode == 65){initImage();} else if (keyCode == 87) {arr = new int[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};initImage();}}
7.菜单功能
1.重新开始
- 给重新游戏绑定点击事件---------->ActionListener
- 重新打乱二维数组中的数字
- 加载图片
- 计步器清零
2.关闭游戏
- 给关闭游戏绑定事件
- 结束虚拟机,关闭所有
3.关于我们
4.代码
(新加代码,非完整)
public class GameJFrame extends javax.swing.JFrame implements KeyListener , ActionListener {//把条目添加到选项中 ----- 移到成员位置functionJMenu.add(replayJMenuItem);functionJMenu.add(reLoginJMenuItem);functionJMenu.add(closeJMenuItem);aboutJMenu.add(accountItem);}private void initJMenuBar() {//.........//给条目绑定事件replayJMenuItem.addActionListener(this);reLoginJMenuItem.addActionListener(this);closeJMenuItem.addActionListener(this);accountItem.addActionListener(this);
}
//initData 截止到现在的完整代码private void initData() {//1.定义一个一维数组int[] tempArr = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};//2.随机打乱一维数组中的数据for (int i = 0; i < tempArr.length; i++) {//获取随机索引int randomIndex = (int)(Math.random()*tempArr.length);//拿着随机索引对应的值和i索引对应的值进行交换int temp = tempArr[i];tempArr[i] = tempArr[randomIndex];tempArr[randomIndex] = temp;}//3.遍历一维数组for (int i = 0; i < tempArr.length; i++) {if (tempArr[i] == 0) {x = i / 4;y = i % 4;} arr[i / 4][i % 4] = tempArr[i];}System.out.println();}@Overridepublic void actionPerformed(ActionEvent e) {//获取被点击的条目对象Object obj = e.getSource();if (obj == replayJMenuItem) {System.out.println("重新游戏");//步数清零step = 0;//重新打乱数据initData();//重新初始化图片initImage();} else if (obj == reLoginJMenuItem) {System.out.println("重新登录");//关闭当前登录的界面this.setVisible(false);//打开登录界面new LoginJFrame();} else if (obj == closeJMenuItem) {System.out.println("关闭游戏");System.exit(0);} else if (obj == accountItem) {System.out.println("公众号");//创建一个弹窗对象JDialog jDialog = new JDialog();//创建一个管理图片的容器JLabel jLabel = new JLabel(new ImageIcon("image\\account.jpg"));//设置位置和宽高jLabel.setBounds(0,0,258,258);//把图片添加到弹窗中jDialog.getContentPane().add(jLabel);//设置弹窗的宽高jDialog.setSize(280,316);//设置弹窗置顶jDialog.setAlwaysOnTop(true);//设置弹窗居中jDialog.setLocationRelativeTo(null);//弹框不关闭无法操作下面的界面jDialog.setModal(true);//让弹窗显示出来jDialog.setVisible(true);}}
8.游戏打包exe(概括)
- 一定要包含图形化界面
- 代码要打包起来
- 游戏用到的图片也要打包起来
- JDK也要打包起来
步骤:
- 把所有代码打包成一个压缩包,jar后缀的压缩包
- 把jar包转换成exe安装包
- 把第二步的exe,图片,JDK整合在一起,变成最终的exe安装包
9.所有完整代码
1.GameJFrame
package com.woziji.ui;import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;public class GameJFrame extends javax.swing.JFrame implements KeyListener , ActionListener {//JFrame 界面,窗体//子类呢? 也表示界面,窗体//规定:GameJFrame 表示游戏的主界面//以后和游戏相关的所有逻辑都写在这个类中//用来管理数据int[][] arr = new int[4][4];//记录空白方块的位置int x = 0;int y = 0;//定义一个变量,记录当前展示图片的路径String path = "";//定义一个二维数组,存储正确的数据int[][] win = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};//定义变量,记录步数int step = 0;//创建选项下面的条目对象JMenuItem replayJMenuItem = new JMenuItem("重新游戏");JMenuItem reLoginJMenuItem = new JMenuItem("重新登录");JMenuItem closeJMenuItem = new JMenuItem("关闭游戏");JMenuItem accountItem = new JMenuItem("公众号");public GameJFrame() {//初始化界面initJFrame();//初始化菜单initJMenuBar();//初始化数据(打乱)initData();//初始化图片initImage();//让界面显示出来,建议写在最后this.setVisible(true);}private void initData() {//1.定义一个一维数组int[] tempArr = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};//2.随机打乱一维数组中的数据for (int i = 0; i < tempArr.length; i++) {//获取随机索引int randomIndex = (int)(Math.random()*tempArr.length);//拿着随机索引对应的值和i索引对应的值进行交换int temp = tempArr[i];tempArr[i] = tempArr[randomIndex];tempArr[randomIndex] = temp;}//3.遍历一维数组for (int i = 0; i < tempArr.length; i++) {if (tempArr[i] == 0) {x = i / 4;y = i % 4;}arr[i / 4][i % 4] = tempArr[i];}System.out.println();}private void initImage() {//清空原本已经出现的图片this.getContentPane().removeAll();//判断游戏是否结束if (isWin()) {//显示胜利的图片ImageIcon winIcon = new ImageIcon("image\\win.jpg");JLabel winJLabel = new JLabel(winIcon);winJLabel.setBounds(203,283,197,73);this.getContentPane().add(winJLabel);}JLabel stepCount = new JLabel("步数:"+step);stepCount.setBounds(50,30,100,20);this.getContentPane().add(stepCount);//路径分两种://1.绝对路径:从盘符开始写的路径 D:\\aaa\\bbb\\ccc.jpg//2.相对路径:从当前项目开始写的路径 aaa\\bbb\\ccc.jpg//添加图片的时候,就需要按照二维数组中管理的数据添加图片//外循环----把内循环的代码重复执行4次for (int i = 0; i < 4; i++) {//内循环----表示在一行中放4个图片for (int j = 0; j < 4; j++) {//获取二维数组中每个索引对应的数字int number = arr[i][j];//创建一个图片ImageIcon对象 参数:图片的路径(没加图片,意思一下得了)//这里的图片最好命名为数字ImageIcon icon = new ImageIcon("image\\background\\"+number+".jpg");//创建一个JLabel对象(管理容器)JLabel jLabel = new JLabel(icon);//设置图片的位置jLabel.setBounds(105*j+83,105*i+134,105,105);//给图片添加边框jLabel.setBorder(new BevelBorder(1));//把JLabel对象添加到界面中this.getContentPane().add(jLabel);//添加一次后number自增1,表示下一次加载后面一张图片}}//细节://先加载的图片在上方,后加载的图片在下方//添加背景图片ImageIcon background = new ImageIcon("image\\background\\background.jpg");JLabel backgroundJLabel = new JLabel(background);backgroundJLabel.setBounds(40,40,508,560);//把背景图片添加到界面中this.getContentPane().add(backgroundJLabel);//刷新界面this.getContentPane().repaint();}private void initJMenuBar() {//创建整个的菜单对象JMenuBar JMenuBar = new JMenuBar();//创建菜单上面的两个选项的对象 (功能 关于我们)JMenu functionJMenu = new JMenu("功能");JMenu aboutJMenu = new JMenu("关于我们");//把条目添加到选项中functionJMenu.add(replayJMenuItem);functionJMenu.add(reLoginJMenuItem);functionJMenu.add(closeJMenuItem);aboutJMenu.add(accountItem);//把选项添加到菜单中JMenuBar.add(functionJMenu);JMenuBar.add(aboutJMenu);//把菜单设置到界面中this.setJMenuBar(JMenuBar);//给条目绑定事件replayJMenuItem.addActionListener(this);reLoginJMenuItem.addActionListener(this);closeJMenuItem.addActionListener(this);accountItem.addActionListener(this);}private void initJFrame() {//设置界面的宽高this.setSize(603,680);//设置界面的标题this.setTitle("拼图单机版 v1.0");//设置界面置顶this.setAlwaysOnTop(true);//设置界面居中this.setLocationRelativeTo(null);//设置界面的关闭方式this.setDefaultCloseOperation(3);//取消默认的居中放置,只有取消了才可以设置坐标this.setLayout(null);//给整个界面添加键盘监听this.addKeyListener(this);}@Overridepublic void keyTyped(KeyEvent e) {}//按下不松,一直触发@Overridepublic void keyPressed(KeyEvent e) {int code = e.getKeyCode();if (code == 65) {//把界面中的所有图片全部删除this.getContentPane().removeAll();//加载第一张完整的图片JLabel allJLabel = new JLabel(new ImageIcon(path+"all.jpg"));//设置图片的位置allJLabel.setBounds(83,134,420,420);//把图片添加到界面中this.getContentPane().add(allJLabel);//加载背景图片ImageIcon background = new ImageIcon("image\\background\\background.jpg");JLabel backgroundJLabel = new JLabel(background);backgroundJLabel.setBounds(40,40,508,560);//把背景图片添加到界面中this.getContentPane().add(backgroundJLabel);//刷新界面this.getContentPane().repaint();}}@Overridepublic void keyReleased(KeyEvent e) {//判断游戏是否胜利,如果胜利,此方法直接结束if (isWin()) {//1.返回结果//2.结束方法return;}//对应键盘上的上下左右键//获取键盘上的键码int keyCode = e.getKeyCode();System.out.println(keyCode);if (keyCode == 38) {System.out.println("上");if (x == 3) {//已经到底了,什么都不做return;}//逻辑://把空白方块下方的数字往上移动//x,y 表示空白方块//x+1,y 表示空白方块上的位置//把x+1,y位置上的数字赋值给x,y位置arr[x][y] = arr[x+1][y];arr[x+1][y] = 0;//空白方块的位置发生了改变x++;step++;//重新初始化图片initImage();} else if (keyCode == 40) {if (x == 0) {//已经到底了,什么都不做return;}System.out.println("下");arr[x][y] = arr[x-1][y];arr[x-1][y] = 0;//空白方块的位置发生了改变x--;step++;//重新初始化图片initImage();} else if (keyCode == 37) {if (y == 3) {//已经到底了,什么都不做return;}System.out.println("左");arr[x][y] = arr[x][y+1];arr[x][y+1] = 0;//空白方块的位置发生了改变y++;step++;//重新初始化图片initImage();} else if (keyCode == 39) {if (y == 0) {//已经到底了,什么都不做return;}System.out.println("右");arr[x][y] = arr[x][y-1];arr[x][y-1] = 0;//空白方块的位置发生了改变y--;step++;//重新初始化图片initImage();} else if( keyCode == 65){initImage();} else if (keyCode == 87) {arr = new int[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};initImage();}}//判断游戏是否胜利public boolean isWin(){for (int i = 0; i < arr.length; i++) {for (int j = 0; j < arr[i].length; j++) {if (arr[i][j] != win[i][j]){return false;}}}return true;}@Overridepublic void actionPerformed(ActionEvent e) {//获取被点击的条目对象Object obj = e.getSource();if (obj == replayJMenuItem) {System.out.println("重新游戏");//步数清零step = 0;//重新打乱数据initData();//重新初始化图片initImage();} else if (obj == reLoginJMenuItem) {System.out.println("重新登录");//关闭当前登录的界面this.setVisible(false);//打开登录界面new LoginJFrame();} else if (obj == closeJMenuItem) {System.out.println("关闭游戏");System.exit(0);} else if (obj == accountItem) {System.out.println("公众号");//创建一个弹窗对象JDialog jDialog = new JDialog();//创建一个管理图片的容器JLabel jLabel = new JLabel(new ImageIcon("image\\account.jpg"));//设置位置和宽高jLabel.setBounds(0,0,258,258);//把图片添加到弹窗中jDialog.getContentPane().add(jLabel);//设置弹窗的宽高jDialog.setSize(280,316);//设置弹窗置顶jDialog.setAlwaysOnTop(true);//设置弹窗居中jDialog.setLocationRelativeTo(null);//弹框不关闭无法操作下面的界面jDialog.setModal(true);//让弹窗显示出来jDialog.setVisible(true);}}
}
2.LoginJFrame
package com.woziji.ui;import javax.swing.*;public class LoginJFrame extends javax.swing.JFrame{//登录界面//以后和登录相关的所有逻辑都写在这个类中public LoginJFrame(){//在创建登陆界面的时候,同时给这个界面去设置一些信息//比如:宽高,直接展示出来this.setSize(488,430);this.setVisible(true);//设置界面的标题this.setTitle("拼图 登录");//设置界面置顶this.setAlwaysOnTop(true);//设置界面居中this.setLocationRelativeTo(null);//设置界面的关闭方式this.setDefaultCloseOperation(3);}
}
3.RegisterJFrame
package com.woziji.ui;public class RegisterJFrame extends javax.swing.JFrame{//注册界面//以后和注册相关的所有逻辑都写在这个类中public RegisterJFrame(){this.setSize(488,500);this.setVisible(true);//设置界面的标题this.setTitle("拼图 注册");//设置界面置顶this.setAlwaysOnTop(true);//设置界面居中this.setLocationRelativeTo(null);//设置界面的关闭方式this.setDefaultCloseOperation(3);}
}
4.主入口
import com.woziji.ui.GameJFrame;
import com.woziji.ui.LoginJFrame;
import com.woziji.ui.RegisterJFrame;public class App {public static void main(String[] args) {//表示程序的入口//如果我们想开启一个界面,就创建谁的对象//new LoginJFrame();//new RegisterJFrame();new GameJFrame();}
}