5

I am currently making a maze solving game in Java, and I am currently running into a snag. All of the random maze generation algorithms that I could find output in a way that I couldn't figure out how to implement into my current code. I was considering using the Depth First Search, Recursive Backtracker, or Prim's Algorithm, since I thought they would be the easiest to implement while still generating good mazes. What would be a working use of one of those algorithms that works with my current program? This is my Game Class: (Feel free to point out any bad practices as well, I am pretty new to 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;
        }
    }
}
  • sorry, what exactly is your question? – Scary Wombat Apr 16 '15 at 02:24
  • Well... how do "All of the random maze generation algorithms that [you] could find" output the maze? – Andy Turner Apr 16 '15 at 02:24
  • @ScaryWombat I couldn't come up with an algorithm that would work with my current code. None of them had the same way of storing the maze, so I was having trouble implementing them. –  Apr 16 '15 at 02:25
  • @AndyTurner They mostly output thin lines as walls, instead or storing a wall the same way as a passageway –  Apr 16 '15 at 02:28
  • What do the 0, 1, 2, 3 cell values signify? – sprinter Apr 16 '15 at 03:25
  • Those are not maze generation algorithms, they are maza solving algorithms. Which one do you want? – Daniel Langdon Apr 16 '15 at 04:06
  • post only relevant code in this case the structure for maze of yours and perhaps some routines for it like draw ... clear and generation I think keyboard events and the game it self is not necessary to distract with for this question. also as sprinter pointed explain all the values in your maze array. Define the maze properties like how many entry/exit points where they are located, how many possible paths or always just one? and more so this can be actually answered. (+close for now) – Spektre Apr 16 '15 at 06:41
  • If you want feedback on your code, please post it to codereview.stackexhange.com – Rob Audenaerde Apr 16 '15 at 06:55

1 Answers1

1

as start I would

  1. clear maze
  2. randomly add walls
  3. create random path for all entry/exit points pairs present

    • clear the maze cells along them.

If you just need maze solver (some algos for maze generation needs them)

with use of solver you can change algorithm to

  1. clear maze
  2. add random wall

    • if adding it still provides solution
  3. loop bullet(2) N times

You need to be careful about how to add the walls

  • for example if you add just simple lines then the maze will look like this:
  • maze example

This is the code for it (uses the class from linked answer)

// 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;
    }

generated by this code:

 A_star map;
 map.resize(256,256); 
 map.generate(5,5,250,250,500);
Community
  • 1
  • 1
Spektre
  • 49,595
  • 11
  • 110
  • 380