【进阶篇-Day4:使用JAVA编写石头迷阵游戏】

news2024/11/26 3:37:07

在这里插入图片描述

目录

  • 1、绘制界面
  • 2、打乱石头方块
  • 3、移动业务
  • 4、游戏判定胜利
  • 5、统计步数
  • 6、重新游戏
  • 7、完整代码:

1、绘制界面

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

上述思路是:使用一个二维数组存放图片的编号,然后在后持遍历即可获取对应的图片。

在这里插入图片描述

在这里插入图片描述

代码如下:

package com.itheima.stonepuzzle;
import javax.swing.*;

public class MainFrame extends JFrame {
    //data使用一个二维数组存放图片的编号,然后在后持遍历即可获取对应的图片。
    int[][] data = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 0}
    };

    /**
     * 因为初始化窗体 和 绘制游戏界面,是在进入游戏就要执行的,
     * 因此只需要在new对象时执行即可,而new对象时构造方法一定会执行,
     * 所以在构造方法里调用即可
     */
    public MainFrame(){
        //初始化窗体
        initFrame();
        //绘制游戏界面
        paintView();
        //设置窗体可见
        setVisible(true);
    }

    /**
     * 此方法用于窗体初始化
     */
    public void initFrame(){
//        JFrame jf = new JFrame(); --因为此类继承了JFrame,因此下面的方法可以直接调用
        //设置窗体大小
        setSize(514, 595);
        //设置窗体关闭模式:关闭窗口时,结束程序
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        //设置窗体标题
        setTitle("石头迷阵单机版V1.0");
        //设置窗体永在最上层
        setAlwaysOnTop(true);
        //设置窗体居中
        setLocationRelativeTo(null);
        //设置取消默认布局
        setLayout(null);
    }

    /**
     * 此方法用于绘制游戏的界面
     */
    public void paintView(){
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                JLabel jl = new JLabel(new ImageIcon("C:\\Users\\MSZ\\Desktop\\java_test\\dev\\image\\" + data[i][j] + ".jpg"));
                //设置图片对象大小
                jl.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);
                //将图片对象塞进窗体
                getContentPane().add(jl);
            }
        }
        
        JLabel background = new JLabel(new ImageIcon("C:\\Users\\MSZ\\Desktop\\java_test\\dev\\image\\background.jpg"));
        //设置图片对象大小
        background.setBounds(26, 30, 450, 484);
        //将图片对象塞进窗体
        super.getContentPane().add(background);
    }
}

运行代码,绘制界面的结果如下:
在这里插入图片描述

2、打乱石头方块

在这里插入图片描述

代码:

/**
 * 初始化数据(随机打乱石头)
 */
public void initData(){
    Random r = new Random();
    //1、遍历二维数组,获取每一个元素
    for (int i = 0; i < data.length; i++) {
        for (int j = 0; j < data[i].length; j++) {
            //2、随机获取 (x坐, y坐标),找到其中一个数
            int x = r.nextInt(4);//x坐标
            int y = r.nextInt(4);//y坐标
            //3、将当前遍历到的元素,和随机获取到的元素做交换
            int temp = data[i][j];
            data[i][j] = data[x][y];
            data[x][y] = temp;
        }
    }
}

3、移动业务

在这里插入图片描述

    /**
     * 按下键盘时出发事件
     * @param e
     */
    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        move(keyCode);
    }

    /**
     * 此方法用于处理移动业务
     * @param keyCode
     */
    private static 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("下移动业务...");
        }
    }

在这里插入图片描述

移动石头块,实际上只需要交换二维数组中的两个数即可,然后再刷新就实现了移动业务。

做法:
在这里插入图片描述
在这里插入图片描述

//寻找0号元素的位置
lo:
for (int i = 0; i < data.length; i++) {
    for (int j = 0; j < data[i].length; j++) {
        if (data[i][j] == 0) {
            row = i;
            col = j;
            break lo;
        }
    }
}

下面看下上、下、左、右移动:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

注意:
在这里插入图片描述
在这里插入图片描述

/**
 * 此方法用于处理移动业务
 *
 * @param keyCode
 */
private void move(int keyCode) {
    int temp = data[row][col];//0号元素
    if (keyCode == 37 && col < 3) {
        System.out.println("左移动业务...");
        //左移动时,空白块和右边的数做交换
        data[row][col] = data[row][col + 1];
        data[row][col + 1] = temp;
        //记录0号元素的列坐标也要随之改变
        col++;
    } else if (keyCode == 38 && row < 3) {
        System.out.println("上移动业务...");
        //上移动时,空白块和下边的数做交换
        data[row][col] = data[row + 1][col];
        data[row + 1][col] = temp;
        //记录0号元素的列坐标也要随之改变
        row++;
    } else if (keyCode == 39 && col > 0) {
        System.out.println("右移动业务...");
        //右移动时,空白块和左边的数做交换
        data[row][col] = data[row][col - 1];
        data[row][col - 1] = temp;
        //记录0号元素的列坐标也要随之改变
        col--;
    } else if (keyCode == 40 && row > 0) {
        System.out.println("下移动业务...");
        //下移动时,空白块和上边的数做交换
        data[row][col] = data[row - 1][col];
        data[row - 1][col] = temp;
        //记录0号元素的列坐标也要随之改变
        row--;
    }else if (keyCode == 90){//z键
        //触发作弊器
        data = new int[][]{
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12},
            {13, 14, 15, 0}
        };
    }
    System.out.println(row + "," + col);
}

4、游戏判定胜利

在这里插入图片描述

/**
 * 判断游戏是否胜利
 * @return
 */
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]){
                return false;
            }
        }
    }
    //运行到这里,表明游戏胜利了
    return true;
    }

在这里插入图片描述

5、统计步数

在这里插入图片描述

6、重新游戏

在这里插入图片描述

7、完整代码:

package com.itheima.stonepuzzle;

public class Test {
    public static void main(String[] args) {
    //启动器
        new MainFrame();
    }
}
package com.itheima.stonepuzzle;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

public class MainFrame extends JFrame implements KeyListener {
    //data使用一个二维数组存放图片的编号,然后在后持遍历即可获取对应的图片。
    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 col; //0号元素的列坐标

    int count = 0;//记录操作的次数

    /**
     * 因为初始化窗体 和 绘制游戏界面,是在进入游戏就要执行的,
     * 因此只需要在new对象时执行即可,而new对象时构造方法一定会执行,
     * 所以在构造方法里调用即可
     */
    public MainFrame() {
        //键盘监听:
        //窗体对象.addKeyListener(KeyListener实现类对象)
        //this:当前对象,两个身份
        //1)窗体对象
        //2)KeyListener实现类对象
        this.addKeyListener(this);

        //初始化窗体
        initFrame();
        //初始化数据(随机打乱石头)
        initData();
        //绘制游戏界面
        paintView();
        //设置窗体可见
        setVisible(true);
    }

    /**
     * 此方法用于窗体初始化
     */
    public void initFrame() {
//        JFrame jf = new JFrame(); --因为此类继承了JFrame,因此下面的方法可以直接调用
        //设置窗体大小
        setSize(514, 595);
        //设置窗体关闭模式:关闭窗口时,结束程序
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        //设置窗体标题
        setTitle("石头迷阵单机版V1.0");
        //设置窗体永在最上层
        setAlwaysOnTop(true);
        //设置窗体居中
        setLocationRelativeTo(null);
        //设置取消默认布局
        setLayout(null);
    }

    /**
     * 初始化数据(随机打乱石头)
     */
    public void initData() {
        Random r = new Random();
        //1、遍历二维数组,获取每一个元素
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                //2、随机获取 (x坐, y坐标),找到其中一个数
                int x = r.nextInt(4);//x坐标
                int y = r.nextInt(4);//y坐标
                //3、将当前遍历到的元素,和随机获取到的元素做交换
                int temp = data[i][j];
                data[i][j] = data[x][y];
                data[x][y] = temp;
            }
        }

        //寻找0号元素的位置
        lo:
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                if (data[i][j] == 0) {
                    row = i;
                    col = j;
                    break lo;
                }
            }
        }
    }

    /**
     * 此方法用于绘制游戏的界面
     */
    public void paintView() {
        //每次绘制之前,都清空之前绘制的界面
        super.getContentPane().removeAll();

        //加载胜利图片资源,添加到窗体中
        if (victory()){
            JLabel victoryJl = new JLabel(new ImageIcon("C:\\Users\\MSZ\\Desktop\\java_test\\dev\\image\\victory.jpg"));
            victoryJl.setBounds(124, 230, 266, 100);
            getContentPane().add(victoryJl);
        }

        //加载重新开始按钮
        if (count > 0){
            JButton jb = new JButton("重新开始");
            jb.setBounds(350, 10, 100, 20);
            jb.setFocusable(false);//取消焦点
            jb.addActionListener(new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    //统计步数归0
                    count = 0;
                    //重新初始化数据
                    initData();
                    //重新绘制游戏界面
                    paintView();
                }
            });
            getContentPane().add(jb);
        }

        //加载记录步数组件
        JLabel stepJl = new JLabel("步数:" + count);
        stepJl.setBounds(50, 10, 100, 20);
        getContentPane().add(stepJl);

        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                JLabel jl = new JLabel(new ImageIcon("C:\\Users\\MSZ\\Desktop\\java_test\\dev\\image\\" + data[i][j] + ".jpg"));
                //设置图片对象大小
                jl.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);
                //将图片对象塞进窗体
                getContentPane().add(jl);
            }
        }

        //加载背景图
        JLabel background = new JLabel(new ImageIcon("C:\\Users\\MSZ\\Desktop\\java_test\\dev\\image\\background.jpg"));
        //设置图片对象大小
        background.setBounds(26, 30, 450, 484);
        //将图片对象塞进窗体
        super.getContentPane().add(background);

        //刷新
        super.getContentPane().repaint();
    }

    /**
     * 按下键盘时出发事件
     *
     * @param e
     */
    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        move(keyCode);
        //判断是否胜利
        victory();
        //每次移动之后,都重新绘制游戏界面
        paintView();
    }

    /**
     * 此方法用于处理移动业务
     *
     * @param keyCode
     */
    private void move(int keyCode) {
        //如果游戏胜利了,则不允许操作
        if (victory()){
            return;
        }

        int temp = data[row][col];//0号元素
        if (keyCode == 37 && col < 3) {
//            System.out.println("左移动业务...");
            //左移动时,空白块和右边的数做交换
            data[row][col] = data[row][col + 1];
            data[row][col + 1] = temp;
            //记录0号元素的列坐标也要随之改变
            col++;
            count++;
        } else if (keyCode == 38 && row < 3) {
//            System.out.println("上移动业务...");
            //上移动时,空白块和下边的数做交换
            data[row][col] = data[row + 1][col];
            data[row + 1][col] = temp;
            //记录0号元素的列坐标也要随之改变
            row++;
            count++;
        } else if (keyCode == 39 && col > 0) {
//            System.out.println("右移动业务...");
            //右移动时,空白块和左边的数做交换
            data[row][col] = data[row][col - 1];
            data[row][col - 1] = temp;
            //记录0号元素的列坐标也要随之改变
            col--;
            count++;
        } else if (keyCode == 40 && row > 0) {
//            System.out.println("下移动业务...");
            //下移动时,空白块和上边的数做交换
            data[row][col] = data[row - 1][col];
            data[row - 1][col] = temp;
            //记录0号元素的列坐标也要随之改变
            row--;
            count++;
        }else if (keyCode == 90){//z键
            //触发作弊器
            data = new int[][]{
                {1, 2, 3, 4},
                {5, 6, 7, 8},
                {9, 10, 11, 12},
                {13, 14, 15, 0}
            };
            count++;
        }
//        System.out.println(row + "," + col);
    }

    /**
     * 判断游戏是否胜利
     * @return
     */
    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]){
                    return false;
                }
            }
        }
        //运行到这里,表明游戏胜利了
        return true;
    }

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

    @Override
    public void keyReleased(KeyEvent e) {
    }
    //-------------------------------------
}

界面图片已放在资源里,可下载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1849233.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

异步FIFO

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 参考代码 描述 请根据题目中给出的双口RAM代码和接口描述&#xff0c;实现异步FIFO&#xff0c;要求FIFO位宽和深度参数化可配置。 电路的接口如下图所示。 双口RAM端口说明&#xff1a; 端口名 I/O 描述 wclk i…

centos中安装并设置vsftpd

vsftpd是一个可安装在linux上的ftp服务器软件。 一、安装 安装前保证服务器能上互联网。如果不能上网&#xff0c;看看能不能设法利用局域网代理上网。 sudo yum -y install vsftpd二、配置 1、修改配置文件 cd /etc/vsftpd #修改之前记得备份&#xff01;&#xff01;&am…

D触发器(D Flip-Flop)与D锁存器(D Latch)

1 基础概念 我们先来简单回顾一下D触发器&#xff08;D flip-flop&#xff09;和D锁存器&#xff08;D latch&#xff09;的概念&#xff0c;以及它们在数字电路中的作用。 1.1 D触发器&#xff08;D Flip-Flop&#xff09; D触发器是一种数字存储器件&#xff0c;它在时钟信号…

深入理解计算机系统 CSAPP 家庭作业6.46

理解题意:G是有向图g的邻接矩阵 G[j*dim i] G[j*dim i] || G[i*dim j]; 通过i和j遍历G中的所有元素,||运算将遍历到的元素对称起来. 下面我们来优化col_convert(int *G, int dim) : void col_convert(int N, int G[N][N], int bsize) {if(bsize < 0 || bsize > N…

Elasticsearch基础(一):阿里云Elasticsearch简介

文章目录 阿里云Elasticsearch简介 一、什么是阿里云Elasticsearch 1、开源Elasticsearch 2、阿里云Elasticsearch 3、阿里云Elasticsearch介绍 4、总结 二、 阿里云Elasticsearch组件 1、X-Pack&#xff08;商业版扩展包&#xff09; 2、 Beats&#xff08;数据采集中…

调试器接口是什么?

目录 一、调试器接口 1.1 什么是下载调试器&#xff1f; 1.2 JTAG标准/协议 1.3 SWD标准 一、调试器接口 1.1 什么是下载调试器&#xff1f; 简单来讲&#xff0c;它就是一种能把PC端发送的命令&#xff08;通过USB协议&#xff09;转换为MCU能理解的语言&#xff08;SWD协…

媒体邀约有啥要注意的

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体宣传加速季&#xff0c;100万补贴享不停&#xff0c;一手媒体资源&#xff0c;全国100城线下落地执行。详情请联系胡老师。 媒体邀约是邀请媒体参与活动或报道的重要过程&#xff0c…

【Proteus仿真】【Arduino单片机】基于物联网新能源电动车检测系统设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用LCD1602液晶显示模块、WIFI模块、蜂鸣器、LED按键、ADC、DS18B20温度传感器等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示温…

外星人Alienware m15R7 原厂Windows11系统

装后恢复到您开箱的体验界面&#xff0c;包括所有原机所有驱动AWCC、Mydell、office、mcafee等所有预装软件。 最适合您电脑的系统&#xff0c;经厂家手调试最佳状态&#xff0c;性能与功耗直接拉满&#xff0c;体验最原汁原味的系统。 原厂系统下载网址&#xff1a;http://w…

JavaFX 下拉框

组合框允许用户选择几个选项之一。用户可以滚动到下拉列表。组合框可以是可编辑和不可编辑的。 创建组合框 以下代码将选项列表包装到ObservableList中&#xff0c;然后使用observable列表实例化ComboBox类。 ObservableList<String> options FXCollections.observab…

区块链媒体发布推广秘籍大揭秘-华媒舍

区块链技术迅猛发展&#xff0c;成为全球瞩目的热门领域。随之而来的是区块链媒体的兴起&#xff0c;成为传播和推广区块链知识、项目和应用的重要平台。本文将揭示区块链媒体发布推广的秘籍&#xff0c;为读者深入了解该领域提供详尽科普介绍。 一、什么是区块链媒体&#xff…

Docker:安装RediSearch全文搜索

1、简述 在本文中&#xff0c;我们将介绍如何使用Docker快速、简便地安装RediSearch&#xff0c;Redis的全文搜索模块。RediSearch提供了高效的全文搜索功能&#xff0c;通过Docker安装&#xff0c;可以轻松地在任何环境中部署和管理RediSearch。 官网地址&#xff1a;https:/…

18.cobra框架了解

目录 概述举例安装实践实践 概述 github cobra cobra 快速的实现一个命令行客户端&#xff0c;命令行解析工具。 cobra 中的主要概念 -Commands 表示执行运作-Args 执行参数-Flags 这些运作的标识符 举例 git clone 命令 git clone https://github.com/spf13/cobra.git -…

白嫖游戏指南,Epic喜加二:《Freshly Frosted》《Rumble Club》

前言 Epic喜加二&#xff1a;《Freshly Frosted》《Rumble Club》《Freshly Frosted》简介&#xff1a; 《Rumble Club》简介&#xff1a; 前言 接下来有时间会分享一些游戏相关可以白嫖的资源&#xff0c;包括游戏本体、游戏素材资源等等。 有需要的小伙伴可以关注这个专栏&…

文件批量改名利器:一键实现文件名中字母统一转为大写,让文件管理更高效有序!

在日常工作和生活中&#xff0c;我们经常会遇到需要批量重命名文件的情况。尤其是当文件名中包含字母时&#xff0c;如果希望将所有字母统一更改为大写&#xff0c;传统的逐个修改方式无疑会耗费大量时间。不过&#xff0c;有了高效的文件批量改名工具&#xff0c;这一难题将迎…

【C++】平衡二叉树(AVL树)的实现

目录 一、AVL树的概念二、AVL树的实现1、AVL树的定义2. 平衡二叉树的插入2.1 按照二叉排序树的方式插入并更新平衡因子2.2 AVL树的旋转2.2.1 新节点插入较高左子树的左侧&#xff08;LL平衡旋转&#xff09;2.2.2 新节点插入较高右子树的右侧&#xff08;RR平衡旋转&#xff09…

【计算机毕业设计】204基于微信小程序疫情期间学生请假与销假系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

windows使用curl命令出现乱码的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

第3章 小功能大用处-发布订阅

Redis提供了基于“发布/订阅”模式的消息机制&#xff0c;此种模式下&#xff0c;消息发布者和订阅者不进行直接通信&#xff0c;发布者客户端向指定的频道&#xff08;channel&#xff09;发布消息&#xff0c;订阅该频道的每个客户端都可以收到该消息。 命令&#xff1a;Red…