1. 游戏演示及构建游戏窗体
package com.itheima.stonepuzzle;
import javax.swing.*;
public class Test {
public static void main(String[] args) {
JFrame frame = new JFrame();
// 设置窗体的大小
frame.setSize(514, 595);
// 设置窗体的关闭模式
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置窗体的标题
frame.setTitle("石头迷阵单机版V1.0");
// 设置窗体居中
frame.setLocationRelativeTo(null);
// 设置窗体可见
frame.setVisible(true);
}
}
2. 绘制界面
2.1 恶心的写法
package com.itheima.stonepuzzle;
import javax.swing.*;
public class Test {
public static void main(String[] args) {
JFrame frame = new JFrame();
// 设置窗体的大小
frame.setSize(514, 595);
// 设置窗体的关闭模式
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置窗体的标题
frame.setTitle("石头迷阵单机版V1.0");
// 设置窗体居中
frame.setLocationRelativeTo(null);
// 取消默认布局
frame.setLayout(null);
// 创建JLabel对象, 加载图片资源(构造方法中new ImageIcon())
JLabel jl1 = new JLabel(new ImageIcon("D:\\image\\8.png"));
// 设置摆放位置
jl1.setBounds(50, 90, 100, 100);
// 窗体对象调用getContentPane方法拿到面板对象,再调用add方法把JLabel对象jl1塞进去
frame.getContentPane().add(jl1);
JLabel jl2 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl2.setBounds(150, 90, 100, 100);
frame.getContentPane().add(jl2);
JLabel jl3 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl3.setBounds(250, 90, 100, 100);
frame.getContentPane().add(jl3);
JLabel jl4 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl4.setBounds(350, 90, 100, 100);
frame.getContentPane().add(jl4);
JLabel jl5 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl5.setBounds(50, 190, 100, 100);
frame.getContentPane().add(jl5);
JLabel jl6 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl6.setBounds(150, 190, 100, 100);
frame.getContentPane().add(jl6);
JLabel jl7 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl7.setBounds(250, 190, 100, 100);
frame.getContentPane().add(jl7);
JLabel jl8 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl8.setBounds(350, 190, 100, 100);
frame.getContentPane().add(jl8);
JLabel jl9 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl9.setBounds(50, 290, 100, 100);
frame.getContentPane().add(jl9);
JLabel jl10 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl10.setBounds(150, 290, 100, 100);
frame.getContentPane().add(jl10);
JLabel jl11 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl11.setBounds(250, 290, 100, 100);
frame.getContentPane().add(jl11);
JLabel jl12 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl12.setBounds(350, 290, 100, 100);
frame.getContentPane().add(jl12);
JLabel jl13 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl13.setBounds(50, 390, 100, 100);
frame.getContentPane().add(jl13);
JLabel jl14 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl14.setBounds(150, 390, 100, 100);
frame.getContentPane().add(jl14);
JLabel jl15 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl15.setBounds(250, 390, 100, 100);
frame.getContentPane().add(jl15);
JLabel jl16 = new JLabel(new ImageIcon("D:\\image\\8.png"));
jl16.setBounds(350, 390, 100, 100);
frame.getContentPane().add(jl16);
JLabel background = new JLabel(new ImageIcon("D:\\image\\background.png"));
background.setBounds(26, 30, 450, 484);
frame.getContentPane().add(background);
// 设置窗体可见
frame.setVisible(true);
}
}
2.2 使用循环和二维数组优化
2.2.1 使用循环
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
JLabel imageLabel = new JLabel(new ImageIcon("D:\\image\\"+data[i][j]+".png"));
imageLabel.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);
frame.getContentPane().add(imageLabel);
}
}
2.2.2 二维数组优化
package com.itheima.stonepuzzle;
import javax.swing.*;
public class Test {
public static void main(String[] args) {
int[][] data = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
JFrame frame = new JFrame();
// 设置窗体的大小
frame.setSize(514, 595);
// 设置窗体的关闭模式
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置窗体的标题
frame.setTitle("石头迷阵单机版V1.0");
// 设置窗体居中
frame.setLocationRelativeTo(null);
// 取消默认布局
frame.setLayout(null);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
JLabel imageLabel = new JLabel(new ImageIcon("D:\\image\\"+data[i][j]+".png"));
imageLabel.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);
frame.getContentPane().add(imageLabel);
}
}
JLabel background = new JLabel(new ImageIcon("D:\\image\\background.png"));
background.setBounds(26, 30, 450, 484);
frame.getContentPane().add(background);
// 设置窗体可见
frame.setVisible(true);
}
}
3. 使用继承重构代码
package com.itheima.stonepuzzle;
import javax.swing.*;
public class MainFrame extends JFrame {
int[][] data = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
public MainFrame(){
initFrame();
paintView();
// 设置窗体可见
setVisible(true);
}
/**
* 此方法用于初始化窗口
*/
public void initFrame() {
// 设置窗体的大小
setSize(514, 595);
// 设置窗体的关闭模式
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置窗体的标题
setTitle("石头迷阵单机版V1.0");
// 设置窗体居中
setLocationRelativeTo(null);
// 取消默认布局
setLayout(null);
}
/**
* 此方法用户绘制窗口
*/
public void paintView() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
JLabel imageLabel = new JLabel(new ImageIcon("D:\\image\\" + data[i][j] + ".png"));
imageLabel.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);
getContentPane().add(imageLabel);
}
}
JLabel background = new JLabel(new ImageIcon("D:\\image\\background.png"));
background.setBounds(26, 30, 450, 484);
getContentPane().add(background);
}
}
package com.itheima.stonepuzzle;
import javax.swing.*;
public class Test {
public static void main(String[] args) {
new MainFrame();
}
}
4. 打乱石头方块
package com.itheima.stonepuzzle;
import javax.swing.*;
import java.util.Random;
public class MainFrame extends JFrame {
int[][] data = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
public MainFrame() {
initFrame();
initData();
paintView();
// 设置窗体可见
setVisible(true);
}
/**
* 初始化数据(打乱绘图)
*/
public void initData() {
// 产生随机数
Random r = new Random();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
int RandomX = r.nextInt(4);
int RandomY = r.nextInt(4);
int temp = data[i][j];
data[i][j] = data[RandomX][RandomY];
data[RandomX][RandomY] = temp;
}
}
}
/**
* 此方法用于初始化窗口
*/
public void initFrame() {
// 设置窗体的大小
setSize(514, 595);
// 设置窗体的关闭模式
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置窗体的标题
setTitle("石头迷阵单机版V1.0");
// 设置窗体居中
setLocationRelativeTo(null);
// 取消默认布局
setLayout(null);
}
/**
* 此方法用户窗口绘图
*/
public void paintView() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
JLabel imageLabel = new JLabel(new ImageIcon("D:\\image\\" + data[i][j] + ".png"));
imageLabel.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);
getContentPane().add(imageLabel);
}
}
JLabel background = new JLabel(new ImageIcon("D:\\image\\background.png"));
background.setBounds(26, 30, 450, 484);
getContentPane().add(background);
}
}
5. 移动业务准备
5.1 注册键盘
package com.itheima.stonepuzzle;
import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class MainFrame extends JFrame implements KeyListener {
int[][] data = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
public MainFrame() {
// 窗体对象.addKeyListener(KeyListener实现类对象)
this.addKeyListener(this);
// this: 当前类对象
// 1) 窗体对象
// 2) KeyListener实现类对象
initFrame();
initData();
paintView();
// 设置窗体可见
setVisible(true);
}
/**
* 初始化数据(打乱绘图)
*/
public void initData() {
// 产生随机数
Random r = new Random();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
int RandomX = r.nextInt(4);
int RandomY = r.nextInt(4);
int temp = data[i][j];
data[i][j] = data[RandomX][RandomY];
data[RandomX][RandomY] = temp;
}
}
}
/**
* 此方法用于初始化窗口
*/
public void initFrame() {
// 设置窗体的大小
setSize(514, 595);
// 设置窗体的关闭模式
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置窗体的标题
setTitle("石头迷阵单机版V1.0");
// 设置窗体居中
setLocationRelativeTo(null);
// 取消默认布局
setLayout(null);
}
/**
* 此方法用户窗口绘图
*/
public void paintView() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
JLabel imageLabel = new JLabel(new ImageIcon("D:\\image\\" + data[i][j] + ".png"));
imageLabel.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);
getContentPane().add(imageLabel);
}
}
JLabel background = new JLabel(new ImageIcon("D:\\image\\background.png"));
background.setBounds(26, 30, 450, 484);
getContentPane().add(background);
}
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
move(keyCode);
}
/**
* 此方法用于处理移动业务
*/
private void move(int keyCode) {
if (keyCode == 37) {
System.out.println("左移动业务执行");
} else if (keyCode == 38) {
System.out.println("上移动业务执行");
} else if (keyCode == 39) {
System.out.println("右移动业务执行");
} else if (keyCode == 40) {
System.out.println("下移动业务执行");
}
}
// --------------------------------------------------------------
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
// --------------------------------------------------------------
}
5.2 确定0号元素所在
package com.itheima.stonepuzzle;
import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class MainFrame extends JFrame implements KeyListener {
int[][] data = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
int row; // 0号元素行坐标位置
int column; // 0号元素列坐标位置
public MainFrame() {
// 窗体对象.addKeyListener(KeyListener实现类对象)
this.addKeyListener(this);
// this: 当前类对象
// 1) 窗体对象
// 2) KeyListener实现类对象
initFrame();
initData();
paintView();
// 设置窗体可见
setVisible(true);
}
/**
* 初始化数据(打乱绘图)
*/
public void initData() {
// 产生随机数
Random r = new Random();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
int RandomX = r.nextInt(4);
int RandomY = r.nextInt(4);
int temp = data[i][j];
data[i][j] = data[RandomX][RandomY];
data[RandomX][RandomY] = temp;
}
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (data[i][j] == 0) {
row = i;
column = j;
}
}
}
System.out.println("0号元素的初始坐标位置为: " + row + ", " + column);
}
/**
* 此方法用于初始化窗口
*/
public void initFrame() {
// 设置窗体的大小
setSize(514, 595);
// 设置窗体的关闭模式
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置窗体的标题
setTitle("石头迷阵单机版V1.0");
// 设置窗体居中
setLocationRelativeTo(null);
// 取消默认布局
setLayout(null);
}
/**
* 此方法用户窗口绘图
*/
public void paintView() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
JLabel imageLabel = new JLabel(new ImageIcon("D:\\image\\" + data[i][j] + ".png"));
imageLabel.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);
getContentPane().add(imageLabel);
}
}
JLabel background = new JLabel(new ImageIcon("D:\\image\\background.png"));
background.setBounds(26, 30, 450, 484);
getContentPane().add(background);
}
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
move(keyCode);
}
/**
* 此方法用于处理移动业务
*/
private void move(int keyCode) {
if (keyCode == 37) {
System.out.println("左移动业务执行");
} else if (keyCode == 38) {
System.out.println("上移动业务执行");
} else if (keyCode == 39) {
System.out.println("右移动业务执行");
} else if (keyCode == 40) {
System.out.println("下移动业务执行");
}
}
// --------------------------------------------------------------
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
// --------------------------------------------------------------
}
6. 移动业务
6.1 基本实现
6.2 错误解决
添加 if 判断条件
package com.itheima.stonepuzzle;
import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class MainFrame extends JFrame implements KeyListener {
int[][] data = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
int row; // 0号元素行坐标位置
int column; // 0号元素列坐标位置
public MainFrame() {
// 窗体对象.addKeyListener(KeyListener实现类对象)
this.addKeyListener(this);
// this: 当前类对象
// 1) 窗体对象
// 2) KeyListener实现类对象
initFrame();
initData();
paintView();
// 设置窗体可见
setVisible(true);
}
/**
* 初始化数据(打乱绘图)
*/
public void initData() {
// 产生随机数
Random r = new Random();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
int RandomX = r.nextInt(4);
int RandomY = r.nextInt(4);
int temp = data[i][j];
data[i][j] = data[RandomX][RandomY];
data[RandomX][RandomY] = temp;
}
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (data[i][j] == 0) {
row = i;
column = j;
}
}
}
System.out.println("0号元素的初始坐标位置为: " + row + ", " + column);
}
/**
* 此方法用于初始化窗口
*/
public void initFrame() {
// 设置窗体的大小
setSize(514, 595);
// 设置窗体的关闭模式
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置窗体的标题
setTitle("石头迷阵单机版V1.0");
// 设置窗体居中
setLocationRelativeTo(null);
// 取消默认布局
setLayout(null);
}
/**
* 此方法用户窗口绘图
*/
public void paintView() {
// 移除现有组件
getContentPane().removeAll();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
JLabel imageLabel = new JLabel(new ImageIcon("D:\\image\\" + data[i][j] + ".png"));
imageLabel.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);
getContentPane().add(imageLabel);
}
}
JLabel background = new JLabel(new ImageIcon("D:\\image\\background.png"));
background.setBounds(26, 30, 450, 484);
getContentPane().add(background);
// 加载后, 刷新页面
getContentPane().repaint();
}
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
move(keyCode);
// 每一次移动之后, 都重新绘制游戏界面
paintView();
}
/**
* 此方法用于处理移动业务
*/
private void move(int keyCode) {
if (keyCode == 37) {
if (column == 3){
return;
}
// 左移动: 空白块和右侧数据进行交换
// data[row][column] data[row][column+1]
int temp = data[row][column];
data[row][column] = data[row][column + 1];
data[row][column + 1] = temp;
column++;
} else if (keyCode == 38) {
if (row == 3){
return;
}
// 上移动: 空白块和下方数据进行交换
// data[row][column] data[row+1][column]
int temp = data[row][column];
data[row][column] = data[row + 1][column];
data[row + 1][column] = temp;
row++;
} else if (keyCode == 39) {
if (column == 0){
return;
}
// 右移动: 空白块和左侧数据进行交换
// data[row][column] data[row][column-1]
int temp = data[row][column];
data[row][column] = data[row][column-1];
data[row][column-1] = temp;
column--;
} else if (keyCode == 40) {
if (row == 0){
return;
}
// 下移动: 空白块和上方数据进行交换
// data[row][column] data[row-1][column]
int temp = data[row][column];
data[row][column] = data[row - 1][column];
data[row - 1][column] = temp;
row--;
} else if (keyCode == 90) {
data = new int[][]{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
}
}
/**
* 此方法用于二维数组元素交换
*/
private void Exchage(int a, int b) {
int temp = a;
a = b;
b = temp;
}
// --------------------------------------------------------------
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
// --------------------------------------------------------------
}
7. 判断胜利-统计步数-重新游戏
7.1 游戏判定胜利
package com.itheima.stonepuzzle;
import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class MainFrame extends JFrame implements KeyListener {
int[][] data = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
int[][] win = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
int row; // 0号元素行坐标位置
int column; // 0号元素列坐标位置
public MainFrame() {
// 窗体对象.addKeyListener(KeyListener实现类对象)
this.addKeyListener(this);
// this: 当前类对象
// 1) 窗体对象
// 2) KeyListener实现类对象
initFrame();
initData();
paintView();
// 设置窗体可见
setVisible(true);
}
/**
* 初始化数据(打乱绘图)
*/
public void initData() {
// 产生随机数
Random r = new Random();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
int RandomX = r.nextInt(4);
int RandomY = r.nextInt(4);
int temp = data[i][j];
data[i][j] = data[RandomX][RandomY];
data[RandomX][RandomY] = temp;
}
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (data[i][j] == 0) {
row = i;
column = j;
}
}
}
System.out.println("0号元素的初始坐标位置为: " + row + ", " + column);
}
/**
* 此方法用于初始化窗口
*/
public void initFrame() {
// 设置窗体的大小
setSize(514, 595);
// 设置窗体的关闭模式
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置窗体的标题
setTitle("石头迷阵单机版V1.0");
// 设置窗体居中
setLocationRelativeTo(null);
// 取消默认布局
setLayout(null);
}
/**
* 此方法用户窗口绘图
*/
public void paintView() {
// 移除现有组件
getContentPane().removeAll();
// 判断是否胜利, 从而展示胜利图片
if (victory()){
JLabel winLabel = new JLabel(new ImageIcon("D:\\image\\win.png"));
winLabel.setBounds(124, 230, 266, 88);
getContentPane().add(winLabel);
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
JLabel imageLabel = new JLabel(new ImageIcon("D:\\image\\" + data[i][j] + ".png"));
imageLabel.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);
getContentPane().add(imageLabel);
}
}
JLabel background = new JLabel(new ImageIcon("D:\\image\\background.png"));
background.setBounds(26, 30, 450, 484);
getContentPane().add(background);
// 加载后, 刷新页面
getContentPane().repaint();
}
/**
* 判断游戏是否胜利
*/
private boolean victory(){
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if(data[i][j] != win[i][j]){
return false;
}
}
}
return true;
}
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
move(keyCode);
// 每一次移动之后, 都重新绘制游戏界面
paintView();
}
/**
* 此方法用于处理移动业务
*/
private void move(int keyCode) {
if (victory()){
return;
}
if (keyCode == 37) {
if (column == 3){
return;
}
// 左移动: 空白块和右侧数据进行交换
// data[row][column] data[row][column+1]
int temp = data[row][column];
data[row][column] = data[row][column + 1];
data[row][column + 1] = temp;
column++;
} else if (keyCode == 38) {
if (row == 3){
return;
}
// 上移动: 空白块和下方数据进行交换
// data[row][column] data[row+1][column]
int temp = data[row][column];
data[row][column] = data[row + 1][column];
data[row + 1][column] = temp;
row++;
} else if (keyCode == 39) {
if (column == 0){
return;
}
// 右移动: 空白块和左侧数据进行交换
// data[row][column] data[row][column-1]
int temp = data[row][column];
data[row][column] = data[row][column-1];
data[row][column-1] = temp;
column--;
} else if (keyCode == 40) {
if (row == 0){
return;
}
// 下移动: 空白块和上方数据进行交换
// data[row][column] data[row-1][column]
int temp = data[row][column];
data[row][column] = data[row - 1][column];
data[row - 1][column] = temp;
row--;
} else if (keyCode == 90) {
data = new int[][]{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
}
}
/**
* 此方法用于二维数组元素交换
*/
private void exchage(int a, int b) {
int temp = a;
a = b;
b = temp;
}
// --------------------------------------------------------------
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
// --------------------------------------------------------------
}
7.2 统计步数-重新游戏
7.2.1 统计步数
7.2.2 重新游戏
package com.itheima.stonepuzzle;
import javax.swing.*;
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 MainFrame extends JFrame implements KeyListener {
int[][] data = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
int[][] win = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
int count = 0;
int row; // 0号元素行坐标位置
int column; // 0号元素列坐标位置
public MainFrame() {
// 窗体对象.addKeyListener(KeyListener实现类对象)
this.addKeyListener(this);
// this: 当前类对象
// 1) 窗体对象
// 2) KeyListener实现类对象
initFrame();
initData();
paintView();
// 设置窗体可见
setVisible(true);
}
/**
* 初始化数据(打乱绘图)
*/
public void initData() {
// 产生随机数
Random r = new Random();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
int RandomX = r.nextInt(4);
int RandomY = r.nextInt(4);
int temp = data[i][j];
data[i][j] = data[RandomX][RandomY];
data[RandomX][RandomY] = temp;
}
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (data[i][j] == 0) {
row = i;
column = j;
}
}
}
System.out.println("0号元素的初始坐标位置为: " + row + ", " + column);
}
/**
* 此方法用于初始化窗口
*/
public void initFrame() {
// 设置窗体的大小
setSize(514, 595);
// 设置窗体的关闭模式
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置窗体的标题
setTitle("石头迷阵单机版V1.0");
// 设置窗体居中
setLocationRelativeTo(null);
// 取消默认布局
setLayout(null);
}
/**
* 此方法用户窗口绘图
*/
public void paintView() {
// 移除现有组件
getContentPane().removeAll();
// 判断是否胜利, 从而展示胜利图片
if (victory()) {
JLabel winLabel = new JLabel(new ImageIcon("D:\\image\\win.png"));
winLabel.setBounds(124, 230, 266, 88);
getContentPane().add(winLabel);
}
JLabel scoreLabel = new JLabel("步数为:" + count);
scoreLabel.setBounds(50, 20, 100, 20);
getContentPane().add(scoreLabel);
JButton btn = new JButton("重新游戏");
btn.setBounds(350, 20, 100, 20);
getContentPane().add(btn);
// 设置默认焦点为false
btn.setFocusable(false);
btn.addActionListener(e -> {
count = 0;
initData();
paintView();
});
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
JLabel imageLabel = new JLabel(new ImageIcon("D:\\image\\" + data[i][j] + ".png"));
imageLabel.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);
getContentPane().add(imageLabel);
}
}
JLabel background = new JLabel(new ImageIcon("D:\\image\\background.png"));
background.setBounds(26, 30, 450, 484);
getContentPane().add(background);
// 加载后, 刷新页面
getContentPane().repaint();
}
/**
* 判断游戏是否胜利
*/
private boolean victory() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (data[i][j] != win[i][j]) {
return false;
}
}
}
return true;
}
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
move(keyCode);
// 每一次移动之后, 都重新绘制游戏界面
paintView();
}
/**
* 此方法用于处理移动业务
*/
private void move(int keyCode) {
if (victory()) {
return;
}
if (keyCode == 37) {
if (column == 3) {
return;
}
// 左移动: 空白块和右侧数据进行交换
// data[row][column] data[row][column+1]
int temp = data[row][column];
data[row][column] = data[row][column + 1];
data[row][column + 1] = temp;
column++;
count++;
} else if (keyCode == 38) {
if (row == 3) {
return;
}
// 上移动: 空白块和下方数据进行交换
// data[row][column] data[row+1][column]
int temp = data[row][column];
data[row][column] = data[row + 1][column];
data[row + 1][column] = temp;
row++;
count++;
} else if (keyCode == 39) {
if (column == 0) {
return;
}
// 右移动: 空白块和左侧数据进行交换
// data[row][column] data[row][column-1]
int temp = data[row][column];
data[row][column] = data[row][column - 1];
data[row][column - 1] = temp;
column--;
count++;
} else if (keyCode == 40) {
if (row == 0) {
return;
}
// 下移动: 空白块和上方数据进行交换
// data[row][column] data[row-1][column]
int temp = data[row][column];
data[row][column] = data[row - 1][column];
data[row - 1][column] = temp;
row--;
count++;
} else if (keyCode == 90) {
// Ctrl + Z 作弊器
data = new int[][]{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
}
}
// --------------------------------------------------------------
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
// --------------------------------------------------------------
}
由此完结...