实验三 基于A*算法的迷宫游戏开发

实验要求:

1、迷宫随机生成

2、玩家走迷宫,留下足迹;

3、系统用A*算法寻路,输出路径

解决问题:

1、如何显示迷宫的图形界面;

2、如何生成随机的迷宫;
3、怎样移动游戏中走迷宫的“玩家”;

4、用A*算法求解迷宫;

生成随机迷宫的方法:

  1. 深度优先遍历:利用深度遍历的思想。访问到一个节点时,搜索这个节点没有被访问过的相邻节点,选择一个继续做同样的操作,直到没有邻节点为止再回溯到上一个访问的节点,并选择另外的邻节点。这种方案生成的迷宫会有一条明显的主路,这条主路特别长,贯穿大部分区域的路线,同时,迷宫的路线一般比较扭曲。这种采用深度优先算法(递归回溯算法)生成的迷宫称之为“主路扭曲型”迷宫。

  2. 普利姆算法:把图中预置的通路节点分成两个集合,已经在通路里的属于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) + &
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
假设迷宫图是一个二维数组maze,其中0表示通路,1表示障碍物,起点的坐标是(start_x, start_y),终点的坐标是(end_x, end_y),则可以使用深度优先搜索(DFS)和栈来寻找路径。 具体实现步骤如下: 1. 定义一个栈stack,将起点坐标(start_x, start_y)压入栈中。 2. 定义一个二维数组visited,用于记录每个位置是否已经被访问过,初始值为False。 3. 当栈不为空时,取出栈顶元素(x, y),判断是否为终点,如果是,则返回路径;如果不是,则继续执行下面的步骤。 4. 标记当前位置为已访问,即visited[x][y]=True。 5. 判断当前位置的四个方向是否为通路,如果是,则将该方向的坐标压入栈中。 6. 重复步骤3-5,直到找到终点或栈为空。 7. 如果栈为空仍未找到终点,则返回空列表表示路径不存在。 下面是具体的代码实现: ```python def findPath(maze, start_x, start_y, end_x, end_y): stack = [(start_x, start_y)] # 初始化栈,将起点压入栈中 visited = [[False]*len(maze[0]) for _ in range(len(maze))] # 初始化visited数组 visited[start_x][start_y] = True # 标记起点为已访问 while stack: x, y = stack.pop() # 取出栈顶元素 if x == end_x and y == end_y: # 判断是否为终点 return getPath(start_x, start_y, end_x, end_y, visited) # 返回路径 for dx, dy in [(0, 1), (1, 0), (0, -1), (-1, 0)]: # 遍历四个方向 nx, ny = x+dx, y+dy if 0 <= nx < len(maze) and 0 <= ny < len(maze[0]) and maze[nx][ny] == 0 and not visited[nx][ny]: stack.append((nx, ny)) # 将该方向的坐标压入栈中 visited[nx][ny] = True # 标记该位置为已访问 return [] # 栈为空,表示路径不存在 def getPath(start_x, start_y, end_x, end_y, visited): path = [(end_x, end_y)] while path[-1] != (start_x, start_y): x, y = path[-1] for dx, dy in [(0, 1), (1, 0), (0, -1), (-1, 0)]: nx, ny = x+dx, y+dy if 0 <= nx < len(visited) and 0 <= ny < len(visited[0]) and visited[nx][ny]: path.append((nx, ny)) break return list(reversed(path)) # 返回路径 ``` 使用示例: ```python maze = [[0, 1, 0, 0, 0], [0, 1, 0, 1, 0], [0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 1, 0]] start_x, start_y = 0, 0 end_x, end_y = 4, 4 path = findPath(maze, start_x, start_y, end_x, end_y) print(path) # 输出[(0, 0), (1, 0), (2, 0), (2, 1), (2, 2), (2, 3), (3, 3), (4, 3), (4, 4)] ``` 上述代码中,getPath函数用于从visited数组中获取路径,具体实现是从终点开始,依次向四周扩展,找到第一个已访问的位置,将其加入路径中,并继续向该位置扩展,直到起点为止。最后需要将路径反转,因为是从终点往起点扩展的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值