实验要求:
1、迷宫随机生成
2、玩家走迷宫,留下足迹;
3、系统用A*算法寻路,输出路径
解决问题:
1、如何显示迷宫的图形界面;
2、如何生成随机的迷宫;
3、怎样移动游戏中走迷宫的“玩家”;
4、用A*算法求解迷宫;
生成随机迷宫的方法:
-
深度优先遍历:利用深度遍历的思想。访问到一个节点时,搜索这个节点没有被访问过的相邻节点,选择一个继续做同样的操作,直到没有邻节点为止再回溯到上一个访问的节点,并选择另外的邻节点。这种方案生成的迷宫会有一条明显的主路,这条主路特别长,贯穿大部分区域的路线,同时,迷宫的路线一般比较扭曲。这种采用深度优先算法(递归回溯算法)生成的迷宫称之为“主路扭曲型”迷宫。
-
普利姆算法:把图中预置的通路节点分成两个集合,已经在通路里的属于U,未添加到通路里的属于V-U,通过这样的添加节点策略,把节点间的蓝色0当成最小生成树的边,依次添加到TE里,直到所有节点都添加到U里,这样,在任意两个节点间就形成了一个通路。prim算法形成的主路相对于深度优先算法,比较自然,但迷宫的分岔比较多,所以迷宫会更复杂,玩家需要做的选择次数可能会比较多。
-
这里我选择的是普利姆算法, 根据这个算法的思想,大致的过程是:
-
1.生成一个基础地图。格子先用黄色1和灰色0来表示。
-
2.随机取一个地图边缘的黄色1,把它标记为红色1.即 变成通路。然后把它旁边的灰色0标记成为蓝色0,表示“待定”。
3.随机选择一个蓝色0,然后看红色1隔着这个蓝色0对面的格子,是否是黄色的1,
1)如果是,则把对面的黄色1标记成红色1,即变成通路,然后把蓝色0变成红色的,即也变成通路;
2)如果不是,就把这个蓝色的0变成灰色的;
4.继续为红色通路集合寻找待定的蓝色0,然后随机选择一个蓝色0,然后看红色1隔着这个蓝色0对面的格子,是否是黄色的1,
1)如果是,则把对面的黄色1标记成红色1,即变成通路,然后把蓝色0变成红色的,即也变成通路;
2)如果不是,就把这个蓝色的0变成灰色的;
如果随机选的蓝色的0隔着红色1对面的不是黄色1,说明这不是一条通路,就把这个蓝色的0变成灰色0,变成确定的障碍物;接下来就继续随机找另一个蓝色的0;即不停地重复上面的步骤3,直到整个地图都没有蓝色0了,地图就生成完毕。大致就是这么一个思路。
我们就先把迷宫生成吧。
主方法类:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Maze {
public static JFrame jFrame1 = new JFrame("迷宫");
public static JFrame jFrame2 = new JFrame("迷宫");
public static JFrame jFrame3 = new JFrame("迷宫3");
public static JPanel jPanel1 = new JPanel();
public static void main(String[] args) {
jFrame1.setBounds(450, 100, 1000, 1000);
jFrame1.setResizable(true);
jFrame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame2.setBounds(450, 100, 1000, 900);
jFrame2.setResizable(true);
jFrame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame3.setBounds(200, 200, 1100, 1100);
jFrame3.setResizable(true);
jFrame3.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel jLabel1 = new JLabel("难度选择");
JButton jButton1 = new JButton("简单");
JButton jButton2 = new JButton("中等");
JButton jButton3 = new JButton("困难");
jPanel1.setLayout(null);
jPanel1.add(jLabel1);
jPanel1.add(jButton1);
jPanel1.add(jButton2);
jPanel1.add(jButton3);
jLabel1.setFont(new Font("微软雅黑", Font.BOLD + Font.ITALIC, 40));
jLabel1.setBounds(420, 200, 700, 50);
jButton1.setBounds(450, 400, 100, 50);
jButton2.setBounds(450, 500, 100, 50);
jButton3.setBounds(450, 600, 100, 50);
jFrame1.add(jPanel1);
jButton1.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
jFrame1.dispose();
jFrame2.add(new Build1());
jFrame2.setVisible(true);
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
});
jButton2.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
});
jFrame1.setVisible(true);
}
}
这样就有了一个界面的基本框架。
接着做普利姆算法的第一步,
难度一的地图类:(第一步)
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.*;
import java.util.List;
public class Build1 extends JPanel implements KeyListener, ActionListener {
int[] stardustX = new int[600];
int[] stardustY = new int[500];
int[] mazeX = new int[600];
int[] mazeY = new int[500];
String forward;
//方格的宽度和长度
int BLOCK_WIDTH = 70;
int BLOCK_HEIGHT = 70;
Random random = new Random();
HashMap<String, String> hashMap1 = new HashMap<String, String>();
HashMap<String, String> hashMap2 = new HashMap<String, String>();
List<String> arraylist =new ArrayList<String>();
public Build1() {
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
hashMap1.put(String.valueOf(i) + "," + String.valueOf(j), "灰色0");
}
}
for (int i = 1; i < 11; i = i + 2) {
for (int j = 1; j < 11; j = j + 2) {
hashMap1.replace(String.valueOf(i) + "," + String.valueOf(j), "黄色1");
}
}
int x = 2 * random.nextInt(5) + 1;
int y;
if (x == 1 || x == 9) {
y = 2 * random.nextInt(5) + 1;
} else {
y = random.nextInt(2);
if (y == 0) {
y = 1;
} else {
y = 9;
}
}
hashMap1.replace(String.valueOf(x) + "," + String.valueOf(y), "红色1");
if (x + 1 != 10) {
hashMap1.replace(String.valueOf(x + 1) + "," + String.valueOf(y), "蓝色0");
arraylist.add(String.valueOf(x + 1) + "," + String.valueOf(y));
}
if (x - 1 != 0) {
hashMap1.replace(String.valueOf(x - 1) + "," + String.valueOf(y), "蓝色0");
arraylist.add(String.valueOf(x + 1) + "," + String.valueOf(y));
}
if (y + 1 != 10) {
hashMap1.replace(String.valueOf(x) + "," + String.valueOf(y + 1), "蓝色0");
arraylist.add(String.valueOf(x + 1) + "," + String.valueOf(y));
}
if (y - 1 != 0) {
hashMap1.replace(String.valueOf(x) + "," + String.valueOf(y - 1), "蓝色0");
arraylist.add(String.valueOf(x + 1) + "," + String.valueOf(y));
}
inti();
this.setFocusable(true);
this.addKeyListener(this);
this.setSize(12 * BLOCK_HEIGHT, 12 * BLOCK_WIDTH);//界面的方格的行数和列数
this.setLocation(0, 0);
}
public void inti() {
}
@Override
protected void paintComponent(Graphics Picture) {
super.paintComponent(Picture);
this.setBackground(Color.black);
Picture.setColor(Color.white);
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (hashMap1.get(String.valueOf(i) + "," + String.valueOf(j)).equals("红色1")) {
Picture.setColor(Color.red);
Picture.fillRect(i * 70, j * 70, 70, 70);
}
if (hashMap1.get(String.valueOf(i) + "," + String.valueOf(j)).equals("黄色1")) {
Picture.setColor(Color.yellow);
Picture.fillRect(i * 70, j * 70, 70, 70);
}
if (hashMap1.get(String.valueOf(i) + "," + String.valueOf(j)).equals("灰色0")) {
Picture.setColor(Color.gray);
Picture.fillRect(i * 70, j * 70, 70, 70);
}
if (hashMap1.get(String.valueOf(i) + "," + String.valueOf(j)).equals("蓝色0")) {
Picture.setColor(Color.blue);
Picture.fillRect(i * 70, j * 70, 70, 70);
}
}
}
Picture.setColor(Color.white);
for (int i = 0; i < 12; i++) {
Picture.drawLine(0, i * BLOCK_HEIGHT, 12 * BLOCK_WIDTH, i * BLOCK_HEIGHT);
}
for (int i = 0; i < 12; i++) {
Picture.drawLine(i * BLOCK_WIDTH, 0, i * BLOCK_WIDTH, 12 * BLOCK_HEIGHT);
}
Picture.setColor(Color.black);
Picture.fillRect(771, 0, 900, 900);
Picture.fillRect(0, 771, 900, 900);
}
@Override
public void actionPerformed(ActionEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
}
难度一的地图类:(第二步)由第一步做了一些计算的更新
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.*;
import java.util.List;
public class Build1 extends JPanel implements KeyListener, ActionListener {
int[] stardustX = new int[600];
int[] stardustY = new int[500];
int[] mazeX = new int[600];
int[] mazeY = new int[500];
int fx;
int fy;
String forward;
//方格的宽度和长度
int BLOCK_WIDTH = 70;
int BLOCK_HEIGHT = 70;
Random random = new Random();
HashMap<String, String> hashMap1 = new HashMap<String, String>();
HashMap<String, String> hashMap2 = new HashMap<String, String>();
List<String> arraylist = new ArrayList<String>();
public Build1() {
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
hashMap1.put(String.valueOf(i) + "," + String.valueOf(j), "灰色0");
}
}
for (int i = 1; i < 11; i = i + 2) {
for (int j = 1; j < 11; j = j + 2) {
hashMap1.replace(String.valueOf(i) + "," + String.valueOf(j), "黄色1");
}
}
fx = 2 * random.nextInt(5) + 1;
if (fx == 1 || fx == 9) {
fy = 2 * random.nextInt(5) + 1;
} else {
fy = random.nextInt(2);
if (fy == 0) {
fy = 1;
} else {
fy = 9;
}
}
hashMap1.replace(String.valueOf(fx) + &