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としても、
-v オプションで値を変えたい変数に対しては、
上の "" との比較をチェックするように
書いておく必要があります。