6.美化界面
6.1 调整 jLabel 小图片位置
private void initImage() {
//指定图片位置
jLabel.setBounds(105 * j + 83, 105 * i + 134, 105,
}6.2 加入背景图片
//细节:先加载的图片会在上方,后加载的图片在下面
//添加背景图片
ImageIcon bg = new ImageIcon("day16-day17\\image\\background.png"); //新建ImageIcon,写入图片路径
JLabel background = new JLabel(bg); //新建JLabel,ImageIcon加入JLabel
background.setBounds(40, 40, 508, 560); //JLabel设置位置、宽高
this.getContentPane().add(background); //将背景添加到界面中6.3 JLabel 中给图片设置边框
//给图片添加边框 0:让图片凸起来 1:表示让图片凹下去
jLabel.setBorder(new BevelBorder(1));
//jLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); //让图片凸起来 0
//jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED)); //让图片凹下去 16.4 路径优化
//路径分为两种:
//绝对路径:从盘符开始
//相对路径:非盘符开始
JLabel jLabel = new JLabel(new ImageIcon("day16-day17\\image\\animal\\animal3\\" + num + ".jpg"));
ImageIcon bg = new ImageIcon("day16-day17\\image\\background.png"); //新建ImageIcon,写入图片路径
6.5 完整代码
GameJFrame.java
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.util.Random;
public class GameJFrame extends JFrame {
//创建一个二维数组,用来管理数据,加载图片时,会根据二维数组中的数据进行加载
int[][] data = new int[4][4];
//游戏相关的所有代码,在此类中
public GameJFrame() {
//初始化界面
initJFrame();
//初始化菜单
initJMnuBar();
//初始化数据(打乱)
initData();
//初始化图片(根据打乱之后的结果去加载图片)
initImage();
//让界面显示,写在最后
this.setVisible(true);
}
//初始化数据(打乱)
private void initData() {
//定义一个一维数组
int[] tempArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
//打乱数组中数据的顺序
Random r = new Random();
for (int i = 0; i < tempArr.length; i++) {
//获取随机索引
int index = r.nextInt(tempArr.length);
int temp = tempArr[i];
tempArr[i] = tempArr[index];
tempArr[index] = temp;
}
//给二维数组添加数据
/*
//解法一:遍历一维数组tempArr得到每一个元素,然后把每一个元素添加到二维数组中
for (int i = 0; i < tempArr.length; i++) {
data[i/4][i%4] = tempArr[i];
}
//遍历二维数组
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
System.out.print(data[i][j]+ " ");
}
System.out.println();
}
*/
//解法二:遍历二维数组,给里面的每一个数组赋值
int index = 0;
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
data[i][j] = tempArr[index];
index++;
}
}
}
//初始化图片,添加图片时,需要按照二维数组中管理的数据添加图片
private void initImage() {
//细节:先加载的图片会在上方,后加载的图片在下面
//外循环 -- 将内循环重复执行了4次
for (int i = 0; i < 4; i++) {
//内循环 -- 表示在一行添加4张图片
for (int j = 0; j < 4; j++) {
//获取当前加载图片的序号
int num = data[i][j];
//创建一个JLable的对象(管理容器)
JLabel jLabel = new JLabel(new ImageIcon("day16-day17\\image\\animal\\animal3\\" + num + ".jpg"));
//指定图片位置
jLabel.setBounds(105 * j + 83, 105 * i + 134, 105, 105);
//给图片添加边框 0:让图片凸起来 1:表示让图片凹下去
jLabel.setBorder(new BevelBorder(1));
//jLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); //让图片凸起来 0
//jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED)); //让图片凹下去 1
//将管理容器添加到界面中
//this.add(jLabel);
this.getContentPane().add(jLabel);
}
}
//添加背景图片
ImageIcon bg = new ImageIcon("day16-day17\\image\\background.png"); //新建ImageIcon,写入图片路径
JLabel background = new JLabel(bg); //新建JLabel,ImageIcon加入JLabel
background.setBounds(40, 40, 508, 560); //JLabel设置位置、宽高
this.getContentPane().add(background); //将背景添加到界面中
}
private void initJMnuBar() {
//创建整个菜单对象
JMenuBar jMenuBar = new JMenuBar();
//创建菜单上面的两个选项的对象(功能 关于我们)
JMenu functionJMenu = new JMenu("功能");
JMenu aboutJMenu = new JMenu("关于我们");
//创建选项下面的条目对象
JMenuItem replayItem = new JMenuItem("重新游戏");
JMenuItem reLoginItem = new JMenuItem("重新登录");
JMenuItem closeItem = new JMenuItem("关闭游戏");
JMenuItem accountItem = new JMenuItem("公众号");
//将每一个选项下面的条目,添加到选项中
functionJMenu.add(replayItem);
functionJMenu.add(reLoginItem);
functionJMenu.add(closeItem);
aboutJMenu.add(accountItem);
//将菜单里面的两个选项添加到菜单当中
jMenuBar.add(functionJMenu);
jMenuBar.add(aboutJMenu);
//给整个界面设置菜单
this.setJMenuBar(jMenuBar);
}
private void initJFrame() {
//设置界面的宽高
this.setSize(603, 680);
//设置界面的标题
this.setTitle("拼图单机版 v1.0");
//设置界面置顶
this.setAlwaysOnTop(true);
//设置界面居中
this.setLocationRelativeTo(null);
//设置关闭模式
//this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setDefaultCloseOperation(3);
//取消默认剧中放置
this.setLayout(null);
}
}App.java
import com.yq.ui.GameJFrame;
public class App {
public static void main(String[] args) {
//表示程序的启动入口
//new LoginJFrame();
//new RegisterJFrame();
new GameJFrame();
}
}7.移动图片
上移动:将空白下面的图片,向上移动
7.1 添加事件
给整个界面添加键盘监听事件 KeyListener
public class GameJFrame extends JFrame implements KeyListener {
private void initJFrame() {
//。。。
//给整个界面添加键盘监听事件
this.addKeyListener(this);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
}
7.2 统计空白图片的位置
将data 数据中,值为0 的索引(x, y)记录
public class GameJFrame extends JFrame implements KeyListener {
//记录空白方块在二维数组中的位置
int x = 0;
int y = 0;
//游戏相关的所有代码,在此类中
public GameJFrame() {
//...
}
//初始化数据(打乱)
private void initData() {
//给二维数组添加数据
//解法二:遍历二维数组,给里面的每一个数组赋值
int index = 0;
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
if (tempArr[index] == 0) {
x = i;
y = j;
index++;
} else {
data[i][j] = tempArr[index];
index++;
}
}
}
}
}
7.3 移动逻辑
逻辑:将空白下方的数字往上移动
值为0 的索引(2, 1) 表示空白方块,(2+1, 1)表示空白下方的方块
值为0 的索引(x, y) 表示空白方块,(x+1, y)表示空白下方的方块

示例代码:
//按键逻辑
@Override
public void keyReleased(KeyEvent e) {
//对 上37、下38、左39、右40 进行判断
int code = e.getKeyCode();
if (code == 38) {
System.out.println("向上移动");
//将空白方块与下方的方块进行调换
data[x][y] = data[x+1][y]; //空白下面方块的值,赋值给空白方块
data[x+1][y] = 0; //空白下方方块的值,定义为0
x++; //调换以后,表示空白的索引(x,y)发生了变化,需要x+1
initImage(); //重新加载图片
}
}
//更新重新加载图片的代码
private void initImage() {
//清空如果已经存在的图片
this.getContentPane().removeAll();
//刷新界面
this.getContentPane().repaint();
}7.4 移动的小bug
需要处理空白方块在边界时,索引的变化问题
//按键逻辑
@Override
public void keyReleased(KeyEvent e) {
//对 上37、下38、左39、右40 进行判断
int code = e.getKeyCode();
if (code == 38) {
System.out.println("向上移动");
if (x == 3) {
//表示空白方块已经在最下方,下面没有方块,不能再执行往上移动
return;
}
//将空白方块与下方的方块进行调换
data[x][y] = data[x+1][y]; //空白下面方块的值,赋值给空白方块
data[x+1][y] = 0; //空白下方方块的值,定义为0
x++; //调换以后,表示空白的索引(x,y)发生了变化,需要x+1
initImage(); //重新加载图片
}
}7.5 完整代码
GameJFrame.java
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class GameJFrame extends JFrame implements KeyListener {
//创建一个二维数组,用来管理数据,加载图片时,会根据二维数组中的数据进行加载
int[][] data = new int[4][4];
//记录空白方块在二维数组中的位置
int x = 0;
int y = 0;
//游戏相关的所有代码,在此类中
public GameJFrame() {
//初始化界面
initJFrame();
//初始化菜单
initJMnuBar();
//初始化数据(打乱)
initData();
//初始化图片(根据打乱之后的结果去加载图片)
initImage();
//让界面显示,写在最后
this.setVisible(true);
}
//初始化数据(打乱)
private void initData() {
//定义一个一维数组
int[] tempArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
//打乱数组中数据的顺序
Random r = new Random();
for (int i = 0; i < tempArr.length; i++) {
//获取随机索引
int index = r.nextInt(tempArr.length);
int temp = tempArr[i];
tempArr[i] = tempArr[index];
tempArr[index] = temp;
}
//给二维数组添加数据
/*
//解法一:遍历一维数组tempArr得到每一个元素,然后把每一个元素添加到二维数组中
for (int i = 0; i < tempArr.length; i++) {
data[i/4][i%4] = tempArr[i];
}
//遍历二维数组
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
System.out.print(data[i][j]+ " ");
}
System.out.println();
}
*/
//解法二:遍历二维数组,给里面的每一个数组赋值
int index = 0;
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
if (tempArr[index] == 0) {
x = i;
y = j;
index++;
} else {
data[i][j] = tempArr[index];
index++;
}
}
}
}
//初始化图片,添加图片时,需要按照二维数组中管理的数据添加图片
private void initImage() {
//清空如果已经存在的图片
this.getContentPane().removeAll();
//细节:先加载的图片会在上方,后加载的图片在下面
//外循环 -- 将内循环重复执行了4次
for (int i = 0; i < 4; i++) {
//内循环 -- 表示在一行添加4张图片
for (int j = 0; j < 4; j++) {
//获取当前加载图片的序号
int num = data[i][j];
//创建一个JLable的对象(管理容器)
JLabel jLabel = new JLabel(new ImageIcon("day16-day17\\image\\animal\\animal3\\" + num + ".jpg"));
//指定图片位置
jLabel.setBounds(105 * j + 83, 105 * i + 134, 105, 105);
//给图片添加边框 0:让图片凸起来 1:表示让图片凹下去
jLabel.setBorder(new BevelBorder(1));
//jLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); //让图片凸起来 0
//jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED)); //让图片凹下去 1
//将管理容器添加到界面中
//this.add(jLabel);
this.getContentPane().add(jLabel);
}
}
//添加背景图片
ImageIcon bg = new ImageIcon("day16-day17\\image\\background.png"); //新建ImageIcon,写入图片路径
JLabel background = new JLabel(bg); //新建JLabel,ImageIcon加入JLabel
background.setBounds(40, 40, 508, 560); //JLabel设置位置、宽高
this.getContentPane().add(background); //将背景添加到界面中
//刷新界面
this.getContentPane().repaint();
}
private void initJMnuBar() {
//创建整个菜单对象
JMenuBar jMenuBar = new JMenuBar();
//创建菜单上面的两个选项的对象(功能 关于我们)
JMenu functionJMenu = new JMenu("功能");
JMenu aboutJMenu = new JMenu("关于我们");
//创建选项下面的条目对象
JMenuItem replayItem = new JMenuItem("重新游戏");
JMenuItem reLoginItem = new JMenuItem("重新登录");
JMenuItem closeItem = new JMenuItem("关闭游戏");
JMenuItem accountItem = new JMenuItem("公众号");
//将每一个选项下面的条目,添加到选项中
functionJMenu.add(replayItem);
functionJMenu.add(reLoginItem);
functionJMenu.add(closeItem);
aboutJMenu.add(accountItem);
//将菜单里面的两个选项添加到菜单当中
jMenuBar.add(functionJMenu);
jMenuBar.add(aboutJMenu);
//给整个界面设置菜单
this.setJMenuBar(jMenuBar);
}
private void initJFrame() {
//设置界面的宽高
this.setSize(603, 680);
//设置界面的标题
this.setTitle("拼图单机版 v1.0");
//设置界面置顶
this.setAlwaysOnTop(true);
//设置界面居中
this.setLocationRelativeTo(null);
//设置关闭模式
//this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setDefaultCloseOperation(3);
//取消默认剧中放置
this.setLayout(null);
//给整个界面添加键盘监听事件
this.addKeyListener(this);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
//对 上37、下38、左39、右40 进行判断
int code = e.getKeyCode();
System.out.println(code);
if (code == 37) {
System.out.println("向左移动");
if (y == 3) {
return;
}
data[x][y] = data[x][y + 1];
data[x][y + 1] = 0;
y++;
initImage();
} else if (code == 38) {
System.out.println("向上移动");
if (x == 3) {
//表示空白方块已经在最下方,下面没有方块,不能再执行往上移动
return;
}
//将空白方块与下方的方块进行调换
data[x][y] = data[x + 1][y]; //空白下面方块的值,赋值给空白方块
data[x + 1][y] = 0; //空白下方方块的值,定义为0
x++; //调换以后,表示空白的索引(x,y)发生了变化,需要x+1
initImage(); //重新加载图片
} else if (code == 39) {
System.out.println("向右移动");
if (y == 0) {
return;
}
data[x][y] = data[x][y - 1];
data[x][y - 1] = 0;
y--;
initImage();
} else if (code == 40) {
System.out.println("向下移动");
if (x == 0) {
return;
}
data[x][y] = data[x - 1][y];
data[x - 1][y] = 0;
x--;
initImage();
}
}
}App.java
public class App {
public static void main(String[] args) {
//表示程序的启动入口
//new LoginJFrame();
//new RegisterJFrame();
new GameJFrame();
}
}8.查看完整图片
8.1 完整图片的键盘事件
GameJFrame.java
public class GameJFrame extends JFrame implements KeyListener {
//按下不松时会调用此方法
@Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == 65){
System.out.println("按着A不松");
//删除界面中所有的图片
this.getContentPane().removeAll();
//加载第一张完整的图片
JLabel all = new JLabel(new ImageIcon("day16-day17\\image\\animal\\animal4\\all.jpg"));
all.setBounds(83,134,420,420);
this.getContentPane().add(all);
//添加背景图片
ImageIcon bg = new ImageIcon("day16-day17\\image\\background.png"); //新建ImageIcon,写入图片路径
JLabel background = new JLabel(bg); //新建JLabel,ImageIcon加入JLabel
background.setBounds(40, 40, 508, 560); //JLabel设置位置、宽高
this.getContentPane().add(background); //将背景添加到界面中
//刷新界面
this.getContentPane().repaint();
}
}
@Override
public void keyReleased(KeyEvent e) {
//对 上37、下38、左39、右40 进行判断
int code = e.getKeyCode();
System.out.println(code);
if (code == 65) {
initImage();
}
}
}8.2 优化路径设置
GameJFrame.java
public class GameJFrame extends JFrame implements KeyListener {
//定义一个变量,记录图片路径
String path = "day16-day17\\image\\animal\\animal4\\";
//创建一个JLable的对象(管理容器)
JLabel jLabel = new JLabel(new ImageIcon(path + num + ".jpg"));
//加载第一张完整的图片
JLabel all = new JLabel(new ImageIcon(path + "all.jpg"));8.3 完整代码
GameJFrame.java
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class GameJFrame extends JFrame implements KeyListener {
//创建一个二维数组,用来管理数据,加载图片时,会根据二维数组中的数据进行加载
int[][] data = new int[4][4];
//记录空白方块在二维数组中的位置
int x = 0;
int y = 0;
//定义一个变量,记录图片路径
String path = "day16-day17\\image\\animal\\animal4\\";
//游戏相关的所有代码,在此类中
public GameJFrame() {
//初始化界面
initJFrame();
//初始化菜单
initJMnuBar();
//初始化数据(打乱)
initData();
//初始化图片(根据打乱之后的结果去加载图片)
initImage();
//让界面显示,写在最后
this.setVisible(true);
}
//初始化数据(打乱)
private void initData() {
//定义一个一维数组
int[] tempArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
//打乱数组中数据的顺序
Random r = new Random();
for (int i = 0; i < tempArr.length; i++) {
//获取随机索引
int index = r.nextInt(tempArr.length);
int temp = tempArr[i];
tempArr[i] = tempArr[index];
tempArr[index] = temp;
}
//给二维数组添加数据
/*
//解法一:遍历一维数组tempArr得到每一个元素,然后把每一个元素添加到二维数组中
for (int i = 0; i < tempArr.length; i++) {
data[i/4][i%4] = tempArr[i];
}
//遍历二维数组
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
System.out.print(data[i][j]+ " ");
}
System.out.println();
}
*/
//解法二:遍历二维数组,给里面的每一个数组赋值
int index = 0;
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
if (tempArr[index] == 0) {
x = i;
y = j;
index++;
} else {
data[i][j] = tempArr[index];
index++;
}
}
}
}
//初始化图片,添加图片时,需要按照二维数组中管理的数据添加图片
private void initImage() {
//清空如果已经存在的图片
this.getContentPane().removeAll();
//细节:先加载的图片会在上方,后加载的图片在下面
//外循环 -- 将内循环重复执行了4次
for (int i = 0; i < 4; i++) {
//内循环 -- 表示在一行添加4张图片
for (int j = 0; j < 4; j++) {
//获取当前加载图片的序号
int num = data[i][j];
//创建一个JLable的对象(管理容器)
JLabel jLabel = new JLabel(new ImageIcon(path + num + ".jpg"));
//指定图片位置
jLabel.setBounds(105 * j + 83, 105 * i + 134, 105, 105);
//给图片添加边框 0:让图片凸起来 1:表示让图片凹下去
jLabel.setBorder(new BevelBorder(1));
//jLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); //让图片凸起来 0
//jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED)); //让图片凹下去 1
//将管理容器添加到界面中
//this.add(jLabel);
this.getContentPane().add(jLabel);
}
}
//添加背景图片
ImageIcon bg = new ImageIcon("day16-day17\\image\\background.png"); //新建ImageIcon,写入图片路径
JLabel background = new JLabel(bg); //新建JLabel,ImageIcon加入JLabel
background.setBounds(40, 40, 508, 560); //JLabel设置位置、宽高
this.getContentPane().add(background); //将背景添加到界面中
//刷新界面
this.getContentPane().repaint();
}
private void initJMnuBar() {
//创建整个菜单对象
JMenuBar jMenuBar = new JMenuBar();
//创建菜单上面的两个选项的对象(功能 关于我们)
JMenu functionJMenu = new JMenu("功能");
JMenu aboutJMenu = new JMenu("关于我们");
//创建选项下面的条目对象
JMenuItem replayItem = new JMenuItem("重新游戏");
JMenuItem reLoginItem = new JMenuItem("重新登录");
JMenuItem closeItem = new JMenuItem("关闭游戏");
JMenuItem accountItem = new JMenuItem("公众号");
//将每一个选项下面的条目,添加到选项中
functionJMenu.add(replayItem);
functionJMenu.add(reLoginItem);
functionJMenu.add(closeItem);
aboutJMenu.add(accountItem);
//将菜单里面的两个选项添加到菜单当中
jMenuBar.add(functionJMenu);
jMenuBar.add(aboutJMenu);
//给整个界面设置菜单
this.setJMenuBar(jMenuBar);
}
private void initJFrame() {
//设置界面的宽高
this.setSize(603, 680);
//设置界面的标题
this.setTitle("拼图单机版 v1.0");
//设置界面置顶
this.setAlwaysOnTop(true);
//设置界面居中
this.setLocationRelativeTo(null);
//设置关闭模式
//this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setDefaultCloseOperation(3);
//取消默认剧中放置
this.setLayout(null);
//给整个界面添加键盘监听事件
this.addKeyListener(this);
}
@Override
public void keyTyped(KeyEvent e) {
}
//按下不松时会调用此方法
@Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == 65){
System.out.println("按着A不松");
//删除界面中所有的图片
this.getContentPane().removeAll();
//加载第一张完整的图片
JLabel all = new JLabel(new ImageIcon(path + "all.jpg"));
all.setBounds(83,134,420,420);
this.getContentPane().add(all);
//添加背景图片
ImageIcon bg = new ImageIcon("day16-day17\\image\\background.png"); //新建ImageIcon,写入图片路径
JLabel background = new JLabel(bg); //新建JLabel,ImageIcon加入JLabel
background.setBounds(40, 40, 508, 560); //JLabel设置位置、宽高
this.getContentPane().add(background); //将背景添加到界面中
//刷新界面
this.getContentPane().repaint();
}
}
@Override
public void keyReleased(KeyEvent e) {
//对 上37、下38、左39、右40 进行判断
int code = e.getKeyCode();
System.out.println(code);
if (code == 37) {
System.out.println("向左移动");
if (y == 3) {
return;
}
data[x][y] = data[x][y + 1];
data[x][y + 1] = 0;
y++;
initImage();
} else if (code == 38) {
System.out.println("向上移动");
if (x == 3) {
//表示空白方块已经在最下方,下面没有方块,不能再执行往上移动
return;
}
//将空白方块与下方的方块进行调换
data[x][y] = data[x + 1][y]; //空白下面方块的值,赋值给空白方块
data[x + 1][y] = 0; //空白下方方块的值,定义为0
x++; //调换以后,表示空白的索引(x,y)发生了变化,需要x+1
initImage(); //重新加载图片
} else if (code == 39) {
System.out.println("向右移动");
if (y == 0) {
return;
}
data[x][y] = data[x][y - 1];
data[x][y - 1] = 0;
y--;
initImage();
} else if (code == 40) {
System.out.println("向下移动");
if (x == 0) {
return;
}
data[x][y] = data[x - 1][y];
data[x - 1][y] = 0;
x--;
initImage();
} else if (code == 65) {
initImage();
}
}
}9.作弊码
9.1 作弊码的键盘事件
GameJFrame.java
public class GameJFrame extends JFrame implements KeyListener {
//按下按键的时候会调用这个方法
@Override
public void keyReleased(KeyEvent e) {
//对 上37、下38、左39、右40 进行判断
int code = e.getKeyCode();
System.out.println(code);
if (code == 87) {
data = new int[][]{
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,0}
};
initImage();
}
}
}10.判断胜利
判断二维数组中数字是否正确
1.定义正确的二维数组win
2.加载图片之前,判断二维数组中数字与win数组是否相同
3.相同则显示胜利图标
4.不同则不显示胜利图标10.1 胜利逻辑
public class GameJFrame extends JFrame implements KeyListener {
//定义二位数组,存储正确的数据
int[][] win = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
private void initImage() {
//清空如果已经存在的图片
this.getContentPane().removeAll();
//细节:先加载的图片会在上方,后加载的图片在下面
if (victory()){
//显示胜利图标
JLabel winJLbel = new JLabel(new ImageIcon("day16-day17\\image\\win.png"));
winJLbel.setBounds(203,283,197,73);
this.getContentPane().add(winJLbel);
}
//。。。其他逻辑
}
//判断data数组中数据 与 win数据是否相同。相同则返回true,否则返回false
public boolean victory() {
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
if (data[i][j] != win[i][j]) {
//只要有一个数据不一样,则返回false
return false;
}
}
}
//循环遍历结束,表示全都一样,返回true
return true;
}
}10.2 胜利后不能再移动图片
public void keyReleased(KeyEvent e) {
//判断游戏是否胜利,若胜利,此方法不能再执行
if (victory()) {
return; //结束方法
}
}11.计步功能
1.定义变量用来统计步数 2.每次按上下左右,变量自增一次
public class GameJFrame extends JFrame implements KeyListener {
//定义变量,统计步数
int step = 0;
private void initImage() {
//清空如果已经存在的图片
this.getContentPane().removeAll();
//细节:先加载的图片会在上方,后加载的图片在下面
if (victory()) {
//显示胜利图标
JLabel winJLbel = new JLabel(new ImageIcon("day16-day17\\image\\win.png"));
winJLbel.setBounds(203, 283, 197, 73);
this.getContentPane().add(winJLbel);
}
//界面中放入显示步数的位置
JLabel stepCount = new JLabel("步数: " + step);
stepCount.setBounds(50, 30, 100, 20);
this.getContentPane().add(stepCount);
//...
}
@Override
public void keyReleased(KeyEvent e) {
//判断游戏是否胜利,若胜利,此方法不能再执行
if (victory()) {
return; //结束方法
}
//对 上37、下38、左39、右40 进行判断
int code = e.getKeyCode();
System.out.println(code);
if (code == 37) {
System.out.println("向左移动");
if (y == 3) {
return;
}
data[x][y] = data[x][y + 1];
data[x][y + 1] = 0;
y++;
//每次移动,计步器自增一次
step++;
initImage();
}
//其他类似
}
}12.重新开始
1.给重新游戏绑定点击事件 ActionListener 2.重新打乱二维数组中的数字、加载图片 3.计步器清零
public class GameJFrame extends JFrame implements KeyListener, ActionListener {
//创建选项下面的条目对象
JMenuItem replayItem = new JMenuItem("重新游戏");
JMenuItem reLoginItem = new JMenuItem("重新登录");
JMenuItem closeItem = new JMenuItem("关闭游戏");
JMenuItem accountItem = new JMenuItem("公众号");
private void initData() {
//定义一个一维数组
int[] tempArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
//打乱数组中数据的顺序
Random r = new Random();
for (int i = 0; i < tempArr.length; i++) {
//获取随机索引
int index = r.nextInt(tempArr.length);
int temp = tempArr[i];
tempArr[i] = tempArr[index];
tempArr[index] = temp;
}
//给二维数组添加数据
/*
//解法一:遍历一维数组tempArr得到每一个元素,然后把每一个元素添加到二维数组中
for (int i = 0; i < tempArr.length; i++) {
data[i/4][i%4] = tempArr[i];
}
//遍历二维数组
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
System.out.print(data[i][j]+ " ");
}
System.out.println();
}
*/
//解法二:遍历二维数组,给里面的每一个数组赋值
int index = 0;
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
if (tempArr[index] == 0) {
x = i;
y = j;
}
//无论一维数组中的值是否为0,都要赋值给二维数组,避免游戏重开以后,空白图片消失
data[i][j] = tempArr[index];
index++;
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
Object obj = e.getSource();
if (obj == replayItem) {
System.out.println("重新游戏");
//计步器清零
step = 0;
//再次打乱二位数组中数据
initData();
//重新加载图片
initImage();
}
}
}13.重新登录、关闭游戏
@Override
public void actionPerformed(ActionEvent e) {
Object obj = e.getSource();
if (obj == replayItem) {
System.out.println("重新游戏");
//计步器清零
step = 0;
//再次打乱二位数组中数据
initData();
//重新加载图片
initImage();
} else if (obj == reLoginItem) {
System.out.println("重新登录");
//关闭当前的游戏界面
this.setVisible(false);
//打开登录界面
new LoginJFrame();
} else if (obj == closeItem) {
System.out.println("关闭游戏");
//直接关闭虚拟机即可
System.exit(0);
}
}14.关于我们
@Override
public void actionPerformed(ActionEvent e) {
Object obj = e.getSource();
if (obj == accountItem) {
System.out.println("公众号");
//创建一个弹框对象
JDialog jDialog = new JDialog();
//创建管理图片的容器对象JLabel
JLabel jLabel = new JLabel(new ImageIcon("day16-day17\\image\\about.png"));
jLabel.setBounds(0,0,258,258); //位置是相对于弹框设置的
jDialog.getContentPane().add(jLabel); //将图片放入弹框
jDialog.setSize(344,344); //设置弹框大小
jDialog.setAlwaysOnTop(true); //让弹框置顶
jDialog.setLocationRelativeTo(null); //让弹框居中
jDialog.setModal(true); //弹框不关闭,则无法操作下面的界面
jDialog.setVisible(true); //显示弹框
}
}15.完整代码
GameJFrame.java
package com.yq.ui;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class GameJFrame extends JFrame implements KeyListener, ActionListener {
//创建一个二维数组,用来管理数据,加载图片时,会根据二维数组中的数据进行加载
int[][] data = new int[4][4];
//记录空白方块在二维数组中的位置
int x = 0;
int y = 0;
//定义一个变量,记录图片路径
String path = "day16-day17\\image\\animal\\animal3\\";
//定义二位数组,存储正确的数据
int[][] win = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
//定义变量,统计步数
int step = 0;
//创建选项下面的条目对象
JMenuItem replayItem = new JMenuItem("重新游戏");
JMenuItem reLoginItem = new JMenuItem("重新登录");
JMenuItem closeItem = new JMenuItem("关闭游戏");
JMenuItem accountItem = new JMenuItem("公众号");
//游戏相关的所有代码,在此类中
public GameJFrame() {
//初始化界面
initJFrame();
//初始化菜单
initJMnuBar();
//初始化数据(打乱)
initData();
//初始化图片(根据打乱之后的结果去加载图片)
initImage();
//让界面显示,写在最后
this.setVisible(true);
}
//初始化数据(打乱)
private void initData() {
//定义一个一维数组
int[] tempArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
//打乱数组中数据的顺序
Random r = new Random();
for (int i = 0; i < tempArr.length; i++) {
//获取随机索引
int index = r.nextInt(tempArr.length);
int temp = tempArr[i];
tempArr[i] = tempArr[index];
tempArr[index] = temp;
}
//给二维数组添加数据
/*
//解法一:遍历一维数组tempArr得到每一个元素,然后把每一个元素添加到二维数组中
for (int i = 0; i < tempArr.length; i++) {
data[i/4][i%4] = tempArr[i];
}
//遍历二维数组
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
System.out.print(data[i][j]+ " ");
}
System.out.println();
}
*/
//解法二:遍历二维数组,给里面的每一个数组赋值
int index = 0;
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
if (tempArr[index] == 0) {
x = i;
y = j;
}
data[i][j] = tempArr[index];
index++;
}
}
}
//初始化图片,添加图片时,需要按照二维数组中管理的数据添加图片
private void initImage() {
//清空如果已经存在的图片
this.getContentPane().removeAll();
//细节:先加载的图片会在上方,后加载的图片在下面
if (victory()) {
//显示胜利图标
JLabel winJLbel = new JLabel(new ImageIcon("day16-day17\\image\\win.png"));
winJLbel.setBounds(203, 283, 197, 73);
this.getContentPane().add(winJLbel);
}
//界面中放入显示步数的位置
JLabel stepCount = new JLabel("步数: " + step);
stepCount.setBounds(50, 30, 100, 20);
this.getContentPane().add(stepCount);
//外循环 -- 将内循环重复执行了4次
for (int i = 0; i < 4; i++) {
//内循环 -- 表示在一行添加4张图片
for (int j = 0; j < 4; j++) {
//获取当前加载图片的序号
int num = data[i][j];
//创建一个JLable的对象(管理容器)
JLabel jLabel = new JLabel(new ImageIcon(path + num + ".jpg"));
//指定图片位置
jLabel.setBounds(105 * j + 83, 105 * i + 134, 105, 105);
//给图片添加边框 0:让图片凸起来 1:表示让图片凹下去
jLabel.setBorder(new BevelBorder(1));
//jLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); //让图片凸起来 0
//jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED)); //让图片凹下去 1
//将管理容器添加到界面中
//this.add(jLabel);
this.getContentPane().add(jLabel);
}
}
//添加背景图片
ImageIcon bg = new ImageIcon("day16-day17\\image\\background.png"); //新建ImageIcon,写入图片路径
JLabel background = new JLabel(bg); //新建JLabel,ImageIcon加入JLabel
background.setBounds(40, 40, 508, 560); //JLabel设置位置、宽高
this.getContentPane().add(background); //将背景添加到界面中
//刷新界面
this.getContentPane().repaint();
}
private void initJMnuBar() {
//创建整个菜单对象
JMenuBar jMenuBar = new JMenuBar();
//创建菜单上面的两个选项的对象(功能 关于我们)
JMenu functionJMenu = new JMenu("功能");
JMenu aboutJMenu = new JMenu("关于我们");
//将每一个选项下面的条目,添加到选项中
functionJMenu.add(replayItem);
functionJMenu.add(reLoginItem);
functionJMenu.add(closeItem);
aboutJMenu.add(accountItem);
//给条目绑定事件
replayItem.addActionListener(this);
reLoginItem.addActionListener(this);
closeItem.addActionListener(this);
accountItem.addActionListener(this);
//将菜单里面的两个选项添加到菜单当中
jMenuBar.add(functionJMenu);
jMenuBar.add(aboutJMenu);
//给整个界面设置菜单
this.setJMenuBar(jMenuBar);
}
private void initJFrame() {
//设置界面的宽高
this.setSize(603, 680);
//设置界面的标题
this.setTitle("拼图单机版 v1.0");
//设置界面置顶
this.setAlwaysOnTop(true);
//设置界面居中
this.setLocationRelativeTo(null);
//设置关闭模式
//this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setDefaultCloseOperation(3);
//取消默认剧中放置
this.setLayout(null);
//给整个界面添加键盘监听事件
this.addKeyListener(this);
}
@Override
public void keyTyped(KeyEvent e) {
}
//按下不松时会调用此方法
@Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == 65) {
System.out.println("按着A不松");
//删除界面中所有的图片
this.getContentPane().removeAll();
//加载第一张完整的图片
JLabel all = new JLabel(new ImageIcon(path + "all.jpg"));
all.setBounds(83, 134, 420, 420);
this.getContentPane().add(all);
//添加背景图片
ImageIcon bg = new ImageIcon("day16-day17\\image\\background.png"); //新建ImageIcon,写入图片路径
JLabel background = new JLabel(bg); //新建JLabel,ImageIcon加入JLabel
background.setBounds(40, 40, 508, 560); //JLabel设置位置、宽高
this.getContentPane().add(background); //将背景添加到界面中
//刷新界面
this.getContentPane().repaint();
}
}
//按下按键的时候会调用这个方法
@Override
public void keyReleased(KeyEvent e) {
//判断游戏是否胜利,若胜利,此方法不能再执行
if (victory()) {
return; //结束方法
}
//对 上37、下38、左39、右40 进行判断
int code = e.getKeyCode();
System.out.println(code);
if (code == 37) {
System.out.println("向左移动");
if (y == 3) {
return;
}
data[x][y] = data[x][y + 1];
data[x][y + 1] = 0;
y++;
//每次移动,计步器自增一次
step++;
initImage();
} else if (code == 38) {
System.out.println("向上移动");
if (x == 3) {
//表示空白方块已经在最下方,下面没有方块,不能再执行往上移动
return;
}
//将空白方块与下方的方块进行调换
data[x][y] = data[x + 1][y]; //空白下面方块的值,赋值给空白方块
data[x + 1][y] = 0; //空白下方方块的值,定义为0
x++; //调换以后,表示空白的索引(x,y)发生了变化,需要x+1
//每次移动,计步器自增一次
step++;
initImage(); //重新加载图片
} else if (code == 39) {
System.out.println("向右移动");
if (y == 0) {
return;
}
data[x][y] = data[x][y - 1];
data[x][y - 1] = 0;
y--;
//每次移动,计步器自增一次
step++;
initImage();
} else if (code == 40) {
System.out.println("向下移动");
if (x == 0) {
return;
}
data[x][y] = data[x - 1][y];
data[x - 1][y] = 0;
x--;
//每次移动,计步器自增一次
step++;
initImage();
} else if (code == 65) {
initImage();
} else if (code == 87) {
data = new int[][]{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
initImage();
}
}
//判断data数组中数据 与 win数据是否相同。相同则返回true,否则返回false
public boolean victory() {
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
if (data[i][j] != win[i][j]) {
//只要有一个数据不一样,则返回false
return false;
}
}
}
//循环遍历结束,表示全都一样,返回true
return true;
}
@Override
public void actionPerformed(ActionEvent e) {
Object obj = e.getSource();
if (obj == replayItem) {
System.out.println("重新游戏");
//计步器清零
step = 0;
//再次打乱二位数组中数据
initData();
//重新加载图片
initImage();
} else if (obj == reLoginItem) {
System.out.println("重新登录");
//关闭当前的游戏界面
this.setVisible(false);
//打开登录界面
new LoginJFrame();
} else if (obj == closeItem) {
System.out.println("关闭游戏");
//直接关闭虚拟机即可
System.exit(0);
} else if (obj == accountItem) {
System.out.println("公众号");
//创建一个弹框对象
JDialog jDialog = new JDialog();
//创建管理图片的容器对象JLabel
JLabel jLabel = new JLabel(new ImageIcon("day16-day17\\image\\about.png"));
jLabel.setBounds(0,0,258,258); //位置是相对于弹框设置的
jDialog.getContentPane().add(jLabel); //将图片放入弹框
jDialog.setSize(344,344); //设置弹框大小
jDialog.setAlwaysOnTop(true); //让弹框置顶
jDialog.setLocationRelativeTo(null); //让弹框居中
jDialog.setModal(true); //弹框不关闭,则无法操作下面的界面
jDialog.setVisible(true); //显示弹框
}
}
}App.java
import com.yq.ui.GameJFrame;
import com.yq.ui.LoginJFrame;
import com.yq.ui.RegisterJFrame;
public class App {
public static void main(String[] args) {
//表示程序的启动入口
//new LoginJFrame();
//new RegisterJFrame();
new GameJFrame();
}
}
评论区