function array2str(N,array, j,s) { s="" for(j=1;j<=N;j++) s=s array[j] return s }逆に、入力文字列を配列に直すのは、[2] で見たように split(str,input,"") でできます。
以上をまとめると以下のようになります。
BEGIN{ Maxloop=20 # 制限回数 if(N=="") N=4 # 数字列の長さ if(L=="") L=10 # 使用する数字の個数 Times=1 # 回数を記録する変数 win=0 # (1) 課題文を作成してゲーム開始 printf "数当てゲームを開始します。\n" printf "使用する数は 0~%d, 数字列の長さは %d です。\n",L-1,N printf "判定結果の意味は以下の通りです。\n" printf " H=数も位置も合ってる数\n" printf " B=数のみ合ってる数\n" if(mkkadai(N,L,kadai)<0){ printf "Error.\n"; errorexit=1; exit } else printf "準備 OK です。%d 個の数の並びを入力してください。\n",N printf "[%d] ",Times } { ## ここはキーボードからの 1 行の入力が済んだ後に実行される # (2) 入力文字列を確認 gsub(/[ \t]/,"") if(split($0,input,"")!=N || inputcheck(N,L,input)<0){ printf "入力エラー\n" printf "[%d] ",Times # 改めて入力をうながす next } # (3) 入力行と課題文とを比較 ret=judgeinput(N,input,kadai) # (4) 違いがなければ終了し、 # 違いがあれば判定結果を表示 if(ret==1){ win=1; exit } else printf "%dH%dB\n",H,B if(Times>=Maxloop){ win=-1; exit } else printf "[%d] ",++Times } END{ if(errorexit) exit # (5) 途中でやめた場合はそのような表示をする # (6) 正常終了した場合はそのような表示をする if(win==0) printf "途中であきらめましたね。\n" else if(win==-1) printf "制限回数 (%d) 内に回答できませんでした。\n",Maxloop else printf "おめでとう。正解です。\n" printf "回数 %d、正解 %s\n",Times,array2str(N,kadai) } # 配列 --> 文字列 function array2str(N,array, j,s) { s="" for(j=1;j<=N;j++) s=s array[j] return s } # 入力チェック関数 function inputcheck(N,L,input, j,k) { for(j=1;j<=N;j++) if(input[j] !~ /^[0-9]$/ || input[j]>=L) return -1 for(j=1;j<N;j++) for(k=j+1;k<=N;k++) if(input[j]==input[k]) return -2 return 0 } # 回答チェック # 一致したら 1, そうでなければ 0 を返す # B,H は大域変数としてそこに結果を代入する function judgeinput(N,input,kadai, j,k,A) { H=0 # 数も場所も合っているものの個数 A=0 # 数が合っている (H も含む) ものの個数 for(j=1;j<=N;j++) for(k=1;k<=N;k++) if(input[k]==kadai[j]){ A++ if(j==k) H++ break } B=A-H if(H>=N) return 1 else return 0 } # 課題の作成 function mkkadai(N,L,kadai, j,k,x,m,a,L1) { srand() for(j=0;j<L;j++) a[j]=0 L1=L # 使っていない数字の個数 for(j=1;j<=N;j++){ x=int(rand()*L1)+1 # 1 から L1 までの乱数 m=0; for(k=0;k<L;k++){ # x 番目の使っていない数の検索 if(a[k]==0) m++ if(m==x) break } if(k>=L) return -1 # エラー if(a[k]!=0) return -2 # エラー a[k]=1 kadai[j]=k # j 番目の課題数字を k とする L1-- } return 0 }
ここでは一応 Maxloop() 回を制限回数とし、 これ以上かかったら強制終了としています。
また、最初の BEGIN ブロックで、, を、
if(N=="") N=4 # 数字列の長さ if(L=="") L=10 # 使用する数字の個数としていますが、 これは実行時に , を容易に変更できるようにするための仕組みです。 通常は、最初は , の値は定義されていませんから、 空文字列として
""
という値を取りますから、
それぞれデフォルトの 4, 10 が設定されますが、
awk のコマンドラインオプションで -v
オプションを使って、
awk -v N=3 -v L=5 -f kazuate.awkのように変数の値の初期値を設定すれば、 スクリプトを書きかえずに変数の値を変更できます。
なお、同じように例えば Maxloop
を変えようとして
awk -v Maxloop=100 -f kazuate.awkとしても、 は BEGIN ブロックで強制的に初期値が設定されますから、 このようにして変更することはできません。 awk の
-v
オプションで値を変えたい変数に対しては、
上の , のように ""
との比較をチェックするように
書いておく必要があります。