ods noresults;
ods html path="★出力先のパスを指定" file="maze2.html";
*--- 穴掘り法による迷路の生成 ----------------------------------------------;
data _NULL_;
* 乱数のシード ;
call streaminit(&init);
* 迷路のブロックを入れておく箱を用意 ;
dcl hash hs(ordered:'yes');
hs.definekey("x","y");
hs.definedata("block");
hs.definedone();
* 始点候補のブロックを入れておく箱を用意 ;
dcl hash st(ordered:'yes');
st.definekey("no");
st.definedata("x","y");
st.definedone();
* ブロックを作って箱に放り込む ;
do y2=1 to &n;
do x2=1 to &n;
* 外側を道ブロック,それ以外壁ブロックを詰める(1:道ブロック 2:壁ブロック) ;
if x2 in (1,&n) or y2 in (1,&n) then BLOCK=1;
else BLOCK=2;
* ブロックを放り込む ;
hs.add(key:x2, key:y2, data:block);
* 始点候補のブロックを放り込む ;
if BLOCK=2 and mod(x2*y2,2)=1 then do;
no+1;
st.add(key:no, data:x2, data:y2);
end;
end;
end;
do i=1 by 1 while (1);
* 始点候補更新 ;
if i>1 then do;
no=0;
st.clear();
do y2=1 to &n;
do x2=1 to &n;
* 始点候補のブロックを放り込む ;
if x2^in (1,&n) and y2^in (1,&n) and mod(x2*y2,2)=1 then do;
hs.find(key:x2, key:y2);
if block=1 then do;
* 上下左右いずれか2マス先が壁ブロックだったら始点候補にする ;
block_num=0;
hs.find(key:x2-2, key:y2 ); block_num+(block=2);
hs.find(key:x2+2, key:y2 ); block_num+(block=2);
hs.find(key:x2, key:y2-2); block_num+(block=2);
hs.find(key:x2, key:y2+2); block_num+(block=2);
if block_num>0 then do;
no+1;
st.add(key:no,data:x2,data:y2);
end;
end;
end;
end;
end;
end;
if st.num_items=0 then leave;
* 始点をランダムに決めてブロックの位置を取得 ;
no = ceil(rand('uniform') * st.num_items);
st.find(key:no);
x2=x; y2=y;
* 進めなくなるまで道ブロックを詰めこんでいく ;
do while (1);
* 進めるか確認 ;
block_num=0;
hs.find(key:x2-2, key:y2 ); block_num+(block=2);
hs.find(key:x2+2, key:y2 ); block_num+(block=2);
hs.find(key:x2, key:y2-2); block_num+(block=2);
hs.find(key:x2, key:y2+2); block_num+(block=2);
if block_num=0 then leave;
* 進行方向を決める ;
RAND = ceil(rand('uniform')*4);
* 進行方向の2マス先が壁なら掘る ;
if RAND=1 then do; x_move=0; y_move=-1; end; * 上 ;
if RAND=2 then do; x_move=0; y_move=1; end; * 下 ;
if RAND=3 then do; x_move=1; y_move=0; end; * 右 ;
if RAND=4 then do; x_move=-1; y_move=0; end; * 左 ;
if i=1 then hs.replace(key:x2, key:y2, data:1) ;
hs.find( key:x2+x_move*2 , key:y2+y_move*2);
if block=1 then continue;
hs.replace(key:x2+x_move , key:y2+y_move , data:1) ;
hs.replace(key:x2+x_move*2, key:y2+y_move*2, data:1) ;
* 2マス先に移動 ;
x2=x2+x_move*2;
y2=y2+y_move*2;
end;
end;
* ブロックを箱から出して迷路組み立て(迷路の描画) ;
length WID HEI $10.;
dcl odsout ob();
ob.table_start();
do y=1 to &n;
ob.row_start();
do x=1 to &n;
hs.find(key:x, key:y);
wid="7mm";
hei="7mm";
if (x=2 and y=3) or (x=&n-1 and y=&n-2) then do;
block=1;
end;
if mod(x,2)=0 then wid="1mm";
if mod(y,2)=0 then hei="1mm";
*** 壁と床を描画 ;
if (x=3 and y=3) or (x=&n-2 and y=&n-2) then do;
block=1;
end;
ob.format_cell(style_attr: " bordercolor="|| choosec(block,"white","black") ||
" background=" || choosec(block,"white","black") ||
" height="|| hei || " width=" || wid);
end;
ob.row_end();
end;
ob.table_end();
stop;
run;
ods html close;
ods html;
ods results;