拼图小游戏Java简易版

技术需求

Java基础封装、继承、多态。

代码实现

创建一个子类继承自父类JFrame,好处是继承到父类的所有方法,直接使用,更为方便。

public class MyFrame{}

创建方法用于设置窗口参数

public void window(){
        // 设置窗口大小
        setSize(514,594);
        // 设置窗口标题
        setTitle("单机游戏v1.0");
        // 设置窗口居中显示
        setLocationRelativeTo(null);
        // 设置窗口置顶
        setAlwaysOnTop(true);
        // 设置程序关闭模式为窗口关闭
        setDefaultCloseOperation(MyFrameDemo.EXIT_ON_CLOSE);
        // 取消默认布局
        setLayout(null);
    }

图片本身不能移动,将图片映射为二维数组下标,数组下标的改变实际上就模拟了图片的移动。
程序每次运行都需要打乱图片的摆放顺序,这里采取的办法是:将图片编号,然后把图片的序号存到一维数组中,打乱一维数组中的数据,然后把一维数组的数据再赋值给二维数组。

// 创建成员变量二维数组,用来存放随机生成的图片
int[][] arr = new int[4][4];
// 创建顺序正确的二维数组,用于校验游戏是否成功
int[][] win = {
            {0,1,2,3},
            {4,5,6,7},
            {8,9,10,11},
            {12,13,14,15}
    };

// 创建成员变量行、列(用于记录空白图片的位置)、步数(用来统计步数)
int row;
int column;
int count = 0;

创建方法将二维数组随机化,以模拟图片打乱

public void initData(){
        Random random = new Random();
        // 用来保存图片的正确顺序
        int[] a = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
        // 打乱顺序
        for (int i = 0; i < a.length; i++) {
            int index = random.nextInt(a.length);
            int temp = a[i];
            a[i] = a[index];
            a[index] = temp;
        }
        // 一位数组下标计数器
        int index = 0;
        // 将打乱好的数据存入二位数组中
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                arr[i][j] = a[index];
                // 定位空白图片位置
                if (arr[i][j] == 0){
                    row = i;
                    column = j;
                }
                // 更新一维数组小标
                index++;
            }
        }
    }

接下来完成图片的加载,上面我们已经将图片的名字编号,然后将打乱顺序的编号存入了二维数组中,接下来利用这些编号,将图片加载进容器内并显示出来。

// 加载图片
    public void view(){
        // 清除容器内的所有组件,后面图片移动时我们要刷新页面,
        // 如果页面中存在有组件的话,后加载的组件会被先加载的组件覆盖
        // JFrame中的重合问题采用的是先来先显示
        getContentPane().removeAll();

        // 创建标签用来显示移动的步数
        JLabel countLabel = new JLabel("一共走了" + count + "步");
        // 设置标签大小
        countLabel.setBounds(50,20,100,20);
        // 将标签加载到容器中(因为取消了默认布局,必须手动加载)
        getContentPane().add(countLabel);

        // 加载图片
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                // 创建图片对象用于存放图片,注意图片的路径的\要写\\,避免转义
                // 注意:图片的名字已映射为二位数组中的数据,所以图片的名字要
                //      用二维数组替换
                //      如:E:\\image\\" + arr[i][j] + ".png
                ImageIcon imageIcon = new ImageIcon("图片的全路径");
                // 创建标签,将图片对象添加进去
                JLabel imageLabel = new JLabel(imageIcon);
                // 设置标签大小
                // 将每个图片的显示位置动态设置,体现出我们设置二维数组的便捷性
                imageLabel.setBounds(50 + j*100, 90 + i*100, 100, 100);
                // 将标签添加进容器
                getContentPane().add(imageLabel);
            }
        }

        // 添加背景图片(为啥要将背景图片放到下面?知道的可以在评论区留言哦)
        ImageIcon imageIcon = new ImageIcon("背景图片全路径");
        JLabel backgroundLabel = new JLabel(imageIcon);
        getContentPane().add(backgroundLabel);

        // 获取当前容器对象,重新编辑组件(这行代码的作用?)
        getContentPane().repaint();
    }

到这完成了游戏界面的加载工作,我们希望创建对象时能自动加载界面,所以需要再空参构造器中进行初始化工作。

// 构造方法完成初始化
    public MyFrame(){
        // 初始化窗口
        showView();
        // 数据初始化
        initData();
        // 初始化图片
        printView();
        // 注册键盘监听器(这里用的this就体现出继承的好处了)
        this.addKeyListener(this);
        // 设置窗口可见
        setVisible(true);
    }

本质上图片是不能发生移动的,我们将图片映射到了二位数组中,就可以通过改变二维数组的下边来模拟移动操作,比如往左移,那么只需要将两个数组的数据互换就行。而每次移动都要去判断是否游戏胜利。

// 完成状态
    public boolean check(){
        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;
    }

通过键盘移动图片,需要对键盘设置监听器,需要实现键盘监听器接口

 // 键盘监听
    @Override
    public void keyReleased(KeyEvent e) {
        move(e.getKeyCode());
        // 刷新页面
        printView();
    }
// 键盘监听
    public void move(int key){
        // 胜利
        if (check()){
            return;
        }
        // 左
        if (key == 37){
            if (column != 3){
                arr[row][column] = arr[row][column + 1];
                arr[row][column + 1] = 0;
                column++;
                count++;
            }
            // 上
        } else if (key == 38) {
            if (row != 3){
                arr[row][column] = arr[row + 1][column];
                arr[row + 1][column] = 0;
                row++;
                count++;
            }
            // 右
        } else if (key == 39) {
            if (column != 0){
                arr[row][column] = arr[row][column - 1];
                arr[row][column - 1] = 0;
                column--;
                count++;
            }
            // 下
        } else if (key == 40) {
            if (row != 0) {
                arr[row][column] = arr[row - 1][column];
                arr[row - 1][column] = 0;
                row--;
                count++;
            }
        } else if (key == 90){
            arr = new int[][]{
                        {0, 1, 2, 3},
                        {4, 5, 6, 7},
                        {8, 9, 10, 11},
                        {12, 13, 14, 15}
            };
        }
    }
    // 下面方法用不到就不管
    @Override
    public void keyTyped(KeyEvent e) {
    }
    @Override
    public void keyPressed(KeyEvent e) {
    }

完整代码

MyFrame类

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 MyFrame extends JFrame implements KeyListener, ActionListener {

    // 二维数组控制图片编号
    int[][] arr = new int[4][4];
    int[][] win = {
            {0,1,2,3},
            {4,5,6,7},
            {8,9,10,11},
            {12,13,14,15}
    };
    // 行
    int row;
    // 列
    int column;
    // 步数
    int count = 0;

    // 构造方法完成初始化
    public MyFrame(){
        // 初始化窗口
        showView();
        // 数据初始化
        initData();
        // 初始化图片
        printView();
        // 初始化菜单
        Menu();
        // 注册键盘监听器
        this.addKeyListener(this);
        // 设置窗口可见
        setVisible(true);
    }

    // 菜单
    public void Menu(){
        // 创建菜单对象
       JMenuBar jMenuBar = new JMenuBar();
        // 创建栏目对象
        JMenu jMenu1 = new JMenu("功能");
        JMenu jMenu2 = new JMenu("关于");
        // 创建条目对象
        JMenuItem jMenuItem = new JMenuItem("Replay");

        // 条目添加进栏目
        jMenu1.add(jMenuItem);
        // 栏目添加进菜单
        jMenuBar.add(jMenu1);
        jMenuBar.add(jMenu2);
        // 菜单添加进窗口
        this.setJMenuBar(jMenuBar);

        // 给条目添加监听
        jMenuItem.addActionListener(this);
    }

    // 二位数组随机化
    public void initData() {
        Random random = new Random();
        int[] arr1 = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
        for (int i = 0; i < arr.length; i++) {
            int index = random.nextInt(arr1.length);
            int temp = arr1[i];
            arr1[i] = arr1[index];
            arr1[index] = temp;
        }
        int index = 0;
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                arr[i][j] = arr1[index];
                if (arr[i][j] == 0){
                    row = i;
                    column = j;
                }
                index++;
            }
        }
    }

    // 窗口设置
    public void showView(){
        // 设置窗口大小
        setSize(514,594);
        // 设置关闭模式
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 设置置顶显示
        setAlwaysOnTop(true);
        // 设置居中显示
        setLocationRelativeTo(null);
        // 设置窗口标题
        setTitle("石头迷阵v1.0单机版");
        // 取消默认布局
        setLayout(null);
    }

    // 界面加载
    public void printView(){
        // 清除界面
        getContentPane().removeAll();
        // 胜利,输出图片
        if (check()){
            JLabel winLabel = new JLabel(new ImageIcon("E:\\黑马程序员\\image\\image\\win.png"));
            winLabel.setBounds(124,230,266,88);
            getContentPane().add(winLabel);
        }
        // 步数加载
        JLabel jLabel = new JLabel("步数:" + count);
        jLabel.setBounds(50,20,100,20);
        getContentPane().add(jLabel);

        // 添加图片
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
            											//这个地址要根据你自己的地址来写
                JLabel image = new JLabel(new ImageIcon("E:\\image\\"+arr[i][j]+".png"));
                image.setBounds(50 + j*100, 90 + i*100, 100 ,100);
                getContentPane().add(image);
            }
        }
        // 背景图片
        JLabel backgroung = new JLabel(new ImageIcon("E:\\image\\background.png"));
        backgroung.setBounds(26,30,450,484);
        getContentPane().add(backgroung);

        // 获取当前容器对象,重新编辑组件
        getContentPane().repaint();
    }

    // 键盘监听
    @Override
    public void keyReleased(KeyEvent e) {
        move(e.getKeyCode());
        // 刷新页面
        printView();
    }

    // 完成状态
    public boolean check(){
        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;
    }
    // 键盘监听
    public void move(int key){
        // 胜利
        if (check()){
            return;
        }
        // 左
        if (key == 37){
            if (column != 3){
                arr[row][column] = arr[row][column + 1];
                arr[row][column + 1] = 0;
                column++;
                count++;
            }
            // 上
        } else if (key == 38) {
            if (row != 3){
                arr[row][column] = arr[row + 1][column];
                arr[row + 1][column] = 0;
                row++;
                count++;
            }
            // 右
        } else if (key == 39) {
            if (column != 0){
                arr[row][column] = arr[row][column - 1];
                arr[row][column - 1] = 0;
                column--;
                count++;
            }
            // 下
        } else if (key == 40) {
            if (row != 0) {
                arr[row][column] = arr[row - 1][column];
                arr[row - 1][column] = 0;
                row--;
                count++;
            }
        } else if (key == 90){
            arr = new int[][]{
                        {0, 1, 2, 3},
                        {4, 5, 6, 7},
                        {8, 9, 10, 11},
                        {12, 13, 14, 15}
            };
        }
    }

    //
    @Override
    public void keyTyped(KeyEvent e) {

    }

    //
    @Override
    public void keyPressed(KeyEvent e) {

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // 初始化数据
        initData();
        // 步数初始化
        count = 0;
        // 初始化图片图片
        printView();
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        new MyFrame();
    }
}

相关图片

可以做任何自己想做的拼图游戏,根据大小自己切割。
上述代码用到的图片:
百度网盘
链接:https://pan.baidu.com/s/1FCoXXOm6spF9qsdfjTWYug
提取码:785g
(上述代码为简易版,供学习参考,如有不足欢迎及时指正)

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值