続々awkでPGその4
4.1.1 サンプル(1/2)
では、今回の参考用Yさ版スクリプトです。
長くなりますので、2つに分けてUPします。
<<重要>> 今回のスクリプトだけでは動作しません。
第二回の1/2のスクリプト(MAZE3DM1.000)および
今回の2/2のスクリプト(MAZE3DS3.003)を
編集して追加してください。
(maze3d.002 と言う名前で編集した場合)
jgawk -f maze3d.002 -v _DISP3D_TEST=1[ENTER]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
などとして、実行してください。
-----^ MAZE3DS2.002 ( date:02-05-01 time:00:00:00 ) --------------< cut here
# 3D迷路脱出Game Sub#2 - Disp 3D maze - written by Yさ
function setDT(x,y,s,len, r,l)
{ l=(x<2)?"":substr(DispTbl[y],1,x);
r=(x+len>=31)?"":substr(DispTbl[y],x+len+1);
DispTbl[y]=l s r;}
function setLine(x1,y1,x2,y2,s, x,y,dx,dy)
{ dx=(x1<x2)?1:((x1>x2)?-1:0); dy=(y1<y2)?1:((y1>y2)?-1:0);
x=x1; y=y1; while(!(x==x2 && y==y2)){ setDT(x*2,y,s,2); x+=dx; y+=dy;}
setDT(x*2,y,s,2);}
function put3D( i,c,rdir,ldir)
{ # 表示テーブルを空白で埋める 0....5....0....5....0....5....0.
for(i=0; i<16; ++i) DispTbl[i]=" ";
# 表示テーブルにセット
if(NowDir==3) rdir=0; else rdir=NowDir+1; # 向かって右方向set
if(NowDir==0) ldir=3; else ldir=NowDir-1; # 向かって左方向set
xParam=NowXPos; yParam=NowYPos; c=put3Dsub(ldir,rdir,0);
if(c!=1 && c!=2 && c!=3) c=put3Dsub(ldir,rdir,1);
if(c!=1 && c!=2 && c!=3) c=put3Dsub(ldir,rdir,2);
if(c!=1 && c!=2 && c!=3) c=put3Dsub(ldir,rdir,3);
# 表示
system("cls"); # clear screen--if cls does not work, try "clear"
for(i=0; i<16; ++i) print DispTbl[i];}
function put3Dsub(ldir,rdir,r, c,lc,rc,lc2,rc2)
{ lc=Mtbl[xParam+XMove[ldir],yParam+YMove[ldir]]; writeLEFT(lc, r); # 左側
rc=Mtbl[xParam+XMove[rdir],yParam+YMove[rdir]]; writeRIGHT(rc, r); # 右側
xParam+=XMove[NowDir]; yParam+=YMove[NowDir]; # 一歩前
lc2=Mtbl[xParam+XMove[ldir],yParam+YMove[ldir]]; # 左側
rc2=Mtbl[xParam+XMove[rdir],yParam+YMove[rdir]]; # 右側
c=Mtbl[xParam,yParam]; writeFORWARD(c,lc,rc,lc2,rc2, r); # 正面
if(c==4) writeKEY(r); # 鍵
if(c==3) writeEXIT(r); # 出口
return c;}
function writeKEY(r)
{ if(r==0) setDT(8*2,12,"$",2);
if(r==1) setDT(8*2, 9,"・",2);}
function writeEXIT(r)
{ if(r==0){ setDT(4*2,2,"__",2); setDT(10*2,2,"_____ ",2*3);
setDT(3*2,3," |__ \/ | | ",2*9);
setDT(3*2,4," |__ /\ | | ",2*9);}
if(r==1) setDT(6*2,5,"EXIT",2*4);
if(r==2) setDT(7*2,7,"''''",4);}
function writeLEFT(lc,r)
{ if(lc==1 || lc==2){ set3D(LTW[r+1],sLTW); set3D(LBW[r+1],sLBW);} # 左側は 壁
else{ set3D(LTR[r+1],sLTR); set3D(LBR[r+1],sLBR);}}# 道
function writeRIGHT(rc,r)
{ if(rc==1 || rc==2){ set3D(RTW[r+1],sRTW); set3D(RBW[r+1],sRBW);} # 右側は 壁
else{ set3D(RTR[r+1],sRTR); set3D(RBR[r+1],sRBR);}}# 道
function writeFORWARD(c,lc,rc,lc2,rc2,r)
{ if(c==1 || c==2){ # 正面は壁?
set3D(FTW[r+1],sFW); set3D(FBW[r+1],sFW);
if(lc==1 || lc==2){ set3D(LFW[r+1],sLFW);} # 左は壁
else{ set3D(LFTR[r+1],sLFTR); set3D(LFBR[r+1],sLFBR);} # 道
if(rc==1 || rc==2){ set3D(RFW[r+1],sRFW);} # 右は壁
else{ set3D(RFTR[r+1],sRFTR); set3D(RFBR[r+1],sRFBR);} # 道
}else{ # 正面は道
# 左側に壁があれば描く
if(lc!=1 && lc!=2 || lc2!=1 && lc2!=2 || c==3) set3D(LFW[r+1],sLFW);
# すぐ左が壁ではないなら道を描く
if(lc!=1 && lc!=2){ set3D(LFTR[r+1],sLFT2R); set3D(LFB2R[r+1],sLFB2R);}
# 右側に壁があれば描く
if(rc!=1 && rc!=2 || rc2!=1 && rc2!=2 || c==3) set3D(RFW[r+1],sRFW);
# すぐ右が壁ではないなら道を描く
if(rc!=1 && rc!=2){ set3D(RFTR[r+1],sRFT2R); set3D(RFB2R[r+1],sRFB2R);}
} }
-----$ MAZE3DS2.002 ( lines:64 words:274 bytes:3124 ) ------------< cut here
4.1.2 サンプル(2/2)
-----^ MAZE3DS3.003 ( date:02-05-01 time:00:00:00 ) --------------< cut here
# 3D迷路脱出Game Sub#3 - 3D maze data & sub - written by Yさ
function init3Ddata()
{ # (road/wall) Left = L+Top/Bottom+Road/Wall[range +1]
split("-1, 2, 0, 1@ 2, 4, 3, 4@-1, 2, 5, 6@-1, 2, 7, 7",LTR,"@");
split("-1, 2, 0,13@ 2,10, 3,10@-1, 2, 5, 8@", LBR,"@");
split(" 0, 0, 1, 1@ 2, 2, 4, 4@ 5, 5, 6, 6@-1, 2, 7, 7",LTW,"@");
split(" 0,15, 1,14@ 2,13, 4,11@ 5,10, 6, 9@-1, 2, 7, 8",LBW,"@");
sLTR=sLBR="__"; sLTW="\"; sLBW="/";
# (road/wall) Right = R+Top/Bottom+Road/Wall[range +1]
split("-1, 2,15, 1@..., 4,13, 4@-1, 2,10, 6@-1, 2, 8, 7",RTR,"@");
split("-1, 2,15,13@...,10,13,10@-1, 2,10, 8@", RBR,"@");
split("14, 1,15, 0@..., 4,13, 2@ 9, 6,10, 5@-1, 2, 8, 7",RTW,"@");
split("14,14,15,15@...,11,13,13@ 9, 9,10,10@-1, 2, 8, 8",RBW,"@");
sRTR=sRBR="__"; sRTW="/"; sRBW="\";
# wall Forward = F+Top/Bottom+Wall[range +1]
split(" 2, 1,13, 1@ 5, 4,10, 4@ 7, 6, 8, 6@",FTW,"@");
split(" 2,13,13,13@ 5,10,10,10@ 7, 8, 8, 8@",FBW,"@");
sFW="__";
# wall Left - (road/wall) Forward = LF+Wall[range +1]
split(" 1, 2, 1,13@ 4, 5, 4,10@ 6, 7, 6, 8@",LFW,"@");
sLFW=" |";
# road Left - (wall/road) Forward = LF+Top/Bottom/Bottom#2+Road[range +1]
split("-1, 2, 1, 1@-1, 2, 4, 4@-1, 2, 6, 6@",LFTR,"@");
split("-1, 2, 1,13@-1, 2, 4,10@-1, 2, 6, 8@",LFBR,"@");
# split("-1, 2, 1, 1@-1, 2, 4, 4@-1, 2, 6, 6@",LFT2R,"@");
split("-1,-1, 1,13@-1,-1, 4,10@-1,-1, 6, 8@",LFB2R,"@");
sLFTR=sLFBR="__"; sLFT2R="_ "; sLFB2R="_";
# wall Right - (road/wall) Forward = RFW[range +1]
split("14, 2,14,13@..., 5,11,10@ 9, 7, 9, 8@",RFW,"@");
sRFW="| ";
# road Right - (road/wall) Forward = RF+Top/Bottom/Bottom#2+Road[range +1]
split("-1, 2,14, 1@-1, 2,11, 4@-1, 2, 9, 6@",RFTR,"@");
split("-1, 2,14,13@-1, 2,11,10@-1, 2, 9, 8@",RFBR,"@");
# split("-1, 2,14, 1@-1, 2,11, 4@-1, 2, 9, 6@",RFT2R,"@");
split("-1, 1,14,13@-1, 1,11,10@-1, 1, 9, 8@",RFB2R,"@");
sRFTR=sRFBR="__"; sRFT2R=" _"; sRFB2R="_";}
function set3D(fmt,s, i,wk,x1,y1,x2,y2)
{ if(""==fmt) return; else split(fmt,wk,",");
x1=wk[1]+0; y1=wk[2]+0; x2=wk[3]+0; y2=wk[4]+0; for(i in wk) delete wk[i];
if(x1>=0) setLine(x1,y1,x2,y2,s);
else setDT(x2*2+((y1==1)?1:0),y2,s,((y1<0)?-y1:y1));}
_DISP3D_TEST{ NowDir=0; NowXPos=2; NowYPos=4; split($1,wk,",");
Mtbl[1,1]=int(wk[1]/100); Mtbl[2,1]=int(wk[1]/10)%10; Mtbl[3,1]=wk[1]%10;
Mtbl[1,2]=int(wk[2]/100); Mtbl[2,2]=int(wk[2]/10)%10; Mtbl[3,2]=wk[2]%10;
Mtbl[1,3]=int(wk[3]/100); Mtbl[2,3]=int(wk[3]/10)%10; Mtbl[3,3]=wk[3]%10;
Mtbl[1,4]=int(wk[4]/100); Mtbl[2,4]=int(wk[4]/10)%10; Mtbl[3,4]=wk[4]%10;
for(i=1; i<=4; ++i){ for(j=1; j<=3; ++j) printf Mtbl[j,i]; printf "\n";}
for(i in wk) delete wk[i]; put3D(); printf("\nCOMMAND?>"); }
-----$ MAZE3DS3.003 ( lines:48 words:326 bytes:2676 ) ------------< cut here
実行し、3*4 の大きさで表示したい迷路を、例えば 101,000,101,001 の
形式で指定してください。 指定例の意味は、
101 - 3つ先:左右は壁
000 - 2つ先:全て道
101 - 1つ先:左右は壁
001 - 自分がいる場所の左は道、右は壁
です。指定の迷路を(疑似)三次元表示します。
なお 2バイト文字表示ができない環境の場合は、"\"や"/"を"-_"や"_-"
などとしてください。ただし、 \/ が -__- と表示されますので
/\ _--_
いまいちですが d(^^;)
4.2 プログラムの説明など
表示は DispTbl[] を 1byte*32文字で16行分用意して、一度配列にセット
したものを表示するようにしています。 セットは次の順番に行ないます。
1)自分のいる場所の左右と1つ先の正面の壁の有無をセット
2)1つ先が道なら、その左右と、2つ先の正面の壁の有無をセット
3)2つ先が道なら、その左右と、3つ先の正面の壁の有無をセット
4)3つ先が道なら、その左右の壁の有無をセット
(疑似)三次元表示用のデータは、関数 init3Ddata() で、表示用の文字、
場所(左右、正面)と距離(いくつ先か)でパターン化して準備してます。
配列に格納する所の split() を使ったコンパクト化がミソです(^_^)b
次回はいよいよ「(疑似)三次元迷路脱出ゲームでも作ろうかい?」講座の
最終回です。m(_ _)m Yさ