将随机迷宫生成功能加入我的游戏(Java)

5

我目前正在使用Java制作迷宫解谜游戏,但遇到了一些问题。我找到的所有随机生成迷宫算法输出的方式都无法实现到我的当前代码中。我考虑使用深度优先搜索递归回溯普里姆算法,因为我认为它们最容易实现,同时仍然能够生成良好的迷宫。哪种算法可以与我的当前程序配合使用?这是我的游戏类:(如有不良做法,请指出,我对Java还比较陌生)

package game;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Game extends JPanel implements ActionListener, KeyListener {

    private boolean upPressed    = false;
    private boolean downPressed  = false;
    private boolean rightPressed = false;
    private boolean leftPressed  = false;

    private final int playerDiam = 100;
    private final int playerSpeed = 15;
    private final int tileSize = 400;

    private int[][] maze = {{1, 1, 1, 1, 1, 1},
                            {1, 2, 1, 1, 3, 1},
                            {1, 0, 1, 0, 0, 1},
                            {1, 0, 1, 0, 1, 1},
                            {1, 0, 0, 0, 1, 1},
                            {1, 1, 1, 1, 1, 1},
                           };
    private int[][] initX = new int[maze.length][maze.length];
    private int[][] initY = new int[maze.length][maze.length];

    private int deltaX = -210;
    private int deltaY = -210;

    private String screen = "menu";


    public Game() {
        setFocusable(true);
        addKeyListener(this);
        setUpInitialCoordinates();
        Timer timer = new Timer(1000 / 60, this);
        timer.start();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        tick();
    }

    private void setUpInitialCoordinates() {
        int x = 0;
        int y;
        for (int[] rowData : maze) {
            y = 0;
            for (int ignored : rowData) {
                initX[x][y] = x * tileSize;
                initY[x][y] = y * tileSize;
                y++;
            }
            x++;
        }
    }

    private void generateMaze() {
    }

    private void tick() {
        if (screen.equals("playing")) {
            if (upPressed) {
                deltaY += playerSpeed;
            } else if (downPressed) {
                deltaY -= playerSpeed;
            }
            if (rightPressed) {
                deltaX -= playerSpeed;
            } else if (leftPressed) {
                deltaX += playerSpeed;
            }
        }
        repaint();
    }

    @Override
    public void keyTyped(KeyEvent e) {}

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() ==   KeyEvent.VK_W) {
            upPressed = true;
        } else if (e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_S) {
            downPressed = true;
        } else if (e.getKeyCode() == KeyEvent.VK_RIGHT || e.getKeyCode() == KeyEvent.VK_D) {
            rightPressed = true;
        } else if (e.getKeyCode() == KeyEvent.VK_LEFT || e.getKeyCode() == KeyEvent.VK_A) {
            leftPressed = true;
        }
    }


    @Override
    public void keyReleased(KeyEvent e) {
        if (screen.equals("menu") && e.getKeyCode() == KeyEvent.VK_ENTER) {
            upPressed = false;
            downPressed = false;
            rightPressed = false;
            leftPressed = false;
            screen = "playing";
        } else if (screen.equals("playing")) {
            if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() ==    KeyEvent.VK_W) {
                upPressed = false;
            } else if (e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode()   == KeyEvent.VK_S) {
                downPressed = false;
            } else if (e.getKeyCode() == KeyEvent.VK_RIGHT || e.getKeyCode() == KeyEvent.VK_D) {
                rightPressed = false;
            } else if (e.getKeyCode() == KeyEvent.VK_LEFT || e.getKeyCode() == KeyEvent.VK_A) {
                leftPressed = false;
            } else if (e.getKeyCode() == KeyEvent.VK_P) {
                screen = "paused";
            }
        } else if (screen.equals("paused" ) && e.getKeyCode() ==     KeyEvent.VK_P) {
            upPressed = false;
            downPressed = false;
            rightPressed = false;
            leftPressed = false;
            screen = "playing";
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setFont(new Font("Aharoni", Font.PLAIN, 36));
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, getWidth(), getHeight());
        switch (screen) {
            case "menu":
                g.setColor(Color.BLACK);
                g.drawString("Labyrinth", 300, 200);
                g.drawString("Press Enter to Play!", getWidth() / 3, 500);
                break;
            case "playing":
                int x = 0;
                int y = 0;

                for (int[] rowData : maze) {
                    for (int cellData : rowData) {
                        if (cellData == 1) {
                            g.setColor(Color.DARK_GRAY);
                            g.fillRect(x + deltaX, y + deltaY, tileSize, tileSize);
                        } else if (cellData == 2) {
                            g.setColor(Color.GREEN);
                            g.fillRect(x + deltaX, y + deltaY, tileSize, tileSize);
                        } else if (cellData == 3) {
                            g.setColor(Color.YELLOW);
                            g.fillRect(x + deltaX, y + deltaY, tileSize,   tileSize);
                        }
                        x += tileSize;
                        if (x == maze.length * tileSize) {
                            x = 0;
                            y += tileSize;
                        }
                    }
                }   g.setColor(Color.RED);
                g.fillOval(getWidth() / 2, getHeight() / 2, playerDiam, playerDiam);
                break;
            case "gameOver":
                g.setColor(Color.BLACK);
                g.drawString("Game Over",getWidth() / 3 ,50 );
                break;
            case "paused":
                g.setColor(Color.BLACK);
                g.drawString("Paused", getWidth() / 3, 50);
                break;
        }
    }
}

不好意思,请问您的问题是什么? - Scary Wombat
@ScaryWombat,我想不出一种算法可以与我的当前代码配合使用。它们中没有一个以相同的方式存储迷宫,所以我在实现它们时遇到了麻烦。 - user4608242
这些不是迷宫生成算法,而是迷宫解决算法。你想要哪一个? - Daniel Langdon
只发布与此相关的代码,例如您的迷宫结构以及一些例程,如绘制、清除和生成。我认为键盘事件和游戏本身对于这个问题来说并不必要分散注意力。另外,正如Sprinter所指出的那样,请解释迷宫数组中的所有值。定义迷宫属性,例如有多少个入口/出口点,它们的位置在哪里,有多少条可能的路径或总是只有一条?这样就可以真正回答这个问题。(暂时关闭) - Spektre
如果您想获得有关您的代码的反馈,请将其发布到codereview.stackexhange.com。 - Rob Audenaerde
显示剩余3条评论
1个回答

1
作为开始,我会:
  1. 清除迷宫
  2. 随机添加墙壁
  3. 为所有入口/出口点对创建随机路径

    • 清除沿途的迷宫单元格。

如果你只需要迷宫求解器(一些迷宫生成算法需要它们)

使用求解器,你可以改变算法:

  1. 清除迷宫
  2. 添加随机墙壁

    • 如果仍然提供解决方案,则添加
  3. 重复步骤2 N次

你需要小心如何添加墙壁

  • 例如,如果你只添加简单的线条,那么迷宫将如下所示:
  • maze example

这是它的代码(使用链接答案中的类)

// generate random maze with path from x0,y0 to x1,y1 present, n walls
void A_star::generate(int x0,int y0,int x1,int y1,int n)
    {
    int x,y,i,j,dx,dy,l,*p;
    // [clear map]
    for (y=0;y<ys;y++)
     for (x=0;x<xs;x++)
      map[y][x]=A_star_space;
    // temp space
    p=new int [xs>>1]; if (p==NULL) return;
    // generate n walls
    for (i=0;i<n;i++)
        {
        // random start pos,dir,length
        x =Random(xs);
        y =Random(ys);
        dx=Random(4);
        l =Random(xs>>2)+2;
             if (dx==0) { dx=+1; dy= 0; }
        else if (dx==1) { dx=-1; dy= 0; }
        else if (dx==2) { dx= 0; dy=+1; }
        else if (dx==3) { dx= 0; dy=-1; }
        // add wall to maze remember set cells (for remowal if needed)
        for (j=0;l;l--,x+=dx,y+=dy)
         if ((x>=0)&&(x<xs))
          if ((y>=0)&&(y<ys))
           if (map[y][x]!=A_star_wall)
            {
            p[j]=x; j++;
            p[j]=y; j++;
            map[y][x]=A_star_wall;
            }
        // is there solution?
        compute(x0,y0,x1,y1);
        // if not remowe last added wall
        if (ps==0) for (;j;)
            {
            j--; y=p[j];
            j--; x=p[j];
            map[y][x]=A_star_space;
            }
        }
    delete[] p;
    }

由此代码生成:

 A_star map;
 map.resize(256,256); 
 map.generate(5,5,250,250,500);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接