practice prim maze generation.
Log in to post a comment.
// You can find the Turtle API reference here: https://turtletoy.net/syntax Canvas.setpenopacity(1); // Global code will be evaluated once. const turtle = new Turtle(); function line(x1,y1,x2,y2){turtle.penup();turtle.goto(x1,y1);turtle.pendown();turtle.goto(x2,y2);} // masks const L = 1; const R = 2; const U = 4; const D = 8; const IN = 16; function opposite(direction) { if(direction == L)return R; if(direction == R)return L; if(direction == U)return D; if(direction == D)return U; } // canvas parameters let width = 200.0 let height = 200.0 let margin = 5.0 let maze_width = width - margin*2.0; let maze_height = height - margin*2.0; let maze_left = -maze_width*0.5; let maze_top = -maze_height*0.5; // maze const num_grid = 120; grid_size = maze_width/num_grid; let map =new Array(); for(let y=0;y<num_grid;y++) { map[y]=new Array(); for(let x=0;x<num_grid;x++){ map[y][x]=0; } } let front = new Set() function valid(x,y) { return x>=0 && x<num_grid && y>=0 && y<num_grid } function inside(x,y) { return map[y][x] & IN; } function neighbors(x,y) { let nb = new Array(); if(valid(x-1,y) && inside(x-1,y)){nb.push([x-1,y,L]);} if(valid(x+1,y) && inside(x+1,y)){nb.push([x+1,y,R]);} if(valid(x,y-1) && inside(x,y-1)){nb.push([x,y-1,U]);} if(valid(x,y+1) && inside(x,y+1)){nb.push([x,y+1,D]);} return nb; } function get_xy(id){ return [Math.floor(id/num_grid),id%num_grid]; } function id(x,y){ return x*num_grid+y; } function add_front(x,y){ if(valid(x,y) && !inside(x,y)){ front.add(id(x,y)) } } function mark(x,y) { map[y][x] |= IN; add_front(x-1,y); add_front(x+1,y); add_front(x,y-1); add_front(x,y+1); } function rand_int(max) { return Math.floor(Math.random() * max); } function rand_pop(myset) { let items = Array.from(myset); let it = items[rand_int(items.length)]; myset.delete(it) return it } function generate_maze() { // random start cell let start_x = rand_int(num_grid); let start_y = rand_int(num_grid); mark(start_x,start_x) let steps = 0; // generation loop while(front.size) { // get random element from fontier let xyid = rand_pop(front); let xy = get_xy(xyid); let x = xy[0],y = xy[1]; // find fontier's neighbors nbs = neighbors(x,y); // pick random neighbor let nb = nbs[rand_int(nbs.length)]; let nx = nb[0], ny = nb[1]; let dir = nb[2]; // break the wall and make a way map[y][x] |= dir; map[ny][nx] |= opposite(dir); steps++; // mark the cell as inside mark(x,y); } } generate_maze(); function draw_grid(x,y) { let l = maze_left + grid_size*x; let r = l + grid_size; let t = maze_top + grid_size*y; let b = t + grid_size; let dir = map[y][x]; if(!(dir&L))line(l,t,l,b); if(!(dir&U))line(l,t,r,t); if((x==num_grid-1)&&!(dir&R))line(r,t,r,b); if((y==num_grid-1)&&!(dir&D))line(l,b,r,b); } // The walk function will be called until it returns false. function walk(i) { let xy = get_xy(i); let x = xy[0],y = xy[1]; draw_grid(x,y); return i < num_grid*num_grid-1;//num_grid }