maze_generator_v1.py

Created by gradient01

Created on January 26, 2026

7.14 KB

This is a random maze generator that uses Kruskal’s algorithm. You can change its size by modifying the “size” variable in the “main.py” script. Generating the size 2 maze takes about 1 minute and 30 seconds. After generation, the script will find the two furthest points and place the start and finish at these locations. After that, you can solve it! Once you have found the exit, the solution will be calculated and displayed.

You can also check out maze_generator_v2, which uses depth-first search algorithm.

Good luck!


from kandinsky import *
from ion import *
from time import *
from random import *


###########
# maze.py #
###########

def k(key):
  if keydown(key):
    while keydown(key):
      pass
    return True
  return False

def get_lenght(size):
  return (
    319//size,
    221//size
  )

def draw_base_maze(size,bg_color,wall_color):
  xmax=(319//size)*size
  ymax=(221//size)*size
  fill_rect(0,0,330,230,bg_color)
  for x in range(0,xmax,size):
    fill_rect(x,0,1,ymax,wall_color)
  for y in range(0,ymax,size):
    fill_rect(0,y,xmax,1,wall_color)
  fill_rect(xmax,0,1,ymax,wall_color)
  fill_rect(0,ymax,xmax+1,1,wall_color)

def change_by(size,col1,col2):
  lenght=(
  319//size,
  221//size
  )
  for x in range(lenght[0]):
    for y in range(lenght[1]):
      if get_cell(size,x,y)==col1:
        set_cell(size,x,y,col2)

def get_cell(size,x,y):
  lenght=get_lenght(size)
  if x>lenght[0]-1 or x<0 or y>lenght[1]-1 or y<0:
    return (-1,)*3
  return get_pixel(x*size+1,y*size+1)

def set_cell(size,x,y,col):
  fill_rect(x*size+1,y*size+1,size-1,size-1,col)

def get_cell_wall(size,x,y,dir):
  if dir=="n":
    return get_pixel(x*size+1,y*size)
  elif dir=="w":
    return get_pixel(x*size,y*size+1)
  elif dir=="e":
    return get_pixel(x*size+size,y*size+1)
  elif dir=="s":
    return get_pixel(x*size+1,y*size+size)

def set_cell_wall(size,x,y,dir,col):
  if dir=="n":
    return fill_rect(x*size+1,y*size,size-1,1,col)
  elif dir=="w":
    return fill_rect(x*size,y*size+1,1,size-1,col)
  elif dir=="e":
    return fill_rect(x*size+size,y*size+1,1,size-1,col)
  elif dir=="s":
    return fill_rect(x*size+1,y*size+size,size-1,1,col)

def color_incr(col):
  r,g,b=col
  r+=9
  if r>255:
    r=0
    g+=5
    if g>255:
      g=0
      b+=9
      if b>255:
        b=0
        print("Overflow Warning")
  return r,g,b

def play(size,start=(0,)*2,stop=None):
  lenght=get_lenght(size)
  if stop==None:
    stop=(lenght[0]-1,lenght[1]-1)
  x,y=start
  set_cell(size,x,y,(255,0,0))
  set_cell(size,stop[0],stop[1],(0,255,0))
  while (x,y)!=stop:
    if k(KEY_UP) and get_cell_wall(size,x,y,"n")==(255,)*3:
      set_cell(size,x,y,(255,)*3)
      y-=1
    if k(KEY_DOWN) and get_cell_wall(size,x,y,"s")==(255,)*3:
      set_cell(size,x,y,(255,)*3)
      y+=1
    if k(KEY_RIGHT) and get_cell_wall(size,x,y,"e")==(255,)*3:
      set_cell(size,x,y,(255,)*3)
      x+=1
    if k(KEY_LEFT) and get_cell_wall(size,x,y,"w")==(255,)*3:
      set_cell(size,x,y,(255,)*3)
      x-=1
    set_cell(size,x,y,(255,0,0))
  set_cell(size,x,y,(255,)*3)

def best_stop(size,start):
  change_by(size,(255,)*3,(255,250,255))
  loop=True
  col=(255,)*3
  lasts=[start]
  while loop:
    new_lasts=[]
    for point in lasts:
      set_cell(size,point[0],point[1],col)
      for elem in [(1,0,"e"),(-1,0,"w"),(0,1,"s"),(0,-1,"n")]:
        if get_cell_wall(size,point[0],point[1],elem[2])==(255,)*3 and get_cell(size,point[0]+elem[0],point[1]+elem[1])!=col:
          new_lasts+=[(point[0]+elem[0],point[1]+elem[1])]
    if len(new_lasts)==0:
      return lasts[0]
    lasts=new_lasts


##################
# maze_solver.py #
##################

LINE=(0,255,0)

def search(size,start,stop):
  loop=True
  col=(0,150,80)
  lasts=[stop]
  set_cell(size,lasts[0][0],lasts[0][1],col)
  while loop:
    new_lasts=[]
    for point in lasts:
      if point==start:
        loop=False
      x,y=point
      for elem in [(1,0,"e"),(-1,0,"w"),(0,1,"s"),(0,-1,"n")]:
        if get_cell_wall(size,x,y,elem[2])==(255,)*3 and get_cell(size,x+elem[0],y+elem[1])==(255,)*3:
          new_lasts+=[(x+elem[0],y+elem[1])]
          set_cell(size,x+elem[0],y+elem[1],color_incr(col))
    lasts=new_lasts
    col=color_incr(col)

def clean_maze(size):
  lenght=get_lenght(size)
  for x in range(lenght[0]):
    for y in range(lenght[1]):
      if get_cell(size,x,y)!=LINE:
        set_cell(size,x,y,(255,)*3)

def draw_solution(size,start,stop):
  loop=True
  last=start
  while loop:
    set_cell(size,last[0],last[1],LINE)
    if last==stop:
      break
    res={}
    for elem in [(1,0,"e"),(-1,0,"w"),(0,1,"s"),(0,-1,"n")]:
      other_content=get_cell(size,last[0]+elem[0],last[1]+elem[1])
      if (
        get_cell_wall(size,last[0],last[1],elem[2]) == (0,)*3 or 
        other_content == (-1,)*3 or 
        other_content == LINE
      ):
        pass
      else:
        res[elem[2]]=other_content[0]+other_content[1]*255+other_content[2]*255**2
    mini=min([i for i in res.values()])
    for dir in res.keys():
      if res[dir]==mini:
        good_dir=dir
        break
    set_cell_wall(size,last[0],last[1],good_dir,LINE)
    for elem in [(1,0,"e"),(-1,0,"w"),(0,1,"s"),(0,-1,"n")]:
      if good_dir==elem[2]:
        last=(last[0]+elem[0],last[1]+elem[1])

def solve(size,start,stop):
  search(size,start,stop)
  draw_solution(size,start,stop)
  clean_maze(size)


#####################
# maze_generator.py #
#####################

def spread_from(size,x,y):
  lenght=get_lenght(size)
  loop=True
  col=get_cell(size,x,y)
  lasts=[(x,y)]
  while loop:
    if len(lasts)==0:
      loop=False
    new_lasts=[]
    for point in lasts:
      set_cell(size,point[0],point[1],col)
      for elem in [(1,0,"e"),(-1,0,"w"),(0,1,"s"),(0,-1,"n")]:
        if get_cell_wall(size,point[0],point[1],elem[2])==(255,)*3 and get_cell(size,point[0]+elem[0],point[1]+elem[1])!=col:
          new_lasts+=[(point[0]+elem[0],point[1]+elem[1])]
    lasts=new_lasts

def init_maze(size,bg,walls):
  draw_base_maze(size,bg,walls)
  col=(0,0,0)
  lenght=get_lenght(size)
  for x in range(lenght[0]):
    for y in range(lenght[1]):
      col=color_incr(col)
      fill_rect(x*size+1,y*size+1,size-1,size-1,col)

def create_maze(size):
  #seed(0)
  BG=(255,)*3
  WALLS=(0,)*3
  lenght=get_lenght(size)
  t=monotonic()
  init_maze(size,BG,WALLS)
  huge_limit=monotonic()-t
  huges=[]
  for _ in range(lenght[0]*lenght[1]-1):
    good=False
    while not good:
      x,y=randint(0,lenght[0]-1),randint(0,lenght[1]-1)
      dir=choice(["n","s","e","w"])
      if dir=="n":
        other=x,y-1
      elif dir=="s":
        other=x,y+1
      elif dir=="e":
        other=x+1,y
      elif dir=="w":
        other=x-1,y
      if get_cell_wall(size,x,y,dir)==(0,)*3 and get_cell(size,other[0],other[1])!=get_cell(size,x,y) and get_cell(size,other[0],other[1])!=(-1,)*3:
        set_cell_wall(size,x,y,dir,(255,)*3)
        col_other=get_cell(size,other[0],other[1])
        col=get_cell(size,x,y)
        if (not col_other in huges) and (not col in huges):
          t=monotonic()
          spread_from(size,x,y)
          if monotonic()-t>huge_limit:
            huges+=[col]
        elif (col_other in huges) and (not col in huges):
          spread_from(size,other[0],other[1])
        elif (not col_other in huges) and (col in huges):
          spread_from(size,x,y)
        elif (col_other in huges) and (col in huges):
          change_by(size,col_other,col)
          huges.pop(huges.index(col_other))
        good=True
  col=get_cell(size,0,0)
  change_by(size,col,BG)


###############
# __main__.py #
###############

size=10
start=(319//size//2,221//size//2)
create_maze(size)
for _ in range(3):
  stop=best_stop(size,start)
  start=best_stop(size,stop)
play(size,start,stop)
#while not k(KEY_OK):
#   pass
solve(size,start,stop)

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.