19
votes
\$\begingroup\$

Write a program that generates and prints a random maze using the algorithm of your choice. The maze should be different for multiple runs of the program. Height and width are given as command line arguments. Use | for vertical wall, - for horizontal wall and + for corner. The maze is bounded by walls and the entrances are marked by missing wall. The maze contains a treasure # which must be reachable from at least one entrance.

$ python2 random-maze.py 4 5
+-+-+
  |#|
|   |
+---+
\$\endgroup\$
7
  • \$\begingroup\$ +1 Great Question. A few points though. 1: How is the exit marked? Is it a symbol like * or is there two separate entrances? 2: You should probably specify that the exit must be reachable. \$\endgroup\$
    – snmcdonald
    Commented Jan 30, 2011 at 19:50
  • 1
    \$\begingroup\$ @snmcdonald: let's make it fun and add a treasure :). \$\endgroup\$
    – Alexandru
    Commented Jan 30, 2011 at 20:36
  • 2
    \$\begingroup\$ I can see a follow up golf, about solving them... :) \$\endgroup\$
    – st0le
    Commented Feb 1, 2011 at 6:22
  • \$\begingroup\$ @st0le: I already have some ideas. Mail me if you want to discuss. \$\endgroup\$
    – Alexandru
    Commented Feb 1, 2011 at 17:48
  • 1
    \$\begingroup\$ The puzzle type is unspecified here. I see that people answered it as if it were a [code-golf]. Was that the intent? If so, please tag it as such? \$\endgroup\$ Commented Jun 1, 2011 at 13:25

5 Answers 5

8
votes
\$\begingroup\$

Python, 375 characters

import random,sys
H,V=map(int,sys.argv[1:])
H-=1
V-=1
b,h,v,p=' -|+'
M=H/2*h
n=random.randint(1,(H/2)*(V/2-1))
for i in range(V/2):
 e=s=t='';N=v
 for j in range(H/2):
  if i and(random.randint(0,1)or j==0):s+=N+b;t+=v;N=v;M=M[1:]+p
  else:s+=M[0]+h;t+=b;N=p;M=M[1:]+h
  n-=1;t+=' #'[n==0]
 if H&1:s+=s[-1];t+=b;e=h
 print s+N+'\n'+t+v
if V&1:print t+v
print h.join(M)+e+h+p

This generates a maze with one entrance and a randomly placed treasure. The maze is a simple binary tree maze.

$ ./maze.py 15 15
--------------+
              |
| | ----------+
| |           |
| +-----+ | --+
|       | |   |
| --+ --+ +---+
|   |   |     |
| --+-+ +---+ |
|     |     | |
| --+ +-+ --+ |
|   |   |   |#|
| | | --+ --+-+
| | |   |     |
+-+-+---+-----+
\$\endgroup\$
3
  • \$\begingroup\$ Maybe it was intended, but the top row (just under the wall) is always a long corridor. \$\endgroup\$
    – Alexandru
    Commented Jan 31, 2011 at 0:53
  • \$\begingroup\$ Yes, and the leftmost column is always a long corridor as well. This is a property of the type of maze I'm generating. \$\endgroup\$ Commented Jan 31, 2011 at 5:03
  • \$\begingroup\$ Oh. The mazes are very nice though :). \$\endgroup\$
    – Alexandru
    Commented Jan 31, 2011 at 12:24
6
votes
\$\begingroup\$

Ruby 1.9.2p136 : 90

eval ARGV[0]
z=[l="+"+"-"*@w+"+"]
@h.times{z<<"|"+" "*@w+"|"}
z[rand(@h)+1]="|#"
puts z<<l

Output

$> ruby maze.rb "@h=8;@w=8;"

+------+
|      |
|      |
|      |
|      |
|#
|      |
+------+

Hey, no one said it had to be a good maze. OK, OK, I'll make a real one now.

\$\endgroup\$
6
  • \$\begingroup\$ Good, but make sure it respects the protocol (height and width from command line, maze printed to stdout). \$\endgroup\$
    – Alexandru
    Commented Jan 31, 2011 at 12:24
  • \$\begingroup\$ Actually it doesn't say anything about stdout (that's also not a reasonable stipulation because someone might be using a language that doesn't print to stdout) and it's commonly accepted that inputs are to a function/method. To the person down voting this, it solves the problem as specified so don't hate the mazer hate the maze. \$\endgroup\$
    – Mike Bethany
    Commented Jan 31, 2011 at 16:04
  • \$\begingroup\$ Not really as long as it specified in the question. See meta.codegolf.stackexchange.com/questions/13/… . Moreover, unlike JavaScript Ruby supports argument reading and writing to standard output. Your solution is cheating compared to others who solved the problem the right way. \$\endgroup\$
    – Alexandru
    Commented Jan 31, 2011 at 16:34
  • \$\begingroup\$ Cannot edit. I meant 'incomplete' not 'cheating'. I like the idea of the maze. \$\endgroup\$
    – Alexandru
    Commented Jan 31, 2011 at 16:40
  • \$\begingroup\$ Then the other languages have to include the code it takes to call them or include #!/usr/bin/env python, for example, in their code. As I said I'll write a real solution too, this was just pointing out the poor quality of the question itself (and many others) and demonstrates we need to have better guidelines. And finally pointing to a question does not make the answer to the question the actual rules for the site. But fine, here's your new version... \$\endgroup\$
    – Mike Bethany
    Commented Jan 31, 2011 at 19:26
5
votes
\$\begingroup\$

I think this technically isn't a maze generator, but it creates a maze like result: https://gist.github.com/803450.

Some horrible code in there I know, and it only works less than half the time, and the result doesn't look quite right to do with walls sticking out from other walls. But its close enough that I can't be bothered fixing the rest.

Some example output:

→ ruby random-maze.rb 30 30
+----+-+-----------++-+----+
|    + |           ++ |    |
++  +  | ++ ++   +    + ++ ++
|  ++ ++ |  |    +---+  +   |
| +      | +| +   +++  +  + |
|   +   +| +| +-+  |   + +  |
|        +  +    + + ++  |+ |
| + ++ +  ++   + |  +   ++| |
| |  | ++  + +----+ + +-+ | |
| +  |  +-+  |+        |  | |
|   +-+  +| ++  ++ + + |  | |
| ++   +  + |  ++|   + | ++ |
|  + + + +  +---++-+   +++  |
| +  |  +| +    |  ++   |   |
| | +++ +| + ++ +--+  + |---+
|#+ | |  |   +++     +  +   |
++  | ++ +-+  ++ +--+  +  + |
|  ++  |    +     ++| +  ++ |
| ++   +--------+  +| + +   |
| |     |      +++  |  +  +-+
| |     | +--+  |++ |+ | ++
| |     |  +--+ | | || |  |
| |     +-+     +-+ |+ |+ |
| | +---+   ++      +  |  |
| +-|     +    +      ++ ++
|   +       ++   +---+   |
|              ++   +  +-+
|                 +   ++
+-+ +-------------+---+
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Nice idea. Extra points if you fix it ;) \$\endgroup\$
    – Alexandru
    Commented Feb 2, 2011 at 1:03
  • \$\begingroup\$ This was just a quick rip out and change of output for an algorithm I used for generating a maze for one of my uni assignments. The actual algorithm is mainly stolen from a blog post by CHEVYRAY. I might get around to fixing it up this weekend, I'm not sure if the output format will entirely work since it isn't a true maze, but I'll try and get it as close as possible while looking good. \$\endgroup\$
    – Nemo157
    Commented Feb 2, 2011 at 9:27
  • \$\begingroup\$ Seems a very good maze to me. \$\endgroup\$
    – Alexandru
    Commented Feb 2, 2011 at 12:18
3
votes
\$\begingroup\$

C 844

#include <stdlib.h>
#include <time.h>
h,w,*m,y,x,z;d(t,b,l,r){int i=b-t,j=r-l;if(i>1&&j>1){i=(rand()%--i)|1;j=(rand()%--j)|1;z=rand()%4;x=rand()%i+t;x|=1;for(y=t;y<i+t;y++)if(y!=x||!z)m[y*w+j+l]=124;x=rand()%(b-i-t)+i+t;x|=1;for(y=t+i;y<b+1;y++)if(y!=x||!(z-1))m[y*w+j+l]=124;y=rand()%j+l;y|=1;for(x=l;x<j+l;x++)if(y!=x||!(z-2))m[(i+t)*w+x]=45;y=rand()%(r-j-l)+j+l;y|=1;for(x=l+j;x<r+1;x++)if(y!=x||!(z-3))m[(i+t)*w+x]=45;m[(i+t)*w+j+l]=43;m[(t-1)*w+l+j]=43;m[(b+1)*w+j+l]=43;m[(i+t)*w+l-1]=43;m[(i+t)*w+r+1]=43;d(t,t+i-1,l,l+j-1);d(t+i+1,b,l,l+j-1);d(t,t+i-1,l+j+1,r);d(t+i+1,b,l+j+1,r);}}main(int c,char**v){h=atoi(v[1]),w=atoi(v[2]),m=calloc(h*w,4);srand(time(0));while(y<h){while(x<w){m[y*h+x]=(!y||y==h-1)?(!x||x==w-1)?43:45:(!x||x==w-1)?124:32;x++;}y++;x=0;}d(1,h-2,1,w-2);z=rand()%(w-2);z|=1;m[z]=32;z=rand()%(w-2);z|=1;m[h*(w-2)+z]=35;}

To Test:

#include <stdio.h>//beginning
for(y=0;y<h;y++){for(x=0;x<w;x++){putchar(m[y*h+x]);}putchar('\n');}getchar();//end

3x3

+ +
|#|
+-+

7x8

+-+-- -+
|      |
+ +-+--+
|      |
| +-+ -+
| |  # |
+-+-+--+

18x20

+-+-+ +---+---+-+--+
| | |         |    |
| + + +-- +---+ +--+
|     |       |    |
+ + +-+---+-- +-+ -+
| |   |            |
+-+ +-+-+-+---+-+--+
| | |   |       |  |
| + + + +-+-- --+  |
| |   |         |  |
| | | +-+-+ ----+  |
|   | |         |  |
+ + +-+-+-+-- --+ -+
| |   |         |  |
| + +-+-- +-- --+  |
| |   |   |        |
| | | |  #|     |  |
+-+-+-+---+-----+--+
\$\endgroup\$
2
  • \$\begingroup\$ This is a code-challenge, not a code-golf. Why the barely readable code? \$\endgroup\$ Commented Feb 17, 2014 at 20:42
  • \$\begingroup\$ -1. Not only is this code obfuscated, but there are no clear instructions on how this should be compiled, and how the two blocks of code should be implemented. Usage instructions are sparse, if not entirely missing. It's obvious that your answer is a code-golf. But the question isn't. So the code should be readable, and self-contained for easy copy/paste/compile, so that others can verify that it indeed works without having to decipher how you got the code to work in the first place. \$\endgroup\$ Commented Feb 17, 2014 at 21:25
0
votes
\$\begingroup\$

Here's a simple java solution:

import java.util.*;

public class MazeGen {
    public static void main(String[]a){
        int w,l;
        Random rand=new Random(System.currentTimeMillis()%1000+System.nanoTime());
        if(a.length==2){
            w=Integer.parseInt(a[0]);
            l=Integer.parseInt(a[1]);
        }else{
            System.out.println("No command line arguments, taking from STDIN.");
            Scanner input=new Scanner(System.in);
            w=input.nextInt();
            l=input.nextInt();
            input.close();
        }
        char[][]maze=new char[w][l];
        for(int x=0;x<w;x++){
            for(int y=0;y<l;y++){
                maze[x][y]=' ';
            }
        }
        for(int x=0;x<w;x++){
            maze[x][0]=maze[x][l-1]='|';
        }
        for(int y=0;y<l;y++){
            maze[0][y]=maze[w-1][y]='-';
        }
        maze[0][0]=maze[w-1][0]=maze[w-1][l-1]=maze[0][l-1]='+';
        int dor=1+rand.nextInt(l-2);
        maze[0][dor]=' ';
        int tx=2+rand.nextInt(w-3),ty=1+rand.nextInt(l-2);
        maze[tx][ty]='#';
        if(ty<dor-1){
            maze[tx][ty+1]='|';
            if(tx==w-2){
                maze[tx+1][ty+1]='+';
            }
            if(tx==1){
                maze[0][ty+1]='+';
            }
        }
        if(ty>dor+1){
            maze[tx][ty-1]='|';
            if(tx==w-2){
                maze[tx+1][ty-1]='+';
            }
            if(tx==1){
                maze[0][ty-1]='+';
            }
        }
        if(ty==dor&&tx>3&&(maze[tx][ty+1]==' '||maze[tx][ty-1]==' ')){
            maze[tx-1][ty]='-';
        }
        if(dor>5){
            int z=2+rand.nextInt(dor-3);
            int q=1+rand.nextInt(w-3);
            for(int i=0;i<w;i++){
                if(i==0||i==w-1){
                    maze[i][z]='+';
                }else if(i!=q&&maze[i][z]==' '){
                    maze[i][z]='|';
                }
            }

        }
        if(l-dor>5){
            int z=dor+2+rand.nextInt(l-dor-3);
            int q=1+rand.nextInt(w-3);
            for(int i=0;i<w;i++){
                if(i==0||i==w-1){
                    maze[i][z]='+';
                }else if(i!=q&&maze[i][z]==' '){
                    maze[i][z]='|';
                }
            }

        }
        for(char[]row:maze){
            System.out.println(row);
        }
    }
}

Some sample results:

3x3:

+ +
|#|
+-+

4x4:

+ -+
| #|
|  |
+--+

4x5:

+-+ +
|#| |
|   |
+---+

5x5:

+ --+
|   |
|   |
| |#|
+-+-+

5x8:

+ --+--+
|   |  |
|      |
| # |  |
+---+--+

8x15:

+---- ----+---+
|         |   |
|         |   |
|         |   |
|             |
| #|      |   |
|         |   |
+---------+---+
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.