September Morn Update
This commit is contained in:
parent
4e2d22a71d
commit
aac6731f2c
6856 changed files with 141342 additions and 21127 deletions
|
|
@ -1,27 +1,24 @@
|
|||
void
|
||||
grid_maze(data b, integer N)
|
||||
{
|
||||
data d;
|
||||
integer i, j;
|
||||
|
||||
call_n(N, b_suffix, d, "+---");
|
||||
b_suffix(d, "+\n");
|
||||
N.times(bb_cast, d, "+---");
|
||||
bb_cast(d, "+\n");
|
||||
|
||||
call_n(N, b_suffix, d, "| * ");
|
||||
b_suffix(d, "|\n");
|
||||
N.times(bb_cast, d, "| * ");
|
||||
bb_cast(d, "|\n");
|
||||
|
||||
call_n(N, b_extend, b, d);
|
||||
N.times(bb_copy, b, d);
|
||||
|
||||
b_size(d, N * 4 + 2);
|
||||
|
||||
b_extend(b, d);
|
||||
bb_copy(b, d);
|
||||
}
|
||||
|
||||
void
|
||||
walk_cell(data b, integer N, integer line_size, integer x, integer y,
|
||||
list x_offsets, list y_offsets)
|
||||
walk_cell(data b, integer N, line_size, x, y, list x_offsets, y_offsets)
|
||||
{
|
||||
integer i, r;
|
||||
integer i, p, q, r;
|
||||
|
||||
b_replace(b, y + x, ' ');
|
||||
|
||||
|
|
@ -29,29 +26,25 @@ walk_cell(data b, integer N, integer line_size, integer x, integer y,
|
|||
|
||||
i = 0;
|
||||
while (i < 4) {
|
||||
integer p, q;
|
||||
p = x + x_offsets[q = (r + i) & 3];
|
||||
q = y + y_offsets[q];
|
||||
|
||||
p = x + (p = x_offsets[(r + i) & 3]);
|
||||
q = y_offsets[(r + i) & 3];
|
||||
q += y;
|
||||
|
||||
if (-1 < p && p < line_size
|
||||
&& -1 < q && q < line_size * (N * 2 + 1)) {
|
||||
if (b[q + p] == '*') {
|
||||
walk_cell(b, N, line_size, p, q, x_offsets, y_offsets);
|
||||
if (-1 < p && p < line_size
|
||||
&& -1 < q && q < line_size * (N * 2 + 1)) {
|
||||
if (b[q + p] == '*') {
|
||||
walk_cell(b, N, line_size, p, q, x_offsets, y_offsets);
|
||||
b[(q + y) / 2 + (p + x) / 2] = ' ';
|
||||
if (p == x) {
|
||||
b[(q + y) / 2 + p - 1] = ' ';
|
||||
b[(q + y) / 2 + p + 1] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i += 1;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
walk_maze(data b, integer N)
|
||||
{
|
||||
integer line_size, x, y;
|
||||
|
|
@ -68,18 +61,14 @@ walk_maze(data b, integer N)
|
|||
walk_cell(b, N, line_size, x, y, x_offsets, y_offsets);
|
||||
}
|
||||
|
||||
integer
|
||||
main(void)
|
||||
{
|
||||
data b;
|
||||
integer N;
|
||||
|
||||
N = 10;
|
||||
|
||||
grid_maze(b, N);
|
||||
walk_maze(b, N);
|
||||
grid_maze(b, 10);
|
||||
walk_maze(b, 10);
|
||||
|
||||
o_(b);
|
||||
|
||||
return 0;
|
||||
0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
100 MS=10:REM MAZE SIZE
|
||||
110 DIM S(MS+1,MS+1):REM SOUTH WALLS
|
||||
120 DIM W(MS+1,MS+1):REM WEST WALLS
|
||||
130 DIM V(MS+1,MS+1):REM VISITED CELLS
|
||||
140 PRINT "INITIALIZING..."
|
||||
150 GOSUB 260:REM INITIALIZE MAZE
|
||||
160 PRINT "BUILDING..."
|
||||
170 DIM PC(MS*MS+1):DIM PR(MS*MS+1):REM STACK
|
||||
180 REM PICK RANDOM STARTING CELL
|
||||
190 X = RND(-TI)
|
||||
200 C=(INT(RND(1)*MS)+1)
|
||||
210 R=(INT(RND(1)*MS)+1)
|
||||
220 GOSUB 400:REM BUILD MAZE
|
||||
230 GOSUB 540:REM DRAW MAZE
|
||||
240 END
|
||||
250 REM -----INITIALIZE MAZE-----
|
||||
260 REM SET WALLS ON AND VISITED CELLS OFF
|
||||
270 T=MS+1
|
||||
280 FOR C=0 TO T:FOR R=0 TO T:
|
||||
290 S(C,R)=1:W(C,R)=1:V(C,R)=0
|
||||
300 NEXT R:NEXT C
|
||||
310 REM SET BORDER CELLS TO VISITED
|
||||
320 FOR C=0 TO T
|
||||
330 V(C,0)=1:V(C,T)=1
|
||||
340 NEXT C
|
||||
350 FOR R=0 TO T
|
||||
360 V(0,R)=1:V(T,R)=1
|
||||
370 NEXT R
|
||||
380 RETURN
|
||||
390 REM -----BUILD MAZE-----
|
||||
400 U=U+1:PC(U)=C:PR(U)=R:REM PUSH
|
||||
410 V(C,R)=1
|
||||
420 IF V(C,R+1)=1 AND V(C+1,R)=1 AND V(C,R-1)=1 AND V(C-1,R)=1 THEN GOTO 500
|
||||
430 Z=INT(RND(1)*4)
|
||||
440 IF Z=0 AND V(C,R+1)=0 THEN S(C,R)=0:R=R+1:GOTO 400
|
||||
450 IF Z=1 AND V(C+1,R)=0 THEN W(C+1,R)=0:C=C+1:GOTO 400
|
||||
460 IF Z=2 AND V(C,R-1)=0 THEN S(C,R-1)=0:R=R-1:GOTO 400
|
||||
470 IF Z=3 AND V(C-1,R)=0 THEN W(C,R)=0:C=C-1:GOTO 400
|
||||
480 GOTO 430
|
||||
500 C=PC(U):R=PR(U):U=U-1:REM POP
|
||||
510 IF U > 0 THEN GOTO 420
|
||||
520 RETURN
|
||||
530 REM -----DRAW MAZE-----
|
||||
540 REM OPEN 4,4:CMD 4:REM SEND OUTPUT TO PRINTER
|
||||
550 PRINT "+--+--+--+--+--+--+--+--+--+--+"
|
||||
560 FOR R = 1 TO MS
|
||||
570 FOR C = 1 TO MS+1
|
||||
580 IF W(C,R)=0 THEN PRINT " ";
|
||||
590 IF W(C,R)=1 THEN PRINT ": ";
|
||||
600 NEXT C
|
||||
610 PRINT
|
||||
620 FOR C = 1 TO MS
|
||||
630 IF S(C,R)=0 THEN PRINT "+ ";
|
||||
640 IF S(C,R)=1 THEN PRINT "+--";
|
||||
650 NEXT C
|
||||
660 PRINT "+"
|
||||
670 NEXT R
|
||||
680 REM PRINT#4:CLOSE 4:REM CLOSE PRINTER DEVICE
|
||||
690 RETURN
|
||||
37
Task/Maze-generation/Ol/maze-generation-1.ol
Normal file
37
Task/Maze-generation/Ol/maze-generation-1.ol
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
; maze generation
|
||||
(import (otus random!))
|
||||
(define WIDTH 30)
|
||||
(define HEIGHT 8)
|
||||
|
||||
(define maze
|
||||
(map (lambda (?)
|
||||
(repeat #b01111 WIDTH)) ; 0 - unvisited, 1111 - all walls exists
|
||||
(iota HEIGHT)))
|
||||
(define (at x y)
|
||||
(list-ref (list-ref maze y) x))
|
||||
|
||||
(define (unvisited? x y)
|
||||
(if (and (< -1 x WIDTH) (< -1 y HEIGHT))
|
||||
(zero? (band (at x y) #b10000))))
|
||||
(define neighbors '((-1 . 0) (0 . -1) (+1 . 0) (0 . +1)))
|
||||
(define walls '( #b10111 #b11011 #b11101 #b11110))
|
||||
(define antiwalls '( #b11101 #b11110 #b10111 #b11011))
|
||||
|
||||
(let loop ((x (rand! WIDTH)) (y (rand! HEIGHT)))
|
||||
(list-set! (list-ref maze y) x (bor (at x y) #b10000))
|
||||
(let try ()
|
||||
(if (or
|
||||
(unvisited? (- x 1) y) ; left
|
||||
(unvisited? x (- y 1)) ; top
|
||||
(unvisited? (+ x 1) y) ; right
|
||||
(unvisited? x (+ y 1))) ; bottom
|
||||
(let*((p (rand! 4))
|
||||
(neighbor (list-ref neighbors p)))
|
||||
(let ((nx (+ x (car neighbor)))
|
||||
(ny (+ y (cdr neighbor))))
|
||||
(if (unvisited? nx ny)
|
||||
(let ((ncell (at nx ny)))
|
||||
(list-set! (list-ref maze y) x (band (at x y) (list-ref walls p)))
|
||||
(list-set! (list-ref maze ny) nx (band ncell (list-ref antiwalls p)))
|
||||
(loop nx ny)))
|
||||
(try))))))
|
||||
22
Task/Maze-generation/Ol/maze-generation-2.ol
Normal file
22
Task/Maze-generation/Ol/maze-generation-2.ol
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
; maze printing:
|
||||
(display "+")
|
||||
(for-each (lambda (?) (display "--+")) (iota WIDTH))
|
||||
(print)
|
||||
(for-each (lambda (l)
|
||||
; left wall (always)
|
||||
(display "|")
|
||||
; draw right wall
|
||||
(for-each (lambda (x)
|
||||
(display " ")
|
||||
(display (if (zero? (band x #b10)) " " "|")))
|
||||
l)
|
||||
(print)
|
||||
(display "+")
|
||||
; draw bottom wall
|
||||
(for-each (lambda (x)
|
||||
(display (if (zero? (band x #b01)) " " "--"))
|
||||
(display "+"))
|
||||
l)
|
||||
(print))
|
||||
maze)
|
||||
(print)
|
||||
148
Task/Maze-generation/PHP/maze-generation.php
Normal file
148
Task/Maze-generation/PHP/maze-generation.php
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
class Maze
|
||||
{
|
||||
protected $width;
|
||||
protected $height;
|
||||
protected $grid;
|
||||
protected $path;
|
||||
protected $horWalls;
|
||||
protected $vertWalls;
|
||||
protected $dirs;
|
||||
protected $isDebug;
|
||||
|
||||
public function __construct($x, $y, $debug = false)
|
||||
{
|
||||
$this->width = $x;
|
||||
$this->height = $y;
|
||||
$this->path = [];
|
||||
$this->dirs = [ [0, -1], [0, 1], [-1, 0], [1, 0]]; // array of coordinates of N,S,W,E
|
||||
$this->horWalls = []; // list of removed horizontal walls (---+)
|
||||
$this->vertWalls = [];// list of removed vertical walls (|)
|
||||
$this->isDebug = $debug; // debug flag
|
||||
|
||||
// generate the maze:
|
||||
$this->generate();
|
||||
}
|
||||
|
||||
protected function generate()
|
||||
{
|
||||
$this->initMaze(); // init the stack and an unvisited grid
|
||||
// start from a random cell and then proceed recursively
|
||||
$this->walk(mt_rand(0, $this->width-1), mt_rand(0, $this->height-1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually prints the Maze, on stdOut. Put in a separate method to allow extensibility
|
||||
* For simplicity sake doors are positioned on the north wall and east wall
|
||||
*/
|
||||
public function printOut()
|
||||
{
|
||||
$this->log("Horizontal walls: %s", json_encode($this->horWalls));
|
||||
$this->log("Vertical walls: %s", json_encode($this->vertWalls));
|
||||
|
||||
$northDoor = mt_rand(0,$this->width-1);
|
||||
$eastDoor = mt_rand(0, $this->height-1);
|
||||
|
||||
$str = '+';
|
||||
for ($i=0;$i<$this->width;$i++) {
|
||||
$str .= ($northDoor == $i) ? ' +' : '---+';
|
||||
}
|
||||
$str .= PHP_EOL;
|
||||
for ($i=0; $i<$this->height; $i++) {
|
||||
|
||||
for ($j=0; $j<$this->width; $j++) {
|
||||
$str .= (!empty($this->vertWalls[$j][$i]) ? $this->vertWalls[$j][$i] : '| ');
|
||||
}
|
||||
$str .= ($i == $eastDoor ? ' ' : '|').PHP_EOL.'+';
|
||||
for ($j=0; $j<$this->width; $j++) {
|
||||
$str .= (!empty($this->horWalls[$j][$i]) ? $this->horWalls[$j][$i] : '---+');
|
||||
}
|
||||
$str .= PHP_EOL;
|
||||
}
|
||||
echo $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs to stdOut if debug flag is enabled
|
||||
*/
|
||||
protected function log(...$params)
|
||||
{
|
||||
if ($this->isDebug) {
|
||||
echo vsprintf(array_shift($params), $params).PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
private function walk($x, $y)
|
||||
{
|
||||
$this->log('Entering cell %d,%d', $x, $y);
|
||||
// mark current cell as visited
|
||||
$this->grid[$x][$y] = true;
|
||||
// add cell to path
|
||||
$this->path[] = [$x, $y];
|
||||
// get list of all neighbors
|
||||
$neighbors = $this->getNeighbors($x, $y);
|
||||
$this->log("Valid neighbors: %s", json_encode($neighbors));
|
||||
|
||||
if(empty($neighbors)) {
|
||||
// Dead end, we need now to backtrack, if there's still any cell left to be visited
|
||||
$this->log("Start backtracking along path: %s", json_encode($this->path));
|
||||
array_pop($this->path);
|
||||
if (!empty($this->path)) {
|
||||
$next = array_pop($this->path);
|
||||
return $this->walk($next[0], $next[1]);
|
||||
}
|
||||
} else {
|
||||
// randomize neighbors, as per request
|
||||
shuffle($neighbors);
|
||||
|
||||
foreach ($neighbors as $n) {
|
||||
$nextX = $n[0];
|
||||
$nextY = $n[1];
|
||||
if ($nextX == $x) {
|
||||
$wallY = max($nextY, $y);
|
||||
$this->log("New cell is on the same column (%d,%d), removing %d, (%d-1) horizontal wall", $nextX, $nextY, $x, $wallY);
|
||||
$this->horWalls[$x][min($nextY, $y)] = " +";
|
||||
}
|
||||
if ($nextY == $y) {
|
||||
$wallX = max($nextX, $x);
|
||||
$this->log("New cell is on the same row (%d,%d), removing %d,%d vertical wall", $nextX, $nextY, $wallX, $y);
|
||||
$this->vertWalls[$wallX][$y] = " ";
|
||||
}
|
||||
return $this->walk($nextX, $nextY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize an empty grid of $width * $height dimensions
|
||||
*/
|
||||
private function initMaze()
|
||||
{
|
||||
for ($i=0;$i<$this->width;$i++) {
|
||||
for ($j = 0;$j<$this->height;$j++) {
|
||||
$this->grid[$i][$j] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @return array
|
||||
*/
|
||||
private function getNeighbors($x, $y)
|
||||
{
|
||||
$neighbors = [];
|
||||
foreach ($this->dirs as $dir) {
|
||||
$nextX = $dir[0] + $x;
|
||||
$nextY = $dir[1] + $y;
|
||||
if (($nextX >= 0 && $nextX < $this->width && $nextY >= 0 && $nextY < $this->height) && !$this->grid[$nextX][$nextY]) {
|
||||
$neighbors[] = [$nextX, $nextY];
|
||||
}
|
||||
}
|
||||
return $neighbors;
|
||||
}
|
||||
}
|
||||
|
||||
$maze = new Maze(10,10);
|
||||
$maze->printOut();
|
||||
|
|
@ -1,103 +1,98 @@
|
|||
/*REXX program generates and displays a rectangular solvable maze (of any size).*/
|
||||
height=0; @.=0 /*default for all cells visited. */
|
||||
/*REXX program generates and displays a rectangular solvable maze (of any size). */
|
||||
parse arg rows cols seed . /*allow user to specify the maze size. */
|
||||
if rows='' | rows=="," then rows=19 /*No rows given? Then use the default.*/
|
||||
if cols='' | cols=="," then cols=19 /* " cols " ? " " " " */
|
||||
if seed\=='' then call random ,,seed /*use a random seed for repeatability.*/
|
||||
call buildRow '┌'copies("~┬",cols-1)'~┐' /*construct the top edge of the maze. */
|
||||
if rows='' | rows==',' then rows= 19 /*No rows given? Then use the default.*/
|
||||
if cols='' | cols==',' then cols= 19 /* " cols " ? " " " " */
|
||||
if datatype(seed, 'W') then call random ,,seed /*use a random seed for repeatability.*/
|
||||
ht=0; @.=0 /*HT= # rows in grid; @.: default cell*/
|
||||
call makeRow '┌'copies('~┬', cols - 1)'~┐' /*construct the top edge of the maze. */
|
||||
/* [↓] construct the maze's grid. */
|
||||
do r=1 for rows; _=; __=; hp= "|"; hj='├'
|
||||
do c=1 for cols; _= _||hp'1'; __=__||hj"~"; hj='┼'; hp="│"
|
||||
end /*c*/
|
||||
call buildRow _'│' /*construct the right edge of the cells*/
|
||||
if r\==rows then call buildRow __'┤' /* " " " " " " maze.*/
|
||||
end /*r*/
|
||||
do r=1 for rows; _=; __=; hp= "|"; hj= '├'
|
||||
do c=1 for cols; _= _ || hp'1'; __= __ || hj"~"; hj= '┼'; hp= "│"
|
||||
end /*c*/
|
||||
call makeRow _'│' /*construct the right edge of the cells*/
|
||||
if r\==rows then call makeRow __'┤' /* " " " " " " maze.*/
|
||||
end /*r*/ /* [↑] construct the maze's grid. */
|
||||
|
||||
call buildRow '└'copies("~┴", cols-1)'~┘' /*construct the bottom edge of the maze*/
|
||||
r!=random(1,rows)*2; c!=random(1,cols)*2; @.r!.c!=0 /*choose the first cell in maze*/
|
||||
call makeRow '└'copies("~┴", cols - 1)'~┘' /*construct the bottom edge of the maze*/
|
||||
r!= random(1, rows) *2; c!= random(1, cols) *2; @.r!.c!= 0 /*choose 1st cell.*/
|
||||
/* [↓] traipse through the maze. */
|
||||
do forever; n=hood(r!,c!)
|
||||
if n==0 then if \fCell() then leave
|
||||
call ?; @._r._c=0 /*get the (next) maze direction to go. */
|
||||
ro=r!; co=c!; r!=_r; c!=_c /*save original maze cell coordinates. */
|
||||
?.zr=?.zr%2; ?.zc=?.zc%2 /*get the maze row and cell directions.*/
|
||||
rw=ro+?.zr; cw=co+?.zc /*calculate the next row and column. */
|
||||
@.rw.cw=. /*mark the maze cell as being visited. */
|
||||
do forever; n= hood(r!, c!); if n==0 then if \fCell() then leave /*¬freecell?*/
|
||||
call ?; @._r._c= 0 /*get the (next) maze direction to go. */
|
||||
ro= r!; co= c!; r!= _r; c!= _c /*save original maze cell coordinates. */
|
||||
?.zr= ?.zr % 2; ?.zc= ?.zc % 2 /*get the maze row and cell directions.*/
|
||||
rw= ro + ?.zr; cw= co + ?.zc /*calculate the next row and column. */
|
||||
@.rw.cw= . /*mark the maze cell as being visited. */
|
||||
end /*forever*/
|
||||
|
||||
do r=1 for height; _= /*display the maze. */
|
||||
do c=1 for cols*2 + 1; _=_ || @.r.c; end /*c*/
|
||||
if \(r//2) then _=translate(_, '\', .) /*trans to backslash*/
|
||||
@.r=_ /*save the row in @.*/
|
||||
/* [↓] display maze to the terminal. */
|
||||
do r=1 for ht; _=
|
||||
do c=1 for cols*2 + 1; _= _ || @.r.c; end /*c*/
|
||||
if \(r//2) then _= translate(_, '\', .) /*trans to backslash*/
|
||||
@.r= _ /*save the row in @.*/
|
||||
end /*r*/
|
||||
|
||||
do #=1 for height; _=@.# /*display the maze to the terminal. */
|
||||
call makeNice /*make some cell corners look prettier.*/
|
||||
|
||||
_=changestr(1 , _, 111) /*──────these four ────────────────────*/
|
||||
_=changestr(0 , _, 000) /*───────── statements are ────────────*/
|
||||
_=changestr(. , _, " ") /*────────────── used for preserving ──*/
|
||||
_=changestr('~' , _, "───") /*────────────────── the aspect ratio. */
|
||||
say translate(_ , '─│', "═|\10") /*make it presentable for the screen. */
|
||||
do #=1 for ht; _= @.# /*display the maze to the terminal. */
|
||||
call makeNice /*prettify cell corners and dead─ends. */
|
||||
_= changestr( 1 , _ , 111 ) /*──────these four ────────────────────*/
|
||||
_= changestr( 0 , _ , 000 ) /*───────── statements are ────────────*/
|
||||
_= changestr( . , _ , " " ) /*────────────── used for preserving ──*/
|
||||
_= changestr('~', _ , "───" ) /*────────────────── the aspect ratio. */
|
||||
say translate( _ , '─│' , "═|\10" ) /*make it presentable for the screen. */
|
||||
end /*#*/
|
||||
end /*#*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
@: parse arg _r,_c; return @._r._c /*a fast way to reference a maze cell. */
|
||||
hood: parse arg rh,ch; return @(rh+2,ch) + @(rh-2,ch) + @(rh,ch-2) + @(rh,ch+2)
|
||||
@: parse arg _r,_c; return @._r._c /*a fast way to reference a maze cell. */
|
||||
makeRow: parse arg z; ht= ht+1; do c=1 for length(z); @.ht.c=substr(z,c,1); end; return
|
||||
hood: parse arg rh,ch; return @(rh+2,ch) + @(rh-2,ch) + @(rh,ch-2) + @(rh,ch+2)
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
?: do forever; ?.=0; ?=random(1,4); if ?==1 then ?.zc=-2 /*north*/
|
||||
if ?==2 then ?.zr= 2 /* east*/
|
||||
if ?==3 then ?.zc= 2 /*south*/
|
||||
if ?==4 then ?.zr=-2 /* west*/
|
||||
_r=r!+?.zr; _c=c!+?.zc; if @._r._c==1 then return
|
||||
end /*forever*/
|
||||
?: do forever; ?.= 0; ?= random(1, 4); if ?==1 then ?.zc= -2 /*north*/
|
||||
if ?==2 then ?.zr= 2 /* east*/
|
||||
if ?==3 then ?.zc= 2 /*south*/
|
||||
if ?==4 then ?.zr= -2 /* west*/
|
||||
_r= r! + ?.zr; _c= c! + ?.zc; if @._r._c == 1 then return
|
||||
end /*forever*/
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
buildRow: parse arg z; height=height+1; width=length(z)
|
||||
do c=1 for width; @.height.c=substr(z,c,1); end; return
|
||||
fCell: do r=1 for rows; rr= r + r
|
||||
do c=1 for cols; cc= c + c
|
||||
if hood(rr,cc)==1 then do; r!= rr; c!= cc; @.r!.c!= 0; return 1; end
|
||||
end /*c*/ /* [↑] r! and c! are used by invoker.*/
|
||||
end /*r*/; return 0
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
fCell: do r=1 for rows; rr=r+r
|
||||
do c=1 for cols; cc=c+c
|
||||
if hood(rr, cc)==1 then do; r!=rr; c!=cc; @.r!.c!=0; return 1; end
|
||||
end /*c*/
|
||||
end /*r*/ /* [↑] r! and c! are used by invoker.*/
|
||||
return 0
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
makeNice: width=length(_); old=#-1; new=#+1; old_=@.old; new_=@.new
|
||||
if left(_,2) =='├.' then _=translate(_, "|", '├')
|
||||
if right(_,2)=='.┤' then _=translate(_, "|", '┤')
|
||||
/* [↓] handle the top row of the grid.*/
|
||||
do k=1 for width while #==1; z=substr(_,k,1) /*maze top row.*/
|
||||
if z\=='┬' then iterate
|
||||
if substr(new_,k,1)=='\' then _=overlay("═",_,k)
|
||||
end /*k*/
|
||||
makeNice: width= length(_); old= # - 1; new= # + 1; old_= @.old; new_= @.new
|
||||
if left(_, 2)=='├.' then _= translate(_, "|", '├')
|
||||
if right(_,2)=='.┤' then _= translate(_, "|", '┤')
|
||||
|
||||
do k=1 for width while #==height; z=substr(_,k,1) /*maze bot row.*/
|
||||
if z\=='┴' then iterate
|
||||
if substr(old_, k, 1)=='\' then _=overlay("═", _, k)
|
||||
end /*k*/
|
||||
/* [↓] handle the mid rows of the grid*/
|
||||
do k=3 to width-2 by 2 while #//2; z=substr(_,k,1) /*maze mid rows*/
|
||||
if z\=='┼' then iterate
|
||||
le=substr(_,k-1,1)
|
||||
ri=substr(_,k+1,1)
|
||||
up=substr(old_,k,1)
|
||||
dw=substr(new_,k,1)
|
||||
select
|
||||
when le== . & ri== . & up=='│' & dw=="│" then _=overlay('|',_,k)
|
||||
when le=='~' & ri=="~" & up=='\' & dw=="\" then _=overlay('═',_,k)
|
||||
when le=='~' & ri=="~" & up=='\' & dw=="│" then _=overlay('┬',_,k)
|
||||
when le=='~' & ri=="~" & up=='│' & dw=="\" then _=overlay('┴',_,k)
|
||||
when le=='~' & ri== . & up=='\' & dw=="\" then _=overlay('═',_,k)
|
||||
when le== . & ri=="~" & up=='\' & dw=="\" then _=overlay('═',_,k)
|
||||
when le== . & ri== . & up=='│' & dw=="\" then _=overlay('|',_,k)
|
||||
when le== . & ri== . & up=='\' & dw=="│" then _=overlay('|',_,k)
|
||||
when le== . & ri=="~" & up=='\' & dw=="│" then _=overlay('┌',_,k)
|
||||
when le== . & ri=="~" & up=='│' & dw=="\" then _=overlay('└',_,k)
|
||||
when le=='~' & ri== . & up=='\' & dw=="│" then _=overlay('┐',_,k)
|
||||
when le=='~' & ri== . & up=='│' & dw=="\" then _=overlay('┘',_,k)
|
||||
when le=='~' & ri== . & up=='│' & dw=="│" then _=overlay('┤',_,k)
|
||||
when le== . & ri=="~" & up=='│' & dw=="│" then _=overlay('├',_,k)
|
||||
otherwise nop
|
||||
end /*select*/
|
||||
end /*k*/
|
||||
return
|
||||
do k=1 for width while #==1; z= substr(_, k, 1) /*maze top row.*/
|
||||
if z\=='┬' then iterate
|
||||
if substr(new_, k, 1)=='\' then _= overlay("═", _, k)
|
||||
end /*k*/
|
||||
|
||||
do k=1 for width while #==ht; z= substr(_, k, 1) /*maze bot row.*/
|
||||
if z\=='┴' then iterate
|
||||
if substr(old_, k, 1)=='\' then _= overlay("═", _, k)
|
||||
end /*k*/
|
||||
|
||||
do k=3 to width-2 by 2 while #//2; z= substr(_, k, 1) /*maze mid rows*/
|
||||
if z\=='┼' then iterate
|
||||
le= substr(_ , k-1, 1)
|
||||
ri= substr(_ , k+1, 1)
|
||||
up= substr(old_, k , 1)
|
||||
dw= substr(new_, k , 1)
|
||||
select
|
||||
when le== . & ri== . & up=='│' & dw=="│" then _= overlay('|', _, k)
|
||||
when le=='~' & ri=="~" & up=='\' & dw=="\" then _= overlay('═', _, k)
|
||||
when le=='~' & ri=="~" & up=='\' & dw=="│" then _= overlay('┬', _, k)
|
||||
when le=='~' & ri=="~" & up=='│' & dw=="\" then _= overlay('┴', _, k)
|
||||
when le=='~' & ri== . & up=='\' & dw=="\" then _= overlay('═', _, k)
|
||||
when le== . & ri=="~" & up=='\' & dw=="\" then _= overlay('═', _, k)
|
||||
when le== . & ri== . & up=='│' & dw=="\" then _= overlay('|', _, k)
|
||||
when le== . & ri== . & up=='\' & dw=="│" then _= overlay('|', _, k)
|
||||
when le== . & ri=="~" & up=='\' & dw=="│" then _= overlay('┌', _, k)
|
||||
when le== . & ri=="~" & up=='│' & dw=="\" then _= overlay('└', _, k)
|
||||
when le=='~' & ri== . & up=='\' & dw=="│" then _= overlay('┐', _, k)
|
||||
when le=='~' & ri== . & up=='│' & dw=="\" then _= overlay('┘', _, k)
|
||||
when le=='~' & ri== . & up=='│' & dw=="│" then _= overlay('┤', _, k)
|
||||
when le== . & ri=="~" & up=='│' & dw=="│" then _= overlay('├', _, k)
|
||||
otherwise nop
|
||||
end /*select*/
|
||||
end /*k*/; return
|
||||
|
|
|
|||
|
|
@ -1,58 +1,54 @@
|
|||
/*REXX program generates and displays a rectangular solvable maze (of any size). */
|
||||
height=0; @.=0 /*default for all cells visited. */
|
||||
parse arg rows cols seed . /*allow user to specify the maze size. */
|
||||
if rows='' | rows=="," then rows=19 /*No rows given? Then use the default.*/
|
||||
if cols='' | cols=="," then cols=19 /* " cols " ? " " " " */
|
||||
if seed\=='' then call random ,,seed /*use a random seed for repeatability.*/
|
||||
call buildRow '┌'copies("─┬", cols-1)'─┐' /*construct the top edge of the maze.*/
|
||||
/* [↓] construct the maze's grid. */
|
||||
do r=1 for rows; _=; __=; hp= "|"; hj='├'
|
||||
do c=1 for cols; _= _||hp'1'; __=__||hj"─"; hj='┼'; hp="│"
|
||||
end /*c*/
|
||||
call buildRow _'│' /*construct the right edge of the cells*/
|
||||
if r\==rows then call buildRow __'┤' /* " " " " " " maze.*/
|
||||
end /*r*/
|
||||
if rows='' | rows=="," then rows= 19 /*No rows given? Then use the default.*/
|
||||
if cols='' | cols=="," then cols= 19 /* " cols " ? " " " " */
|
||||
if datatype(seed, 'W') then call random ,,seed /*use a random seed for repeatability.*/
|
||||
ht=0; @.=0 /*HT= # rows in grid; @.: default cell*/
|
||||
call makeRow '┌'copies("─┬", cols-1)'─┐' /*construct the top edge of the maze.*/
|
||||
|
||||
call buildRow '└'copies("─┴", cols-1)'─┘' /*construct the bottom edge of the maze*/
|
||||
r!=random(1,rows)*2; c!=random(1,cols)*2; @.r!.c!=0 /*choose the first cell.*/
|
||||
do r=1 for rows; _=; __=; hp= "|"; hj= '├'
|
||||
do c=1 for cols; _= _ || hp'1'; __= __ || hj"─"; hj= '┼'; hp= "│"
|
||||
end /*c*/
|
||||
call makeRow _'│' /*construct the right edge of the cells*/
|
||||
if r\==rows then call makeRow __'┤' /* " " " " " " maze.*/
|
||||
end /*r*/ /* [↑] construct the maze's grid. */
|
||||
|
||||
call makeRow '└'copies("─┴", cols-1)'─┘' /*construct the bottom edge of the maze*/
|
||||
r!= random(1, rows)*2; c!= random(1, cols)*2; @.r!.c!= 0 /*choose the 1st cell.*/
|
||||
/* [↓] traipse through the maze. */
|
||||
do forever; n=hood(r!, c!) /*number of free maze cells. */
|
||||
if n==0 then if \fCell() then leave /*if no free maze cells left, then done*/
|
||||
call ?; @._r._c=0 /*get the (next) maze direction to go. */
|
||||
ro=r!; co=c!; r!=_r; c!=_c /*save the original cell coordinates. */
|
||||
?.zr=?.zr%2; ?.zc=?.zc%2 /*get the maze row and cell directions.*/
|
||||
rw=ro+?.zr; cw=co+?.zc /*calculate the next maze row and col. */
|
||||
do forever; n= hood(r!, c!) /*number of free maze cells. */
|
||||
if n==0 then if \fCell() then leave /*if no free maze cells left, then done*/
|
||||
call ?; @._r._c= 0 /*get the (next) maze direction to go. */
|
||||
ro= r!; co= c!; r!= _r; c!= _c /*save the original cell coordinates. */
|
||||
?.zr= ?.zr % 2; ?.zc= ?.zc % 2 /*get the maze row and cell directions.*/
|
||||
rw= ro + ?.zr; cw= co + ?.zc /*calculate the next maze row and col. */
|
||||
@.rw.cw=. /*mark the maze cell as being visited. */
|
||||
end /*forever*/
|
||||
|
||||
do r=1 for height; _= /*display the maze. */
|
||||
do c=1 for cols*2 + 1; _=_ || @.r.c; end /*c*/
|
||||
if \(r//2) then _=translate(_, '\', .) /*trans to backslash*/
|
||||
_=changestr(1 , _, 111) /*──────these four ────────────────────*/
|
||||
_=changestr(0 , _, 000) /*───────── statements are ────────────*/
|
||||
_=changestr(. , _, " ") /*────────────── used for preserving ──*/
|
||||
_=changestr('─', _, "───") /*────────────────── the aspect ratio. */
|
||||
say translate(_, '│', "|\10") /*make it presentable for the screen. */
|
||||
/* [↓] display maze to the terminal. */
|
||||
do r=1 for ht; _=
|
||||
do c=1 for cols*2 + 1; _= _ || @.r.c; end /*c*/
|
||||
if \(r//2) then _= translate(_, '\',.) /*translate a period to a backslash.*/
|
||||
_= changestr( 1 , _ , 111 ) /*──────these four ────────────────────*/
|
||||
_= changestr( 0 , _ , 000 ) /*───────── statements are ────────────*/
|
||||
_= changestr( . , _ , " " ) /*────────────── used for preserving ──*/
|
||||
_= changestr('─', _ , "───" ) /*────────────────── the aspect ratio. */
|
||||
say translate( _ , '│' , "|\10") /*make it presentable for the screen. */
|
||||
end /*r*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
@: parse arg _r,_c; return @._r._c /*a fast way to reference a maze cell. */
|
||||
@: parse arg _r,_c; return @._r._c /*a fast way to reference a maze cell. */
|
||||
makeRow: parse arg z; ht= ht+1; do c=1 for length(z); @.ht.c=substr(z,c,1); end; return
|
||||
hood: parse arg rh,ch; return @(rh+2,ch) + @(rh-2,ch) + @(rh,ch-2) + @(rh,ch+2)
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
?: do forever; ?.=0; ?=random(1,4); if ?==1 then ?.zc=-2 /*north*/
|
||||
if ?==2 then ?.zr= 2 /* east*/
|
||||
if ?==3 then ?.zc= 2 /*south*/
|
||||
if ?==4 then ?.zr=-2 /* west*/
|
||||
_r=r!+?.zr; _c=c!+?.zc; if @._r._c==1 then return
|
||||
end /*forever*/
|
||||
?: do forever; ?.= 0; ?= random(1, 4); if ?==1 then ?.zc= -2 /*north*/
|
||||
if ?==2 then ?.zr= 2 /* east*/
|
||||
if ?==3 then ?.zc= 2 /*south*/
|
||||
if ?==4 then ?.zr= -2 /* west*/
|
||||
_r= r! + ?.zr; _c= c! + ?.zc; if @._r._c == 1 then return
|
||||
end /*forever*/
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
buildRow: parse arg z; height=height+1; width=length(z)
|
||||
do c=1 for width; @.height.c=substr(z,c,1); end; return
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
fCell: do r=1 for rows; rr=r+r
|
||||
do c=1 for cols; cc=c+c
|
||||
if hood(rr,cc)==1 then do; r!=rr; c!=cc; @.r!.c!=0; return 1; end
|
||||
end /*c*/
|
||||
end /*r*/ /* [↑] r! and c! are used by invoker.*/
|
||||
return 0
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
hood: parse arg rh,ch; return @(rh+2,ch) + @(rh-2,ch) + @(rh,ch-2) + @(rh,ch+2)
|
||||
fCell: do r=1 for rows; rr= r + r
|
||||
do c=1 for cols; cc= c + c
|
||||
if hood(rr,cc)==1 then do; r!= rr; c!= cc; @.r!.c!= 0; return 1; end
|
||||
end /*c*/ /* [↑] r! and c! are used by invoker.*/
|
||||
end /*r*/; return 0
|
||||
|
|
|
|||
137
Task/Maze-generation/Rust/maze-generation.rust
Normal file
137
Task/Maze-generation/Rust/maze-generation.rust
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
use rand::{thread_rng, Rng, rngs::ThreadRng};
|
||||
|
||||
const WIDTH: usize = 16;
|
||||
const HEIGHT: usize = 16;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Cell {
|
||||
col: usize,
|
||||
row: usize,
|
||||
}
|
||||
|
||||
impl Cell {
|
||||
fn from(col: usize, row: usize) -> Cell {
|
||||
Cell {col, row}
|
||||
}
|
||||
}
|
||||
|
||||
struct Maze {
|
||||
cells: [[bool; HEIGHT]; WIDTH], //cell visited/non visited
|
||||
walls_h: [[bool; WIDTH]; HEIGHT + 1], //horizontal walls existing/removed
|
||||
walls_v: [[bool; WIDTH + 1]; HEIGHT], //vertical walls existing/removed
|
||||
thread_rng: ThreadRng, //Random numbers generator
|
||||
}
|
||||
|
||||
impl Maze {
|
||||
|
||||
///Inits the maze, with all the cells unvisited and all the walls active
|
||||
fn new() -> Maze {
|
||||
Maze {
|
||||
cells: [[true; HEIGHT]; WIDTH],
|
||||
walls_h: [[true; WIDTH]; HEIGHT + 1],
|
||||
walls_v: [[true; WIDTH + 1]; HEIGHT],
|
||||
thread_rng: thread_rng(),
|
||||
}
|
||||
}
|
||||
|
||||
///Randomly chooses the starting cell
|
||||
fn first(&mut self) -> Cell {
|
||||
Cell::from(self.thread_rng.gen_range(0, WIDTH), self.thread_rng.gen_range(0, HEIGHT))
|
||||
}
|
||||
|
||||
///Opens the enter and exit doors
|
||||
fn open_doors(&mut self) {
|
||||
let from_top: bool = self.thread_rng.gen();
|
||||
let limit = if from_top { WIDTH } else { HEIGHT };
|
||||
let door = self.thread_rng.gen_range(0, limit);
|
||||
let exit = self.thread_rng.gen_range(0, limit);
|
||||
if from_top {
|
||||
self.walls_h[0][door] = false;
|
||||
self.walls_h[HEIGHT][exit] = false;
|
||||
} else {
|
||||
self.walls_v[door][0] = false;
|
||||
self.walls_v[exit][WIDTH] = false;
|
||||
}
|
||||
}
|
||||
|
||||
///Removes a wall between the two Cell arguments
|
||||
fn remove_wall(&mut self, cell1: &Cell, cell2: &Cell) {
|
||||
if cell1.row == cell2.row {
|
||||
self.walls_v[cell1.row][if cell1.col > cell2.col { cell1.col } else { cell2.col }] = false;
|
||||
} else {
|
||||
self.walls_h[if cell1.row > cell2.row { cell1.row } else { cell2.row }][cell1.col] = false;
|
||||
};
|
||||
}
|
||||
|
||||
///Returns a random non-visited neighbor of the Cell passed as argument
|
||||
fn neighbor(&mut self, cell: &Cell) -> Option<Cell> {
|
||||
self.cells[cell.col][cell.row] = false;
|
||||
let mut neighbors = Vec::new();
|
||||
if cell.col > 0 && self.cells[cell.col - 1][cell.row] { neighbors.push(Cell::from(cell.col - 1, cell.row)); }
|
||||
if cell.row > 0 && self.cells[cell.col][cell.row - 1] { neighbors.push(Cell::from(cell.col, cell.row - 1)); }
|
||||
if cell.col < WIDTH - 1 && self.cells[cell.col + 1][cell.row] { neighbors.push(Cell::from(cell.col + 1, cell.row)); }
|
||||
if cell.row < HEIGHT - 1 && self.cells[cell.col][cell.row + 1] { neighbors.push(Cell::from(cell.col, cell.row + 1)); }
|
||||
if neighbors.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let next = neighbors.get(self.thread_rng.gen_range(0, neighbors.len())).unwrap();
|
||||
self.remove_wall(cell, next);
|
||||
Some(*next)
|
||||
}
|
||||
}
|
||||
|
||||
///Builds the maze (runs the Depth-first search algorithm)
|
||||
fn build(&mut self) {
|
||||
let mut cell_stack: Vec<Cell> = Vec::new();
|
||||
let mut next = self.first();
|
||||
loop {
|
||||
while let Some(cell) = self.neighbor(&next) {
|
||||
cell_stack.push(cell);
|
||||
next = cell;
|
||||
}
|
||||
match cell_stack.pop() {
|
||||
Some(cell) => next = cell,
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///Displays a wall
|
||||
fn paint_wall(h_wall: bool, active: bool) {
|
||||
if h_wall {
|
||||
print!("{}", if active { "+---" } else { "+ " });
|
||||
} else {
|
||||
print!("{}", if active { "| " } else { " " });
|
||||
}
|
||||
}
|
||||
|
||||
///Displays a final wall for a row
|
||||
fn paint_close_wall(h_wall: bool) {
|
||||
if h_wall { println!("+") } else { println!() }
|
||||
}
|
||||
|
||||
///Displays a whole row of walls
|
||||
fn paint_row(&self, h_walls: bool, index: usize) {
|
||||
let iter = if h_walls { self.walls_h[index].iter() } else { self.walls_v[index].iter() };
|
||||
for &wall in iter {
|
||||
Maze::paint_wall(h_walls, wall);
|
||||
}
|
||||
Maze::paint_close_wall(h_walls);
|
||||
}
|
||||
|
||||
///Paints the maze
|
||||
fn paint(&self) {
|
||||
for i in 0 .. HEIGHT {
|
||||
self.paint_row(true, i);
|
||||
self.paint_row(false, i);
|
||||
}
|
||||
self.paint_row(true, HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut maze = Maze::new();
|
||||
maze.build();
|
||||
maze.open_doors();
|
||||
maze.paint();
|
||||
}
|
||||
|
|
@ -4,13 +4,6 @@
|
|||
(defvar vi)
|
||||
(defvar pa)
|
||||
|
||||
(defun scramble (list)
|
||||
(let ((out ()))
|
||||
(each ((item list))
|
||||
(let ((r (random *r* (+ 1 (length out)))))
|
||||
(set [out r..r] (list item))))
|
||||
out))
|
||||
|
||||
(defun neigh (loc)
|
||||
(let ((x (from loc))
|
||||
(y (to loc)))
|
||||
|
|
@ -19,7 +12,7 @@
|
|||
|
||||
(defun make-maze-rec (cu)
|
||||
(set [vi cu] t)
|
||||
(each ((ne (scramble (neigh cu))))
|
||||
(each ((ne (shuffle (neigh cu))))
|
||||
(cond ((not [vi ne])
|
||||
(push ne [pa cu])
|
||||
(push cu [pa ne])
|
||||
|
|
|
|||
|
|
@ -2,13 +2,6 @@
|
|||
(defvar pa) ;; path connectivity hash
|
||||
(defvar sc) ;; count, derived from straightness fator
|
||||
|
||||
(defun scramble (list)
|
||||
(let ((out ()))
|
||||
(each ((item list))
|
||||
(let ((r (rand (+ 1 (length out)))))
|
||||
(set [out r..r] (list item))))
|
||||
out))
|
||||
|
||||
(defun rnd-pick (list)
|
||||
(if list [list (rand (length list))]))
|
||||
|
||||
|
|
@ -19,23 +12,20 @@
|
|||
x..(- y 1) x..(+ y 1))))
|
||||
|
||||
(defun make-maze-impl (cu)
|
||||
(let ((fr (hash :equal-based))
|
||||
(q (list cu))
|
||||
(let ((q (list cu))
|
||||
(c sc))
|
||||
(set [fr cu] t)
|
||||
(set [vi cu] t)
|
||||
(while q
|
||||
(let* ((cu (first q))
|
||||
(ne (rnd-pick (remove-if (orf vi fr) (neigh cu)))))
|
||||
(cond (ne (set [fr ne] t)
|
||||
(ne (rnd-pick (remove-if vi (neigh cu)))))
|
||||
(cond (ne (set [vi ne] t)
|
||||
(push ne [pa cu])
|
||||
(push cu [pa ne])
|
||||
(push ne q)
|
||||
(cond ((<= (dec c) 0)
|
||||
(set q (scramble q))
|
||||
(set q (shuffle q))
|
||||
(set c sc))))
|
||||
(t (set [vi cu] t)
|
||||
(del [fr cu])
|
||||
(pop q)))))))
|
||||
(t (pop q)))))))
|
||||
|
||||
(defun make-maze (w h sf)
|
||||
(let ((vi (hash :equal-based))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue