Day04-Java进阶-石头迷阵游戏 (游戏演示&绘制界面&重构代码&打乱方块&移动业务&判断胜利&重新开始)

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) {

    }
    // --------------------------------------------------------------
}

由此完结...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码里码理吽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值