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)