此小游戏可通过按钮来实现上下左右的拼图,还可以通过求助和重置按钮来复原和重新开始游戏。
在项目开始之前,希望大家多多支持,点个赞。谢谢!
思路分析:
- – 绘制游戏界面
- – 实现图片打乱
- – 给按钮添加事件
- – 移动空白图片按钮的实现
- – 求助按钮的实现
- – 重置按钮的实现
1、用 GUI 绘制游戏界面
思路分析:
- – 新建一个类:PictureFrame,让这个类继承自JFrame。
- – 在PictureFrame类中编写无参 构造方法 ,在构造方法中调用两个方法;initFrame()方法,用于窗口的基本设置。setVisible(true)方法,用于设置窗口可见。
- – 在initFrame()方法中设置窗口可见:
- 1、窗口大小
- 2、窗口标题
- 3、窗口居中
- 4、窗口关闭是退出程序
- 5、窗口位于其他窗口之上
- 6、取消窗口默认布局
- – 定义方法用于窗口上组件的绘制:paintView();并在构造方法中调用。
- – 把所有的按钮和面板定义为成员变量,写进PictureFrame类中。
- – 定义测试类App;创建PictureFrame的对象进行测试。
public class PictureFrame extends JFrame {
//定义按钮的成员变量
private JButton shangButton;
private JButton zuoButton;
private JButton xiaButton;
private JButton youButton;
private JButton qiuZhuButton;
private JButton chongZhiButton;
//设置一个面板的成员变量
private JPanel imagePanel;
public PictureFrame() {
//用于 窗体 的基本设置
initFrame();
//窗口上组件的绘制
paintview();
//设置窗体可见
this.setVisible(true);
}
public void initFrame() {
//设置窗口大小
this.setSize(, 565);
//设置窗口关闭时默认操作(整数表示:窗口关闭时退出应用程序)
this.setDefaultCloseOperation();
//设置位置,值为null,则窗口位置屏幕中央
this.setLocationRelativeTo(null);
//设置此窗口是否始终位于其他窗口之上
this.setAlwaysOnTop(true);
//设置窗口标题
this.setTitle("动漫拼图");
//取消JFrame的默认布局
this.setLayout(null);
}
//窗体上组件的绘制
public void paintview() {
//标题图片
JLabel titleLabel = new JLabel(new ImageIcon("day\images\title.png"));
titleLabel.setBounds(, 27, 232, 57);
this.add(titleLabel);
//创建面板
imagePanel = new JPanel();
imagePanel.setBounds(, 114, 360, 360);
imagePanel.setLayout(null);
//遍历 二维数组 ,得到图片编号
for (int i =; i < datas.length; i++) {
for (int j =; j < datas[i].length; j++) {
//创建JLabel对象,加载图片资源
JLabel imagesJlabel = new JLabel(new ImageIcon("day\\images\\" + datas[i][j] + ".png"));
//调整照片位置
imagesJlabel.setBounds(j *, i * 90, 90, 90);
imagePanel.add(imagesJlabel);
}
}
//把面板添加到窗体上
this.add(imagePanel);
//拼图参照图
JLabel canZhaoTuLabel = new JLabel(new ImageIcon("day\images\canzhaotu.png"));
canZhaoTuLabel.setBounds(, 114, 122, 121);
this.add(canZhaoTuLabel);
//上下左右、求助、重置按钮
shangButton = new JButton(new ImageIcon("day\images\shang.png"));
shangButton.setBounds(, 265, 57, 57);
this.add(shangButton);
zuoButton = new JButton(new ImageIcon("day\images\zuo.png"));
zuoButton.setBounds(, 347, 57, 57);
this.add(zuoButton);
xiaButton = new JButton(new ImageIcon("day\images\xia.png"));
xiaButton.setBounds(, 347, 57, 57);
this.add(xiaButton);
youButton = new JButton(new ImageIcon("day\images\you.png"));
youButton.setBounds(, 347, 57, 57);
this.add(youButton);
qiuZhuButton = new JButton(new ImageIcon("day\images\qiuzhu.png"));
qiuZhuButton.setBounds(, 444, 108, 45);
this.add(qiuZhuButton);
chongZhiButton = new JButton(new ImageIcon("day\images\chongzhi.png"));
chongZhiButton.setBounds(, 444, 108, 45);
this.add(chongZhiButton);
//展示背景图
JLabel backgroundLabel = new JLabel(new ImageIcon("day\images\background.png"));
backgroundLabel.setBounds(, 0, 960, 530);
this.add(backgroundLabel);
}
}
测试类:
public class App {
public static void main(String[] args) {
PictureFrame pictureFrame = new PictureFrame();
}
}
2、图片打乱并给按钮添加事件(用按钮移动空白图片)
思路分析
- – 定义方法,用于打乱二维数组:initData()
- – 创建Random对象,遍历存储的二维数字,得到每一个元素
- – 产生两个随机索引,进行二维数组元素交换
- – 定义之前现在类中定义一个二维数组
- – 在构造方法中调用initData()方法
- – 数组中的0是用来记录0号索引空白图片
- – 给按钮添加事件,用来实现移动空白图片的位置,
- 1、移动空白图片的位置就是和上下左右的图片进行交互,
- 2、交换完成之后调用重回方法:rePainView(),
- 3、处理边界问题。
- – 在测试类App中测试
“` java
public class PictureFrame extends JFrame {
//定义一个二维数组,用来储存图片的编号
private int[][] datas = {
{, 2, 3, 4},
{, 6, 7, 8,},
{, 10, 11, 12},
{, 14, 15, 0}
};
//定义按钮的成员变量
private JButton shangButton;
private JButton zuoButton;
private JButton xiaButton;
private JButton youButton;
private JButton qiuZhuButton;
private JButton chongZhiButton;
//设置一个面板的成员变量
private JPanel imagePanel;
public PictureFrame() {
//用于窗体的基本设置
initFrame();
//窗口上组件的绘制
paintview();
//设置窗体可见
this.setVisible(true);
}
public void initFrame() {
//设置窗口大小
this.setSize(, 565);
//设置窗体关闭时默认操作(整数表示:窗口关闭时退出应用程序)
this.setDefaultCloseOperation();
//设置位置,值为null,则窗口位置屏幕中央
this.setLocationRelativeTo(null);
//设置此窗口是否始终位于其他窗口之上
this.setAlwaysOnTop(true);
//设置窗口标题
this.setTitle("动漫拼图");
//取消JFrame的默认布局
this.setLayout(null);
}
//窗体上组件的绘制
public void paintview() {
//标题图片
JLabel titleLabel = new JLabel(new ImageIcon("day\images\title.png"));
titleLabel.setBounds(, 27, 232, 57);
this.add(titleLabel);
//创建面板
imagePanel = new JPanel();
imagePanel.setBounds(, 114, 360, 360);
imagePanel.setLayout(null);
//遍历二维数组,得到图片编号
for (int i =; i < datas.length; i++) {
for (int j =; j < datas[i].length; j++) {
//创建JLabel对象,加载图片资源
JLabel imagesJlabel = new JLabel(new ImageIcon("day\\images\\" + datas[i][j] + ".png"));
//调整照片位置
imagesJlabel.setBounds(j *, i * 90, 90, 90);
imagePanel.add(imagesJlabel);
}
}
//把面板添加到窗体上
this.add(imagePanel);
//拼图参照图
JLabel canZhaoTuLabel = new JLabel(new ImageIcon("day\images\canzhaotu.png"));
canZhaoTuLabel.setBounds(, 114, 122, 121);
this.add(canZhaoTuLabel);
//上下左右、求助、重置按钮
shangButton = new JButton(new ImageIcon("day\images\shang.png"));
shangButton.setBounds(, 265, 57, 57);
this.add(shangButton);
zuoButton = new JButton(new ImageIcon("day\images\zuo.png"));
zuoButton.setBounds(, 347, 57, 57);
this.add(zuoButton);
xiaButton = new JButton(new ImageIcon("day\images\xia.png"));
xiaButton.setBounds(, 347, 57, 57);
this.add(xiaButton);
youButton = new JButton(new ImageIcon("day\images\you.png"));
youButton.setBounds(, 347, 57, 57);
this.add(youButton);
qiuZhuButton = new JButton(new ImageIcon("day\images\qiuzhu.png"));
qiuZhuButton.setBounds(, 444, 108, 45);
this.add(qiuZhuButton);
chongZhiButton = new JButton(new ImageIcon("day\images\chongzhi.png"));
chongZhiButton.setBounds(, 444, 108, 45);
this.add(chongZhiButton);
//展示背景图
JLabel backgroundLabel = new JLabel(new ImageIcon("day\images\background.png"));
backgroundLabel.setBounds(, 0, 960, 530);
this.add(backgroundLabel);
//按钮添加事件
shangButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (x == 3) {
return;
}
datas[x][y0] = datas[x0 + 1][y0];
//这一步作用是啥,为什么要让datas[x+1][y0]=0;
//原理是交换,datas[x][y0]=0是固定的,然后把datas[x0+1][y0]赋值给datas[x0][y0]
//再把给datas[x0+1][y0],
datas[x + 1][y0] = 0;
x = x0 + 1;
//对图片进行重新遍历输出
rePaintView();
}
});
zuoButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (y == 3) {
return;
}
datas[x][y0] = datas[x0][y0 + 1];
datas[x][y0 + 1] = 0;
y = y0 + 1;
//对图片进行重新遍历输出
rePaintView();
}
});
xiaButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (x == 0) {
return;
}
datas[x][y0] = datas[x0 - 1][y0];
datas[x - 1][y0] = 0;
x = x0 - 1;
//对图片进行重新遍历输出
rePaintView();
}
});
youButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (y == 0) {
return;
}
datas[x][y0] = datas[x0][y0 - 1];
datas[x][y0 - 1] = 0;
y = y0 - 1;
//对图片进行重新遍历输出
rePaintView();
}
});
}
//定义两个int类型的变量,用于记录号图片的位置
//号图片作用是啥,为什么要定义0号图片
//号图片作用是和数组里面的编号图片作一交换,用来完成拼图
private int x;
private int y;
//打乱二维数组
public void randomData() {
Random random = new Random();
for (int i =; i < datas.length; i++) {
for (int j =; j < datas[i].length; j++) {
int x = random.nextInt(datas.length);
int y = random.nextInt(datas[i].length);
int temp = datas[i][j];
datas[i][j] = datas[x][y];
datas[x][y] = temp;
}
}
//记录号图片的位置 wc作用是啥?wc作用是给最外层for循环起了一个名字,之后用 break 结束整体循环
wc:
for (int i =; i < datas.length; i++) {
for (int j =; j < datas[i].length; j++) {
if (datas[i][j] ==) {
x = i;
y = j;
break wc;
}
}
}
}
//遍历移动后的图形,移动的图形重新绘制
public void rePaintView() {
//移除所有:移除的是JPanel标签上的全部组件,目的就是清空里面的数据
imagePanel.removeAll();
//遍历二维数组
for (int i =; i < datas.length; i++) {
for (int j =; j < datas[i].length; j++) {
//创建JLabel对象,加载图片资源
JLabel imagesJlabel = new JLabel(new ImageIcon("day09\\images\\" + datas[i][j] + ".png"));
//调整照片位置
imagesJlabel.setBounds(j * 90, i * 90, 90, 90);
imagePanel.add(imagesJlabel);
}
}
//对JPanel里面的组件进行从新打印
imagePanel.repaint();
}
}
3、求助按钮和重置按钮、游戏成功后的实现
思路分析
- – 定义移动成功分方法:success();
- 1、在方法中实现成功之后按钮不可用,
- – 在求助按钮中调用两个方式实现操作
- 1、调用success();
- 2、调用rePaintView();
- – 当重置之后需要修个数组,使数组变为之前带有0号图片的数组
- – 打乱数组
- – 重绘面板
- – 设置按钮可用
- – 万一有人成功通过游戏怎么办
- 先在PictureFrame类中定义新的成功的二维数组
- 1、定义一个方法,用于比较两个数组(`新的数组和老的数组`)元素是否相同
- 2、每次移动一个按钮调用这个方法,如果返回为true,则调用success()方法;
- – 去测试类中测试代码的可行性就完成了
public class PictureFrame extends JFrame {
//定义一个二维数组,用来储存图片的编号
private int[][] datas = {
{, 2, 3, 4},
{, 6, 7, 8,},
{, 10, 11, 12},
{, 14, 15, 0}
};
//定义一个成功的二维数组
private int[][] winDatas = {
{, 2, 3, 4},
{, 6, 7, 8},
{, 10, 11, 12},
{, 14, 15, 0}
};
//定义按钮的成员变量
private JButton shangButton;
private JButton zuoButton;
private JButton xiaButton;
private JButton youButton;
private JButton qiuZhuButton;
private JButton chongZhiButton;
//设置一个面板的成员变量
private JPanel imagePanel;
public PictureFrame() {
//用于窗体的基本设置
initFrame();
//窗口上组件的绘制
paintview();
//设置窗体可见
this.setVisible(true);
}
public void initFrame() {
//设置窗口大小
this.setSize(, 565);
//设置窗体关闭时默认操作(整数表示:窗口关闭时退出应用程序)
this.setDefaultCloseOperation();
//设置位置,值为null,则窗口位置屏幕中央
this.setLocationRelativeTo(null);
//设置此窗口是否始终位于其他窗口之上
this.setAlwaysOnTop(true);
//设置窗口标题
this.setTitle("动漫拼图");
//取消JFrame的默认布局
this.setLayout(null);
}
//窗体上组件的绘制
public void paintview() {
//标题图片
JLabel titleLabel = new JLabel(new ImageIcon("day\images\title.png"));
titleLabel.setBounds(, 27, 232, 57);
this.add(titleLabel);
//创建面板
imagePanel = new JPanel();
imagePanel.setBounds(, 114, 360, 360);
imagePanel.setLayout(null);
//遍历二维数组,得到图片编号
for (int i =; i < datas.length; i++) {
for (int j =; j < datas[i].length; j++) {
//创建JLabel对象,加载图片资源
JLabel imagesJlabel = new JLabel(new ImageIcon("day\\images\\" + datas[i][j] + ".png"));
//调整照片位置
imagesJlabel.setBounds(j *, i * 90, 90, 90);
imagePanel.add(imagesJlabel);
}
}
//把面板添加到窗体上
this.add(imagePanel);
//拼图参照图
JLabel canZhaoTuLabel = new JLabel(new ImageIcon("day\images\canzhaotu.png"));
canZhaoTuLabel.setBounds(, 114, 122, 121);
this.add(canZhaoTuLabel);
//上下左右、求助、重置按钮
shangButton = new JButton(new ImageIcon("day\images\shang.png"));
shangButton.setBounds(, 265, 57, 57);
this.add(shangButton);
zuoButton = new JButton(new ImageIcon("day\images\zuo.png"));
zuoButton.setBounds(, 347, 57, 57);
this.add(zuoButton);
xiaButton = new JButton(new ImageIcon("day\images\xia.png"));
xiaButton.setBounds(, 347, 57, 57);
this.add(xiaButton);
youButton = new JButton(new ImageIcon("day\images\you.png"));
youButton.setBounds(, 347, 57, 57);
this.add(youButton);
qiuZhuButton = new JButton(new ImageIcon("day\images\qiuzhu.png"));
qiuZhuButton.setBounds(, 444, 108, 45);
this.add(qiuZhuButton);
chongZhiButton = new JButton(new ImageIcon("day\images\chongzhi.png"));
chongZhiButton.setBounds(, 444, 108, 45);
this.add(chongZhiButton);
//展示背景图
JLabel backgroundLabel = new JLabel(new ImageIcon("day\images\background.png"));
backgroundLabel.setBounds(, 0, 960, 530);
this.add(backgroundLabel);
//按钮添加事件
shangButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (x == 3) {
return;
}
datas[x][y0] = datas[x0 + 1][y0];
//这一步作用是啥,为什么要让datas[x+1][y0]=0;
//原理是交换,datas[x][y0]=0是固定的,然后把datas[x0+1][y0]赋值给datas[x0][y0]
//再把给datas[x0+1][y0],
datas[x + 1][y0] = 0;
x = x0 + 1;
//调用判断方法,成功之后调用提示按钮的方法
if (isSuccess()) {
success();
}
//对图片进行重新遍历输出
rePaintView();
}
});
zuoButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (y == 3) {
return;
}
datas[x][y0] = datas[x0][y0 + 1];
datas[x][y0 + 1] = 0;
y = y0 + 1;
//调用判断方法,成功之后调用提示按钮的方法
if (isSuccess()) {
success();
}
//对图片进行重新遍历输出
rePaintView();
}
});
xiaButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (x == 0) {
return;
}
datas[x][y0] = datas[x0 - 1][y0];
datas[x - 1][y0] = 0;
x = x0 - 1;
//调用判断方法,成功之后调用提示按钮的方法
if (isSuccess()) {
success();
}
//对图片进行重新遍历输出
rePaintView();
}
});
youButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (y == 0) {
return;
}
datas[x][y0] = datas[x0][y0 - 1];
datas[x][y0 - 1] = 0;
y = y0 - 1;
//调用判断方法,成功之后调用提示按钮的方法
if (isSuccess()) {
success();
}
//对图片进行重新遍历输出
rePaintView();
}
});
}
//定义两个int类型的变量,用于记录号图片的位置
//号图片作用是啥,为什么要定义0号图片
//号图片作用是和数组里面的编号图片作一交换,用来完成拼图
private int x;
private int y;
//打乱二维数组
public void randomData() {
Random random = new Random();
for (int i =; i < datas.length; i++) {
for (int j =; j < datas[i].length; j++) {
int x = random.nextInt(datas.length);
int y = random.nextInt(datas[i].length);
int temp = datas[i][j];
datas[i][j] = datas[x][y];
datas[x][y] = temp;
}
}
//记录号图片的位置 wc作用是啥?wc作用是给最外层for循环起了一个名字,之后用break结束整体循环
wc:
for (int i =; i < datas.length; i++) {
for (int j =; j < datas[i].length; j++) {
if (datas[i][j] ==) {
x = i;
y = j;
break wc;
}
}
}
}
//遍历移动后的图形,移动的图形重新绘制
public void rePaintView() {
//移除所有:移除的是JPanel标签上的全部组件,目的就是清空里面的数据
imagePanel.removeAll();
//遍历二维数组
for (int i =; i < datas.length; i++) {
for (int j =; j < datas[i].length; j++) {
//创建JLabel对象,加载图片资源
JLabel imagesJlabel = new JLabel(new ImageIcon("day09\\images\\" + datas[i][j] + ".png"));
//调整照片位置
imagesJlabel.setBounds(j * 90, i * 90, 90, 90);
imagePanel.add(imagesJlabel);
}
}
//对JPanel里面的组件进行从新打印
imagePanel.repaint();
}
//定义一个成功的操作,用提示来调用
public void success() {
datas = new int[][]{
{, 2, 3, 4},
{, 6, 7, 8},
{, 10, 11, 12},
{, 14, 15, 16}
};
shangButton.setEnabled(false);
zuoButton.setEnabled(false);
xiaButton.setEnabled(false);
youButton.setEnabled(false);
}
//定义一个点击按钮判断是否成功的方法
public boolean isSuccess() {
for (int i =; i < datas.length; i++) {
for (int j =; j < datas[i].length; j++) {
if (datas[i][j] != winDatas[i][j]) {
return false;
}
}
}
return true;
}
}