作者: saw
日時: 2002/4/4(10:21)
続々awkでPGその2

 こんばんは、Yさと申します。
 「(疑似)三次元迷路脱出ゲームでも作ろうかい?」講座
 少し早めの第二回目の今回は、迷路ゲームの基本、
二次元迷路をプログラムでどう作るか、についてです。

 ...が、今回は再利用ネタです(^^;)
 別途公開中講座の awkでPG#3 "迷路" 作例編とほぼ同じ内容なので、
解説などは省略させていただきますm(_ _)m


2.1 サンプル
 では、今回の参考用Yさ版スクリプトです。
 長くなりますので、2つに分けます。

 <<重要>> MAZE3DM1.000スクリプトだけでは動作しません。
          MAZE3DS1.001を追加編集してください。

 (maze3d.001 と言う名前で編集した場合)
    jgawk -f maze3d.001 -v _MAKEMAZE_TEST=1[ENTER]
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 などとして、実行してください。
 実行し、大きさを x*y の書式で指定してください。 
 指定サイズの迷路を作成し表示します。 
 (サイズが偶数だった場合は +1 して調整します。)


2.1.1 スクリプト1/2
 迷路の作成準備スクリプトです。

-----^ MAZE3DM1.000 ( date:02-04-01 time:00:00:00 ) --------------< 
cut here
# 3D迷路脱出Game Main#1 - BEGIN -  written by Yさ
function rnd(n){ return int(n*rand());}
BEGIN{ srand();
  XMAX=37;  # 迷路サイズの上限 横
  YMAX=21;  #                  縦
  XMove[0]= 0;  YMove[0]=-1;  # 0:上方向→縦横差分
  XMove[1]= 1;  YMove[1]= 0;  # 1:右
  XMove[2]= 0;  YMove[2]= 1;  # 2:下
  XMove[3]=-1;  YMove[3]= 0;  # 3:左
  Mstr[0]="  ";  # 2D MAP 表示用データ 道
  Mstr[1]="■";  #                     壁
  Mstr[2]="S";  #                     スタート
  Mstr[3]="G";  #                     ゴール
  Mstr[4]="$";  #                     鍵
  # NowXPos, NowYPos;  現在位置
  # NowDir;  向いている方向(0-3)
  Pic[0]="↑";  Pic[1]="→";  Pic[2]="↓";  Pic[3]="←";
  # KeyXPos, KeyYPos;  鍵の位置
  # OXY;  酸素量
  TURN=2;   # 向きを変えた時の酸素消費量
  MOVE=5;   # +移動の場合の酸素消費量
  # ENG;  マップ表示用エネルギー
  MAP=100;  # マップの作成時の消費エネルギー
  # 迷路サイズ入力 & 迷路作成
  if(! _DISP3D_TEST){
    printf("\n Size X*Y (X:3-%d, Y:3-%d) ?",XMAX,YMAX);
    getline tmp < "/dev/stdin";  split(tmp, wk, "*");
    Xsize=(wk[1]%2)?wk[1]:wk[1]+1;  if(Xsize<3 || XMAX<Xsize)  exit;
    Ysize=(wk[2]%2)?wk[2]:wk[2]+1;  if(Ysize<3 || YMAX<Ysize)  exit;
    for(i in wk) delete wk[i];
    initMaze();  if(_MAKEMAZE_TEST){ dispMaze(); exit;}
  }
  if(! _MAKEMAZE_TEST) init3Ddata();  # 3D 表示用データ準備
  # game start
  if(_NO_TEST){
    OXY=200+Xsize*Ysize*5;  ENG=(Xsize+Ysize)*10;
    forward=2;  # 目の前は入口
    put3D();  putStat();  printf(" Get a key and go to EXIT.");
  } printf("\nCOMMAND?>"); }
-----$ MAZE3DM1.000 ( lines:39 words:160 bytes:1502 ) ------------< 
cut here

# 2バイト文字表示ができない環境の場合は、2D MAP 表示用データを
#    Mstr[0]=" ";  # 道
#    Mstr[1]="#";  # 壁
#    Mstr[2]="S";  # スタート
#    Mstr[3]="G";  # ゴール
#    Mstr[4]="$";  # ゴール
#    Pic[0]="A";  Pic[1]=">";  Pic[2]="V";  Pic[3]="<";
# のように 表示可能な文字に変更してください。


2.1.2 スクリプト(2/2)
 迷路の作成と表示のスクリプト本体です。

-----^ MAZE3DS1.001 ( date:02-04-01 time:00:00:00 ) --------------< 
cut here
# 3D迷路脱出Game Sub#1 - make maze -   written by Yさ
function initMaze(  i,j,mark,pos,dir,sx,sy,gx,gy)
{ # 全部道にして...
  for(i=0; i<=Xsize+1; ++i) for(j=0; j<=Ysize+1; ++j) Mtbl[i,j]=0;
  # 周りを壁で囲って
  for(i=0; i<=Xsize+1; ++i) Mtbl[i,0]=Mtbl[i,Ysize+1]=1;
  for(i=0; i<=Ysize+1; ++i) Mtbl[0,i]=Mtbl[Xsize+1,i]=1;
  # 柱を建てて...
  for(i=2; i<Xsize; i+=2) for(j=2; j<Ysize; j+=2) Mtbl[i,j]=1;
  # 壁を付け足しましょう
  dir=rnd(4);                                # 0-3 の方向に付ける
  Mtbl[2+XMove[dir],2+YMove[dir]]=1;
  for(i=4; i<Xsize; i+=2){  dir=rnd(3);      # 0-2 の方向に付ける
    Mtbl[i+XMove[dir],2+YMove[dir]]=1;
    for(j=4; j<Ysize; j+=2){  dir=rnd(2)+1;  # 1-2 の方向に付ける
      Mtbl[i+XMove[dir],j+YMove[dir]]=1;
  } }
  for(i=4; i<Ysize; i+=2){  dir=rnd(3)+1;    # 1-3 の方向に付ける
    Mtbl[2+XMove[dir],i+YMove[dir]]=1;
  }
  # スタート&ゴールをセット
  mark=rnd(2)+2;  # 2:スタート or 3:ゴール
  pos=rnd(4);     # 0:上左,下右  1:上右,下左  2:右上,左下  3:右下,左上
  if(pos==0){ Mtbl[1,0]=mark;           Mtbl[Xsize,Ysize+1]=(mark==3)?
2:3;}
  if(pos==1){ Mtbl[Xsize,0]=mark;       Mtbl[1,Ysize+1]=(mark==3)?2:3;
    }
  if(pos==2){ Mtbl[Xsize+1,1]=mark;     Mtbl[0,Ysize]=(mark==3)?2:3;  
    }
  if(pos==3){ Mtbl[Xsize+1,Ysize]=mark; Mtbl[0,1]=(mark==3)?2:3;      
    }
  # 現在位置をセットして
  if(pos==0 && mark==2 || pos==3 && mark==3){             # 上左,左上
    NowXPos=1;     NowYPos=1;     NowDir=(pos==0)?0:3;}
  if(pos==1 && mark==2 || pos==2 && mark==2){             # 上右,右上
    NowXPos=Xsize; NowYPos=1;     NowDir=(pos==1)?0:1;}
  if(pos==3 && mark==2 || pos==0 && mark==3){             # 右下,下右
    NowXPos=Xsize; NowYPos=Ysize; NowDir=(pos==3)?1:2;}
  if(pos==1 && mark==3 || pos==2 && mark==3){             # 下左,左下
    NowXPos=1;     NowYPos=Ysize; NowDir=(pos==1)?2:3;}
  # 鍵を置いたら終り
  KeyYPos=rnd(int((Ysize+1)/2))*2+1;
  do{ KeyXPos=rnd(int((Xsize+1)/2))*2+1;
  }while(Mtbl[KeyXPos,KeyYPos]!=0  ||  NowXPos==KeyXPos && NowYPos==
KeyYPos);
  Mtbl[KeyXPos,KeyYPos]=4;}
function dispMaze(  i,j)
{ system("cls");  # clear screen--if cls does not work, try "clear"
  for(j=0; j<=Ysize+1; ++j){
    for(i=0; i<=Xsize+1; ++i)
      printf("%s", (NowXPos==i && NowYPos==j)?Pic[NowDir]:Mstr[Mtbl[i,
j]]);
    print "";
} }
-----$ MAZE3DS1.001 ( lines:48 words:193 bytes:2241 ) ------------< 
cut here


 参考用スクリプトには今回実行する内容と関係無い記述がありますが、
次回以降に使用しますので、気にしないでください。


 次回は「(疑似)三次元表示」を題材にする予定です。
(...続く)Yさ