准备环节
-
创建一个模块用于开发石头迷阵游戏,模块名称取名为:stone-maze
-
导入项目需要的资源包到src目录下:主要是一些图片文件,在image文件夹下。
-
创建项目包:com.itheima.
1、创建石头迷阵的界面
-
定义主界面类,MainFrame继承JFrame. 自定义窗口。
-
初始化窗口大小
-
初始化界面图片
-
初始化界面菜单:系统退出,重启游戏。
2、打乱顺序
-
打乱界面的图片顺序,让游戏具备可玩性: 使用方法如下
3、控制上下左右移动
-
给窗口绑定上下左右按键事件
-
控制位置的交换。
--- 定位当前空白色块的位置。
--- 根据用户点击的方位确定交换哪个数据,到数组中交换。
-
重新绘制主界面的内容
--- 让主界面按照二维数组的最新内容刷新界面
4、判断是否通关
-
用户每操作一步,需要立即判断是否已经通关,如果通过,需要显示胜利的标记。
5、统计移动步骤、重启游戏
-
每成功移动一步,都需要累加一次步数。
-
定义一个变量用于累加步数,并实时展示到界面上。
6、拓展问题
数字华容道的乱序操作,并不是可以随意打乱的,必须满足一定的算法去打乱顺序,这样才是有解的,才能让玩家恢复到有序。
MainFrame
Direction
App
package com.itheima;
public class App {
public static void main(String[] args) {
MainFrame mainFrame = new MainFrame();//创建窗口
}
}
package com.itheima;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class MainFrame extends JFrame {
//目标:做一个石头迷阵的游戏
//自定义窗口
//设置图片的绝对路径
public static final String PATH = "stone-maze/src/image";
//设置二维数组,记录图片位置
public static final int[][] arr = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
public static int[][] Windata = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
private int row;// 行
private int column;//列
private int count=0;//统计步数
public MainFrame() {
//1初始化窗口大小
initSize();
//5打乱数组顺序
initArray();
//2初始化界面图片
initImage();
//3初始化界面菜单
initMenu();
//6给窗口添加上下左右按键监听
initKeyPress();
//4 ???这句语句写了之后,菜单栏就有了,不知道为什么
this.setVisible(true);//设置界面可见
}
private void initKeyPress() {
//6给窗口添加上下左右按键监听
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
switch (keyCode) {
case KeyEvent.VK_UP:
switchAndMove(Direction.UP);
count++;
break;
case KeyEvent.VK_DOWN:
switchAndMove(Direction.DOWN);
count++;
break;
case KeyEvent.VK_LEFT:
switchAndMove(Direction.LEFT);
count++;
break;
case KeyEvent.VK_RIGHT:
switchAndMove(Direction.RIGHT);
count++;
break;
}
}
});
}
//写一个控制数据交换和图片交换的 方法
private void switchAndMove(Direction direction) {
switch (direction) {
case DOWN:
if (row > 0) {
arr[row][column] = arr[row - 1][column];
arr[row - 1][column] = 0;
row--;
}
break;
case UP:
if (row < 3) {
arr[row][column] = arr[row + 1][column];
arr[row + 1][column] = 0;
row++;
}
break;
case RIGHT:
if (column > 0) {
arr[row][column] = arr[row][column - 1];
arr[row][column - 1] = 0;
column--;
}
break;
case LEFT:
if (column < 3) {
arr[row][column] = arr[row][column + 1];
arr[row][column + 1] = 0;
column++;
}
break;
}
//重新刷新界面
initImage();
}
private void initArray() {
//打乱数组顺序
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
int random = (int) (Math.random() * 4);
int temp = arr[i][j];
arr[i][j] = arr[i][random];
arr[i][random] = temp;
}
}
//定位0的位置
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if (arr[i][j] == 0) {
row = i;
column = j;
}
}
}
}
private void initMenu() {
//目标:在界面最上方添加菜单,退出系统和重玩游戏
JMenuBar menuBar = new JMenuBar();//创建菜单栏
JMenu menu = new JMenu("菜单");//创建菜单
JMenuItem exit = new JMenuItem("退出");
JMenuItem restart = new JMenuItem("重新开始");
exit.addActionListener(e -> {
System.exit(0);
});
restart.addActionListener(e -> {
initArray();
initImage();
count=0;
this.setVisible(true);
});
menu.add(exit);
menu.add(restart);
menuBar.add(menu);//
this.setJMenuBar(menuBar);//添加菜单栏
}
private void initImage() {
//先删除所有图片
this.getContentPane().removeAll();
//只要刷新界面就判断用户是否完成游戏
if (isWin()) {
//拿文件夹下的图片
JLabel win = new JLabel(new ImageIcon(PATH + "/win.png"));
win.setBounds(124, 230, 266, 88);
this.add(win);
}
this.setIconImage(Toolkit.getDefaultToolkit().getImage(PATH + "/logo.png"));//设置窗口图标
JLabel background = new JLabel(new ImageIcon(PATH + "/background.png"));//创建背景图片
this.add(background);//添加背景图片
background.setBounds(0, 0, 450, 484);//设置背景图片大小
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
int number = arr[i][j];
if (number != 0) {
JLabel label = new JLabel(new ImageIcon(PATH + "/" + number + ".png"));
background.add(label);
label.setBounds(20 + j * 100, 60 + i * 100, 100, 100);
}
}
}
// 刷新新图层,重新绘制
this.repaint();
}
//与Windata数组对比
private boolean isWin() {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if (arr[i][j] != Windata[i][j]) {
return false;
}
}
}
return true;
}
private void initSize() {
this.setSize(465, 580);
this.setVisible(true);//`
this.setLocationRelativeTo(null);//`
this.setTitle("石头迷阵 Tony");
this.setResizable(false);//窗口大小不可变
}
}
package com.itheima;
public enum Direction {
UP, DOWN, LEFT, RIGHT;
}

357

被折叠的 条评论
为什么被折叠?



