■=Perl, ■=結果
マスターマインドは数当てゲームです。ヒットアンドブロウとも呼ばれています。相手が選んだn桁の数を推理して、正解を導き出します。あなたが考えた数に対して、数字も位置も正しいときには[HIT]がいくつ、位置は正しくないが数字が正しいときは[BLOW]がいくつと出題者は答えます。
出題者はPerlにお願いすることにします。ゲームが呑み込めない方は、この解説を読まれる前に、ゲームを楽しんでから戻ってきてください。
このページの実行には、すぐ下にある入力フォームとmastermind.cgi、stdin.txt、fotter.txtが必要です。3つのスクリプトはこのページの最下部にあります。mastermind.cgiのみパーミッション757にしてください。入力フォームを置くディレクトリの下のcgi-binディレクトリに格納することを前提に記述しています。
「マスターマインド」の入力フォームを作りました。
私が選んだn個の数字を当ててください!
(0から9の数字で先頭は0ではありません)
下が入力フォームの記述です。入力される数字(no)、桁数(keta)、回答の最大回数(max)、数の重複の有無(du)をCGIに送ります。また画面には表示されませんが、一回目の回答であることを示すname=yもCGIに渡されます。
<table border="1" bgcolor="#DFEFEE" cellpadding="5"><tr align="center"><td> <hr> 私が選んだn個の数字を当ててください!<br> <font size="-1">(0から9の数字で先頭は0ではありません)</font> <hr> <form action="./cgi-bin/mastermind.cgi" method="POST" name=form> <img src="./images/coco_l.gif" width="42" height="39" align="absmiddle" border="0" alt="勝てるかな?"> <input type="text" name="no" maxlength="5" size="10"> <input type="submit" value="GO!"> <img src="./images/coco_r.gif" width="42" height="39" align="absmiddle" border="0" alt="勝てるかな?"><br> <input type="hidden" name="y" value="0"> <hr> 桁数:<select name="keta"> <option value="3">3桁 <option value="4">4桁 <option selected value="5">5桁 </select> 最大:<select name="max"> <option value="10">10回 <option value="15" selected>15回 <option value="20">20回 <option value="30">30回 </select> 重複:<select name="du"> <option value="0" selected>有 <option value="1">無 </select> </form> </td></tr> </table>
それではスクリプトを順番に示していきます。
#!/usr/local/bin/perl require './stdin.txt';# GET,POST処理 ######入力フォーム取得###### $nomber = $FORM{'no'};# 入力番号 $nagasa = $FORM{'keta'};# 問題の桁数 $maxkai = $FORM{'max'};# 回答の回数MAX $dup = $FORM{'du'};# 数字の重複 0=認める 1=認めない $kai = $FORM{'y'};# 挑戦回数 $kotae = $FORM{'k'};# 答え $nom = $FORM{'n'};# 入力番号履歴 $hb = $FORM{'hb'};# Hit&BLOW履歴 ######初期設定###### $title = "マスターマインド"; $html = 'mastermind_1.html'; $script = 'mastermind.cgi'; ($hit, $ball) = (0, 0);
#!/usr/local/bin/perl
どこにPerlがあるかを宣言しています。(「先ずはこれ」参照)
【→Perl Reference: require】
require './stdin.txt';
stdin.txtを読み込みます。stdin.txtでは入力フォームから送られてくるGETやPOSTデータを受取る際の取り決めをしています。(「テキストの色替え」のPOSTとGETを参照)
$nomber = $FORM{'no'};# 入力番号 $nagasa = $FORM{'keta'};# 問題の桁数 $maxkai = $FORM{'max'};# 回答の回数MAX $dup = $FORM{'du'};# 数字の重複 0=認める 1=認めない $kai = $FORM{'y'};# 挑戦回数 $kotae = $FORM{'k'};# 答え $nom = $FORM{'n'};# 入力番号履歴 $hb = $FORM{'hb'};# Hit&BLOW履歴
入力フォームから送られてくるデータを変数に代入しています。
入力される数字(no)、桁数(keta)、回答の最大回数(max)、数の重複の有無(du)は先ほど示した入力フォームから入力・選択されたデータです。挑戦回数(y)は画面には表示されていませんが、入力フォームに含まれています。
その他の乱数で作成された答え(k)、入力番号履歴(n)、Hit&BLOW履歴(hb)は先ほどの入力フォームには含まれていません。これらは二回目以降のCGIが作り出す入力フォームで使用されます。連続して数を入力してもらい、毎回の履歴も画面に表示させるには、今まで入力された数字も覚えておかなければなりません。そのためには入力された数字を別ファイルに書き込み、それを読み込む必要があります。今回のスクリプトでは履歴のファイルを使わずに、CGIにデータとして毎回、今までの履歴全てを渡す方法をとっています。入力番号の履歴は一回目から前回までの入力された数字の履歴を、Hit&BLOW履歴にはそれぞれのHit数BLOW数の履歴を格納しています。
$title = "マスターマインド"; $html = 'mastermind_1.html'; $script = 'mastermind.cgi'; ($hit, $blow) = (0, 0);
ここでは、初期設定をおこなっています。HTMLに表示するタイトル($title)、入力フォームに表示するCGI名($script)、HTMLファイル名($html)を設定しています。
($hit, $blow) = (0, 0);
位置も数もあっているHITの数、位置は間違っているが数字があっているBLOWの数の初期値をゼロにしています。
次はHTMLのヘッダー部分の記述です。
print "Content-type: text/html\n\n"; ######HTML開始###### print qq| <html> <head> <meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=x-euc-jp"> <title>$title</title> <script> <!-- function sf(){document.form.no.focus();} // --> </script> </head> <body onLoad=sf()> <center> <h2>$title</h2> |;
print "Content-type: text/html\n\n";
Content-typeはサーバからブラウザに送るデータ形式を指示するものです。詳しくは「先ずはこれ」のContent-typeを参照してください。
print qq| 中略 |;
print qq| はprint文のなかに、ダブルコーテーション(")を頻繁に使用するときに使用すると便利です。詳しくは「画面に文字を表示しよう」の print qq| | を参照してください。 ここではHTMLの記述をしているだけですが、画面から数字を入力してもらうときに、毎回入力ボックスをクリックしてからでないと数字が入力できないのは面倒です。画面が表示されれば、既に入力ボックスにカーソルが置かれているようにしました。入力フォームのHTML記述と合わせてご覧になってください。
初めての数字入力かどうかを判断します。初めての入力ならば、乱数から指定された桁数の数字を取得します。二回目以降の入力では、今までの入力履歴に追加処理をおこないます。
######初回のみ回答を取得###### if ($kai == 0) { $kai = 1; $nom = $nomber; while ($kakutei == 0) {#PCの回答数字の発生・チェック $kakutei = 1; $kotae = (rand(1) * ( time % 10000 ) ); $kotae = substr($kotae, length($kotae)-$nagasa, $nagasa); if ($kotae =~ /^0/) {# 先頭の桁にはゼロは付けない $kakutei = 0; } for ($i=0;$i<$nagasa;$i++) {#5桁の数字をバラス $kotae[$i] = substr($kotae,$i,1); } if ($dup == 1) { for ($i=0;$i<$nagasa;$i++) { for ($j=$i+1;$j<$nagasa;$j++) { if ($kotae[$i]==$kotae[$j]) {#数字の重複を除く $kakutei = 0; } } } } } } else { $nom = "$nom" . "$nomber";#入力履歴を接続 $kai++; }
if ($kai == 0) { $kai = 1; $nom = $nomber;
$kaiがゼロ(初めて)なら、$kaiに1を代入します。
$nomber(入力された数字)を$nom(二回目以降に使用する入力履歴)に代入します。
while ($kakutei == 0) { 中略 }
while (条件式) { 処理 }で、繰り返しをおこないます。条件は $kakutei == 0 ですから、$kakutei がゼロのときは処理を続けることになります。目的は指定された桁数の数字の取得。n桁の数字の先頭桁にゼロがこないこと。そして入力フォームで数字の重複無しを選択されたときの重複排除です。条件を満たさない時には、乱数を次々と発生させます。
$kakutei = 1;
$kakuteiに1を代入しています。あとの処理で$kakuteiをゼロに戻す処理がありますが、その条件処理がされないときに、whileの繰り返しから抜け出すための代入です。
$kotae = (rand(1) * ( time % 10000 ) );
ここではtime関数から乱数を取得して、$kotaeに代入をしています。
rand(1) は0から1未満までの小数点以下の端数を含んだ乱数を返します。例えば 0.787567138671875 のような数字です。乱数については「乱数の確率」を参照してください。
【→Perl Reference: rand】time は1970年1月1日0時0分0秒からの経過時間(秒)です。例えば 1015566056 となります。
time % 10000 は time を10000で割って余りを求めています。乱数と組み合わせて適度位取りの小数点以下の値を求めて、$kotaeに代入しています。
$kotae = substr($kotae, length($kotae)-$nagasa, $nagasa);
substr で文字列を取り出します。 substr(対象の文字列, 先頭から何文字目, 取り出す長さ)となります。
【→Perl Reference: substr】
length でスカラー値の長さを得ることができます。length($kotae)で先ほど発生させた乱数の長さが分かります。
【→Perl Reference: length】
$kotaeの文字列から、$kotaeの長さ引く$nagasa(フォームから選択された桁数)を開始位置として、$nagasaの長さ分の文字を取り出します。つまり指定された桁数の数字を得ることができます
if ($kotae =~ /^0/) { $kakutei = 0; }
乱数で取得した数の先頭がゼロではないようにしたいので、if文を使ってみました。
$kotae =~ /^0/ [^]は文字列の先頭の意味です。
$kotae の先頭がゼロならば $kakuteiにゼロを代入します。ゼロのときにはwhileのループから抜け出さないようにしています。
for ($i=0;$i<$nagasa;$i++) { $kotae[$i] = substr($kotae,$i,1); }
ここでは、乱数で得られたn桁の文字を一桁ずつにばらしています。
for 文で処理の繰り返しをしています。($i=0;$i<$nagasa;$i++)は$iに0を代入し、$iが$nagasa未満の間は処理を繰り返します。処理をする度に、$i++で$iに1を加算していきます。
$kotae[$i] = substr($kotae,$i,1) で、$kotaeの左から順番に一文字づつ$kotaeの配列に代入していきます。
if ($dup == 1) { for ($i=0;$i<$nagasa;$i++) { for ($j=$i+1;$j<$nagasa;$j++) { if ($kotae[$i]==$kotae[$j]) {#数字の重複を除く $kakutei = 0; } } } }
$dupが1の場合、つまり数字の重複無しを選択されたときの処理です。
二つのfor文を組み合わせて $kotae[$i]==$kotae[$j] 同じ数字(重複)のときに、$kakuteiにゼロを代入して乱数発生のループから抜け出さないようにしています。
例えば5桁が選択されたときには$kotae[$i]==$kotae[$j]は
$kotae[0]==$kotae[1]
$kotae[0]==$kotae[2]
$kotae[0]==$kotae[3]
$kotae[0]==$kotae[4]
$kotae[1]==$kotae[2]
$kotae[1]==$kotae[3]
$kotae[1]==$kotae[4]
$kotae[2]==$kotae[3]
$kotae[2]==$kotae[4]
$kotae[3]==$kotae[4]
となります。これで同じ組み合わせを二度調べる必要がなくなります。$kakutei = 0;重複があるときには$kakuteiにゼロを代入して、ループから抜け出すことはできません(再度乱数を発生させます)。
} else { $nom = "$nom" . "$nomber"; $kai++; }
条件処理の最後です。if ($kai == 0) { に対する elseです。
一回目の入力でない時を指します。二回目以降は乱数を発生させる必要はありません。$nom = "$nom" . "$nomber"; では$nomに$nomと$nomber(入力された数字)を文字列として接続しています。例えば5桁の入力で一回目が"12345"で二回目が"45678"だったら"1234545678"となります。このようにして入力された数の履歴をつくり、CGIのフォームに引き渡す準備をしています。
最後で$kaiに1を加算しています。
続いて入力された数字のチェック処理です。
######誤入力チェック###### if ($nomber eq '') { &error(1); } if ($nomber =~ /\D/) { &error(2); } if (length($nomber) ne $nagasa) { &error(3); }
$nomber(入力された数字)に何も入力されていない時は、&error(1)でerrorと名づけられたサブルーチンに引数1を渡します。
次の行の /\D/ は数字以外の文字を意味します。$nomberに数字以外が入力されていれば&error(2)を実行します。
最後の判断は選択された桁数と入力された桁数が等しくないときの処理です。length($nomber)で$nomberの長さを調べています。5桁の数字が必要なときに3桁の数字が入力されたらエラールーチンに引数3を渡します。
######エラー表示###### sub error { $error = $_[0]; if ($error == 1) { print "数字を入力してください。"; } if ($error == 2) { print "0から9までの半角数字で入力してください。"; } if ($error == 3) { print "$nagasa桁の半角数字を入力してください。"; } print "<br>もう一度<a href=\"Javascript:history.back()\">入力</a>\n"; exit(1); }
実際にはスクリプトの最後に書かれていますが、説明の都合で先に説明をします。先ほどの条件判断で示されたerrorサブルーチンです。
引数によってエラー表示を変えています。
ここで入力された数字と、答えとのチェックをしています。
######HIT&BLOWのチェック###### for ($i=0;$i<$nagasa;$i++) {#5桁の数字をバラス $kotae[$i]=substr($kotae,$i,1); $anata[$i]=substr($nomber,$i,1); } for ($i=0;$i<$nagasa;$i++) { if ($kotae[$i] eq $anata[$i]) {#数字の位置も正しい $hit++; ($kotae[$i], $anata[$i]) = ('H', 'I');#一度当たった数字を除く } } for ($i=0;$i<$nagasa;$i++) { for ($j=0;$j<$nagasa;$j++) {#数字は正しい if ($kotae[$i] eq $anata[$j]) { $blow++; ($kotae[$i], $anata[$j]) = ('B', 'A');#一度当たった数字を除く } } } $hb = "$hb" . "$hit" . "$blow";#HIT&BLOWの履歴を接続
for ($i=0;$i<$nagasa;$i++) { $kotae[$i]=substr($kotae,$i,1); $anata[$i]=substr($nomber,$i,1); }
答えと入力された数字を一文字ずつ配列に格納しています。配列は1からではなく0から始まります。
for文で $i がゼロから $nagasa 未満の間で処理を行ないます。substrで $kotaeや $nomberを左から一文字ずつ$kotae[$i]と$anatar[$i]の配列に代入しています。
for ($i=0;$i<$nagasa;$i++) { if ($kotae[$i] eq $anata[$i]) { $hit++; ($kotae[$i], $anata[$i]) = ('H', 'I'); } }
先ほど代入した配列の値が等しいときに、$hitに1を加算し、$kotae[$i]に文字列"H"を、$anata[$i]に"I"を代入します。HIT済みんなので、次のBLOWのカウントに含ませないための処理です。
for ($i=0;$i<$nagasa;$i++) { for ($j=0;$j<$nagasa;$j++) { if ($kotae[$i] eq $anata[$j]) { $blow++; ($kotae[$i], $anata[$j]) = ('B', 'A'); } } }
位置は正しくないが、数字がどこかに含まれる場合(BLOW)の処理です。
二重のforによる繰り返しで、等しい数字をチェックしています。等しい時には$blowに1を加算し、$kotae[$i]に"B"を、$anata[$j]には"A"を代入します。
$hb = "$hb" . "$hit" . "$blow";
HITとBLOEWの履歴を$hbに連結しています。例えば一回目がHITが0でBLOWが1、二回目にHITが2でBLOWが1なら、$hbは0121となります。
少し長くなっていますが、今までの入力された値に対する、HITとBLOWの履歴を表示します。
######履歴取得・表示###### print "<table border=\"1\"><tr align=\"center\"><td>回数</td><td> </td>\n"; print "<td width=\"30\" bgcolor=\"lime\">HIT</td>"; print "<td width=\"30\" bgcolor=\"yellow\">BLOW</td></tr>\n"; for ($i = 0; $i < $kai; $i++) { $nomb[$i] = substr($nom, $i*$nagasa, $nagasa);#左から$nagasa文字づつ取得 $nohi[$i] = substr($hb, $i*2, 1);#左から1文字づつ取得 $noba[$i] = substr($hb, $i*2+1, 1);#左から1文字づつ取得 $ii++; print "<tr align=\"center\"><td>$ii</td><td>$nomb[$i]</td>\n"; print "<td colspan=\"2\" bgcolor=\"black\">"; if ($nohi[$i] > 0) { print "<font color=\"lime\">"; for ($j=0; $j < $nohi[$i]; $j++) { print "●"; } print "</font>"; } if ($noba[$i] > 0) { print "<font color=\"yellow\">"; for ($j=0; $j < $noba[$i]; $j++) { print "▲"; } print "</font>"; } if ($nohi[$i] + $noba[$i] < $nagasa) { print "<font color=\"white\">"; for ($j=0; $j < ($nagasa - $nohi[$i] - $noba[$i]); $j++) { print "●"; } print "</font>"; } print "</td></tr>\n"; } print "</table>\n";
今までに説明した同じ関数がたくさん出てきますので、説明は簡単にします。
$nomb[$i] = substr($nom, $i*$nagasa, $nagasa); $nohi[$i] = substr($hb, $i*2, 1); $noba[$i] = substr($hb, $i*2+1, 1);
入力された数字の履歴($nom)を入力回数ごとにばらしています。
またHIT&BLOWの履歴($hb)をHITとBLOW別に、入力回数ごとに分けています。●や▲を含むprint文でHITとBLOWの数から履歴表示を判断しています。下のように表示する部分です。
回数 HIT BLOW 1 123 ●●● 2 406 ▲▲● 3 789 ●●●
最後になります。数字が全て当たっているならコメントを、そうでなければ別のコメント等を表示します。
if ($hit == $nagasa) { print qq|<br><font color=\"red\">大当たり!!</font> <form action="../$html" method="GET"> <input type="submit" value="続ける!!"> </form> |; } elsif ($kai < $maxkai) { print qq| <form action="./$script" method="POST" name="form"> <input type="text" name="no" maxlength="$nagasa" size="10"> <input type="submit" value="GO!"> <input type="hidden" name="n" value="$nom"> <input type="hidden" name="k" value="$kotae"> <input type="hidden" name="y" value="$kai"> <input type="hidden" name="hb" value="$hb"> <input type="hidden" name="keta" value="$nagasa"> <input type="hidden" name="max" value="$maxkai"> </form> |; $nokori = $maxkai - $kai; print "<p>あと$nokori回です。</p>"; print qq|<form action="../$html" method="GET"> <input type="submit" value="始めからもう一度"> </form> |; } else { print qq|<p>残念! $maxkai回です。<br> 答えは[<font color="red">$kotae</font>]でした!</p> <form action="../$html" method="GET"> <input type="submit" value="悔しい!もう一度!!"> </form> |; } print qq| <hr> このページの解説は<a href="./l_mastermind.html">こちらをご覧ください</a> </center> |; require './fotter.txt'; exit;
if ($hit == $nagasa) { print qq|<br><font color=\"red\">大当たり!!</font> <form action="../$html" method="GET"> <input type="submit" value="続ける!!"> </form> |;
全ての数字がHITしたときの処理です。
} elsif ($kai < $maxkai) { print qq| <form action="./$script" method="POST" name="form"> <input type="text" name="no" maxlength="$nagasa" size="10"> <input type="submit" value="GO!"> <input type="hidden" name="n" value="$nom"> <input type="hidden" name="k" value="$kotae"> <input type="hidden" name="y" value="$kai"> <input type="hidden" name="hb" value="$hb"> <input type="hidden" name="keta" value="$nagasa"> <input type="hidden" name="max" value="$maxkai"> </form> |; $nokori = $maxkai - $kai; print "<p>あと$nokori回です。</p>"; print qq|<form action="../$html" method="GET"> <input type="submit" value="始めからもう一度"> </form> |;
全てHITでなく、かつまだゲームの回数が残っているときの処理です。
入力フォームを最初に指定した、ゲーム回数、桁数、重複の有無の情報を含んで表示します。表示はしませんが、hiddenとして、いままでの入力された数の履歴やHIT&BLOWの履歴、さらにゲームの答えもCGIの情報として受け渡しています。
<form で neme=name="form">として、ヘッダーのスクリプト記述に対応させています。
} else { print qq|<p>残念! $maxkai回です。<br> 答えは[<font color="red">$kotae</font>]でした!</p> <form action="../$html" method="GET"> <input type="submit" value="悔しい!もう一度!!"> </form> |; }
条件判断の最後です。ここではゲームオーバーの処理をしています。
print qq| <hr> このページの解説は<a href="./l_mastermind.html">こちらをご覧ください</a> </center> |;
解説ページへのリファー表示です。
require './fotter.txt'; exit;
fotter.txtを読み込んでいます。fotter.txtの内容は下に示しておきます。ページの下にHOMEページなどへのリンク表示、HTMLの締め処理などがか書かれています。
exit;でスクリプト処理の終了です。
これで全てのスクリプトは終了です。今まで部分ごとに説明をしてきましたので、下に使用するスクリプトを、まとめて表示しておきます。
print qq( <hr> <center> <font size="1">| <a href="Javascript:history.back()">Back</a> | | <a href="../../index.html">Coco's Home</a> | | <a href="../index.html">ココとPerlで遊びませんか</a> | <hr> Copyright 2001-2002 Coco's Home. All rights reserved.</font> </center> </body> </html> ); 1;
↓stdin.txt(解説は「テキストの色替え」を参照してください)
############################### # POST GET データ取得 対応 ############################### if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } else { $buffer = $ENV{'QUERY_STRING'}; } @pairs = split(/&/,$buffer); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $FORM{$name} = $value; } 1;
↓mastermind.cgi (パーミッションを757)
#!/usr/local/bin/perl ########################################### ##### マスターマインド ##### ##### 2002.03.09 Coco Sekiguchi ##### ########################################### require './stdin.txt';# GET,POST処理 ######入力フォーム取得###### $nomber = $FORM{'no'};# 入力番号 $nagasa = $FORM{'keta'};# 問題の桁数 $maxkai = $FORM{'max'};# 回答の回数MAX $dup = $FORM{'du'};# 数字の重複 0=認める 1=認めない $kai = $FORM{'y'};# 挑戦回数 $kotae = $FORM{'k'};# 答え $nom = $FORM{'n'};# 入力番号履歴 $hb = $FORM{'hb'};# Hit&BLOW履歴 ######初期設定###### $title = "マスターマインド"; $html = 'mastermind_1.html'; $script = 'mastermind.cgi'; ($hit, $blow) = (0, 0); print "Content-type: text/html\n\n"; ######HTML開始###### print qq| <html> <head> <meta HTTP-EQUIV="content-type" CONTENT="text/html; charset=x-euc-jp"> <title>$title</title> <script> <!-- function sf(){document.form.no.focus();} // --> </script> </head> <body onLoad=sf()> <center> <h2>$title</h2> |; ######初回のみ回答を取得###### if ($kai == 0) { $kai = 1; $nom = $nomber; while ($kakutei == 0) {#PCの回答数字の発生・チェック $kakutei = 1; $kotae = (rand(1) * ( time % 10000 ) ); $kotae = substr($kotae, length($kotae)-$nagasa, $nagasa); if ($kotae =~ /^0/) {# 先頭の桁にはゼロは付けない $kakutei = 0; } for ($i=0;$i<$nagasa;$i++) {#5桁の数字をバラス $kotae[$i] = substr($kotae,$i,1); } if ($dup == 1) { for ($i=0;$i<$nagasa;$i++) { for ($j=$i+1;$j<$nagasa;$j++) { if ($kotae[$i]==$kotae[$j]) {#数字の重複を除く $kakutei = 0; } } } } } } else { $nom = "$nom" . "$nomber";#入力履歴を接続 $kai++; } ######誤入力チェック###### if ($nomber eq '') { &error(1); } if ($nomber =~ /\D/) { &error(2); } if (length($nomber) ne $nagasa) { &error(3); } ######HIT&BLOWのチェック###### for ($i=0;$i<$nagasa;$i++) {#5桁の数字をバラス $kotae[$i]=substr($kotae,$i,1); $anata[$i]=substr($nomber,$i,1); } for ($i=0;$i<$nagasa;$i++) { if ($kotae[$i] eq $anata[$i]) {#数字の位置も正しい $hit++; ($kotae[$i], $anata[$i]) = ('H', 'I');#一度当たった数字を除く } } for ($i=0;$i<$nagasa;$i++) { for ($j=0;$j<$nagasa;$j++) {#数字は正しい if ($kotae[$i] eq $anata[$j]) { $blow++; ($kotae[$i], $anata[$j]) = ('B', 'A');#一度当たった数字を除く } } } $hb = "$hb" . "$hit" . "$blow";#HIT&BLOWの履歴を接続 ######履歴取得・表示###### print "<table border=\"1\"><tr align=\"center\"><td>回数</td><td> </td>\n"; print "<td width=\"30\" bgcolor=\"lime\">HIT</td>"; print "<td width=\"30\" bgcolor=\"yellow\">BLOW</td></tr>\n"; for ($i = 0; $i < $kai; $i++) { $nomb[$i] = substr($nom, $i*$nagasa, $nagasa);#左から$nagasa文字づつ取得 $nohi[$i] = substr($hb, $i*2, 1);#左から1文字づつ取得 $noba[$i] = substr($hb, $i*2+1, 1);#左から1文字づつ取得 $ii++; print "<tr align=\"center\"><td>$ii</td><td>$nomb[$i]</td>\n"; print "<td colspan=\"2\" bgcolor=\"black\">"; if ($nohi[$i] > 0) { print "<font color=\"lime\">"; for ($j=0; $j < $nohi[$i]; $j++) { print "●"; } print "</font>"; } if ($noba[$i] > 0) { print "<font color=\"yellow\">"; for ($j=0; $j < $noba[$i]; $j++) { print "▲"; } print "</font>"; } if ($nohi[$i] + $noba[$i] < $nagasa) { print "<font color=\"white\">"; for ($j=0; $j < ($nagasa - $nohi[$i] - $noba[$i]); $j++) { print "●"; } print "</font>"; } print "</td></tr>\n"; } print "</table>\n"; if ($hit == $nagasa) { print qq|<br><font color=\"red\">大当たり!!</font> <form action="../$html" method="GET"> <input type="submit" value="続ける!!"> </form> |; } elsif ($kai < $maxkai) { print qq| <form action="./$script" method="POST" name="form"> <input type="text" name="no" maxlength="$nagasa" size="10"> <input type="submit" value="GO!"> <input type="hidden" name="n" value="$nom"> <input type="hidden" name="k" value="$kotae"> <input type="hidden" name="y" value="$kai"> <input type="hidden" name="hb" value="$hb"> <input type="hidden" name="keta" value="$nagasa"> <input type="hidden" name="max" value="$maxkai"> </form> |; $nokori = $maxkai - $kai; print "<p>あと$nokori回です。</p>"; print qq|<form action="../$html" method="GET"> <input type="submit" value="始めからもう一度"> </form> |; } else { print qq|<p>残念! $maxkai回です。<br> 答えは[<font color="red">$kotae</font>]でした!</p> <form action="../$html" method="GET"> <input type="submit" value="悔しい!もう一度!!"> </form> |; } print qq| <hr> このページの解説は<a href="./l_mastermind.html">こちらをご覧ください</a> </center> |; require './fotter.txt'; exit; ######エラー表示###### sub error { $error = $_[0]; if ($error == 1) { print "数字を入力してください。"; } if ($error == 2) { print "0から9までの半角数字で入力してください。"; } if ($error == 3) { print "$nagasa桁の半角数字を入力してください。"; } print "<br>もう一度<a href=\"Javascript:history.back()\">入力</a>\n"; exit(1); }
| Back | Coco's Home | ココとPerlで遊びませんか |
Copyright 2001-2002 Coco's Home. All rights reserved.![]()