目录
一、界面搭建
在ui包下创建主界面gameJFrame
在ui包下创建登录界面loginJFrame
在ui包下创建注册界面registerJFrame
包下的APP类游戏启动入口
二、界面设置和菜单设置
将三个页面进行 设置标题、置顶、居中、和关闭的设置
添加菜单
在gameJFrame类中添加菜单
三、给游戏界面添加图片
给游戏界面添加图片
取消默认的居中放置
指定添加全部图片的位置
四、打乱图片
五、美化界面
图片居中
添加背景图片
给每个小图片添加边框
事件 移动图片
事件就是可以被组件识别的操作
六、上下左右移动
给整个游戏界面添加键盘监听事件
七、查看完整图片
八、作弊码
九、判断胜利
十、计步功能
十一、重新游戏、关闭游戏、加入讨论 的菜单实现
重新游戏
重新登录
关闭游戏
加入讨论
其余素材和源码下载链接
完整视频教程
创建一个模块 模块下创建一个ui的包 用于存放三个图形化界面
在模块下创建一个APP的类 用于游戏的启动入口
界面大小要求:
package ui;
import javax.swing.*;
//主界面
public class gameJFrame extends JFrame {
//构造方法
public gameJFrame() {
//设置大小
this.setSize(603, 680); //单位:像素
//界面是默认隐藏的所以要调用setVisible();
this.setVisible(true); //flase为隐藏 true为展示
}
}
package ui;
import javax.swing.*;
//登录界面
public class loginJFrame extends JFrame {
//构造方法
public loginJFrame() {
//设置大小
this.setSize(488, 430);
//显示界面
//界面是默认隐藏的所以要调用setVisible();
this.setVisible(true); //flase为隐藏 true为展示
}
}
package ui;
import javax.swing.*;
//注册界面
public class registerJFrame extends JFrame {
//构造方法
public registerJFrame() {
//设置大小
this.setSize(488, 500);
//显示界面
//界面是默认隐藏的所以要调用setVisible();
this.setVisible(true); //flase为隐藏 true为展示
}
}
import ui.gameJFrame;
import ui.loginJFrame;
import ui.registerJFrame;
//程序的启动入口
public class APP {
public static void main(String[] args) {
//创建主界面
new gameJFrame();
//创建登录界面
new loginJFrame();
//创建注册界面
new registerJFrame();
}
}
这里那么我们第一步就已经完成了 将界面和启动都创建好了
下一步则是将给界面设置和菜单设置
//设置标题
this.setTitle("拼图游戏 v1.0");
//设置页面置顶
this.setAlwaysOnTop(true); //置顶在最上方 会盖住其他的软件
//设置界面居中
this.setLocationRelativeTo(null);
//游戏的关闭
this.setDefaultCloseOperation(3); //setDefaultCloseOperation()中的第三种模式
如图:
//初始化菜单 创建整个菜单对象
JMenuBar JMenuBar0 = new JMenuBar();
//创建菜单中的选项对象
JMenu fJMenu01 = new JMenu("功能");
JMenu fJMenu02 = new JMenu("关于");
//创建选项下的条目对象
JMenuItem JMenuItem01 = new JMenuItem("重新游戏");
JMenuItem JMenuItem02 = new JMenuItem("重新登录");
JMenuItem JMenuItem03 = new JMenuItem("关闭游戏");
JMenuItem JMenuItem04 = new JMenuItem("加入讨论");
//将选项下条目添加到选项当中
fJMenu01.add(JMenuItem01);
fJMenu01.add(JMenuItem02);
fJMenu01.add(JMenuItem03);
fJMenu02.add(JMenuItem04);
//将菜单里的两个选项添加到菜单当中
JMenuBar0.add(fJMenu01);
JMenuBar0.add(fJMenu02);
//给整个界面添加菜单
this.setJMenuBar(JMenuBar0);
运行效果
如图:
图片素材:
java练习拼图游戏的源码及素材-Java文档类资源-CSDN文库
下载后解压将文件夹复制到IDEA的该项目模块中即可
//创建Imagelcon对象
ImageIcon an1_01 = new ImageIcon("C:\\Users\\10076\\IdeaProjects\\untitled\\拼图游戏\\image\\animal\\animal1\\1.jpg");//图片路径
//创建JLabe对象(管理容器)
JLabel jLabel = new JLabel(an1_01);
//将JLabe添加到界面中
this.add(jLabel);
效果:
在gameJFrame类的构造器中写如下方法:
this.setLayout(null);
如图:
因为在该拼图游戏中 图片的宽高为105像素 所以左上角为原点依次计算安排图片位置
调用JLable中的setBounds()方法来调整位置
int number = 1;
//用循环将图片加入主界面
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
//创建JLabe对象(管理容器)
JLabel jLabel = new JLabel(new ImageIcon("C:\\Users\\10076\\IdeaProjects\\untitled\\拼图游戏\\image\\animal\\animal1\\"+number+".jpg"));
//指定位置
jLabel.setBounds(105 * j, 105*i, 105, 105);
//将JLabe添加到界面中
//获取隐藏容器
this.getContentPane().add(jLabel);
number++;
}
因为素材图片每张的名称是从1到15的数字 所以在外定义一个number的变量 循环自增即可将全部图片加入
效果:
每张图片都是用一个数字表示
所以完成打乱图片的思路就是 利用数组存放相应数组 然后在容器中随机打乱顺序
在gameJFrame类中定义一个二维数组
int[][] data = new int[4][4];
打乱图片的初始化方法
//打乱图片
private void Datas(){
//定义一个数组
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 rIndex = r.nextInt(tempArr.length);
//遍历数据交换
int temp = tempArr[i];
tempArr[i] =tempArr[rIndex];
tempArr[rIndex] = temp;
}
//将打乱的数据添加到二维数组
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 InImage(){
//按二维数组中管理图片方式添加数据
//用循环将图片加入主界面
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
//获取要加载图片的序号
int num = data[i][j];
//创建JLabe对象(管理容器)
JLabel jLabel = new JLabel(new ImageIcon("C:\\Users\\10076\\IdeaProjects\\untitled\\拼图游戏\\image\\animal\\animal1\\"+num+".jpg"));
//指定位置
jLabel.setBounds(105 * j, 105*i, 105, 105);
//将JLabe添加到界面中
//获取隐藏容器
this.getContentPane().add(jLabel);
}
}
}
效果:
需求如图:
在指定位置中 计算出合适美观的偏移距离然后加在图片的位置中
//创建JLabe对象(管理容器)
JLabel jLabel = new JLabel(new ImageIcon("C:\\Users\\10076\\IdeaProjects\\untitled\\拼图游戏\\image\\animal\\animal1\\"+num+".jpg"));
//指定位置
jLabel.setBounds(105 * j+83, 105*i+115, 105, 105);
//将JLabe添加到界面中
//获取隐藏容器
this.getContentPane().add(jLabel);
效果:
如图:在素材文件夹中有一个名为background的图片 为背景图片
//添加背景图片
//括号中传递背景图片的路径
//创建一个背景图片的管理容器
JLabel background = new JLabel(new ImageIcon("C:\\Users\\10076\\IdeaProjects\\untitled\\拼图游戏\\image\\background.png"));
//设置位置和宽高
background.setBounds(41,19,508,560);
//把背景图片添加到界面中
this.getContentPane().add(background);
细节:在这里 代码执行先加载的图片在上层 后加载的图片低层 所以要将背景代码写在最后
选用setBorder方法 给图片添加边框 使用BevelBorder对象为斜面边框 0是凹下 1 是突起
//给图片添加边框
jLabel.setBorder(new BevelBorder(1)); //选用setBorder方法 给图片添加边框 使用BevelBorder对象为斜面边框 0是凹下 1 是突起
美化后的效果:
给gameJFram类实现KeyListener接口
public class gameJFrame extends JFrame implements KeyListener
然后重写里面的构造方法
在初始界面方法中给整个界面添加键盘监听事件
//给整个界面添加键盘监听事件
this.addKeyListener(this);
先定义存放坐标的变量
//定义存放坐标的变量
int x = 0;
int y = 0;
再进行判断添加到数组中
//将打乱的数据添加到二维数组
for (int i = 0; i < tempArr.length; i++) {
if (tempArr[i] == 0) {
x = i / 4;
y = i % 4;
}else {
data[i / 4][i % 4] = tempArr[i];
}
}
对上下左右进行判断
@Override
public void keyReleased(KeyEvent keyEvent) {
//对上下左右进行判断
//键盘对应的code码 左:37 上:38 右:39 下:40
int code = keyEvent.getKeyCode();
//对上下左右进行判断
if (code == 37){
System.out.println("向左移动");
}else if (code == 38){
System.out.println("向上移动");
}else if (code == 39){
System.out.println("向右移动");
}else if (code == 40){
System.out.println("向下移动");
}
}
如图:按下对应键盘上的方向键 会有对应提示
向上移动则是将空白方块下的图片向上移动
如图每个图片位置都有二维数组的索引
然后对向下的判断进行修改
@Override
public void keyReleased(KeyEvent keyEvent) {
//对上下左右进行判断
//键盘对应的code码 左:37 上:38 右:39 下:40
int code = keyEvent.getKeyCode();
//对上下左右进行判断
if (code == 37) {
System.out.println("向左移动");
//对边界进行判断
if (y == 3){
return;
}
data[x][y] = data[x][y + 1];
data[x][y + 1] = 0;
y++;
InImage();
} else if (code == 38) {
System.out.println("向上移动");
//对边界进行判断
if (x == 3){
//表示空白方块已经在最下方了 不能移动
return;
}
//逻辑:将空白方块下的数字往上移动
//x,y 就表示空白方块
//x+1,y不变 就表示空白方块下边方块的数字
//把空白方块下的数字赋值给上面的方块 下面的方块要变成0
data[x][y] = data[x + 1][y];
data[x + 1][y] = 0;
x++;
//调用方法 按照最新的数字加载图片
InImage();
} else if (code == 39) {
System.out.println("向右移动");
//对边界进行判断
if (y == 0){
return;
}
data[x][y] = data[x][y - 1];
data[x][y - 1] = 0;
y--;
InImage();
} else if (code == 40) {
System.out.println("向下移动");
//对边界进行判断
if (x == 0){
return;
}
data[x][y] = data[x - 1][y];
data[x - 1][y] = 0;
x--;
InImage();
}
}
再到 InImage()方法中
//清空原本已经出现的所有图片
this.getContentPane().removeAll();
//刷新一下界面
this.getContentPane().repaint();
给整个窗体绑定键盘监听事件
当按下R键时不松 将显示完整图片
//按下松时会调用这个方法
@Override
public void keyPressed(KeyEvent keyEvent) {
int code = keyEvent.getKeyCode();
//R键对应的code码为82
if (code == 82) {
//把界面所有的图片全部删除
this.getContentPane().removeAll();
//加载第一张完整的图片
JLabel all = new JLabel(new ImageIcon("拼图游戏\\image\\animal\\animal1\\all.jpg"));
//设置位置和宽高
all.setBounds(83, 134, 420, 420);
//把图片加载到界面中
this.getContentPane().add(all);
//加载背景图片
//括号中传递背景图片的路径
//创建一个背景图片的管理容器
JLabel background = new JLabel(new ImageIcon("拼图游戏\\image\\background.png"));
//设置位置和宽高
background.setBounds(41, 19, 508, 560);
//把背景图片添加到界面中
this.getContentPane().add(background);
//刷新界面
this.getContentPane().repaint();
}
}
在到 keyReleased方法中接着判断
else if(code == 82){
//重新加载图片
InImage();
重新改进一下路径 避免游戏时切换图片时查看完整图片会出问题
//定义当前展示图片的路径
String path = "拼图游戏\\image\\animal\\animal1\\";
//创建JLabe对象(管理容器)
JLabel jLabel = new JLabel(new ImageIcon( path+num + ".jpg"));
安排一个快捷键 Z 按下即可复原拼图 一键通关
else if (code == 90) { //Z的code码为90
//将二维数组复原
data = new int[][]{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16},
};
//重新加载图片
InImage();
}
效果:
判断二维数组中的数据是否按照正确的顺序排列
//定义一个存放正确顺序的二维数组
int[][] win = new int[][]{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16},
};
//判断data中的数据是否和win数组中相同
public boolean victory() {
for (int i = 0; i < data.length; i++) {
//data[i] 依次表示二维数组中的一维数组、
for (int j = 0; j < data[i].length; j++) {
if (data[i][j] != win[i][j])
return false;
}
}
return true;
}
在InImage()方法中
//调用判断胜利的方法 再对结果进行一个判断
if (victory()) {
//显示胜利的图标
JLabel winJLabel = new JLabel(new ImageIcon("拼图游戏\\image\\win.png"));
//设置位置
winJLabel.setBounds(203,283,197,73);
this.getContentPane().add(winJLabel);
}
在 keyReleased方法中进行判断
//判断游戏是否胜利如果胜利 该方法直接结束(不能再执行下面的移动代码了)
if (victory()){
return;
}
效果:
//定义一个计步变量
int step = 0;
在InImage方法中创建一个 JLabel对象
//为步数显示创建一个对象
JLabel stepCount =new JLabel("步数:"+step);
//设置位置和宽高
stepCount.setBounds(50,30,100,20);
this.getContentPane().add(stepCount);
在 keyReleased方法中 上下左右每个键判断快结束时 让计步器自增一次
//每移动一次 计数器就自增一次
step++;
效果:
给gameJFrame类再实现一个ActionListener接口 并重写里面的方法
public class gameJFrame extends JFrame implements KeyListener, ActionListener {
在初始化菜单Menu方法中 给菜单条目绑定事件
//创建选项下的条目对象
JMenuItem JMenuItem01 = new JMenuItem("重新游戏");
JMenuItem JMenuItem02 = new JMenuItem("重新登录");
JMenuItem JMenuItem03 = new JMenuItem("关闭游戏");
JMenuItem JMenuItem04 = new JMenuItem("加入讨论");
//将选项下条目添加到选项当中
fJMenu01.add(JMenuItem01);
fJMenu01.add(JMenuItem02);
fJMenu01.add(JMenuItem03);
fJMenu02.add(JMenuItem04);
//给条目绑定事件
JMenuItem01.addActionListener(this);
JMenuItem02.addActionListener(this);
JMenuItem03.addActionListener(this);
JMenuItem04.addActionListener(this);
在重写的 actionPerformed方法中做一个点击触发判断
@Override
public void actionPerformed(ActionEvent actionEvent) {
//获取当前被点击的条目对象
Object obj = actionEvent.getSource();
//判断当前点击的是谁
if (obj == JMenuItem01){
System.out.println("重新游戏");
}else if (obj == JMenuItem02){
System.out.println("重新登录");
}else if (obj == JMenuItem03){
System.out.println("关闭游戏");
}else if (obj == JMenuItem04){
System.out.println("加入讨论");
}
}
在重写的 actionPerformed方法中的if判断中实现重新游戏功能
if (obj == JMenuItem01) {
System.out.println("重新游戏");
//逻辑:
//计步器清零
step = 0;
//再次打乱二维数组中的顺序
Datas(); //调用之前写好的打乱方法
//重新加载图片
InImage();
}
else if (obj == JMenuItem02) {
System.out.println("重新登录");
//返回登录界面
//关闭当前游戏界面
this.setVisible(false);
//打开登录界面
new loginJFrame();
}
else if (obj == JMenuItem03) {
System.out.println("关闭游戏");
//直接关闭虚拟机
System.exit(0);
}
点击出现弹窗
新建一个JDalog对象 在到JDalog对象弹窗 添加图片新建一个ImageIcon的对象
else if (obj == JMenuItem04) {
System.out.println("加入讨论");
//创建一个弹框对象
JDialog jdialog =new JDialog();
//创建一个管理图片的容器对象
JLabel jLab = new JLabel(new ImageIcon("拼图游戏\\image\\animal\\animal4\\all.jpg"));
//设置图片在弹框中的位置
jLab.setBounds(0,0,420,420);
//把图片添加到弹框中
jdialog.getContentPane().add(jLab);
//给弹框设置大小
jdialog.setSize(430,430);
//让弹框置顶
jdialog.setAlwaysOnTop(true);
//让弹框居中
jdialog.setLocationRelativeTo(null);
//弹框不关闭则无法操作下面的界面、
jdialog.setModal(true);
//显示弹窗
jdialog.setVisible(true);
}
java练习拼图游戏的源码及素材-Java文档类资源-CSDN文库
拼图游戏项目_哔哩哔哩_bilibili