Data update
This commit is contained in:
parent
4bb20c9b71
commit
cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions
27
Task/Maze-generation/Ada/maze-generation-1.adb
Normal file
27
Task/Maze-generation/Ada/maze-generation-1.adb
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
generic
|
||||
Height : Positive;
|
||||
Width : Positive;
|
||||
package Mazes is
|
||||
|
||||
type Maze_Grid is private;
|
||||
|
||||
procedure Initialize (Maze : in out Maze_Grid);
|
||||
|
||||
procedure Put (Item : Maze_Grid);
|
||||
|
||||
private
|
||||
|
||||
type Directions is (North, South, West, East);
|
||||
|
||||
type Cell_Walls is array (Directions) of Boolean;
|
||||
type Cells is record
|
||||
Walls : Cell_Walls := (others => True);
|
||||
Visited : Boolean := False;
|
||||
end record;
|
||||
|
||||
subtype Height_Type is Positive range 1 .. Height;
|
||||
subtype Width_Type is Positive range 1 .. Width;
|
||||
|
||||
type Maze_Grid is array (Height_Type, Width_Type) of Cells;
|
||||
|
||||
end Mazes;
|
||||
173
Task/Maze-generation/Ada/maze-generation-2.adb
Normal file
173
Task/Maze-generation/Ada/maze-generation-2.adb
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
with Ada.Numerics.Discrete_Random;
|
||||
with Ada.Text_IO;
|
||||
|
||||
package body Mazes is
|
||||
package RNG is new Ada.Numerics.Discrete_Random (Positive);
|
||||
package Random_Direction is new Ada.Numerics.Discrete_Random (Directions);
|
||||
|
||||
Generator : RNG.Generator;
|
||||
Dir_Generator : Random_Direction.Generator;
|
||||
|
||||
function "-" (Dir : Directions) return Directions is
|
||||
begin
|
||||
case Dir is
|
||||
when North =>
|
||||
return South;
|
||||
when South =>
|
||||
return North;
|
||||
when East =>
|
||||
return West;
|
||||
when West =>
|
||||
return East;
|
||||
end case;
|
||||
end "-";
|
||||
|
||||
procedure Move
|
||||
(Row : in out Height_Type;
|
||||
Column : in out Width_Type;
|
||||
Direction : Directions;
|
||||
Valid_Move : out Boolean)
|
||||
is
|
||||
begin
|
||||
Valid_Move := False;
|
||||
case Direction is
|
||||
when North =>
|
||||
if Row > Height_Type'First then
|
||||
Valid_Move := True;
|
||||
Row := Row - 1;
|
||||
end if;
|
||||
when East =>
|
||||
if Column < Width_Type'Last then
|
||||
Valid_Move := True;
|
||||
Column := Column + 1;
|
||||
end if;
|
||||
when West =>
|
||||
if Column > Width_Type'First then
|
||||
Valid_Move := True;
|
||||
Column := Column - 1;
|
||||
end if;
|
||||
when South =>
|
||||
if Row < Height_Type'Last then
|
||||
Valid_Move := True;
|
||||
Row := Row + 1;
|
||||
end if;
|
||||
end case;
|
||||
end Move;
|
||||
|
||||
procedure Depth_First_Algorithm
|
||||
(Maze : in out Maze_Grid;
|
||||
Row : Height_Type;
|
||||
Column : Width_Type)
|
||||
is
|
||||
Next_Row : Height_Type;
|
||||
Next_Column : Width_Type;
|
||||
Next_Direction : Directions;
|
||||
Valid_Direction : Boolean;
|
||||
Tested_Wall : array (Directions) of Boolean := (others => False);
|
||||
All_Tested : Boolean;
|
||||
begin
|
||||
-- mark as visited
|
||||
Maze (Row, Column).Visited := True;
|
||||
loop
|
||||
-- use random direction
|
||||
loop
|
||||
Next_Direction := Random_Direction.Random (Dir_Generator);
|
||||
exit when not Tested_Wall (Next_Direction);
|
||||
end loop;
|
||||
Next_Row := Row;
|
||||
Next_Column := Column;
|
||||
Move (Next_Row, Next_Column, Next_Direction, Valid_Direction);
|
||||
if Valid_Direction then
|
||||
if not Maze (Next_Row, Next_Column).Visited then
|
||||
-- connect the two cells
|
||||
Maze (Row, Column).Walls (Next_Direction) :=
|
||||
False;
|
||||
Maze (Next_Row, Next_Column).Walls (-Next_Direction) :=
|
||||
False;
|
||||
Depth_First_Algorithm (Maze, Next_Row, Next_Column);
|
||||
end if;
|
||||
end if;
|
||||
Tested_Wall (Next_Direction) := True;
|
||||
-- continue as long as there are unvisited neighbours left
|
||||
All_Tested := True;
|
||||
for D in Directions loop
|
||||
All_Tested := All_Tested and Tested_Wall (D);
|
||||
end loop;
|
||||
-- all directions are either visited (from here,
|
||||
-- or previously visited), or invalid.
|
||||
exit when All_Tested;
|
||||
end loop;
|
||||
end Depth_First_Algorithm;
|
||||
|
||||
procedure Initialize (Maze : in out Maze_Grid) is
|
||||
Row, Column : Positive;
|
||||
begin
|
||||
-- initialize random generators
|
||||
RNG.Reset (Generator);
|
||||
Random_Direction.Reset (Dir_Generator);
|
||||
-- choose starting cell
|
||||
Row := RNG.Random (Generator) mod Height + 1;
|
||||
Column := RNG.Random (Generator) mod Width + 1;
|
||||
Ada.Text_IO.Put_Line
|
||||
("Starting generation at " &
|
||||
Positive'Image (Row) &
|
||||
" x" &
|
||||
Positive'Image (Column));
|
||||
Depth_First_Algorithm (Maze, Row, Column);
|
||||
end Initialize;
|
||||
|
||||
procedure Put (Item : Maze_Grid) is
|
||||
begin
|
||||
for Row in Item'Range (1) loop
|
||||
if Row = Item'First (1) then
|
||||
Ada.Text_IO.Put ('+');
|
||||
for Col in Item'Range (2) loop
|
||||
if Item (Row, Col).Walls (North) then
|
||||
Ada.Text_IO.Put ("---+");
|
||||
else
|
||||
Ada.Text_IO.Put (" +");
|
||||
end if;
|
||||
end loop;
|
||||
Ada.Text_IO.New_Line;
|
||||
end if;
|
||||
for Col in Item'Range (2) loop
|
||||
if Col = Item'First (2) then
|
||||
if Item (Row, Col).Walls (West) then
|
||||
Ada.Text_IO.Put ('|');
|
||||
else
|
||||
Ada.Text_IO.Put (' ');
|
||||
end if;
|
||||
elsif Item (Row, Col).Walls (West)
|
||||
and then Item (Row, Col - 1).Walls (East)
|
||||
then
|
||||
Ada.Text_IO.Put ('|');
|
||||
elsif Item (Row, Col).Walls (West)
|
||||
or else Item (Row, Col - 1).Walls (East)
|
||||
then
|
||||
Ada.Text_IO.Put ('>');
|
||||
else
|
||||
Ada.Text_IO.Put (' ');
|
||||
end if;
|
||||
if Item (Row, Col).Visited then
|
||||
Ada.Text_IO.Put (" ");
|
||||
else
|
||||
Ada.Text_IO.Put ("???");
|
||||
end if;
|
||||
end loop;
|
||||
if Item (Row, Item'Last (2)).Walls (East) then
|
||||
Ada.Text_IO.Put_Line ("|");
|
||||
else
|
||||
Ada.Text_IO.Put_Line (" ");
|
||||
end if;
|
||||
Ada.Text_IO.Put ('+');
|
||||
for Col in Item'Range (2) loop
|
||||
if Item (Row, Col).Walls (South) then
|
||||
Ada.Text_IO.Put ("---+");
|
||||
else
|
||||
Ada.Text_IO.Put (" +");
|
||||
end if;
|
||||
end loop;
|
||||
Ada.Text_IO.New_Line;
|
||||
end loop;
|
||||
end Put;
|
||||
end Mazes;
|
||||
8
Task/Maze-generation/Ada/maze-generation-3.adb
Normal file
8
Task/Maze-generation/Ada/maze-generation-3.adb
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
with Mazes;
|
||||
procedure Main is
|
||||
package Small_Mazes is new Mazes (Height => 8, Width => 11);
|
||||
My_Maze : Small_Mazes.Maze_Grid;
|
||||
begin
|
||||
Small_Mazes.Initialize (My_Maze);
|
||||
Small_Mazes.Put (My_Maze);
|
||||
end Main;
|
||||
|
|
@ -1,65 +1,65 @@
|
|||
; Initially build the board
|
||||
Width := 11
|
||||
Height := 8
|
||||
Width := 11
|
||||
Height := 8
|
||||
Loop % height*2+1
|
||||
{
|
||||
Outer := A_Index
|
||||
Loop % Width
|
||||
maze .= Outer & 1 ? "+-" : "|0"
|
||||
maze .= (Outer & 1 ? "+" : "|") "`n"
|
||||
Outer := A_Index
|
||||
Loop % Width
|
||||
maze .= Outer & 1 ? "+-" : "|0"
|
||||
maze .= (Outer & 1 ? "+" : "|") "`n"
|
||||
}
|
||||
StringTrimRight, maze, maze, 1 ; removes trailing newline
|
||||
Clipboard := Walk(maze)
|
||||
|
||||
Walk(S, x=0, y=0){
|
||||
If !x{ ; --Start at a random cell...
|
||||
StringReplace, junk, S, `n,,UseErrorLevel ; Calculate rows
|
||||
Random, y, 1, ErrorLevel//2
|
||||
Random, x, 1, InStr(S, "`n")//2-1 ; Calculate height
|
||||
}
|
||||
|
||||
; --Obtain a list of its neighbors...
|
||||
neighbors := x "," y+1 "`n" x "," y-1 "`n" x+1 "," y "`n" x-1 "," y
|
||||
; --Randomize the list...
|
||||
Sort neighbors, random
|
||||
|
||||
; --Then for each neighbor...
|
||||
Loop Parse, neighbors, `n
|
||||
{
|
||||
pC := InStr(A_LoopField, ","), x2 := SubStr(A_LoopField, 1, pC-1), y2 := SubStr(A_LoopField, pC+1)
|
||||
; If it has not been visited...
|
||||
If GetChar(S, 2*x2, 2*y2) = "0"{
|
||||
; Mark it as visited...
|
||||
S := ChangeChar(s, 2*x2, 2*y2, " ")
|
||||
; Remove the wall between this cell and the neighbor...
|
||||
S := ChangeChar(S, x+x2, y+y2, " ")
|
||||
; Then recurse with the neighbor as the current cell
|
||||
S := Walk(S, x2, y2)
|
||||
}
|
||||
}
|
||||
return S
|
||||
If !x{ ; --Start at a random cell...
|
||||
StringReplace, junk, S, `n,,UseErrorLevel ; Calculate rows
|
||||
Random, y, 1, ErrorLevel//2
|
||||
Random, x, 1, InStr(S, "`n")//2-1 ; Calculate height
|
||||
}
|
||||
|
||||
; --Obtain a list of its neighbors...
|
||||
neighbors := x "," y+1 "`n" x "," y-1 "`n" x+1 "," y "`n" x-1 "," y
|
||||
; --Randomize the list...
|
||||
Sort neighbors, random
|
||||
|
||||
; --Then for each neighbor...
|
||||
Loop Parse, neighbors, `n
|
||||
{
|
||||
pC := InStr(A_LoopField, ","), x2 := SubStr(A_LoopField, 1, pC-1), y2 := SubStr(A_LoopField, pC+1)
|
||||
; If it has not been visited...
|
||||
If GetChar(S, 2*x2, 2*y2) = "0"{
|
||||
; Mark it as visited...
|
||||
S := ChangeChar(s, 2*x2, 2*y2, " ")
|
||||
; Remove the wall between this cell and the neighbor...
|
||||
S := ChangeChar(S, x+x2, y+y2, " ")
|
||||
; Then recurse with the neighbor as the current cell
|
||||
S := Walk(S, x2, y2)
|
||||
}
|
||||
}
|
||||
return S
|
||||
}
|
||||
|
||||
|
||||
; Change a character in a string using x and y coordinates
|
||||
ChangeChar(s, x, y, c){
|
||||
Loop Parse, s, `n
|
||||
{
|
||||
If (A_Index = Y)
|
||||
Loop Parse, A_LoopField
|
||||
If (A_Index = x)
|
||||
out .= c
|
||||
Else out .= A_LoopField
|
||||
Else out .= A_LoopField
|
||||
out .= "`n"
|
||||
}
|
||||
StringTrimRight, out, out, 1
|
||||
return out
|
||||
Loop Parse, s, `n
|
||||
{
|
||||
If (A_Index = Y)
|
||||
Loop Parse, A_LoopField
|
||||
If (A_Index = x)
|
||||
out .= c
|
||||
Else out .= A_LoopField
|
||||
Else out .= A_LoopField
|
||||
out .= "`n"
|
||||
}
|
||||
StringTrimRight, out, out, 1
|
||||
return out
|
||||
}
|
||||
|
||||
; retrieve a character in a string using x and y coordinates
|
||||
GetChar(s, x, y, n=1){
|
||||
x*=n, y*=n
|
||||
Loop Parse, s, `n
|
||||
If (A_Index = Y)
|
||||
return SubStr(A_LoopField, x, 1)
|
||||
x*=n, y*=n
|
||||
Loop Parse, s, `n
|
||||
If (A_Index = Y)
|
||||
return SubStr(A_LoopField, x, 1)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,37 +47,37 @@ SET mz=!mz:~0,%curPos%!!hall!!mz:~%cTmp%!
|
|||
|
||||
:: iterate #cells*2+1 steps of random depth-first search
|
||||
FOR /L %%@ IN (1,1,%loops%) DO (
|
||||
SET "rand=" & SET "crmPos="
|
||||
REM set values for NSEW cell and wall positions
|
||||
SET /A "rCnt=rTmp=0, cTmp=curPos+1, np=curPos+N, sp=curPos+S, ep=curPos+E, wp=curPos+W, wChk=curPos/wide*wide, eChk=wChk+wide, nw=curPos-wide, sw=curPos+wide, ew=curPos+1, ww=curPos-1"
|
||||
REM examine adjacent cells, build direction list, and find last crumb position
|
||||
FOR /F "tokens=1-8" %%A IN ("!np! !sp! !ep! !wp! !nw! !sw! !ew! !ww!") DO (
|
||||
IF !np! GEQ 0 IF "!mz:~%%A,1!" EQU "!wall!" ( SET /A rCnt+=1 & SET "rand=n !rand!"
|
||||
) ELSE IF "!mz:~%%E,1!" EQU "!crumb!" SET /A crmPos=np, cw=nw
|
||||
IF !sp! LEQ !size! IF "!mz:~%%B,1!" EQU "!wall!" ( SET /A rCnt+=1 & SET "rand=s !rand!"
|
||||
) ELSE IF "!mz:~%%F,1!" EQU "!crumb!" SET /A crmPos=sp, cw=sw
|
||||
IF !ep! LEQ !eChk! IF "!mz:~%%C,1!" EQU "!wall!" ( SET /A rCnt+=1 & SET "rand=e !rand!"
|
||||
) ELSE IF "!mz:~%%G,1!" EQU "!crumb!" SET /A crmPos=ep, cw=ew
|
||||
IF !wp! GEQ !wChk! IF "!mz:~%%D,1!" EQU "!wall!" ( SET /A rCnt+=1 & SET "rand=w !rand!"
|
||||
) ELSE IF "!mz:~%%H,1!" EQU "!crumb!" SET /A crmPos=wp, cw=ww
|
||||
)
|
||||
IF DEFINED rand ( REM adjacent unvisited cell is available
|
||||
SET /A rCnt=!RANDOM! %% rCnt
|
||||
FOR %%A IN (!rand!) DO ( REM pick random cell + wall
|
||||
IF !rTmp! EQU !rCnt! SET /A "curPos=!%%Ap!, cTmp=curPos+1, mw=!%%Aw!, mTmp=mw+1"
|
||||
SET /A rTmp+=1
|
||||
)
|
||||
REM write the 2 new characters into the maze
|
||||
FOR /F "tokens=1-4" %%A IN ("!mw! !mTmp! !curPos! !cTmp!") DO (
|
||||
SET "mz=!mz:~0,%%A!!crumb!!mz:~%%B!"
|
||||
SET "mz=!mz:~0,%%C!!hall!!mz:~%%D!"
|
||||
)
|
||||
) ELSE IF DEFINED crmPos ( REM follow the crumbs backward
|
||||
SET /A mTmp=cw+1
|
||||
REM erase the crumb character and set new cursor position
|
||||
FOR /F "tokens=1-2" %%A IN ("!cw! !mTmp!") DO SET "mz=!mz:~0,%%A!!hall!!mz:~%%B!"
|
||||
SET "curPos=!crmPos!"
|
||||
)
|
||||
SET "rand=" & SET "crmPos="
|
||||
REM set values for NSEW cell and wall positions
|
||||
SET /A "rCnt=rTmp=0, cTmp=curPos+1, np=curPos+N, sp=curPos+S, ep=curPos+E, wp=curPos+W, wChk=curPos/wide*wide, eChk=wChk+wide, nw=curPos-wide, sw=curPos+wide, ew=curPos+1, ww=curPos-1"
|
||||
REM examine adjacent cells, build direction list, and find last crumb position
|
||||
FOR /F "tokens=1-8" %%A IN ("!np! !sp! !ep! !wp! !nw! !sw! !ew! !ww!") DO (
|
||||
IF !np! GEQ 0 IF "!mz:~%%A,1!" EQU "!wall!" ( SET /A rCnt+=1 & SET "rand=n !rand!"
|
||||
) ELSE IF "!mz:~%%E,1!" EQU "!crumb!" SET /A crmPos=np, cw=nw
|
||||
IF !sp! LEQ !size! IF "!mz:~%%B,1!" EQU "!wall!" ( SET /A rCnt+=1 & SET "rand=s !rand!"
|
||||
) ELSE IF "!mz:~%%F,1!" EQU "!crumb!" SET /A crmPos=sp, cw=sw
|
||||
IF !ep! LEQ !eChk! IF "!mz:~%%C,1!" EQU "!wall!" ( SET /A rCnt+=1 & SET "rand=e !rand!"
|
||||
) ELSE IF "!mz:~%%G,1!" EQU "!crumb!" SET /A crmPos=ep, cw=ew
|
||||
IF !wp! GEQ !wChk! IF "!mz:~%%D,1!" EQU "!wall!" ( SET /A rCnt+=1 & SET "rand=w !rand!"
|
||||
) ELSE IF "!mz:~%%H,1!" EQU "!crumb!" SET /A crmPos=wp, cw=ww
|
||||
)
|
||||
IF DEFINED rand ( REM adjacent unvisited cell is available
|
||||
SET /A rCnt=!RANDOM! %% rCnt
|
||||
FOR %%A IN (!rand!) DO ( REM pick random cell + wall
|
||||
IF !rTmp! EQU !rCnt! SET /A "curPos=!%%Ap!, cTmp=curPos+1, mw=!%%Aw!, mTmp=mw+1"
|
||||
SET /A rTmp+=1
|
||||
)
|
||||
REM write the 2 new characters into the maze
|
||||
FOR /F "tokens=1-4" %%A IN ("!mw! !mTmp! !curPos! !cTmp!") DO (
|
||||
SET "mz=!mz:~0,%%A!!crumb!!mz:~%%B!"
|
||||
SET "mz=!mz:~0,%%C!!hall!!mz:~%%D!"
|
||||
)
|
||||
) ELSE IF DEFINED crmPos ( REM follow the crumbs backward
|
||||
SET /A mTmp=cw+1
|
||||
REM erase the crumb character and set new cursor position
|
||||
FOR /F "tokens=1-2" %%A IN ("!cw! !mTmp!") DO SET "mz=!mz:~0,%%A!!hall!!mz:~%%B!"
|
||||
SET "curPos=!crmPos!"
|
||||
)
|
||||
)
|
||||
SET /A open=cols/2*2, mTmp=open+1
|
||||
ECHO !wall!!bdr:~0,%open%!!hall!!bdr:~%mTmp%!!wall!
|
||||
|
|
|
|||
|
|
@ -18,81 +18,81 @@ public:
|
|||
myBitmap() : pen( NULL ) {}
|
||||
~myBitmap()
|
||||
{
|
||||
DeleteObject( pen );
|
||||
DeleteDC( hdc );
|
||||
DeleteObject( bmp );
|
||||
DeleteObject( pen );
|
||||
DeleteDC( hdc );
|
||||
DeleteObject( bmp );
|
||||
}
|
||||
|
||||
bool create( int w, int h )
|
||||
{
|
||||
BITMAPINFO bi;
|
||||
ZeroMemory( &bi, sizeof( bi ) );
|
||||
bi.bmiHeader.biSize = sizeof( bi.bmiHeader );
|
||||
bi.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
|
||||
bi.bmiHeader.biCompression = BI_RGB;
|
||||
bi.bmiHeader.biPlanes = 1;
|
||||
bi.bmiHeader.biWidth = w;
|
||||
bi.bmiHeader.biHeight = -h;
|
||||
BITMAPINFO bi;
|
||||
ZeroMemory( &bi, sizeof( bi ) );
|
||||
bi.bmiHeader.biSize = sizeof( bi.bmiHeader );
|
||||
bi.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
|
||||
bi.bmiHeader.biCompression = BI_RGB;
|
||||
bi.bmiHeader.biPlanes = 1;
|
||||
bi.bmiHeader.biWidth = w;
|
||||
bi.bmiHeader.biHeight = -h;
|
||||
|
||||
HDC dc = GetDC( GetConsoleWindow() );
|
||||
bmp = CreateDIBSection( dc, &bi, DIB_RGB_COLORS, &pBits, NULL, 0 );
|
||||
if( !bmp ) return false;
|
||||
HDC dc = GetDC( GetConsoleWindow() );
|
||||
bmp = CreateDIBSection( dc, &bi, DIB_RGB_COLORS, &pBits, NULL, 0 );
|
||||
if( !bmp ) return false;
|
||||
|
||||
hdc = CreateCompatibleDC( dc );
|
||||
SelectObject( hdc, bmp );
|
||||
ReleaseDC( GetConsoleWindow(), dc );
|
||||
width = w; height = h;
|
||||
hdc = CreateCompatibleDC( dc );
|
||||
SelectObject( hdc, bmp );
|
||||
ReleaseDC( GetConsoleWindow(), dc );
|
||||
width = w; height = h;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
ZeroMemory( pBits, width * height * sizeof( DWORD ) );
|
||||
ZeroMemory( pBits, width * height * sizeof( DWORD ) );
|
||||
}
|
||||
|
||||
void setPenColor( DWORD clr )
|
||||
{
|
||||
if( pen ) DeleteObject( pen );
|
||||
pen = CreatePen( PS_SOLID, 1, clr );
|
||||
SelectObject( hdc, pen );
|
||||
if( pen ) DeleteObject( pen );
|
||||
pen = CreatePen( PS_SOLID, 1, clr );
|
||||
SelectObject( hdc, pen );
|
||||
}
|
||||
|
||||
void saveBitmap( string path )
|
||||
{
|
||||
BITMAPFILEHEADER fileheader;
|
||||
BITMAPINFO infoheader;
|
||||
BITMAP bitmap;
|
||||
DWORD wb;
|
||||
BITMAPFILEHEADER fileheader;
|
||||
BITMAPINFO infoheader;
|
||||
BITMAP bitmap;
|
||||
DWORD wb;
|
||||
|
||||
GetObject( bmp, sizeof( bitmap ), &bitmap );
|
||||
GetObject( bmp, sizeof( bitmap ), &bitmap );
|
||||
|
||||
DWORD* dwpBits = new DWORD[bitmap.bmWidth * bitmap.bmHeight];
|
||||
ZeroMemory( dwpBits, bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD ) );
|
||||
ZeroMemory( &infoheader, sizeof( BITMAPINFO ) );
|
||||
ZeroMemory( &fileheader, sizeof( BITMAPFILEHEADER ) );
|
||||
DWORD* dwpBits = new DWORD[bitmap.bmWidth * bitmap.bmHeight];
|
||||
ZeroMemory( dwpBits, bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD ) );
|
||||
ZeroMemory( &infoheader, sizeof( BITMAPINFO ) );
|
||||
ZeroMemory( &fileheader, sizeof( BITMAPFILEHEADER ) );
|
||||
|
||||
infoheader.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
|
||||
infoheader.bmiHeader.biCompression = BI_RGB;
|
||||
infoheader.bmiHeader.biPlanes = 1;
|
||||
infoheader.bmiHeader.biSize = sizeof( infoheader.bmiHeader );
|
||||
infoheader.bmiHeader.biHeight = bitmap.bmHeight;
|
||||
infoheader.bmiHeader.biWidth = bitmap.bmWidth;
|
||||
infoheader.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD );
|
||||
infoheader.bmiHeader.biBitCount = sizeof( DWORD ) * 8;
|
||||
infoheader.bmiHeader.biCompression = BI_RGB;
|
||||
infoheader.bmiHeader.biPlanes = 1;
|
||||
infoheader.bmiHeader.biSize = sizeof( infoheader.bmiHeader );
|
||||
infoheader.bmiHeader.biHeight = bitmap.bmHeight;
|
||||
infoheader.bmiHeader.biWidth = bitmap.bmWidth;
|
||||
infoheader.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * sizeof( DWORD );
|
||||
|
||||
fileheader.bfType = 0x4D42;
|
||||
fileheader.bfOffBits = sizeof( infoheader.bmiHeader ) + sizeof( BITMAPFILEHEADER );
|
||||
fileheader.bfSize = fileheader.bfOffBits + infoheader.bmiHeader.biSizeImage;
|
||||
fileheader.bfType = 0x4D42;
|
||||
fileheader.bfOffBits = sizeof( infoheader.bmiHeader ) + sizeof( BITMAPFILEHEADER );
|
||||
fileheader.bfSize = fileheader.bfOffBits + infoheader.bmiHeader.biSizeImage;
|
||||
|
||||
GetDIBits( hdc, bmp, 0, height, ( LPVOID )dwpBits, &infoheader, DIB_RGB_COLORS );
|
||||
GetDIBits( hdc, bmp, 0, height, ( LPVOID )dwpBits, &infoheader, DIB_RGB_COLORS );
|
||||
|
||||
HANDLE file = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
WriteFile( file, &fileheader, sizeof( BITMAPFILEHEADER ), &wb, NULL );
|
||||
WriteFile( file, &infoheader.bmiHeader, sizeof( infoheader.bmiHeader ), &wb, NULL );
|
||||
WriteFile( file, dwpBits, bitmap.bmWidth * bitmap.bmHeight * 4, &wb, NULL );
|
||||
CloseHandle( file );
|
||||
HANDLE file = CreateFile( path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
WriteFile( file, &fileheader, sizeof( BITMAPFILEHEADER ), &wb, NULL );
|
||||
WriteFile( file, &infoheader.bmiHeader, sizeof( infoheader.bmiHeader ), &wb, NULL );
|
||||
WriteFile( file, dwpBits, bitmap.bmWidth * bitmap.bmHeight * 4, &wb, NULL );
|
||||
CloseHandle( file );
|
||||
|
||||
delete [] dwpBits;
|
||||
delete [] dwpBits;
|
||||
}
|
||||
|
||||
HDC getDC() const { return hdc; }
|
||||
|
|
@ -101,10 +101,10 @@ public:
|
|||
|
||||
private:
|
||||
HBITMAP bmp;
|
||||
HDC hdc;
|
||||
HDC hdc;
|
||||
HPEN pen;
|
||||
void *pBits;
|
||||
int width, height;
|
||||
int width, height;
|
||||
};
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
class mazeGenerator
|
||||
|
|
@ -112,132 +112,132 @@ class mazeGenerator
|
|||
public:
|
||||
mazeGenerator()
|
||||
{
|
||||
_world = 0;
|
||||
_bmp.create( BMP_SIZE, BMP_SIZE );
|
||||
_bmp.setPenColor( RGB( 0, 255, 0 ) );
|
||||
_world = 0;
|
||||
_bmp.create( BMP_SIZE, BMP_SIZE );
|
||||
_bmp.setPenColor( RGB( 0, 255, 0 ) );
|
||||
}
|
||||
|
||||
~mazeGenerator() { killArray(); }
|
||||
|
||||
void create( int side )
|
||||
{
|
||||
_s = side;
|
||||
generate();
|
||||
display();
|
||||
_s = side;
|
||||
generate();
|
||||
display();
|
||||
}
|
||||
|
||||
private:
|
||||
void generate()
|
||||
{
|
||||
killArray();
|
||||
_world = new BYTE[_s * _s];
|
||||
ZeroMemory( _world, _s * _s );
|
||||
_ptX = rand() % _s; _ptY = rand() % _s;
|
||||
carve();
|
||||
killArray();
|
||||
_world = new BYTE[_s * _s];
|
||||
ZeroMemory( _world, _s * _s );
|
||||
_ptX = rand() % _s; _ptY = rand() % _s;
|
||||
carve();
|
||||
}
|
||||
|
||||
void carve()
|
||||
{
|
||||
while( true )
|
||||
{
|
||||
int d = getDirection();
|
||||
if( d < NOR ) return;
|
||||
while( true )
|
||||
{
|
||||
int d = getDirection();
|
||||
if( d < NOR ) return;
|
||||
|
||||
switch( d )
|
||||
{
|
||||
case NOR:
|
||||
_world[_ptX + _s * _ptY] |= NOR; _ptY--;
|
||||
_world[_ptX + _s * _ptY] = SOU | SOU << 4;
|
||||
break;
|
||||
case EAS:
|
||||
_world[_ptX + _s * _ptY] |= EAS; _ptX++;
|
||||
_world[_ptX + _s * _ptY] = WES | WES << 4;
|
||||
break;
|
||||
case SOU:
|
||||
_world[_ptX + _s * _ptY] |= SOU; _ptY++;
|
||||
_world[_ptX + _s * _ptY] = NOR | NOR << 4;
|
||||
break;
|
||||
case WES:
|
||||
_world[_ptX + _s * _ptY] |= WES; _ptX--;
|
||||
_world[_ptX + _s * _ptY] = EAS | EAS << 4;
|
||||
}
|
||||
}
|
||||
switch( d )
|
||||
{
|
||||
case NOR:
|
||||
_world[_ptX + _s * _ptY] |= NOR; _ptY--;
|
||||
_world[_ptX + _s * _ptY] = SOU | SOU << 4;
|
||||
break;
|
||||
case EAS:
|
||||
_world[_ptX + _s * _ptY] |= EAS; _ptX++;
|
||||
_world[_ptX + _s * _ptY] = WES | WES << 4;
|
||||
break;
|
||||
case SOU:
|
||||
_world[_ptX + _s * _ptY] |= SOU; _ptY++;
|
||||
_world[_ptX + _s * _ptY] = NOR | NOR << 4;
|
||||
break;
|
||||
case WES:
|
||||
_world[_ptX + _s * _ptY] |= WES; _ptX--;
|
||||
_world[_ptX + _s * _ptY] = EAS | EAS << 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void display()
|
||||
{
|
||||
_bmp.clear();
|
||||
HDC dc = _bmp.getDC();
|
||||
for( int y = 0; y < _s; y++ )
|
||||
{
|
||||
int yy = y * _s;
|
||||
for( int x = 0; x < _s; x++ )
|
||||
{
|
||||
BYTE b = _world[x + yy];
|
||||
int nx = x * CELL_SIZE,
|
||||
ny = y * CELL_SIZE;
|
||||
|
||||
if( !( b & NOR ) )
|
||||
{
|
||||
MoveToEx( dc, nx, ny, NULL );
|
||||
LineTo( dc, nx + CELL_SIZE + 1, ny );
|
||||
}
|
||||
if( !( b & EAS ) )
|
||||
{
|
||||
MoveToEx( dc, nx + CELL_SIZE, ny, NULL );
|
||||
LineTo( dc, nx + CELL_SIZE, ny + CELL_SIZE + 1 );
|
||||
}
|
||||
if( !( b & SOU ) )
|
||||
{
|
||||
MoveToEx( dc, nx, ny + CELL_SIZE, NULL );
|
||||
LineTo( dc, nx + CELL_SIZE + 1, ny + CELL_SIZE );
|
||||
}
|
||||
if( !( b & WES ) )
|
||||
{
|
||||
MoveToEx( dc, nx, ny, NULL );
|
||||
LineTo( dc, nx, ny + CELL_SIZE + 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
_bmp.clear();
|
||||
HDC dc = _bmp.getDC();
|
||||
for( int y = 0; y < _s; y++ )
|
||||
{
|
||||
int yy = y * _s;
|
||||
for( int x = 0; x < _s; x++ )
|
||||
{
|
||||
BYTE b = _world[x + yy];
|
||||
int nx = x * CELL_SIZE,
|
||||
ny = y * CELL_SIZE;
|
||||
|
||||
//_bmp.saveBitmap( "f:\\rc\\maze.bmp" );
|
||||
BitBlt( GetDC( GetConsoleWindow() ), 10, 60, BMP_SIZE, BMP_SIZE, _bmp.getDC(), 0, 0, SRCCOPY );
|
||||
if( !( b & NOR ) )
|
||||
{
|
||||
MoveToEx( dc, nx, ny, NULL );
|
||||
LineTo( dc, nx + CELL_SIZE + 1, ny );
|
||||
}
|
||||
if( !( b & EAS ) )
|
||||
{
|
||||
MoveToEx( dc, nx + CELL_SIZE, ny, NULL );
|
||||
LineTo( dc, nx + CELL_SIZE, ny + CELL_SIZE + 1 );
|
||||
}
|
||||
if( !( b & SOU ) )
|
||||
{
|
||||
MoveToEx( dc, nx, ny + CELL_SIZE, NULL );
|
||||
LineTo( dc, nx + CELL_SIZE + 1, ny + CELL_SIZE );
|
||||
}
|
||||
if( !( b & WES ) )
|
||||
{
|
||||
MoveToEx( dc, nx, ny, NULL );
|
||||
LineTo( dc, nx, ny + CELL_SIZE + 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//_bmp.saveBitmap( "f:\\rc\\maze.bmp" );
|
||||
BitBlt( GetDC( GetConsoleWindow() ), 10, 60, BMP_SIZE, BMP_SIZE, _bmp.getDC(), 0, 0, SRCCOPY );
|
||||
}
|
||||
|
||||
int getDirection()
|
||||
{
|
||||
int d = 1 << rand() % 4;
|
||||
while( true )
|
||||
{
|
||||
for( int x = 0; x < 4; x++ )
|
||||
{
|
||||
if( testDir( d ) ) return d;
|
||||
d <<= 1;
|
||||
if( d > 8 ) d = 1;
|
||||
}
|
||||
d = ( _world[_ptX + _s * _ptY] & 0xf0 ) >> 4;
|
||||
if( !d ) return -1;
|
||||
switch( d )
|
||||
{
|
||||
case NOR: _ptY--; break;
|
||||
case EAS: _ptX++; break;
|
||||
case SOU: _ptY++; break;
|
||||
case WES: _ptX--; break;
|
||||
}
|
||||
int d = 1 << rand() % 4;
|
||||
while( true )
|
||||
{
|
||||
for( int x = 0; x < 4; x++ )
|
||||
{
|
||||
if( testDir( d ) ) return d;
|
||||
d <<= 1;
|
||||
if( d > 8 ) d = 1;
|
||||
}
|
||||
d = ( _world[_ptX + _s * _ptY] & 0xf0 ) >> 4;
|
||||
if( !d ) return -1;
|
||||
switch( d )
|
||||
{
|
||||
case NOR: _ptY--; break;
|
||||
case EAS: _ptX++; break;
|
||||
case SOU: _ptY++; break;
|
||||
case WES: _ptX--; break;
|
||||
}
|
||||
d = 1 << rand() % 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool testDir( int d )
|
||||
{
|
||||
switch( d )
|
||||
{
|
||||
case NOR: return ( _ptY - 1 > -1 && !_world[_ptX + _s * ( _ptY - 1 )] );
|
||||
case EAS: return ( _ptX + 1 < _s && !_world[_ptX + 1 + _s * _ptY] );
|
||||
case SOU: return ( _ptY + 1 < _s && !_world[_ptX + _s * ( _ptY + 1 )] );
|
||||
case WES: return ( _ptX - 1 > -1 && !_world[_ptX - 1 + _s * _ptY] );
|
||||
}
|
||||
return false;
|
||||
switch( d )
|
||||
{
|
||||
case NOR: return ( _ptY - 1 > -1 && !_world[_ptX + _s * ( _ptY - 1 )] );
|
||||
case EAS: return ( _ptX + 1 < _s && !_world[_ptX + 1 + _s * _ptY] );
|
||||
case SOU: return ( _ptY + 1 < _s && !_world[_ptX + _s * ( _ptY + 1 )] );
|
||||
case WES: return ( _ptX - 1 > -1 && !_world[_ptX - 1 + _s * _ptY] );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void killArray() { if( _world ) delete [] _world; }
|
||||
|
|
@ -256,13 +256,13 @@ int main( int argc, char* argv[] )
|
|||
int s;
|
||||
while( true )
|
||||
{
|
||||
cout << "Enter the maze size, an odd number bigger than 2 ( 0 to QUIT ): "; cin >> s;
|
||||
if( !s ) return 0;
|
||||
if( !( s & 1 ) ) s++;
|
||||
if( s >= 3 ) mg.create( s );
|
||||
cout << endl;
|
||||
system( "pause" );
|
||||
system( "cls" );
|
||||
cout << "Enter the maze size, an odd number bigger than 2 ( 0 to QUIT ): "; cin >> s;
|
||||
if( !s ) return 0;
|
||||
if( !( s & 1 ) ) s++;
|
||||
if( s >= 3 ) mg.create( s );
|
||||
cout << endl;
|
||||
system( "pause" );
|
||||
system( "cls" );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
#define DOUBLE_SPACE 1
|
||||
|
||||
#if DOUBLE_SPACE
|
||||
# define SPC " "
|
||||
# define SPC " "
|
||||
#else
|
||||
# define SPC " "
|
||||
# define SPC " "
|
||||
#endif
|
||||
|
||||
wchar_t glyph[] = L""SPC"│││─┘┐┤─└┌├─┴┬┼"SPC"┆┆┆┄╯╮ ┄╰╭ ┄";
|
||||
|
|
@ -22,23 +22,23 @@ int w, h, avail;
|
|||
|
||||
int irand(int n)
|
||||
{
|
||||
int r, rmax = n * (RAND_MAX / n);
|
||||
while ((r = rand()) >= rmax);
|
||||
return r / (RAND_MAX/n);
|
||||
int r, rmax = n * (RAND_MAX / n);
|
||||
while ((r = rand()) >= rmax);
|
||||
return r / (RAND_MAX/n);
|
||||
}
|
||||
|
||||
void show()
|
||||
{
|
||||
int i, j, c;
|
||||
each(i, 0, 2 * h) {
|
||||
each(j, 0, 2 * w) {
|
||||
c = cell[i][j];
|
||||
if (c > V) printf("\033[31m");
|
||||
printf("%lc", glyph[c]);
|
||||
if (c > V) printf("\033[m");
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
int i, j, c;
|
||||
each(i, 0, 2 * h) {
|
||||
each(j, 0, 2 * w) {
|
||||
c = cell[i][j];
|
||||
if (c > V) printf("\033[31m");
|
||||
printf("%lc", glyph[c]);
|
||||
if (c > V) printf("\033[m");
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
inline int max(int a, int b) { return a >= b ? a : b; }
|
||||
|
|
@ -47,100 +47,100 @@ inline int min(int a, int b) { return b >= a ? a : b; }
|
|||
static int dirs[4][2] = {{-2, 0}, {0, 2}, {2, 0}, {0, -2}};
|
||||
void walk(int x, int y)
|
||||
{
|
||||
int i, t, x1, y1, d[4] = { 0, 1, 2, 3 };
|
||||
int i, t, x1, y1, d[4] = { 0, 1, 2, 3 };
|
||||
|
||||
cell[y][x] |= V;
|
||||
avail--;
|
||||
cell[y][x] |= V;
|
||||
avail--;
|
||||
|
||||
for (x1 = 3; x1; x1--)
|
||||
if (x1 != (y1 = irand(x1 + 1)))
|
||||
i = d[x1], d[x1] = d[y1], d[y1] = i;
|
||||
for (x1 = 3; x1; x1--)
|
||||
if (x1 != (y1 = irand(x1 + 1)))
|
||||
i = d[x1], d[x1] = d[y1], d[y1] = i;
|
||||
|
||||
for (i = 0; avail && i < 4; i++) {
|
||||
x1 = x + dirs[ d[i] ][0], y1 = y + dirs[ d[i] ][1];
|
||||
for (i = 0; avail && i < 4; i++) {
|
||||
x1 = x + dirs[ d[i] ][0], y1 = y + dirs[ d[i] ][1];
|
||||
|
||||
if (cell[y1][x1] & V) continue;
|
||||
if (cell[y1][x1] & V) continue;
|
||||
|
||||
/* break walls */
|
||||
if (x1 == x) {
|
||||
t = (y + y1) / 2;
|
||||
cell[t][x+1] &= ~W, cell[t][x] &= ~(E|W), cell[t][x-1] &= ~E;
|
||||
} else if (y1 == y) {
|
||||
t = (x + x1)/2;
|
||||
cell[y-1][t] &= ~S, cell[y][t] &= ~(N|S), cell[y+1][t] &= ~N;
|
||||
}
|
||||
walk(x1, y1);
|
||||
}
|
||||
/* break walls */
|
||||
if (x1 == x) {
|
||||
t = (y + y1) / 2;
|
||||
cell[t][x+1] &= ~W, cell[t][x] &= ~(E|W), cell[t][x-1] &= ~E;
|
||||
} else if (y1 == y) {
|
||||
t = (x + x1)/2;
|
||||
cell[y-1][t] &= ~S, cell[y][t] &= ~(N|S), cell[y+1][t] &= ~N;
|
||||
}
|
||||
walk(x1, y1);
|
||||
}
|
||||
}
|
||||
|
||||
int solve(int x, int y, int tox, int toy)
|
||||
{
|
||||
int i, t, x1, y1;
|
||||
int i, t, x1, y1;
|
||||
|
||||
cell[y][x] |= V;
|
||||
if (x == tox && y == toy) return 1;
|
||||
cell[y][x] |= V;
|
||||
if (x == tox && y == toy) return 1;
|
||||
|
||||
each(i, 0, 3) {
|
||||
x1 = x + dirs[i][0], y1 = y + dirs[i][1];
|
||||
if (cell[y1][x1]) continue;
|
||||
each(i, 0, 3) {
|
||||
x1 = x + dirs[i][0], y1 = y + dirs[i][1];
|
||||
if (cell[y1][x1]) continue;
|
||||
|
||||
/* mark path */
|
||||
if (x1 == x) {
|
||||
t = (y + y1)/2;
|
||||
if (cell[t][x] || !solve(x1, y1, tox, toy)) continue;
|
||||
/* mark path */
|
||||
if (x1 == x) {
|
||||
t = (y + y1)/2;
|
||||
if (cell[t][x] || !solve(x1, y1, tox, toy)) continue;
|
||||
|
||||
cell[t-1][x] |= S, cell[t][x] |= V|N|S, cell[t+1][x] |= N;
|
||||
} else if (y1 == y) {
|
||||
t = (x + x1)/2;
|
||||
if (cell[y][t] || !solve(x1, y1, tox, toy)) continue;
|
||||
cell[t-1][x] |= S, cell[t][x] |= V|N|S, cell[t+1][x] |= N;
|
||||
} else if (y1 == y) {
|
||||
t = (x + x1)/2;
|
||||
if (cell[y][t] || !solve(x1, y1, tox, toy)) continue;
|
||||
|
||||
cell[y][t-1] |= E, cell[y][t] |= V|E|W, cell[y][t+1] |= W;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
cell[y][t-1] |= E, cell[y][t] |= V|E|W, cell[y][t+1] |= W;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* backtrack */
|
||||
cell[y][x] &= ~V;
|
||||
return 0;
|
||||
/* backtrack */
|
||||
cell[y][x] &= ~V;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void make_maze()
|
||||
{
|
||||
int i, j;
|
||||
int h2 = 2 * h + 2, w2 = 2 * w + 2;
|
||||
byte **p;
|
||||
int i, j;
|
||||
int h2 = 2 * h + 2, w2 = 2 * w + 2;
|
||||
byte **p;
|
||||
|
||||
p = calloc(sizeof(byte*) * (h2 + 2) + w2 * h2 + 1, 1);
|
||||
p = calloc(sizeof(byte*) * (h2 + 2) + w2 * h2 + 1, 1);
|
||||
|
||||
p[1] = (byte*)(p + h2 + 2) + 1;
|
||||
each(i, 2, h2) p[i] = p[i-1] + w2;
|
||||
p[0] = p[h2];
|
||||
cell = &p[1];
|
||||
p[1] = (byte*)(p + h2 + 2) + 1;
|
||||
each(i, 2, h2) p[i] = p[i-1] + w2;
|
||||
p[0] = p[h2];
|
||||
cell = &p[1];
|
||||
|
||||
each(i, -1, 2 * h + 1) cell[i][-1] = cell[i][w2 - 1] = V;
|
||||
each(j, 0, 2 * w) cell[-1][j] = cell[h2 - 1][j] = V;
|
||||
each(i, 0, h) each(j, 0, 2 * w) cell[2*i][j] |= E|W;
|
||||
each(i, 0, 2 * h) each(j, 0, w) cell[i][2*j] |= N|S;
|
||||
each(j, 0, 2 * w) cell[0][j] &= ~N, cell[2*h][j] &= ~S;
|
||||
each(i, 0, 2 * h) cell[i][0] &= ~W, cell[i][2*w] &= ~E;
|
||||
each(i, -1, 2 * h + 1) cell[i][-1] = cell[i][w2 - 1] = V;
|
||||
each(j, 0, 2 * w) cell[-1][j] = cell[h2 - 1][j] = V;
|
||||
each(i, 0, h) each(j, 0, 2 * w) cell[2*i][j] |= E|W;
|
||||
each(i, 0, 2 * h) each(j, 0, w) cell[i][2*j] |= N|S;
|
||||
each(j, 0, 2 * w) cell[0][j] &= ~N, cell[2*h][j] &= ~S;
|
||||
each(i, 0, 2 * h) cell[i][0] &= ~W, cell[i][2*w] &= ~E;
|
||||
|
||||
avail = w * h;
|
||||
walk(irand(2) * 2 + 1, irand(h) * 2 + 1);
|
||||
avail = w * h;
|
||||
walk(irand(2) * 2 + 1, irand(h) * 2 + 1);
|
||||
|
||||
/* reset visited marker (it's also used by path finder) */
|
||||
each(i, 0, 2 * h) each(j, 0, 2 * w) cell[i][j] &= ~V;
|
||||
solve(1, 1, 2 * w - 1, 2 * h - 1);
|
||||
/* reset visited marker (it's also used by path finder) */
|
||||
each(i, 0, 2 * h) each(j, 0, 2 * w) cell[i][j] &= ~V;
|
||||
solve(1, 1, 2 * w - 1, 2 * h - 1);
|
||||
|
||||
show();
|
||||
show();
|
||||
}
|
||||
|
||||
int main(int c, char **v)
|
||||
{
|
||||
setlocale(LC_ALL, "");
|
||||
if (c < 2 || (w = atoi(v[1])) <= 0) w = 16;
|
||||
if (c < 3 || (h = atoi(v[2])) <= 0) h = 8;
|
||||
setlocale(LC_ALL, "");
|
||||
if (c < 2 || (w = atoi(v[1])) <= 0) w = 16;
|
||||
if (c < 3 || (h = atoi(v[2])) <= 0) h = 8;
|
||||
|
||||
make_maze();
|
||||
make_maze();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
56
Task/Maze-generation/Chapel/maze-generation.chpl
Normal file
56
Task/Maze-generation/Chapel/maze-generation.chpl
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
use Random;
|
||||
|
||||
config const rows: int = 9;
|
||||
config const cols: int = 16;
|
||||
if rows < 1 || cols < 1 {
|
||||
writeln("Maze must be at least 1x1 in size.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
enum direction {N = 1, E = 2, S = 3, W = 4};
|
||||
|
||||
record Cell {
|
||||
var spaces: [direction.N .. direction.W] bool;
|
||||
var visited: bool;
|
||||
}
|
||||
|
||||
const dirs = [
|
||||
((-1, 0), direction.N, direction.S), // ((rowDir, colDir), myWall, neighbourWall)
|
||||
((0, 1), direction.E, direction.W),
|
||||
((1, 0), direction.S, direction.N),
|
||||
((0, -1), direction.W, direction.E)
|
||||
];
|
||||
|
||||
var maze: [1..rows, 1..cols] Cell;
|
||||
var startingCell = (choose(maze.dim(0)), choose(maze.dim(1)));
|
||||
|
||||
checkCell(maze, startingCell);
|
||||
displayMaze(maze);
|
||||
|
||||
proc checkCell(ref maze, cell) {
|
||||
maze[cell].visited = true;
|
||||
for dir in permute(dirs) {
|
||||
var (offset, thisDir, neighbourDir) = dir;
|
||||
var neighbour = cell + offset;
|
||||
if maze.domain.contains(neighbour) && !maze[neighbour].visited {
|
||||
maze[cell].spaces[thisDir] = true;
|
||||
maze[neighbour].spaces[neighbourDir] = true;
|
||||
checkCell(maze, neighbour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc displayMaze(maze) {
|
||||
for row in maze.dim(0) {
|
||||
for col in maze.dim(1) {
|
||||
write(if maze[row, col].spaces[direction.N] then "+ " else "+---");
|
||||
}
|
||||
writeln("+");
|
||||
for col in maze.dim(1) {
|
||||
write(if maze[row, col].spaces[direction.W] then " " else "| ");
|
||||
}
|
||||
writeln("|");
|
||||
}
|
||||
write("+---" * maze.dim(1).size);
|
||||
writeln("+");
|
||||
}
|
||||
|
|
@ -8,48 +8,48 @@
|
|||
|
||||
(defun make-maze (w h)
|
||||
(let ((vis (2d-array w h))
|
||||
(ver (2d-array w h))
|
||||
(hor (2d-array w h)))
|
||||
(ver (2d-array w h))
|
||||
(hor (2d-array w h)))
|
||||
(labels
|
||||
((walk (y x)
|
||||
(setf (aref vis y x) 1)
|
||||
(loop
|
||||
(let (x2 y2)
|
||||
(loop for (dx dy) in '((-1 0) (1 0) (0 -1) (0 1))
|
||||
with cnt = 0 do
|
||||
(let ((xx (+ x dx))
|
||||
(yy (+ y dy)))
|
||||
(if (and (array-in-bounds-p vis yy xx)
|
||||
(zerop (aref vis yy xx))
|
||||
(zerop (random (incf cnt))))
|
||||
(setf x2 xx y2 yy))))
|
||||
(if (not x2) (return-from walk))
|
||||
(if (= x x2)
|
||||
(setf (aref hor (min y y2) x) 1)
|
||||
(setf (aref ver y (min x x2)) 1))
|
||||
(walk y2 x2))))
|
||||
(setf (aref vis y x) 1)
|
||||
(loop
|
||||
(let (x2 y2)
|
||||
(loop for (dx dy) in '((-1 0) (1 0) (0 -1) (0 1))
|
||||
with cnt = 0 do
|
||||
(let ((xx (+ x dx))
|
||||
(yy (+ y dy)))
|
||||
(if (and (array-in-bounds-p vis yy xx)
|
||||
(zerop (aref vis yy xx))
|
||||
(zerop (random (incf cnt))))
|
||||
(setf x2 xx y2 yy))))
|
||||
(if (not x2) (return-from walk))
|
||||
(if (= x x2)
|
||||
(setf (aref hor (min y y2) x) 1)
|
||||
(setf (aref ver y (min x x2)) 1))
|
||||
(walk y2 x2))))
|
||||
|
||||
(show ()
|
||||
(let ((g " │││─┘┐┤─└┌├─┴┬┼"))
|
||||
(loop for i from 0 to h do
|
||||
(loop for j from 0 to w do
|
||||
(format t "~c~a"
|
||||
(char g
|
||||
(+ (or-and 1 (= i 0) (> j 0) (aref ver (1- i) (1- j)))
|
||||
(or-and 2 (= i h) (> j 0) (aref ver i (1- j)))
|
||||
(or-and 4 (= j 0) (> i 0) (aref hor (1- i) (1- j)))
|
||||
(or-and 8 (= j w) (> i 0) (aref hor (1- i) j ))))
|
||||
(if (and (< j w)
|
||||
(or (= i 0)
|
||||
(= 0 (aref hor (1- i) j))))
|
||||
"───" " ")))
|
||||
(terpri)
|
||||
(when (< i h)
|
||||
(loop for j from 0 below w do
|
||||
(format t (if (or (= j 0)
|
||||
(= 0 (aref ver i (1- j))))
|
||||
"│ " " ")))
|
||||
(format t "│~%"))))))
|
||||
(let ((g " │││─┘┐┤─└┌├─┴┬┼"))
|
||||
(loop for i from 0 to h do
|
||||
(loop for j from 0 to w do
|
||||
(format t "~c~a"
|
||||
(char g
|
||||
(+ (or-and 1 (= i 0) (> j 0) (aref ver (1- i) (1- j)))
|
||||
(or-and 2 (= i h) (> j 0) (aref ver i (1- j)))
|
||||
(or-and 4 (= j 0) (> i 0) (aref hor (1- i) (1- j)))
|
||||
(or-and 8 (= j w) (> i 0) (aref hor (1- i) j ))))
|
||||
(if (and (< j w)
|
||||
(or (= i 0)
|
||||
(= 0 (aref hor (1- i) j))))
|
||||
"───" " ")))
|
||||
(terpri)
|
||||
(when (< i h)
|
||||
(loop for j from 0 below w do
|
||||
(format t (if (or (= j 0)
|
||||
(= 0 (aref ver i (1- j))))
|
||||
"│ " " ")))
|
||||
(format t "│~%"))))))
|
||||
|
||||
(walk (random h) (random w))
|
||||
(show))))
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ program MazeGen
|
|||
|
||||
// First and last columns/rows are "dead" cells. Makes generating
|
||||
// a maze with border walls much easier. Therefore, a visible
|
||||
// 20x20 maze has a maze size of 22.
|
||||
// 20x20 maze has a maze size of 22.
|
||||
mazeSize int = 22;
|
||||
|
||||
south boolean[][];
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ proc m_maze pos .
|
|||
show_maze
|
||||
d[] = [ 1 2 3 4 ]
|
||||
for i = 4 downto 1
|
||||
d = random i
|
||||
d = random 1 i
|
||||
dir = offs[d[d]]
|
||||
d[d] = d[i]
|
||||
if m[pos + dir] = 1 and m[pos + 2 * dir] = 1
|
||||
|
|
@ -35,16 +35,14 @@ proc m_maze pos .
|
|||
.
|
||||
endpos = n * n - 1
|
||||
proc make_maze .
|
||||
for i = 1 to len m[]
|
||||
m[i] = 1
|
||||
.
|
||||
for i = 1 to len m[] : m[i] = 1
|
||||
for i = 1 to n
|
||||
m[i] = 2
|
||||
m[n * i] = 2
|
||||
m[n * i - n + 1] = 2
|
||||
m[n * n - n + i] = 2
|
||||
.
|
||||
h = 2 * random 15 - n + n * 2 * random 15
|
||||
h = 2 * random 1 size - n + n * 2 * random 1 size
|
||||
m_maze h
|
||||
m[endpos] = 0
|
||||
.
|
||||
|
|
|
|||
193
Task/Maze-generation/Emacs-Lisp/maze-generation.el
Normal file
193
Task/Maze-generation/Emacs-Lisp/maze-generation.el
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
(require 'cl-lib)
|
||||
|
||||
(cl-defstruct maze rows cols data)
|
||||
|
||||
(defmacro maze-pt (w r c)
|
||||
`(+ (* (mod ,r (maze-rows ,w)) (maze-cols ,w))
|
||||
(mod ,c (maze-cols ,w))))
|
||||
|
||||
(defmacro maze-ref (w r c)
|
||||
`(aref (maze-data ,w) (maze-pt ,w ,r ,c)))
|
||||
|
||||
(defun new-maze (rows cols)
|
||||
(setq rows (1+ rows)
|
||||
cols (1+ cols))
|
||||
(let ((m (make-maze :rows rows :cols cols :data (make-vector (* rows cols) nil))))
|
||||
|
||||
(dotimes (r rows)
|
||||
(dotimes (c cols)
|
||||
(setf (maze-ref m r c) (copy-sequence '(wall ceiling)))))
|
||||
|
||||
(dotimes (r rows)
|
||||
(maze-set m r (1- cols) 'visited))
|
||||
|
||||
(dotimes (c cols)
|
||||
(maze-set m (1- rows) c 'visited))
|
||||
|
||||
(maze-unset m 0 0 'ceiling) ;; Maze Entrance
|
||||
(maze-unset m (1- rows) (- cols 2) 'ceiling) ;; Maze Exit
|
||||
|
||||
m))
|
||||
|
||||
(defun maze-is-set (maze r c v)
|
||||
(member v (maze-ref maze r c)))
|
||||
|
||||
(defun maze-set (maze r c v)
|
||||
(let ((cell (maze-ref maze r c)))
|
||||
(when (not (member v cell))
|
||||
(setf (maze-ref maze r c) (cons v cell)))))
|
||||
|
||||
(defun maze-unset (maze r c v)
|
||||
(setf (maze-ref maze r c) (delete v (maze-ref maze r c))))
|
||||
|
||||
(defun print-maze (maze &optional marks)
|
||||
(dotimes (r (1- (maze-rows maze)))
|
||||
|
||||
(dotimes (c (1- (maze-cols maze)))
|
||||
(princ (if (maze-is-set maze r c 'ceiling) "+---" "+ ")))
|
||||
(princ "+")
|
||||
(terpri)
|
||||
|
||||
(dotimes (c (1- (maze-cols maze)))
|
||||
(princ (if (maze-is-set maze r c 'wall) "|" " "))
|
||||
(princ (if (member (cons r c) marks) " * " " ")))
|
||||
(princ "|")
|
||||
(terpri))
|
||||
|
||||
(dotimes (c (1- (maze-cols maze)))
|
||||
(princ (if (maze-is-set maze (1- (maze-rows maze)) c 'ceiling) "+---" "+ ")))
|
||||
(princ "+")
|
||||
(terpri))
|
||||
|
||||
(defun shuffle (lst)
|
||||
(sort lst (lambda (a b) (= 1 (random 2)))))
|
||||
|
||||
(defun to-visit (maze row col)
|
||||
(let (unvisited)
|
||||
(dolist (p '((0 . +1) (0 . -1) (+1 . 0) (-1 . 0)))
|
||||
(let ((r (+ row (car p)))
|
||||
(c (+ col (cdr p))))
|
||||
(unless (maze-is-set maze r c 'visited)
|
||||
(push (cons r c) unvisited))))
|
||||
unvisited))
|
||||
|
||||
(defun make-passage (maze r1 c1 r2 c2)
|
||||
(if (= r1 r2)
|
||||
(if (< c1 c2)
|
||||
(maze-unset maze r2 c2 'wall) ; right
|
||||
(maze-unset maze r1 c1 'wall)) ; left
|
||||
(if (< r1 r2)
|
||||
(maze-unset maze r2 c2 'ceiling) ; up
|
||||
(maze-unset maze r1 c1 'ceiling)))) ; down
|
||||
|
||||
(defun dig-maze (maze row col)
|
||||
(let (backup
|
||||
(run 0))
|
||||
(maze-set maze row col 'visited)
|
||||
(push (cons row col) backup)
|
||||
(while backup
|
||||
(setq run (1+ run))
|
||||
(when (> run (/ (+ row col) 3))
|
||||
(setq run 0)
|
||||
(setq backup (shuffle backup)))
|
||||
(setq row (caar backup)
|
||||
col (cdar backup))
|
||||
(let ((p (shuffle (to-visit maze row col))))
|
||||
(if p
|
||||
(let ((r (caar p))
|
||||
(c (cdar p)))
|
||||
(make-passage maze row col r c)
|
||||
(maze-set maze r c 'visited)
|
||||
(push (cons r c) backup))
|
||||
(pop backup)
|
||||
(setq backup (shuffle backup))
|
||||
(setq run 0))))))
|
||||
|
||||
(defun generate (rows cols)
|
||||
(let* ((m (new-maze rows cols)))
|
||||
(dig-maze m (random rows) (random cols))
|
||||
(print-maze m)))
|
||||
|
||||
(defun parse-ceilings (line)
|
||||
(let (rtn
|
||||
(i 1))
|
||||
(while (< i (length line))
|
||||
(push (eq ?- (elt line i)) rtn)
|
||||
(setq i (+ i 4)))
|
||||
(nreverse rtn)))
|
||||
|
||||
(defun parse-walls (line)
|
||||
(let (rtn
|
||||
(i 0))
|
||||
(while (< i (length line))
|
||||
(push (eq ?| (elt line i)) rtn)
|
||||
(setq i (+ i 4)))
|
||||
(nreverse rtn)))
|
||||
|
||||
(defun parse-maze (file-name)
|
||||
(let ((rtn)
|
||||
(lines (with-temp-buffer
|
||||
(insert-file-contents-literally file-name)
|
||||
(split-string (buffer-string) "\n" t))))
|
||||
(while lines
|
||||
(push (parse-ceilings (pop lines)) rtn)
|
||||
(push (parse-walls (pop lines)) rtn))
|
||||
(nreverse rtn)))
|
||||
|
||||
(defun read-maze (file-name)
|
||||
(let* ((raw (parse-maze file-name))
|
||||
(rows (1- (/ (length raw) 2)))
|
||||
(cols (length (car raw)))
|
||||
(maze (new-maze rows cols)))
|
||||
(dotimes (r rows)
|
||||
(let ((ceilings (pop raw)))
|
||||
(dotimes (c cols)
|
||||
(unless (pop ceilings)
|
||||
(maze-unset maze r c 'ceiling))))
|
||||
(let ((walls (pop raw)))
|
||||
(dotimes (c cols)
|
||||
(unless (pop walls)
|
||||
(maze-unset maze r c 'wall)))))
|
||||
maze))
|
||||
|
||||
(defun find-exits (maze row col)
|
||||
(let (exits)
|
||||
(dolist (p '((0 . +1) (0 . -1) (-1 . 0) (+1 . 0)))
|
||||
(let ((r (+ row (car p)))
|
||||
(c (+ col (cdr p))))
|
||||
(unless
|
||||
(cond
|
||||
((equal p '(0 . +1)) (maze-is-set maze r c 'wall))
|
||||
((equal p '(0 . -1)) (maze-is-set maze row col 'wall))
|
||||
((equal p '(+1 . 0)) (maze-is-set maze r c 'ceiling))
|
||||
((equal p '(-1 . 0)) (maze-is-set maze row col 'ceiling)))
|
||||
(push (cons r c) exits))))
|
||||
exits))
|
||||
|
||||
(defun drop-visited (maze points)
|
||||
(let (not-visited)
|
||||
(while points
|
||||
(unless (maze-is-set maze (caar points) (cdar points) 'visited)
|
||||
(push (car points) not-visited))
|
||||
(pop points))
|
||||
not-visited))
|
||||
|
||||
(defun solve-maze (maze)
|
||||
(let (solution
|
||||
(exit (cons (- (maze-rows maze) 2) (- (maze-cols maze) 2)))
|
||||
(pt (cons 0 0)))
|
||||
(while (not (equal pt exit))
|
||||
(maze-set maze (car pt) (cdr pt) 'visited)
|
||||
(let ((exits (drop-visited maze (find-exits maze (car pt) (cdr pt)))))
|
||||
(if (null exits)
|
||||
(setq pt (pop solution))
|
||||
(push pt solution)
|
||||
(setq pt (pop exits)))))
|
||||
(push pt solution)))
|
||||
|
||||
(defun solve (file-name)
|
||||
(let* ((maze (read-maze file-name))
|
||||
(solution (solve-maze maze)))
|
||||
(print-maze maze solution)))
|
||||
|
||||
(generate 20 20)
|
||||
|
|
@ -16,8 +16,8 @@ cell_pid( X, Y, Maze ) -> dict:fetch( {X, Y}, Maze#maze.dict ).
|
|||
cell_position( Pid ) -> read( Pid, position ).
|
||||
|
||||
display( #maze{dict=Dict, max_x=Max_x, max_y=Max_y} ) ->
|
||||
Position_pids = dict:to_list( Dict ),
|
||||
display( Max_x, Max_y, reads(Position_pids, content), reads(Position_pids, walls) ).
|
||||
Position_pids = dict:to_list( Dict ),
|
||||
display( Max_x, Max_y, reads(Position_pids, content), reads(Position_pids, walls) ).
|
||||
|
||||
generation( Max_x, Max_y ) ->
|
||||
Controller = erlang:self(),
|
||||
|
|
@ -52,13 +52,13 @@ cell_create( Controller, Max_x, Max_y, {X, Y} ) -> erlang:spawn_link( fun() -> r
|
|||
display( Max_x, Max_y, Position_contents, Position_walls ) ->
|
||||
All_rows = [display_row( Max_x, Y, Position_contents, Position_walls ) || Y <- lists:seq(Max_y, 1, -1)],
|
||||
[io:fwrite("~s+~n~s|~n", [North, West]) || {North, West} <- All_rows],
|
||||
io:fwrite("~s+~n", [lists:flatten(lists:duplicate(Max_x, display_row_north(true)))] ).
|
||||
io:fwrite("~s+~n", [lists:flatten(lists:duplicate(Max_x, display_row_north(true)))] ).
|
||||
|
||||
display_row( Max_x, Y, Position_contents, Position_walls ) ->
|
||||
North_wests = [display_row_walls(proplists:get_value({X,Y}, Position_contents), proplists:get_value({X,Y}, Position_walls)) || X <- lists:seq(1, Max_x)],
|
||||
North = lists:append( [North || {North, _West} <- North_wests] ),
|
||||
West = lists:append( [West || {_X, West} <- North_wests] ),
|
||||
{North, West}.
|
||||
North_wests = [display_row_walls(proplists:get_value({X,Y}, Position_contents), proplists:get_value({X,Y}, Position_walls)) || X <- lists:seq(1, Max_x)],
|
||||
North = lists:append( [North || {North, _West} <- North_wests] ),
|
||||
West = lists:append( [West || {_X, West} <- North_wests] ),
|
||||
{North, West}.
|
||||
|
||||
display_row_walls( Content, Walls ) -> {display_row_north( lists:member(north, Walls) ), display_row_west( lists:member(west, Walls), Content )}.
|
||||
|
||||
|
|
@ -71,47 +71,47 @@ display_row_west( false, Content ) -> " " ++ Content ++ " ".
|
|||
loop( State ) ->
|
||||
receive
|
||||
{accessible_neighbours, Pid} ->
|
||||
Pid ! {accessible_neighbours, loop_accessible_neighbours( State#state.neighbours, State#state.walls ), erlang:self()},
|
||||
Pid ! {accessible_neighbours, loop_accessible_neighbours( State#state.neighbours, State#state.walls ), erlang:self()},
|
||||
loop( State );
|
||||
{content, Pid} ->
|
||||
Pid ! {content, State#state.content, erlang:self()},
|
||||
Pid ! {content, State#state.content, erlang:self()},
|
||||
loop( State );
|
||||
{content, Content, _Pid} ->
|
||||
loop( State#state{content=Content} );
|
||||
{dig, Pid} ->
|
||||
Not_dug_neighbours = loop_not_dug( State#state.neighbours ),
|
||||
New_walls = loop_dig( Not_dug_neighbours, lists:delete( loop_wall_from_pid(Pid, State#state.neighbours), State#state.walls), Pid ),
|
||||
loop( State#state{is_dug=true, walls=New_walls, walk_done=Pid} );
|
||||
Not_dug_neighbours = loop_not_dug( State#state.neighbours ),
|
||||
New_walls = loop_dig( Not_dug_neighbours, lists:delete( loop_wall_from_pid(Pid, State#state.neighbours), State#state.walls), Pid ),
|
||||
loop( State#state{is_dug=true, walls=New_walls, walk_done=Pid} );
|
||||
{dig_done} ->
|
||||
Not_dug_neighbours = loop_not_dug( State#state.neighbours ),
|
||||
New_walls = loop_dig( Not_dug_neighbours, State#state.walls, State#state.walk_done ),
|
||||
loop( State#state{walls=New_walls} );
|
||||
Not_dug_neighbours = loop_not_dug( State#state.neighbours ),
|
||||
New_walls = loop_dig( Not_dug_neighbours, State#state.walls, State#state.walk_done ),
|
||||
loop( State#state{walls=New_walls} );
|
||||
{is_dug, Pid} ->
|
||||
Pid ! {is_dug, State#state.is_dug, erlang:self()},
|
||||
loop( State );
|
||||
Pid ! {is_dug, State#state.is_dug, erlang:self()},
|
||||
loop( State );
|
||||
{position, Pid} ->
|
||||
Pid ! {position, State#state.position, erlang:self()},
|
||||
Pid ! {position, State#state.position, erlang:self()},
|
||||
loop( State );
|
||||
{position_pids, Position_pids} ->
|
||||
{_My_position, Neighbours} = lists:foldl( fun loop_neighbours/2, {State#state.position, []}, Position_pids ),
|
||||
erlang:garbage_collect(), % Shrink process after using large Pid_positions. For memory starved systems.
|
||||
loop( State#state{neighbours=Neighbours} );
|
||||
{stop, Controller} when Controller =:= State#state.controller ->
|
||||
ok;
|
||||
ok;
|
||||
{walls, Pid} ->
|
||||
Pid ! {walls, State#state.walls, erlang:self()},
|
||||
loop( State )
|
||||
Pid ! {walls, State#state.walls, erlang:self()},
|
||||
loop( State )
|
||||
end.
|
||||
|
||||
loop_accessible_neighbours( Neighbours, Walls ) -> [Pid || {Direction, Pid} <- Neighbours, not lists:member(Direction, Walls)].
|
||||
|
||||
loop_dig( [], Walls, Pid ) ->
|
||||
Pid ! {dig_done},
|
||||
Walls;
|
||||
Pid ! {dig_done},
|
||||
Walls;
|
||||
loop_dig( Not_dug_neighbours, Walls, _Pid ) ->
|
||||
{Dig_pid, Dig_direction} = lists:nth( random:uniform(erlang:length(Not_dug_neighbours)), Not_dug_neighbours ),
|
||||
Dig_pid ! {dig, erlang:self()},
|
||||
lists:delete( Dig_direction, Walls ).
|
||||
lists:delete( Dig_direction, Walls ).
|
||||
|
||||
loop_neighbours( {{X, Y}, Pid}, {{X, My_y}, Acc} ) when Y =:= My_y + 1 -> {{X, My_y}, [{north, Pid} | Acc]};
|
||||
loop_neighbours( {{X, Y}, Pid}, {{X, My_y}, Acc} ) when Y =:= My_y - 1 -> {{X, My_y}, [{south, Pid} | Acc]};
|
||||
|
|
@ -120,17 +120,17 @@ loop_neighbours( {{X, Y}, Pid}, {{My_x, Y}, Acc} ) when X =:= My_x - 1 -> {{My_x
|
|||
loop_neighbours( _Position_pid, Acc ) -> Acc.
|
||||
|
||||
loop_not_dug( Neighbours ) ->
|
||||
My_pid = erlang:self(),
|
||||
[Pid ! {is_dug, My_pid} || {_Direction, Pid} <- Neighbours],
|
||||
[{Pid, Direction} || {Direction, Pid} <- Neighbours, not read_receive(Pid, is_dug)].
|
||||
My_pid = erlang:self(),
|
||||
[Pid ! {is_dug, My_pid} || {_Direction, Pid} <- Neighbours],
|
||||
[{Pid, Direction} || {Direction, Pid} <- Neighbours, not read_receive(Pid, is_dug)].
|
||||
|
||||
loop_wall_from_pid( Pid, Neighbours ) -> loop_wall_from_pid_result( lists:keyfind(Pid, 2, Neighbours) ).
|
||||
loop_wall_from_pid_result( {Direction, _Pid} ) -> Direction;
|
||||
loop_wall_from_pid_result( false ) -> controller.
|
||||
|
||||
read( Pid, Key ) ->
|
||||
Pid ! {Key, erlang:self()},
|
||||
read_receive( Pid, Key ).
|
||||
Pid ! {Key, erlang:self()},
|
||||
read_receive( Pid, Key ).
|
||||
|
||||
read_receive( Pid, Key ) ->
|
||||
receive
|
||||
|
|
|
|||
|
|
@ -3,69 +3,69 @@ import Mathematics as math;
|
|||
import Terminal as term;
|
||||
|
||||
class Maze {
|
||||
_rows = none;
|
||||
_cols = none;
|
||||
_data = none;
|
||||
constructor( rows_, cols_ ) {
|
||||
_rows = ( rows_ / 2 ) * 2 - 1;
|
||||
_cols = ( cols_ / 2 ) * 2 - 1;
|
||||
_data = [].resize( _rows + 2, [].resize( _cols + 2, false ) );
|
||||
x = 0;
|
||||
y = 0;
|
||||
path = [];
|
||||
rng = math.Randomizer( math.Randomizer.DISTRIBUTION.DISCRETE, 0, integer( $2 ^ $63 - $1 ) );
|
||||
for ( _ : algo.range( _rows * _cols / 3 ) ) {
|
||||
_data[y + 1][x + 1] = true;
|
||||
while ( true ) {
|
||||
n = neighbours( y, x );
|
||||
ns = size( n );
|
||||
if ( ns == 0 ) {
|
||||
if ( size( path ) == 0 ) {
|
||||
break;
|
||||
}
|
||||
y, x = path[-1];
|
||||
path.pop();
|
||||
continue;
|
||||
}
|
||||
oy, ox = ( y, x );
|
||||
y, x = n[rng.next() % ns];
|
||||
_data[(y + oy) / 2 + 1][(x + ox) / 2 + 1] = true;
|
||||
path.push( ( y, x ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
_data[0][1] = true;
|
||||
_data[-1][-2] = true;
|
||||
}
|
||||
neighbours( y_, x_ ) {
|
||||
n = [];
|
||||
if ( ( x_ > 1 ) && ! _data[y_ + 1][x_ - 1] ) {
|
||||
n.push( ( y_, x_ - 2 ) );
|
||||
}
|
||||
if ( ( y_ > 1 ) && ! _data[y_ - 1][x_ + 1] ) {
|
||||
n.push( ( y_ - 2, x_ ) );
|
||||
}
|
||||
if ( ( x_ < ( _cols - 2 ) ) && ! _data[y_ + 1][x_ + 3] ) {
|
||||
n.push( ( y_, x_ + 2 ) );
|
||||
}
|
||||
if ( ( y_ < ( _rows - 2 ) ) && ! _data[y_ + 3][x_ + 1] ) {
|
||||
n.push( ( y_ + 2, x_ ) );
|
||||
}
|
||||
return ( n );
|
||||
}
|
||||
to_string() {
|
||||
s = "";
|
||||
for ( r : _data ) {
|
||||
s += ∑( algo.map( r, @( b ) { b ? " " : "#"; } ) );
|
||||
s += "\n";
|
||||
}
|
||||
return ( s );
|
||||
}
|
||||
_rows = none;
|
||||
_cols = none;
|
||||
_data = none;
|
||||
constructor( rows_, cols_ ) {
|
||||
_rows = ( rows_ / 2 ) * 2 - 1;
|
||||
_cols = ( cols_ / 2 ) * 2 - 1;
|
||||
_data = [].resize( _rows + 2, [].resize( _cols + 2, false ) );
|
||||
x = 0;
|
||||
y = 0;
|
||||
path = [];
|
||||
rng = math.Randomizer( math.Randomizer.DISTRIBUTION.DISCRETE, 0, integer( $2 ^ $63 - $1 ) );
|
||||
for ( _ : algo.range( _rows * _cols / 3 ) ) {
|
||||
_data[y + 1][x + 1] = true;
|
||||
while ( true ) {
|
||||
n = neighbours( y, x );
|
||||
ns = size( n );
|
||||
if ( ns == 0 ) {
|
||||
if ( size( path ) == 0 ) {
|
||||
break;
|
||||
}
|
||||
y, x = path[-1];
|
||||
path.pop();
|
||||
continue;
|
||||
}
|
||||
oy, ox = ( y, x );
|
||||
y, x = n[rng.next() % ns];
|
||||
_data[(y + oy) / 2 + 1][(x + ox) / 2 + 1] = true;
|
||||
path.push( ( y, x ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
_data[0][1] = true;
|
||||
_data[-1][-2] = true;
|
||||
}
|
||||
neighbours( y_, x_ ) {
|
||||
n = [];
|
||||
if ( ( x_ > 1 ) && ! _data[y_ + 1][x_ - 1] ) {
|
||||
n.push( ( y_, x_ - 2 ) );
|
||||
}
|
||||
if ( ( y_ > 1 ) && ! _data[y_ - 1][x_ + 1] ) {
|
||||
n.push( ( y_ - 2, x_ ) );
|
||||
}
|
||||
if ( ( x_ < ( _cols - 2 ) ) && ! _data[y_ + 1][x_ + 3] ) {
|
||||
n.push( ( y_, x_ + 2 ) );
|
||||
}
|
||||
if ( ( y_ < ( _rows - 2 ) ) && ! _data[y_ + 3][x_ + 1] ) {
|
||||
n.push( ( y_ + 2, x_ ) );
|
||||
}
|
||||
return ( n );
|
||||
}
|
||||
to_string() {
|
||||
s = "";
|
||||
for ( r : _data ) {
|
||||
s += ∑( algo.map( r, @( b ) { b ? " " : "#"; } ) );
|
||||
s += "\n";
|
||||
}
|
||||
return ( s );
|
||||
}
|
||||
}
|
||||
|
||||
main() {
|
||||
rows = term.lines() - 2;
|
||||
cols = term.columns() - 1;
|
||||
maze = Maze( rows, cols );
|
||||
print( "{}".format( maze ) );
|
||||
rows = term.lines() - 2;
|
||||
cols = term.columns() - 1;
|
||||
maze = Maze( rows, cols );
|
||||
print( "{}".format( maze ) );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,83 +9,83 @@ import java.util.Arrays;
|
|||
* http://weblog.jamisbuck.org/2010/12/27/maze-generation-recursive-backtracking
|
||||
*/
|
||||
public class MazeGenerator {
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int[][] maze;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int[][] maze;
|
||||
|
||||
public MazeGenerator(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
maze = new int[this.x][this.y];
|
||||
generateMaze(0, 0);
|
||||
}
|
||||
public MazeGenerator(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
maze = new int[this.x][this.y];
|
||||
generateMaze(0, 0);
|
||||
}
|
||||
|
||||
public void display() {
|
||||
for (int i = 0; i < y; i++) {
|
||||
// draw the north edge
|
||||
for (int j = 0; j < x; j++) {
|
||||
System.out.print((maze[j][i] & 1) == 0 ? "+---" : "+ ");
|
||||
}
|
||||
System.out.println("+");
|
||||
// draw the west edge
|
||||
for (int j = 0; j < x; j++) {
|
||||
System.out.print((maze[j][i] & 8) == 0 ? "| " : " ");
|
||||
}
|
||||
System.out.println("|");
|
||||
}
|
||||
// draw the bottom line
|
||||
for (int j = 0; j < x; j++) {
|
||||
System.out.print("+---");
|
||||
}
|
||||
System.out.println("+");
|
||||
}
|
||||
public void display() {
|
||||
for (int i = 0; i < y; i++) {
|
||||
// draw the north edge
|
||||
for (int j = 0; j < x; j++) {
|
||||
System.out.print((maze[j][i] & 1) == 0 ? "+---" : "+ ");
|
||||
}
|
||||
System.out.println("+");
|
||||
// draw the west edge
|
||||
for (int j = 0; j < x; j++) {
|
||||
System.out.print((maze[j][i] & 8) == 0 ? "| " : " ");
|
||||
}
|
||||
System.out.println("|");
|
||||
}
|
||||
// draw the bottom line
|
||||
for (int j = 0; j < x; j++) {
|
||||
System.out.print("+---");
|
||||
}
|
||||
System.out.println("+");
|
||||
}
|
||||
|
||||
private void generateMaze(int cx, int cy) {
|
||||
DIR[] dirs = DIR.values();
|
||||
Collections.shuffle(Arrays.asList(dirs));
|
||||
for (DIR dir : dirs) {
|
||||
int nx = cx + dir.dx;
|
||||
int ny = cy + dir.dy;
|
||||
if (between(nx, x) && between(ny, y)
|
||||
&& (maze[nx][ny] == 0)) {
|
||||
maze[cx][cy] |= dir.bit;
|
||||
maze[nx][ny] |= dir.opposite.bit;
|
||||
generateMaze(nx, ny);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void generateMaze(int cx, int cy) {
|
||||
DIR[] dirs = DIR.values();
|
||||
Collections.shuffle(Arrays.asList(dirs));
|
||||
for (DIR dir : dirs) {
|
||||
int nx = cx + dir.dx;
|
||||
int ny = cy + dir.dy;
|
||||
if (between(nx, x) && between(ny, y)
|
||||
&& (maze[nx][ny] == 0)) {
|
||||
maze[cx][cy] |= dir.bit;
|
||||
maze[nx][ny] |= dir.opposite.bit;
|
||||
generateMaze(nx, ny);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean between(int v, int upper) {
|
||||
return (v >= 0) && (v < upper);
|
||||
}
|
||||
private static boolean between(int v, int upper) {
|
||||
return (v >= 0) && (v < upper);
|
||||
}
|
||||
|
||||
private enum DIR {
|
||||
N(1, 0, -1), S(2, 0, 1), E(4, 1, 0), W(8, -1, 0);
|
||||
private final int bit;
|
||||
private final int dx;
|
||||
private final int dy;
|
||||
private DIR opposite;
|
||||
private enum DIR {
|
||||
N(1, 0, -1), S(2, 0, 1), E(4, 1, 0), W(8, -1, 0);
|
||||
private final int bit;
|
||||
private final int dx;
|
||||
private final int dy;
|
||||
private DIR opposite;
|
||||
|
||||
// use the static initializer to resolve forward references
|
||||
static {
|
||||
N.opposite = S;
|
||||
S.opposite = N;
|
||||
E.opposite = W;
|
||||
W.opposite = E;
|
||||
}
|
||||
// use the static initializer to resolve forward references
|
||||
static {
|
||||
N.opposite = S;
|
||||
S.opposite = N;
|
||||
E.opposite = W;
|
||||
W.opposite = E;
|
||||
}
|
||||
|
||||
private DIR(int bit, int dx, int dy) {
|
||||
this.bit = bit;
|
||||
this.dx = dx;
|
||||
this.dy = dy;
|
||||
}
|
||||
};
|
||||
private DIR(int bit, int dx, int dy) {
|
||||
this.bit = bit;
|
||||
this.dx = dx;
|
||||
this.dy = dy;
|
||||
}
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
int x = args.length >= 1 ? (Integer.parseInt(args[0])) : 8;
|
||||
int y = args.length == 2 ? (Integer.parseInt(args[1])) : 8;
|
||||
MazeGenerator maze = new MazeGenerator(x, y);
|
||||
maze.display();
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
int x = args.length >= 1 ? (Integer.parseInt(args[0])) : 8;
|
||||
int y = args.length == 2 ? (Integer.parseInt(args[1])) : 8;
|
||||
MazeGenerator maze = new MazeGenerator(x, y);
|
||||
maze.display();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,63 +1,63 @@
|
|||
function maze(x,y) {
|
||||
var n=x*y-1;
|
||||
if (n<0) {alert("illegal maze dimensions");return;}
|
||||
var horiz =[]; for (var j= 0; j<x+1; j++) horiz[j]= [],
|
||||
verti =[]; for (var j= 0; j<x+1; j++) verti[j]= [],
|
||||
here = [Math.floor(Math.random()*x), Math.floor(Math.random()*y)],
|
||||
path = [here],
|
||||
unvisited = [];
|
||||
for (var j = 0; j<x+2; j++) {
|
||||
unvisited[j] = [];
|
||||
for (var k= 0; k<y+1; k++)
|
||||
unvisited[j].push(j>0 && j<x+1 && k>0 && (j != here[0]+1 || k != here[1]+1));
|
||||
}
|
||||
while (0<n) {
|
||||
var potential = [[here[0]+1, here[1]], [here[0],here[1]+1],
|
||||
[here[0]-1, here[1]], [here[0],here[1]-1]];
|
||||
var neighbors = [];
|
||||
for (var j = 0; j < 4; j++)
|
||||
if (unvisited[potential[j][0]+1][potential[j][1]+1])
|
||||
neighbors.push(potential[j]);
|
||||
if (neighbors.length) {
|
||||
n = n-1;
|
||||
next= neighbors[Math.floor(Math.random()*neighbors.length)];
|
||||
unvisited[next[0]+1][next[1]+1]= false;
|
||||
if (next[0] == here[0])
|
||||
horiz[next[0]][(next[1]+here[1]-1)/2]= true;
|
||||
else
|
||||
verti[(next[0]+here[0]-1)/2][next[1]]= true;
|
||||
path.push(here = next);
|
||||
} else
|
||||
here = path.pop();
|
||||
}
|
||||
return {x: x, y: y, horiz: horiz, verti: verti};
|
||||
var n=x*y-1;
|
||||
if (n<0) {alert("illegal maze dimensions");return;}
|
||||
var horiz =[]; for (var j= 0; j<x+1; j++) horiz[j]= [],
|
||||
verti =[]; for (var j= 0; j<x+1; j++) verti[j]= [],
|
||||
here = [Math.floor(Math.random()*x), Math.floor(Math.random()*y)],
|
||||
path = [here],
|
||||
unvisited = [];
|
||||
for (var j = 0; j<x+2; j++) {
|
||||
unvisited[j] = [];
|
||||
for (var k= 0; k<y+1; k++)
|
||||
unvisited[j].push(j>0 && j<x+1 && k>0 && (j != here[0]+1 || k != here[1]+1));
|
||||
}
|
||||
while (0<n) {
|
||||
var potential = [[here[0]+1, here[1]], [here[0],here[1]+1],
|
||||
[here[0]-1, here[1]], [here[0],here[1]-1]];
|
||||
var neighbors = [];
|
||||
for (var j = 0; j < 4; j++)
|
||||
if (unvisited[potential[j][0]+1][potential[j][1]+1])
|
||||
neighbors.push(potential[j]);
|
||||
if (neighbors.length) {
|
||||
n = n-1;
|
||||
next= neighbors[Math.floor(Math.random()*neighbors.length)];
|
||||
unvisited[next[0]+1][next[1]+1]= false;
|
||||
if (next[0] == here[0])
|
||||
horiz[next[0]][(next[1]+here[1]-1)/2]= true;
|
||||
else
|
||||
verti[(next[0]+here[0]-1)/2][next[1]]= true;
|
||||
path.push(here = next);
|
||||
} else
|
||||
here = path.pop();
|
||||
}
|
||||
return {x: x, y: y, horiz: horiz, verti: verti};
|
||||
}
|
||||
|
||||
function display(m) {
|
||||
var text= [];
|
||||
for (var j= 0; j<m.x*2+1; j++) {
|
||||
var line= [];
|
||||
if (0 == j%2)
|
||||
for (var k=0; k<m.y*4+1; k++)
|
||||
if (0 == k%4)
|
||||
line[k]= '+';
|
||||
else
|
||||
if (j>0 && m.verti[j/2-1][Math.floor(k/4)])
|
||||
line[k]= ' ';
|
||||
else
|
||||
line[k]= '-';
|
||||
else
|
||||
for (var k=0; k<m.y*4+1; k++)
|
||||
if (0 == k%4)
|
||||
if (k>0 && m.horiz[(j-1)/2][k/4-1])
|
||||
line[k]= ' ';
|
||||
else
|
||||
line[k]= '|';
|
||||
else
|
||||
line[k]= ' ';
|
||||
if (0 == j) line[1]= line[2]= line[3]= ' ';
|
||||
if (m.x*2-1 == j) line[4*m.y]= ' ';
|
||||
text.push(line.join('')+'\r\n');
|
||||
}
|
||||
return text.join('');
|
||||
var text= [];
|
||||
for (var j= 0; j<m.x*2+1; j++) {
|
||||
var line= [];
|
||||
if (0 == j%2)
|
||||
for (var k=0; k<m.y*4+1; k++)
|
||||
if (0 == k%4)
|
||||
line[k]= '+';
|
||||
else
|
||||
if (j>0 && m.verti[j/2-1][Math.floor(k/4)])
|
||||
line[k]= ' ';
|
||||
else
|
||||
line[k]= '-';
|
||||
else
|
||||
for (var k=0; k<m.y*4+1; k++)
|
||||
if (0 == k%4)
|
||||
if (k>0 && m.horiz[(j-1)/2][k/4-1])
|
||||
line[k]= ' ';
|
||||
else
|
||||
line[k]= '|';
|
||||
else
|
||||
line[k]= ' ';
|
||||
if (0 == j) line[1]= line[2]= line[3]= ' ';
|
||||
if (m.x*2-1 == j) line[4*m.y]= ' ';
|
||||
text.push(line.join('')+'\r\n');
|
||||
}
|
||||
return text.join('');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
function step() {
|
||||
if (0<n) {
|
||||
function step() {
|
||||
if (0<n) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
document.getElementById('out').innerHTML= display({x: x, y: y, horiz: horiz, verti: verti, here: here});
|
||||
setTimeout(step, 100);
|
||||
}
|
||||
}
|
||||
step();
|
||||
document.getElementById('out').innerHTML= display({x: x, y: y, horiz: horiz, verti: verti, here: here});
|
||||
setTimeout(step, 100);
|
||||
}
|
||||
}
|
||||
step();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
if (m.here && m.here[0]*2+1 == j && m.here[1]*4+2 == k)
|
||||
line[k]= '#'
|
||||
else if (0 == k%4) {
|
||||
if (m.here && m.here[0]*2+1 == j && m.here[1]*4+2 == k)
|
||||
line[k]= '#'
|
||||
else if (0 == k%4) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
here= next;
|
||||
if (1 < neighbors.length)
|
||||
path.push(here);
|
||||
here= next;
|
||||
if (1 < neighbors.length)
|
||||
path.push(here);
|
||||
|
|
|
|||
|
|
@ -10,100 +10,100 @@ td.v { background: skyblue}
|
|||
</style>
|
||||
<script type="application/javascript">
|
||||
Node.prototype.add = function(tag, cnt, txt) {
|
||||
for (var i = 0; i < cnt; i++)
|
||||
this.appendChild(ce(tag, txt));
|
||||
for (var i = 0; i < cnt; i++)
|
||||
this.appendChild(ce(tag, txt));
|
||||
}
|
||||
Node.prototype.ins = function(tag) {
|
||||
this.insertBefore(ce(tag), this.firstChild)
|
||||
this.insertBefore(ce(tag), this.firstChild)
|
||||
}
|
||||
Node.prototype.kid = function(i) { return this.childNodes[i] }
|
||||
Node.prototype.cls = function(t) { this.className += ' ' + t }
|
||||
|
||||
NodeList.prototype.map = function(g) {
|
||||
for (var i = 0; i < this.length; i++) g(this[i]);
|
||||
for (var i = 0; i < this.length; i++) g(this[i]);
|
||||
}
|
||||
|
||||
function ce(tag, txt) {
|
||||
var x = document.createElement(tag);
|
||||
if (txt !== undefined) x.innerHTML = txt;
|
||||
return x
|
||||
var x = document.createElement(tag);
|
||||
if (txt !== undefined) x.innerHTML = txt;
|
||||
return x
|
||||
}
|
||||
|
||||
function gid(e) { return document.getElementById(e) }
|
||||
function irand(x) { return Math.floor(Math.random() * x) }
|
||||
|
||||
function make_maze() {
|
||||
var w = parseInt(gid('rows').value || 8, 10);
|
||||
var h = parseInt(gid('cols').value || 8, 10);
|
||||
var tbl = gid('maze');
|
||||
tbl.innerHTML = '';
|
||||
tbl.add('tr', h);
|
||||
tbl.childNodes.map(function(x) {
|
||||
x.add('th', 1);
|
||||
x.add('td', w, '*');
|
||||
x.add('th', 1)});
|
||||
tbl.ins('tr');
|
||||
tbl.add('tr', 1);
|
||||
tbl.firstChild.add('th', w + 2);
|
||||
tbl.lastChild.add('th', w + 2);
|
||||
for (var i = 1; i <= h; i++) {
|
||||
for (var j = 1; j <= w; j++) {
|
||||
tbl.kid(i).kid(j).neighbors = [
|
||||
tbl.kid(i + 1).kid(j),
|
||||
tbl.kid(i).kid(j + 1),
|
||||
tbl.kid(i).kid(j - 1),
|
||||
tbl.kid(i - 1).kid(j)
|
||||
];
|
||||
}
|
||||
}
|
||||
walk(tbl.kid(irand(h) + 1).kid(irand(w) + 1));
|
||||
gid('solve').style.display='inline';
|
||||
var w = parseInt(gid('rows').value || 8, 10);
|
||||
var h = parseInt(gid('cols').value || 8, 10);
|
||||
var tbl = gid('maze');
|
||||
tbl.innerHTML = '';
|
||||
tbl.add('tr', h);
|
||||
tbl.childNodes.map(function(x) {
|
||||
x.add('th', 1);
|
||||
x.add('td', w, '*');
|
||||
x.add('th', 1)});
|
||||
tbl.ins('tr');
|
||||
tbl.add('tr', 1);
|
||||
tbl.firstChild.add('th', w + 2);
|
||||
tbl.lastChild.add('th', w + 2);
|
||||
for (var i = 1; i <= h; i++) {
|
||||
for (var j = 1; j <= w; j++) {
|
||||
tbl.kid(i).kid(j).neighbors = [
|
||||
tbl.kid(i + 1).kid(j),
|
||||
tbl.kid(i).kid(j + 1),
|
||||
tbl.kid(i).kid(j - 1),
|
||||
tbl.kid(i - 1).kid(j)
|
||||
];
|
||||
}
|
||||
}
|
||||
walk(tbl.kid(irand(h) + 1).kid(irand(w) + 1));
|
||||
gid('solve').style.display='inline';
|
||||
}
|
||||
|
||||
function shuffle(x) {
|
||||
for (var i = 3; i > 0; i--) {
|
||||
j = irand(i + 1);
|
||||
if (j == i) continue;
|
||||
var t = x[j]; x[j] = x[i]; x[i] = t;
|
||||
}
|
||||
return x;
|
||||
for (var i = 3; i > 0; i--) {
|
||||
j = irand(i + 1);
|
||||
if (j == i) continue;
|
||||
var t = x[j]; x[j] = x[i]; x[i] = t;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
var dirs = ['s', 'e', 'w', 'n'];
|
||||
function walk(c) {
|
||||
c.innerHTML = ' ';
|
||||
var idx = shuffle([0, 1, 2, 3]);
|
||||
for (var j = 0; j < 4; j++) {
|
||||
var i = idx[j];
|
||||
var x = c.neighbors[i];
|
||||
if (x.textContent != '*') continue;
|
||||
c.cls(dirs[i]), x.cls(dirs[3 - i]);
|
||||
walk(x);
|
||||
}
|
||||
c.innerHTML = ' ';
|
||||
var idx = shuffle([0, 1, 2, 3]);
|
||||
for (var j = 0; j < 4; j++) {
|
||||
var i = idx[j];
|
||||
var x = c.neighbors[i];
|
||||
if (x.textContent != '*') continue;
|
||||
c.cls(dirs[i]), x.cls(dirs[3 - i]);
|
||||
walk(x);
|
||||
}
|
||||
}
|
||||
|
||||
function solve(c, t) {
|
||||
if (c === undefined) {
|
||||
c = gid('maze').kid(1).kid(1);
|
||||
c.cls('v');
|
||||
}
|
||||
if (t === undefined)
|
||||
t = gid('maze') .lastChild.previousSibling
|
||||
.lastChild.previousSibling;
|
||||
if (c === undefined) {
|
||||
c = gid('maze').kid(1).kid(1);
|
||||
c.cls('v');
|
||||
}
|
||||
if (t === undefined)
|
||||
t = gid('maze') .lastChild.previousSibling
|
||||
.lastChild.previousSibling;
|
||||
|
||||
if (c === t) return 1;
|
||||
c.vis = 1;
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var x = c.neighbors[i];
|
||||
if (x.tagName.toLowerCase() == 'th') continue;
|
||||
if (x.vis || !c.className.match(dirs[i]) || !solve(x, t))
|
||||
continue;
|
||||
if (c === t) return 1;
|
||||
c.vis = 1;
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var x = c.neighbors[i];
|
||||
if (x.tagName.toLowerCase() == 'th') continue;
|
||||
if (x.vis || !c.className.match(dirs[i]) || !solve(x, t))
|
||||
continue;
|
||||
|
||||
x.cls('v');
|
||||
return 1;
|
||||
}
|
||||
c.vis = null;
|
||||
return 0;
|
||||
x.cls('v');
|
||||
return 1;
|
||||
}
|
||||
c.vis = null;
|
||||
return 0;
|
||||
}
|
||||
|
||||
</script></head>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#version 3.7;
|
||||
|
||||
global_settings {
|
||||
assumed_gamma 1
|
||||
assumed_gamma 1
|
||||
}
|
||||
|
||||
#declare Rows = 15;
|
||||
|
|
@ -10,166 +10,166 @@ global_settings {
|
|||
#declare Seed = seed(2); // A seed produces a fixed sequence of pseudorandom numbers
|
||||
|
||||
#declare Wall = prism {
|
||||
0, 0.8, 7,
|
||||
<0, -0.5>, <0.05, -0.45>, <0.05, 0.45>, <0, 0.5>,
|
||||
<-0.05, 0.45>, <-0.05, -0.45>, <0, -0.5>
|
||||
texture {
|
||||
pigment {
|
||||
brick colour rgb 1, colour rgb <0.8, 0.25, 0.1> // Colour mortar, colour brick
|
||||
brick_size 3*<0.25, 0.0525, 0.125>
|
||||
mortar 3*0.01 // Size of the mortar
|
||||
}
|
||||
normal { wrinkles 0.75 scale 0.01 }
|
||||
finish { diffuse 0.9 phong 0.2 }
|
||||
0, 0.8, 7,
|
||||
<0, -0.5>, <0.05, -0.45>, <0.05, 0.45>, <0, 0.5>,
|
||||
<-0.05, 0.45>, <-0.05, -0.45>, <0, -0.5>
|
||||
texture {
|
||||
pigment {
|
||||
brick colour rgb 1, colour rgb <0.8, 0.25, 0.1> // Colour mortar, colour brick
|
||||
brick_size 3*<0.25, 0.0525, 0.125>
|
||||
mortar 3*0.01 // Size of the mortar
|
||||
}
|
||||
normal { wrinkles 0.75 scale 0.01 }
|
||||
finish { diffuse 0.9 phong 0.2 }
|
||||
}
|
||||
}
|
||||
|
||||
#macro Fisher_Yates_Shuffle(Stack, Start, Top)
|
||||
#for (I, Top, Start+1, -1)
|
||||
#local J = floor(rand(Seed)*I + 0.5);
|
||||
#if (J != I) // Waste of time swapping an element with itself
|
||||
#local Src_Row = Stack[I][0];
|
||||
#local Src_Col = Stack[I][1];
|
||||
#local Dst_Row = Stack[I][2];
|
||||
#local Dst_Col = Stack[I][3];
|
||||
#declare Stack[I][0] = Stack[J][0];
|
||||
#declare Stack[I][1] = Stack[J][1];
|
||||
#declare Stack[I][2] = Stack[J][2];
|
||||
#declare Stack[I][3] = Stack[J][3];
|
||||
#declare Stack[J][0] = Src_Row;
|
||||
#declare Stack[J][1] = Src_Col;
|
||||
#declare Stack[J][2] = Dst_Row;
|
||||
#declare Stack[J][3] = Dst_Col;
|
||||
#end
|
||||
#end
|
||||
#for (I, Top, Start+1, -1)
|
||||
#local J = floor(rand(Seed)*I + 0.5);
|
||||
#if (J != I) // Waste of time swapping an element with itself
|
||||
#local Src_Row = Stack[I][0];
|
||||
#local Src_Col = Stack[I][1];
|
||||
#local Dst_Row = Stack[I][2];
|
||||
#local Dst_Col = Stack[I][3];
|
||||
#declare Stack[I][0] = Stack[J][0];
|
||||
#declare Stack[I][1] = Stack[J][1];
|
||||
#declare Stack[I][2] = Stack[J][2];
|
||||
#declare Stack[I][3] = Stack[J][3];
|
||||
#declare Stack[J][0] = Src_Row;
|
||||
#declare Stack[J][1] = Src_Col;
|
||||
#declare Stack[J][2] = Dst_Row;
|
||||
#declare Stack[J][3] = Dst_Col;
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
|
||||
#macro Initialise(Visited, North_Walls, East_Walls)
|
||||
#for (R, 0, Rows-1)
|
||||
#for (C, 0, Cols-1)
|
||||
#declare Visited[R][C] = false;
|
||||
#declare North_Walls[R][C] = true;
|
||||
#declare East_Walls[R][C] = true;
|
||||
#end
|
||||
#end
|
||||
#for (R, 0, Rows-1)
|
||||
#for (C, 0, Cols-1)
|
||||
#declare Visited[R][C] = false;
|
||||
#declare North_Walls[R][C] = true;
|
||||
#declare East_Walls[R][C] = true;
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
|
||||
#macro Push(Stack, Top, Src_Row, Src_Col, Dst_Row, Dst_Col)
|
||||
#declare Top = Top + 1;
|
||||
#declare Stack[Top][0] = Src_Row;
|
||||
#declare Stack[Top][1] = Src_Col;
|
||||
#declare Stack[Top][2] = Dst_Row;
|
||||
#declare Stack[Top][3] = Dst_Col;
|
||||
#declare Top = Top + 1;
|
||||
#declare Stack[Top][0] = Src_Row;
|
||||
#declare Stack[Top][1] = Src_Col;
|
||||
#declare Stack[Top][2] = Dst_Row;
|
||||
#declare Stack[Top][3] = Dst_Col;
|
||||
#end
|
||||
|
||||
#macro Generate_Maze(Visited, North_Walls, East_Walls)
|
||||
#local Stack = array[Rows*Cols][4]; // 0: from row, 1: from col, 2: to row, 3: to col
|
||||
#local Row = floor(rand(Seed)*(Rows-1) + 0.5); // Random start row
|
||||
#local Col = floor(rand(Seed)*(Cols-1) + 0.5); // Random start column
|
||||
#local Top = -1;
|
||||
Push(Stack, Top, Row, Col, Row, Col)
|
||||
#local Stack = array[Rows*Cols][4]; // 0: from row, 1: from col, 2: to row, 3: to col
|
||||
#local Row = floor(rand(Seed)*(Rows-1) + 0.5); // Random start row
|
||||
#local Col = floor(rand(Seed)*(Cols-1) + 0.5); // Random start column
|
||||
#local Top = -1;
|
||||
Push(Stack, Top, Row, Col, Row, Col)
|
||||
|
||||
#while (Top >= 0)
|
||||
#declare Visited[Row][Col] = true;
|
||||
#local Start = Top + 1;
|
||||
#while (Top >= 0)
|
||||
#declare Visited[Row][Col] = true;
|
||||
#local Start = Top + 1;
|
||||
|
||||
#if (Row < Rows-1) // Add north neighbour
|
||||
#if (Visited[Row+1][Col] = false)
|
||||
Push(Stack, Top, Row, Col, Row+1, Col)
|
||||
#end
|
||||
#end
|
||||
#if (Row < Rows-1) // Add north neighbour
|
||||
#if (Visited[Row+1][Col] = false)
|
||||
Push(Stack, Top, Row, Col, Row+1, Col)
|
||||
#end
|
||||
#end
|
||||
|
||||
#if (Col < Cols-1) // Add east neighbour
|
||||
#if (Visited[Row][Col+1] = false)
|
||||
Push(Stack, Top, Row, Col, Row, Col+1)
|
||||
#end
|
||||
#end
|
||||
#if (Col < Cols-1) // Add east neighbour
|
||||
#if (Visited[Row][Col+1] = false)
|
||||
Push(Stack, Top, Row, Col, Row, Col+1)
|
||||
#end
|
||||
#end
|
||||
|
||||
#if (Row > 0) // Add south neighbour
|
||||
#if (Visited[Row-1][Col] = false)
|
||||
Push(Stack, Top, Row, Col, Row-1, Col)
|
||||
#end
|
||||
#end
|
||||
#if (Row > 0) // Add south neighbour
|
||||
#if (Visited[Row-1][Col] = false)
|
||||
Push(Stack, Top, Row, Col, Row-1, Col)
|
||||
#end
|
||||
#end
|
||||
|
||||
#if (Col > 0) // Add west neighbour
|
||||
#if (Visited[Row][Col-1] = false)
|
||||
Push(Stack, Top, Row, Col, Row, Col-1)
|
||||
#end
|
||||
#end
|
||||
#if (Col > 0) // Add west neighbour
|
||||
#if (Visited[Row][Col-1] = false)
|
||||
Push(Stack, Top, Row, Col, Row, Col-1)
|
||||
#end
|
||||
#end
|
||||
|
||||
Fisher_Yates_Shuffle(Stack, Start, Top)
|
||||
Fisher_Yates_Shuffle(Stack, Start, Top)
|
||||
|
||||
#local Removed_Wall = false;
|
||||
#while (Top >= 0 & Removed_Wall = false)
|
||||
#local Src_Row = Stack[Top][0];
|
||||
#local Src_Col = Stack[Top][1];
|
||||
#local Dst_Row = Stack[Top][2];
|
||||
#local Dst_Col = Stack[Top][3];
|
||||
#declare Top = Top - 1;
|
||||
#local Removed_Wall = false;
|
||||
#while (Top >= 0 & Removed_Wall = false)
|
||||
#local Src_Row = Stack[Top][0];
|
||||
#local Src_Col = Stack[Top][1];
|
||||
#local Dst_Row = Stack[Top][2];
|
||||
#local Dst_Col = Stack[Top][3];
|
||||
#declare Top = Top - 1;
|
||||
|
||||
#if (Visited[Dst_Row][Dst_Col] = false)
|
||||
#if (Dst_Row = Src_Row+1 & Dst_Col = Src_Col) // North wall
|
||||
#declare North_Walls[Src_Row][Src_Col] = false;
|
||||
#elseif (Dst_Row = Src_Row & Dst_Col = Src_Col+1) // East wall
|
||||
#declare East_Walls[Src_Row][Src_Col] = false;
|
||||
#elseif (Dst_Row = Src_Row-1 & Dst_Col = Src_Col) // South wall
|
||||
#declare North_Walls[Dst_Row][Src_Col] = false;
|
||||
#elseif (Dst_Row = Src_Row & Dst_Col = Src_Col-1) // West wall
|
||||
#declare East_Walls[Src_Row][Dst_Col] = false;
|
||||
#else
|
||||
#error "Unknown wall!\n"
|
||||
#end
|
||||
#if (Visited[Dst_Row][Dst_Col] = false)
|
||||
#if (Dst_Row = Src_Row+1 & Dst_Col = Src_Col) // North wall
|
||||
#declare North_Walls[Src_Row][Src_Col] = false;
|
||||
#elseif (Dst_Row = Src_Row & Dst_Col = Src_Col+1) // East wall
|
||||
#declare East_Walls[Src_Row][Src_Col] = false;
|
||||
#elseif (Dst_Row = Src_Row-1 & Dst_Col = Src_Col) // South wall
|
||||
#declare North_Walls[Dst_Row][Src_Col] = false;
|
||||
#elseif (Dst_Row = Src_Row & Dst_Col = Src_Col-1) // West wall
|
||||
#declare East_Walls[Src_Row][Dst_Col] = false;
|
||||
#else
|
||||
#error "Unknown wall!\n"
|
||||
#end
|
||||
|
||||
#declare Row = Dst_Row;
|
||||
#declare Col = Dst_Col;
|
||||
#declare Removed_Wall = true;
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
#declare Row = Dst_Row;
|
||||
#declare Col = Dst_Col;
|
||||
#declare Removed_Wall = true;
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
|
||||
#macro Draw_Maze(North_Walls, East_Walls)
|
||||
merge {
|
||||
#for (R, 0, Rows-1)
|
||||
object { Wall translate <1, 0, 0.5> translate <-1, 0, R> } // West edge
|
||||
#for (C, 0, Cols-1)
|
||||
#if (R = 0) // South edge
|
||||
object { Wall rotate y*90 translate <0.5, 0, 1> translate <C, 0, -1> }
|
||||
#end
|
||||
#if (North_Walls[R][C])
|
||||
object { Wall rotate y*90 translate <0.5, 0, 1> translate <C, 0, R> }
|
||||
#end
|
||||
#if (East_Walls[R][C])
|
||||
object { Wall translate <1, 0, 0.5> translate <C, 0, R> }
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
translate <-0.5*Cols, 0, 0> // Centre maze on x=0
|
||||
}
|
||||
merge {
|
||||
#for (R, 0, Rows-1)
|
||||
object { Wall translate <1, 0, 0.5> translate <-1, 0, R> } // West edge
|
||||
#for (C, 0, Cols-1)
|
||||
#if (R = 0) // South edge
|
||||
object { Wall rotate y*90 translate <0.5, 0, 1> translate <C, 0, -1> }
|
||||
#end
|
||||
#if (North_Walls[R][C])
|
||||
object { Wall rotate y*90 translate <0.5, 0, 1> translate <C, 0, R> }
|
||||
#end
|
||||
#if (East_Walls[R][C])
|
||||
object { Wall translate <1, 0, 0.5> translate <C, 0, R> }
|
||||
#end
|
||||
#end
|
||||
#end
|
||||
translate <-0.5*Cols, 0, 0> // Centre maze on x=0
|
||||
}
|
||||
#end
|
||||
|
||||
camera {
|
||||
location <0, 13, -2>
|
||||
right x*image_width/image_height
|
||||
look_at <0, 2, 5>
|
||||
location <0, 13, -2>
|
||||
right x*image_width/image_height
|
||||
look_at <0, 2, 5>
|
||||
}
|
||||
|
||||
light_source {
|
||||
<-0.1*Cols, Rows, 0.5*Rows>, colour rgb <1, 1, 1>
|
||||
area_light
|
||||
x, y, 3, 3
|
||||
circular orient
|
||||
<-0.1*Cols, Rows, 0.5*Rows>, colour rgb <1, 1, 1>
|
||||
area_light
|
||||
x, y, 3, 3
|
||||
circular orient
|
||||
}
|
||||
|
||||
box {
|
||||
<-0.5*Cols, -0.1, 0>, <0.5*Cols, 0, Rows>
|
||||
texture {
|
||||
pigment {
|
||||
checker colour rgb <0, 0.3, 0> colour rgb <0, 0.4, 0>
|
||||
scale 0.5
|
||||
}
|
||||
finish { specular 0.5 reflection { 0.1 } }
|
||||
}
|
||||
<-0.5*Cols, -0.1, 0>, <0.5*Cols, 0, Rows>
|
||||
texture {
|
||||
pigment {
|
||||
checker colour rgb <0, 0.3, 0> colour rgb <0, 0.4, 0>
|
||||
scale 0.5
|
||||
}
|
||||
finish { specular 0.5 reflection { 0.1 } }
|
||||
}
|
||||
}
|
||||
|
||||
#declare Visited = array[Rows][Cols];
|
||||
|
|
|
|||
|
|
@ -11,26 +11,26 @@ my @ver = map([("| ") x $w], 1 .. $h);
|
|||
my @hor = map([("+--") x $w], 0 .. $h);
|
||||
|
||||
sub walk {
|
||||
my ($x, $y) = @_;
|
||||
$cell[$y][$x] = '';
|
||||
$avail-- or return; # no more bottles, er, cells
|
||||
my ($x, $y) = @_;
|
||||
$cell[$y][$x] = '';
|
||||
$avail-- or return; # no more bottles, er, cells
|
||||
|
||||
my @d = ([-1, 0], [0, 1], [1, 0], [0, -1]);
|
||||
while (@d) {
|
||||
my $i = splice @d, int(rand @d), 1;
|
||||
my ($x1, $y1) = ($x + $i->[0], $y + $i->[1]);
|
||||
my @d = ([-1, 0], [0, 1], [1, 0], [0, -1]);
|
||||
while (@d) {
|
||||
my $i = splice @d, int(rand @d), 1;
|
||||
my ($x1, $y1) = ($x + $i->[0], $y + $i->[1]);
|
||||
|
||||
$cell[$y1][$x1] or next;
|
||||
$cell[$y1][$x1] or next;
|
||||
|
||||
if ($x == $x1) { $hor[ max($y1, $y) ][$x] = '+ ' }
|
||||
if ($y == $y1) { $ver[$y][ max($x1, $x) ] = ' ' }
|
||||
walk($x1, $y1);
|
||||
}
|
||||
if ($x == $x1) { $hor[ max($y1, $y) ][$x] = '+ ' }
|
||||
if ($y == $y1) { $ver[$y][ max($x1, $x) ] = ' ' }
|
||||
walk($x1, $y1);
|
||||
}
|
||||
}
|
||||
|
||||
walk(int rand $w, int rand $h); # generate
|
||||
walk(int rand $w, int rand $h); # generate
|
||||
|
||||
for (0 .. $h) { # display
|
||||
print @{$hor[$_]}, "+\n";
|
||||
print @{$ver[$_]}, "|\n" if $_ < $h;
|
||||
for (0 .. $h) { # display
|
||||
print @{$hor[$_]}, "+\n";
|
||||
print @{$ver[$_]}, "|\n" if $_ < $h;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,89 +1,89 @@
|
|||
:- dynamic cell/2.
|
||||
|
||||
maze(Lig,Col) :-
|
||||
retractall(cell(_,_)),
|
||||
retractall(cell(_,_)),
|
||||
|
||||
new(D, window('Maze')),
|
||||
new(D, window('Maze')),
|
||||
|
||||
% creation of the grid
|
||||
forall(between(0,Lig, I),
|
||||
(XL is 50, YL is I * 30 + 50,
|
||||
XR is Col * 30 + 50,
|
||||
new(L, line(XL, YL, XR, YL)),
|
||||
send(D, display, L))),
|
||||
% creation of the grid
|
||||
forall(between(0,Lig, I),
|
||||
(XL is 50, YL is I * 30 + 50,
|
||||
XR is Col * 30 + 50,
|
||||
new(L, line(XL, YL, XR, YL)),
|
||||
send(D, display, L))),
|
||||
|
||||
forall(between(0,Col, I),
|
||||
(XT is 50 + I * 30, YT is 50,
|
||||
YB is Lig * 30 + 50,
|
||||
new(L, line(XT, YT, XT, YB)),
|
||||
send(D, display, L))),
|
||||
forall(between(0,Col, I),
|
||||
(XT is 50 + I * 30, YT is 50,
|
||||
YB is Lig * 30 + 50,
|
||||
new(L, line(XT, YT, XT, YB)),
|
||||
send(D, display, L))),
|
||||
|
||||
SX is Col * 30 + 100,
|
||||
SY is Lig * 30 + 100,
|
||||
send(D, size, new(_, size(SX, SY))),
|
||||
SX is Col * 30 + 100,
|
||||
SY is Lig * 30 + 100,
|
||||
send(D, size, new(_, size(SX, SY))),
|
||||
|
||||
% choosing a first cell
|
||||
L0 is random(Lig),
|
||||
C0 is random(Col),
|
||||
assert(cell(L0, C0)),
|
||||
\+search(D, Lig, Col, L0, C0),
|
||||
send(D, open).
|
||||
% choosing a first cell
|
||||
L0 is random(Lig),
|
||||
C0 is random(Col),
|
||||
assert(cell(L0, C0)),
|
||||
\+search(D, Lig, Col, L0, C0),
|
||||
send(D, open).
|
||||
|
||||
search(D, Lig, Col, L, C) :-
|
||||
Dir is random(4),
|
||||
nextcell(Dir, Lig, Col, L, C, L1, C1),
|
||||
assert(cell(L1,C1)),
|
||||
assert(cur(L1,C1)),
|
||||
erase_line(D, L, C, L1, C1),
|
||||
search(D, Lig, Col, L1, C1).
|
||||
Dir is random(4),
|
||||
nextcell(Dir, Lig, Col, L, C, L1, C1),
|
||||
assert(cell(L1,C1)),
|
||||
assert(cur(L1,C1)),
|
||||
erase_line(D, L, C, L1, C1),
|
||||
search(D, Lig, Col, L1, C1).
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
erase_line(D, L, C, L, C1) :-
|
||||
( C < C1 -> C2 = C1; C2 = C),
|
||||
XT is C2 * 30 + 50,
|
||||
YT is L * 30 + 51, YR is (L+1) * 30 + 50,
|
||||
new(Line, line(XT, YT, XT, YR)),
|
||||
send(Line, colour, white),
|
||||
send(D, display, Line).
|
||||
( C < C1 -> C2 = C1; C2 = C),
|
||||
XT is C2 * 30 + 50,
|
||||
YT is L * 30 + 51, YR is (L+1) * 30 + 50,
|
||||
new(Line, line(XT, YT, XT, YR)),
|
||||
send(Line, colour, white),
|
||||
send(D, display, Line).
|
||||
|
||||
erase_line(D, L, C, L1, C) :-
|
||||
XT is 51 + C * 30, XR is 50 + (C + 1) * 30,
|
||||
( L < L1 -> L2 is L1; L2 is L),
|
||||
YT is L2 * 30 + 50,
|
||||
new(Line, line(XT, YT, XR, YT)),
|
||||
send(Line, colour, white),
|
||||
send(D, display, Line).
|
||||
XT is 51 + C * 30, XR is 50 + (C + 1) * 30,
|
||||
( L < L1 -> L2 is L1; L2 is L),
|
||||
YT is L2 * 30 + 50,
|
||||
new(Line, line(XT, YT, XR, YT)),
|
||||
send(Line, colour, white),
|
||||
send(D, display, Line).
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
nextcell(Dir, Lig, Col, L, C, L1, C1) :-
|
||||
next(Dir, Lig, Col, L, C, L1, C1);
|
||||
( Dir1 is (Dir+3) mod 4,
|
||||
next(Dir1, Lig, Col, L, C, L1, C1));
|
||||
( Dir2 is (Dir+1) mod 4,
|
||||
next(Dir2, Lig, Col, L, C, L1, C1));
|
||||
( Dir3 is (Dir+2) mod 4,
|
||||
next(Dir3, Lig, Col, L, C, L1, C1)).
|
||||
next(Dir, Lig, Col, L, C, L1, C1);
|
||||
( Dir1 is (Dir+3) mod 4,
|
||||
next(Dir1, Lig, Col, L, C, L1, C1));
|
||||
( Dir2 is (Dir+1) mod 4,
|
||||
next(Dir2, Lig, Col, L, C, L1, C1));
|
||||
( Dir3 is (Dir+2) mod 4,
|
||||
next(Dir3, Lig, Col, L, C, L1, C1)).
|
||||
|
||||
% 0 => northward
|
||||
next(0, _Lig, _Col, L, C, L1, C) :-
|
||||
L > 0,
|
||||
L1 is L - 1,
|
||||
\+cell(L1, C).
|
||||
L > 0,
|
||||
L1 is L - 1,
|
||||
\+cell(L1, C).
|
||||
|
||||
% 1 => rightward
|
||||
next(1, _Lig, Col, L, C, L, C1) :-
|
||||
C < Col - 1,
|
||||
C1 is C + 1,
|
||||
\+cell(L, C1).
|
||||
C < Col - 1,
|
||||
C1 is C + 1,
|
||||
\+cell(L, C1).
|
||||
|
||||
% 2 => southward
|
||||
next(2, Lig, _Col, L, C, L1, C) :-
|
||||
L < Lig - 1,
|
||||
L1 is L + 1,
|
||||
\+cell(L1, C).
|
||||
L < Lig - 1,
|
||||
L1 is L + 1,
|
||||
\+cell(L1, C).
|
||||
|
||||
% 3 => leftward
|
||||
next(2, _Lig, _Col, L, C, L, C1) :-
|
||||
C > 0,
|
||||
C1 is C - 1,
|
||||
\+cell(L, C1).
|
||||
C > 0,
|
||||
C1 is C - 1,
|
||||
\+cell(L, C1).
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
constant mapping = :OPEN(' '),
|
||||
:N< ╵ >,
|
||||
:E< ╶ >,
|
||||
:NE< └ >,
|
||||
:S< ╷ >,
|
||||
:NS< │ >,
|
||||
:ES< ┌ >,
|
||||
:NES< ├ >,
|
||||
:W< ╴ >,
|
||||
:NW< ┘ >,
|
||||
:EW< ─ >,
|
||||
:NEW< ┴ >,
|
||||
:SW< ┐ >,
|
||||
:NSW< ┤ >,
|
||||
:ESW< ┬ >,
|
||||
:NESW< ┼ >,
|
||||
:TODO< x >,
|
||||
:TRIED< · >;
|
||||
:N< ╵ >,
|
||||
:E< ╶ >,
|
||||
:NE< └ >,
|
||||
:S< ╷ >,
|
||||
:NS< │ >,
|
||||
:ES< ┌ >,
|
||||
:NES< ├ >,
|
||||
:W< ╴ >,
|
||||
:NW< ┘ >,
|
||||
:EW< ─ >,
|
||||
:NEW< ┴ >,
|
||||
:SW< ┐ >,
|
||||
:NSW< ┤ >,
|
||||
:ESW< ┬ >,
|
||||
:NESW< ┼ >,
|
||||
:TODO< x >,
|
||||
:TRIED< · >;
|
||||
|
||||
enum Sym (mapping.map: *.key);
|
||||
my @ch = mapping.map: *.value;
|
||||
|
|
@ -31,8 +31,8 @@ sub gen_maze ( $X,
|
|||
push @maze, $[ flat ES, -N, (ESW, EW) xx $X - 1, SW ];
|
||||
push @maze, $[ flat (NS, TODO) xx $X, NS ];
|
||||
for 1 ..^ $Y {
|
||||
push @maze, $[ flat NES, EW, (NESW, EW) xx $X - 1, NSW ];
|
||||
push @maze, $[ flat (NS, TODO) xx $X, NS ];
|
||||
push @maze, $[ flat NES, EW, (NESW, EW) xx $X - 1, NSW ];
|
||||
push @maze, $[ flat (NS, TODO) xx $X, NS ];
|
||||
}
|
||||
push @maze, $[ flat NE, (EW, NEW) xx $X - 1, -NS, NW ];
|
||||
@maze[$start_y][$start_x] = OPEN;
|
||||
|
|
@ -52,35 +52,35 @@ sub gen_maze ( $X,
|
|||
return @maze;
|
||||
|
||||
sub pick_direction([$x,$y]) {
|
||||
my @neighbors =
|
||||
(Up if @maze[$y - 2][$x]),
|
||||
(Down if @maze[$y + 2][$x]),
|
||||
(Left if @maze[$y][$x - 2]),
|
||||
(Right if @maze[$y][$x + 2]);
|
||||
@neighbors.pick or DeadEnd;
|
||||
my @neighbors =
|
||||
(Up if @maze[$y - 2][$x]),
|
||||
(Down if @maze[$y + 2][$x]),
|
||||
(Left if @maze[$y][$x - 2]),
|
||||
(Right if @maze[$y][$x + 2]);
|
||||
@neighbors.pick or DeadEnd;
|
||||
}
|
||||
|
||||
sub move ($dir, @cur) {
|
||||
my ($x,$y) = @cur;
|
||||
given $dir {
|
||||
when Up { @maze[--$y][$x] = OPEN; @maze[$y][$x-1] -= E; @maze[$y--][$x+1] -= W; }
|
||||
when Down { @maze[++$y][$x] = OPEN; @maze[$y][$x-1] -= E; @maze[$y++][$x+1] -= W; }
|
||||
when Left { @maze[$y][--$x] = OPEN; @maze[$y-1][$x] -= S; @maze[$y+1][$x--] -= N; }
|
||||
when Right { @maze[$y][++$x] = OPEN; @maze[$y-1][$x] -= S; @maze[$y+1][$x++] -= N; }
|
||||
}
|
||||
@maze[$y][$x] = 0;
|
||||
[$x,$y];
|
||||
my ($x,$y) = @cur;
|
||||
given $dir {
|
||||
when Up { @maze[--$y][$x] = OPEN; @maze[$y][$x-1] -= E; @maze[$y--][$x+1] -= W; }
|
||||
when Down { @maze[++$y][$x] = OPEN; @maze[$y][$x-1] -= E; @maze[$y++][$x+1] -= W; }
|
||||
when Left { @maze[$y][--$x] = OPEN; @maze[$y-1][$x] -= S; @maze[$y+1][$x--] -= N; }
|
||||
when Right { @maze[$y][++$x] = OPEN; @maze[$y-1][$x] -= S; @maze[$y+1][$x++] -= N; }
|
||||
}
|
||||
@maze[$y][$x] = 0;
|
||||
[$x,$y];
|
||||
}
|
||||
}
|
||||
|
||||
sub display (@maze) {
|
||||
for @maze -> @y {
|
||||
for @y.rotor(2) -> ($w, $c) {
|
||||
print @ch[abs $w];
|
||||
if $c >= 0 { print @ch[$c] x 3 }
|
||||
else { print ' ', @ch[abs $c], ' ' }
|
||||
}
|
||||
say @ch[@y[*-1]];
|
||||
for @y.rotor(2) -> ($w, $c) {
|
||||
print @ch[abs $w];
|
||||
if $c >= 0 { print @ch[$c] x 3 }
|
||||
else { print ' ', @ch[abs $c], ' ' }
|
||||
}
|
||||
say @ch[@y[*-1]];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,27 +3,27 @@ import util::Math;
|
|||
import List;
|
||||
|
||||
public void make_maze(int w, int h){
|
||||
vis = [[0 | _ <- [1..w]] | _ <- [1..h]];
|
||||
ver = [["| "| _ <- [1..w]] + ["|"] | _ <- [1..h]] + [[]];
|
||||
hor = [["+--"| _ <- [1..w]] + ["+"] | _ <- [1..h + 1]];
|
||||
vis = [[0 | _ <- [1..w]] | _ <- [1..h]];
|
||||
ver = [["| "| _ <- [1..w]] + ["|"] | _ <- [1..h]] + [[]];
|
||||
hor = [["+--"| _ <- [1..w]] + ["+"] | _ <- [1..h + 1]];
|
||||
|
||||
void walk(int x, int y){
|
||||
vis[y][x] = 1;
|
||||
void walk(int x, int y){
|
||||
vis[y][x] = 1;
|
||||
|
||||
d = [<x - 1, y>, <x, y + 1>, <x + 1, y>, <x, y - 1>];
|
||||
while (d != []){
|
||||
<<xx, yy>, d> = takeOneFrom(d);
|
||||
if (xx < 0 || yy < 0 || xx >= w || yy >= w) continue;
|
||||
if (vis[yy][xx] == 1) continue;
|
||||
if (xx == x) hor[max([y, yy])][x] = "+ ";
|
||||
if (yy == y) ver[y][max([x, xx])] = " ";
|
||||
walk(xx, yy);
|
||||
}
|
||||
}
|
||||
|
||||
walk(arbInt(w), arbInt(h));
|
||||
for (<a, b> <- zip(hor, ver)){
|
||||
println(("" | it + "<z>" | z <- a));
|
||||
println(("" | it + "<z>" | z <- b));
|
||||
}
|
||||
d = [<x - 1, y>, <x, y + 1>, <x + 1, y>, <x, y - 1>];
|
||||
while (d != []){
|
||||
<<xx, yy>, d> = takeOneFrom(d);
|
||||
if (xx < 0 || yy < 0 || xx >= w || yy >= w) continue;
|
||||
if (vis[yy][xx] == 1) continue;
|
||||
if (xx == x) hor[max([y, yy])][x] = "+ ";
|
||||
if (yy == y) ver[y][max([x, xx])] = " ";
|
||||
walk(xx, yy);
|
||||
}
|
||||
}
|
||||
|
||||
walk(arbInt(w), arbInt(h));
|
||||
for (<a, b> <- zip(hor, ver)){
|
||||
println(("" | it + "<z>" | z <- a));
|
||||
println(("" | it + "<z>" | z <- b));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
72
Task/Maze-generation/Rebol/maze-generation.rebol
Normal file
72
Task/Maze-generation/Rebol/maze-generation.rebol
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
Rebol [
|
||||
title: "Rosetta code: Maze generation"
|
||||
file: %Maze_generation.r3
|
||||
url: https://rosettacode.org/wiki/Maze_generation
|
||||
]
|
||||
|
||||
make-maze: function/with [
|
||||
width [integer!]
|
||||
height [integer!]
|
||||
][
|
||||
clear visited
|
||||
clear walls
|
||||
clear exploring
|
||||
|
||||
size: as-pair width height
|
||||
append/dup walls 1x1 width * height
|
||||
repend exploring [random size - 1x1]
|
||||
|
||||
until [
|
||||
expand exploring/1
|
||||
empty? exploring
|
||||
]
|
||||
reduce [width height copy walls]
|
||||
][
|
||||
size: _ visited: [] walls: [] exploring: []
|
||||
offsetof: function [pos] [pos/y * size/x + pos/x + 1]
|
||||
visited?: function [pos] [find visited pos]
|
||||
|
||||
newneighbour: function [pos][
|
||||
nnbs: collect [
|
||||
if all [pos/x > 0 not visited? p: pos - 1x0] [keep p]
|
||||
if all [pos/x < (size/x - 1) not visited? p: pos + 1x0] [keep p]
|
||||
if all [pos/y > 0 not visited? p: pos - 0x1] [keep p]
|
||||
if all [pos/y < (size/y - 1) not visited? p: pos + 0x1] [keep p]
|
||||
]
|
||||
pick nnbs random length? nnbs
|
||||
]
|
||||
expand: function [pos][
|
||||
insert visited pos
|
||||
either npos: newneighbour pos [
|
||||
insert exploring npos
|
||||
do select [
|
||||
0x-1 [o: offsetof npos walls/:o/y: 0]
|
||||
1x0 [o: offsetof pos walls/:o/x: 0]
|
||||
0x1 [o: offsetof pos walls/:o/y: 0]
|
||||
-1x0 [o: offsetof npos walls/:o/x: 0]
|
||||
] npos - pos
|
||||
][
|
||||
remove exploring
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
draw-maze: function[spec][
|
||||
set [cols: rows: walls:] spec
|
||||
out: copy ""
|
||||
append/dup out " _" cols
|
||||
append out LF
|
||||
repeat j rows [
|
||||
append out "|"
|
||||
repeat i cols [
|
||||
p: pick walls (j - 1 * cols + i)
|
||||
append out ajoin [pick " _" 1 + p/y pick " |" 1 + p/x]
|
||||
]
|
||||
append out LF
|
||||
]
|
||||
copy out
|
||||
]
|
||||
|
||||
random/seed now/time
|
||||
maze: make-maze 15 15
|
||||
print draw-maze maze
|
||||
|
|
@ -6,43 +6,43 @@ offsetof: function [pos] [pos/y * size/x + pos/x + 1]
|
|||
visited?: function [pos] [find visited pos]
|
||||
|
||||
newneighbour: function [pos][
|
||||
nnbs: collect [
|
||||
if all [pos/x > 0 not visited? p: pos - 1x0] [keep p]
|
||||
if all [pos/x < (size/x - 1) not visited? p: pos + 1x0] [keep p]
|
||||
if all [pos/y > 0 not visited? p: pos - 0x1] [keep p]
|
||||
if all [pos/y < (size/y - 1) not visited? p: pos + 0x1] [keep p]
|
||||
]
|
||||
pick nnbs random length? nnbs
|
||||
nnbs: collect [
|
||||
if all [pos/x > 0 not visited? p: pos - 1x0] [keep p]
|
||||
if all [pos/x < (size/x - 1) not visited? p: pos + 1x0] [keep p]
|
||||
if all [pos/y > 0 not visited? p: pos - 0x1] [keep p]
|
||||
if all [pos/y < (size/y - 1) not visited? p: pos + 0x1] [keep p]
|
||||
]
|
||||
pick nnbs random length? nnbs
|
||||
]
|
||||
expand: function [pos][
|
||||
insert visited pos
|
||||
either npos: newneighbour pos [
|
||||
insert exploring npos
|
||||
do select [
|
||||
0x-1 [o: offsetof npos walls/:o/y: 0]
|
||||
1x0 [o: offsetof pos walls/:o/x: 0]
|
||||
0x1 [o: offsetof pos walls/:o/y: 0]
|
||||
-1x0 [o: offsetof npos walls/:o/x: 0]
|
||||
] npos - pos
|
||||
][
|
||||
remove exploring
|
||||
]
|
||||
expand: function [pos][
|
||||
insert visited pos
|
||||
either npos: newneighbour pos [
|
||||
insert exploring npos
|
||||
do select [
|
||||
0x-1 [o: offsetof npos walls/:o/y: 0]
|
||||
1x0 [o: offsetof pos walls/:o/x: 0]
|
||||
0x1 [o: offsetof pos walls/:o/y: 0]
|
||||
-1x0 [o: offsetof npos walls/:o/x: 0]
|
||||
] npos - pos
|
||||
][
|
||||
remove exploring
|
||||
]
|
||||
]
|
||||
visited: []
|
||||
walls: append/dup [] 1x1 size/x * size/y
|
||||
exploring: reduce [random size - 1x1]
|
||||
|
||||
until [
|
||||
expand exploring/1
|
||||
empty? exploring
|
||||
expand exploring/1
|
||||
empty? exploring
|
||||
]
|
||||
|
||||
print append/dup "" " _" size/x
|
||||
repeat j size/y [
|
||||
prin "|"
|
||||
repeat i size/x [
|
||||
p: pick walls (j - 1 * size/x + i)
|
||||
prin rejoin [pick " _" 1 + p/y pick " |" 1 + p/x]
|
||||
]
|
||||
print ""
|
||||
prin "|"
|
||||
repeat i size/x [
|
||||
p: pick walls (j - 1 * size/x + i)
|
||||
prin rejoin [pick " _" 1 + p/y pick " |" 1 + p/x]
|
||||
]
|
||||
print ""
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,32 +3,32 @@
|
|||
~grid = { 0 ! 60 } ! 60;
|
||||
|
||||
~at = { |coord|
|
||||
var col = ~grid.at(coord[0]);
|
||||
if(col.notNil) { col.at(coord[1]) }
|
||||
var col = ~grid.at(coord[0]);
|
||||
if(col.notNil) { col.at(coord[1]) }
|
||||
};
|
||||
~put = { |coord, value|
|
||||
var col = ~grid.at(coord[0]);
|
||||
if(col.notNil) { col.put(coord[1], value) }
|
||||
var col = ~grid.at(coord[0]);
|
||||
if(col.notNil) { col.put(coord[1], value) }
|
||||
};
|
||||
|
||||
~coord = ~grid.shape.rand;
|
||||
~next = { |p|
|
||||
var possible = [p] + [[0, 1], [1, 0], [-1, 0], [0, -1]];
|
||||
possible = possible.select { |x|
|
||||
var c = ~at.(x);
|
||||
c.notNil and: { c == 0 }
|
||||
};
|
||||
possible.choose
|
||||
var possible = [p] + [[0, 1], [1, 0], [-1, 0], [0, -1]];
|
||||
possible = possible.select { |x|
|
||||
var c = ~at.(x);
|
||||
c.notNil and: { c == 0 }
|
||||
};
|
||||
possible.choose
|
||||
};
|
||||
~walkN = { |p, scale|
|
||||
var next = ~next.(p);
|
||||
if(next.notNil) {
|
||||
~put.(next, 1);
|
||||
Pen.lineTo(~topoint.(next, scale));
|
||||
~walkN.(next, scale);
|
||||
~walkN.(next, scale);
|
||||
Pen.moveTo(~topoint.(p, scale));
|
||||
};
|
||||
var next = ~next.(p);
|
||||
if(next.notNil) {
|
||||
~put.(next, 1);
|
||||
Pen.lineTo(~topoint.(next, scale));
|
||||
~walkN.(next, scale);
|
||||
~walkN.(next, scale);
|
||||
Pen.moveTo(~topoint.(p, scale));
|
||||
};
|
||||
};
|
||||
|
||||
~topoint = { |c, scale| (c + [1, 1] * scale).asPoint };
|
||||
|
|
@ -44,13 +44,13 @@ w = Window("so-a-mazing", b);
|
|||
w.view.background_(Color.black);
|
||||
|
||||
w.drawFunc = {
|
||||
var p = ~grid.shape.rand;
|
||||
var scale = b.width / ~grid.size * 0.98;
|
||||
Pen.moveTo(~topoint.(p, scale));
|
||||
~walkN.(p, scale);
|
||||
Pen.width = scale / 4;
|
||||
Pen.color = Color.white;
|
||||
Pen.stroke;
|
||||
var p = ~grid.shape.rand;
|
||||
var scale = b.width / ~grid.size * 0.98;
|
||||
Pen.moveTo(~topoint.(p, scale));
|
||||
~walkN.(p, scale);
|
||||
Pen.width = scale / 4;
|
||||
Pen.color = Color.white;
|
||||
Pen.stroke;
|
||||
};
|
||||
w.front.refresh;
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,85 +10,85 @@ proc tcl::mathfunc::idx {v x y} {lindex $v $x $y}
|
|||
oo::class create maze {
|
||||
variable x y horiz verti content
|
||||
constructor {width height} {
|
||||
set y $width
|
||||
set x $height
|
||||
set y $width
|
||||
set x $height
|
||||
|
||||
set n [expr {$x * $y - 1}]
|
||||
if {$n < 0} {error "illegal maze dimensions"}
|
||||
set horiz [set verti [lrepeat $x [lrepeat $y 0]]]
|
||||
# This matrix holds the output for the Maze Solving task; not used for generation
|
||||
set content [lrepeat $x [lrepeat $y " "]]
|
||||
set unvisited [lrepeat [expr {$x+2}] [lrepeat [expr {$y+2}] 0]]
|
||||
# Helper to write into a list of lists (with offsets)
|
||||
proc unvisited= {x y value} {
|
||||
upvar 1 unvisited u
|
||||
lset u [expr {$x+1}] [expr {$y+1}] $value
|
||||
}
|
||||
set n [expr {$x * $y - 1}]
|
||||
if {$n < 0} {error "illegal maze dimensions"}
|
||||
set horiz [set verti [lrepeat $x [lrepeat $y 0]]]
|
||||
# This matrix holds the output for the Maze Solving task; not used for generation
|
||||
set content [lrepeat $x [lrepeat $y " "]]
|
||||
set unvisited [lrepeat [expr {$x+2}] [lrepeat [expr {$y+2}] 0]]
|
||||
# Helper to write into a list of lists (with offsets)
|
||||
proc unvisited= {x y value} {
|
||||
upvar 1 unvisited u
|
||||
lset u [expr {$x+1}] [expr {$y+1}] $value
|
||||
}
|
||||
|
||||
lappend stack [set here [list [rand $x] [rand $y]]]
|
||||
for {set j 0} {$j < $x} {incr j} {
|
||||
for {set k 0} {$k < $y} {incr k} {
|
||||
unvisited= $j $k [expr {$here ne [list $j $k]}]
|
||||
}
|
||||
}
|
||||
lappend stack [set here [list [rand $x] [rand $y]]]
|
||||
for {set j 0} {$j < $x} {incr j} {
|
||||
for {set k 0} {$k < $y} {incr k} {
|
||||
unvisited= $j $k [expr {$here ne [list $j $k]}]
|
||||
}
|
||||
}
|
||||
|
||||
while {0 < $n} {
|
||||
lassign $here hx hy
|
||||
set neighbours {}
|
||||
foreach {dx dy} {1 0 0 1 -1 0 0 -1} {
|
||||
if {idx($unvisited, $hx+$dx+1, $hy+$dy+1)} {
|
||||
lappend neighbours [list [expr {$hx+$dx}] [expr {$hy+$dy}]]
|
||||
}
|
||||
}
|
||||
if {[llength $neighbours]} {
|
||||
lassign [set here [pick $neighbours]] nx ny
|
||||
unvisited= $nx $ny 0
|
||||
if {$nx == $hx} {
|
||||
lset horiz $nx [expr {min($ny, $hy)}] 1
|
||||
} else {
|
||||
lset verti [expr {min($nx, $hx)}] $ny 1
|
||||
}
|
||||
lappend stack $here
|
||||
incr n -1
|
||||
} else {
|
||||
set here [lindex $stack end]
|
||||
set stack [lrange $stack 0 end-1]
|
||||
}
|
||||
}
|
||||
while {0 < $n} {
|
||||
lassign $here hx hy
|
||||
set neighbours {}
|
||||
foreach {dx dy} {1 0 0 1 -1 0 0 -1} {
|
||||
if {idx($unvisited, $hx+$dx+1, $hy+$dy+1)} {
|
||||
lappend neighbours [list [expr {$hx+$dx}] [expr {$hy+$dy}]]
|
||||
}
|
||||
}
|
||||
if {[llength $neighbours]} {
|
||||
lassign [set here [pick $neighbours]] nx ny
|
||||
unvisited= $nx $ny 0
|
||||
if {$nx == $hx} {
|
||||
lset horiz $nx [expr {min($ny, $hy)}] 1
|
||||
} else {
|
||||
lset verti [expr {min($nx, $hx)}] $ny 1
|
||||
}
|
||||
lappend stack $here
|
||||
incr n -1
|
||||
} else {
|
||||
set here [lindex $stack end]
|
||||
set stack [lrange $stack 0 end-1]
|
||||
}
|
||||
}
|
||||
|
||||
rename unvisited= {}
|
||||
rename unvisited= {}
|
||||
}
|
||||
|
||||
# Maze displayer; takes a maze dictionary, returns a string
|
||||
method view {} {
|
||||
set text {}
|
||||
for {set j 0} {$j < $x*2+1} {incr j} {
|
||||
set line {}
|
||||
for {set k 0} {$k < $y*4+1} {incr k} {
|
||||
if {$j%2 && $k%4==2} {
|
||||
# At the centre of the cell, put the "content" of the cell
|
||||
append line [expr {idx($content, $j/2, $k/4)}]
|
||||
} elseif {$j%2 && ($k%4 || $k && idx($horiz, $j/2, $k/4-1))} {
|
||||
append line " "
|
||||
} elseif {$j%2} {
|
||||
append line "|"
|
||||
} elseif {0 == $k%4} {
|
||||
append line "+"
|
||||
} elseif {$j && idx($verti, $j/2-1, $k/4)} {
|
||||
append line " "
|
||||
} else {
|
||||
append line "-"
|
||||
}
|
||||
}
|
||||
if {!$j} {
|
||||
lappend text [string replace $line 1 3 " "]
|
||||
} elseif {$x*2-1 == $j} {
|
||||
lappend text [string replace $line end end " "]
|
||||
} else {
|
||||
lappend text $line
|
||||
}
|
||||
}
|
||||
return [join $text \n]
|
||||
set text {}
|
||||
for {set j 0} {$j < $x*2+1} {incr j} {
|
||||
set line {}
|
||||
for {set k 0} {$k < $y*4+1} {incr k} {
|
||||
if {$j%2 && $k%4==2} {
|
||||
# At the centre of the cell, put the "content" of the cell
|
||||
append line [expr {idx($content, $j/2, $k/4)}]
|
||||
} elseif {$j%2 && ($k%4 || $k && idx($horiz, $j/2, $k/4-1))} {
|
||||
append line " "
|
||||
} elseif {$j%2} {
|
||||
append line "|"
|
||||
} elseif {0 == $k%4} {
|
||||
append line "+"
|
||||
} elseif {$j && idx($verti, $j/2-1, $k/4)} {
|
||||
append line " "
|
||||
} else {
|
||||
append line "-"
|
||||
}
|
||||
}
|
||||
if {!$j} {
|
||||
lappend text [string replace $line 1 3 " "]
|
||||
} elseif {$x*2-1 == $j} {
|
||||
lappend text [string replace $line end end " "]
|
||||
} else {
|
||||
lappend text $line
|
||||
}
|
||||
}
|
||||
return [join $text \n]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
interface mazeData{
|
||||
nodes:Node[]
|
||||
x:number
|
||||
y:number
|
||||
blockSize:number
|
||||
nodes:Node[]
|
||||
x:number
|
||||
y:number
|
||||
blockSize:number
|
||||
}
|
||||
|
||||
class Node{
|
||||
x:number
|
||||
y:number
|
||||
wallsTo:Node[]
|
||||
visited = false
|
||||
constructor(x:number,y:number){
|
||||
this.x = x
|
||||
this.y = y
|
||||
}
|
||||
getTouchingNodes(nodes:Node[],blockSize:number){
|
||||
x:number
|
||||
y:number
|
||||
wallsTo:Node[]
|
||||
visited = false
|
||||
constructor(x:number,y:number){
|
||||
this.x = x
|
||||
this.y = y
|
||||
}
|
||||
getTouchingNodes(nodes:Node[],blockSize:number){
|
||||
return nodes.filter(n=>
|
||||
(this != n) &&
|
||||
(Math.hypot(this.x-n.x,this.y-n.y) == blockSize )
|
||||
)
|
||||
}
|
||||
draw(ctx:CanvasRenderingContext2D,blockSize:number){
|
||||
draw(ctx:CanvasRenderingContext2D,blockSize:number){
|
||||
ctx.fillStyle ='black'
|
||||
this.wallsTo.forEach(el=>{
|
||||
ctx.save()
|
||||
|
|
@ -36,41 +36,41 @@ class Node{
|
|||
}
|
||||
|
||||
export function maze(x:number,y:number):mazeData {
|
||||
let blockSize = 20
|
||||
x *= blockSize
|
||||
y *= blockSize
|
||||
let nodes = Array((x/blockSize)*(y/blockSize)).fill(0).map((_el,i)=>
|
||||
new Node(
|
||||
(i%(x/blockSize)*(blockSize))+(blockSize/2),
|
||||
(Math.floor(i/(x/blockSize))*(blockSize))+(blockSize/2)
|
||||
)
|
||||
)
|
||||
nodes.forEach(n=>n.wallsTo = n.getTouchingNodes(nodes,blockSize))
|
||||
let que = [nodes[0]]
|
||||
while(que.length > 0){
|
||||
let current = que.shift()
|
||||
let unvisited = current
|
||||
.getTouchingNodes(nodes,blockSize)
|
||||
.filter(el=>!el.visited)
|
||||
if(unvisited.length >0){
|
||||
que.push(current)
|
||||
let chosen = unvisited[Math.floor(Math.random()*unvisited.length)];
|
||||
current.wallsTo = current.wallsTo.filter((el)=>el != chosen)
|
||||
chosen.wallsTo = chosen.wallsTo.filter((el)=>el != current)
|
||||
chosen.visited = true
|
||||
que.unshift(chosen)
|
||||
}
|
||||
}
|
||||
return {x:x,y:y,nodes:nodes,blockSize:blockSize}
|
||||
let blockSize = 20
|
||||
x *= blockSize
|
||||
y *= blockSize
|
||||
let nodes = Array((x/blockSize)*(y/blockSize)).fill(0).map((_el,i)=>
|
||||
new Node(
|
||||
(i%(x/blockSize)*(blockSize))+(blockSize/2),
|
||||
(Math.floor(i/(x/blockSize))*(blockSize))+(blockSize/2)
|
||||
)
|
||||
)
|
||||
nodes.forEach(n=>n.wallsTo = n.getTouchingNodes(nodes,blockSize))
|
||||
let que = [nodes[0]]
|
||||
while(que.length > 0){
|
||||
let current = que.shift()
|
||||
let unvisited = current
|
||||
.getTouchingNodes(nodes,blockSize)
|
||||
.filter(el=>!el.visited)
|
||||
if(unvisited.length >0){
|
||||
que.push(current)
|
||||
let chosen = unvisited[Math.floor(Math.random()*unvisited.length)];
|
||||
current.wallsTo = current.wallsTo.filter((el)=>el != chosen)
|
||||
chosen.wallsTo = chosen.wallsTo.filter((el)=>el != current)
|
||||
chosen.visited = true
|
||||
que.unshift(chosen)
|
||||
}
|
||||
}
|
||||
return {x:x,y:y,nodes:nodes,blockSize:blockSize}
|
||||
}
|
||||
|
||||
export function display(c:HTMLCanvasElement,mazeData:mazeData){
|
||||
let ctx = c.getContext('2d')
|
||||
c.width = mazeData.x
|
||||
c.height = mazeData.y
|
||||
ctx.fillStyle = 'white'
|
||||
ctx.strokeStyle = 'black'
|
||||
ctx.fillRect(0,0,mazeData.x,mazeData.y)
|
||||
ctx.strokeRect(0,0,mazeData.x,mazeData.y)
|
||||
mazeData.nodes.forEach(el=>el.draw(ctx,mazeData.blockSize))
|
||||
let ctx = c.getContext('2d')
|
||||
c.width = mazeData.x
|
||||
c.height = mazeData.y
|
||||
ctx.fillStyle = 'white'
|
||||
ctx.strokeStyle = 'black'
|
||||
ctx.fillRect(0,0,mazeData.x,mazeData.y)
|
||||
ctx.strokeRect(0,0,mazeData.x,mazeData.y)
|
||||
mazeData.nodes.forEach(el=>el.draw(ctx,mazeData.blockSize))
|
||||
}
|
||||
|
|
|
|||
93
Task/Maze-generation/V-(Vlang)/maze-generation.v
Normal file
93
Task/Maze-generation/V-(Vlang)/maze-generation.v
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
import rand
|
||||
import os
|
||||
|
||||
struct Direction {
|
||||
bit int
|
||||
dx int
|
||||
dy int
|
||||
}
|
||||
|
||||
struct MazeGenerator {
|
||||
x int
|
||||
y int
|
||||
mut:
|
||||
maze [][]int
|
||||
directions []Direction
|
||||
opposites map[int]Direction
|
||||
}
|
||||
|
||||
fn new_maze_generator(x int, y int) MazeGenerator {
|
||||
mut maze := [][]int{len: x}
|
||||
for i in 0 .. x {
|
||||
maze[i] = []int{len: y, init: 0}
|
||||
}
|
||||
directions := [Direction{bit: 1, dx: 0, dy: -1}, Direction{bit: 2, dx: 0, dy: 1},
|
||||
Direction{bit: 4, dx: 1, dy: 0}, Direction{bit: 8, dx: -1, dy: 0}]
|
||||
opposites := {
|
||||
1: directions[1] // N.opposite = S
|
||||
2: directions[0] // S.opposite = N
|
||||
4: directions[3] // E.opposite = W
|
||||
8: directions[2] // W.opposite = E
|
||||
}
|
||||
return MazeGenerator{
|
||||
x: x
|
||||
y: y
|
||||
maze: maze
|
||||
directions: directions
|
||||
opposites: opposites
|
||||
}
|
||||
}
|
||||
|
||||
fn (mg MazeGenerator) between(v int, upper int) bool {
|
||||
return v >= 0 && v < upper
|
||||
}
|
||||
|
||||
fn (mg MazeGenerator) directions_shuffled() ![]Direction {
|
||||
mut dirs := mg.directions.clone()
|
||||
rand.shuffle(mut dirs) or {0}
|
||||
return dirs
|
||||
}
|
||||
|
||||
fn (mut mg MazeGenerator) generate(cx int, cy int) {
|
||||
mut shuf := mg.directions_shuffled() or {return}
|
||||
for dir in shuf {
|
||||
nx := cx + dir.dx
|
||||
ny := cy + dir.dy
|
||||
if mg.between(nx, mg.x) && mg.between(ny, mg.y) && mg.maze[nx][ny] == 0 {
|
||||
mg.maze[cx][cy] |= dir.bit
|
||||
opp := mg.opposites[dir.bit] or { panic("Opposite direction not found") }
|
||||
mg.maze[nx][ny] |= opp.bit
|
||||
mg.generate(nx, ny)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mg MazeGenerator) display() {
|
||||
for i in 0 .. mg.y {
|
||||
for j in 0 .. mg.x {
|
||||
if (mg.maze[j][i] & 1) == 0 { print("+---") }
|
||||
else { print("+ ") }
|
||||
}
|
||||
println("+")
|
||||
for j in 0 .. mg.x {
|
||||
if (mg.maze[j][i] & 8) == 0 { print("| ") }
|
||||
else { print(" ") }
|
||||
}
|
||||
println("|")
|
||||
}
|
||||
for _ in 0 .. mg.x {
|
||||
print("+---")
|
||||
}
|
||||
println("+")
|
||||
}
|
||||
|
||||
fn main() {
|
||||
args := os.args
|
||||
mut x := 8
|
||||
mut y := 8
|
||||
mut mg := new_maze_generator(x, y)
|
||||
if args.len >= 2 { x = args[1].int() }
|
||||
if args.len >= 3 { y = args[2].int() }
|
||||
mg.generate(0, 0)
|
||||
mg.display()
|
||||
}
|
||||
|
|
@ -9,10 +9,10 @@ fcn make_maze(w = 16, h = 8){
|
|||
|
||||
d:=L(T(x - 1, y), T(x, y + 1), T(x + 1, y), T(x, y - 1)).shuffle();
|
||||
foreach xx,yy in (d){
|
||||
if(vis[yy][xx]) continue;
|
||||
if(xx==x) hor[y.max(yy)][x]="+ ";
|
||||
if(yy==y) ver[y][x.max(xx)]=" ";
|
||||
self.fcn(xx,yy,vis,ver,hor);
|
||||
if(vis[yy][xx]) continue;
|
||||
if(xx==x) hor[y.max(yy)][x]="+ ";
|
||||
if(yy==y) ver[y][x.max(xx)]=" ";
|
||||
self.fcn(xx,yy,vis,ver,hor);
|
||||
}
|
||||
}((0).random(w),(0).random(h),vis,ver,hor);
|
||||
foreach a,b in (hor.zip(ver)) { println(a.concat(),"\n",b.concat()) }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue