CGIを書く
クライアントから受け取ったデータを使ってサーバ側で処理を行い、結果をクライアントに返します。
そこで、CGIを使ってサーバ側で処理を行うためのスクリプトを書きます。
データの内容を決める
ゲームを作る上で、サーバ側にどのようなデータが保存されるべきかを考えます。
ここでは一人のユーザに関するゲーム状況を、以下のような項目を使って一行で表します。
- 最後に行動したユーザのユーザID
- ユーザ1のユーザID
- ユーザ2のユーザID
- ユーザ1の体力
- ユーザ2の体力
- ユーザ1に表示されたメッセージ
- ユーザ2に表示されたメッセージ
他のクライアントとデータを共有する必要があるため、お互いの情報を記録する必要があります。
271695 | 271695 | 131559 | 100 | 100 | 相手の番です。 | あなたの番です。 |
230468 | 478053 | 230468 | 85 | 75 | 敵の攻撃。\nあなたは15ポイントのダメージを受けた。 | あなたの攻撃。\n敵に15ポイントのダメージを与えた。 |
66999 | 66999 | 316545 | 100 | 100 | お昼寝をした。\nあなたは1ポイント回復した。 | 敵はお昼寝をした。\n敵は1ポイント回復した。 |
271331 | 563499 | 271331 | 100 | 100 | あなたの番です。 | 相手の番です。 |
584660 | 107515 | 584660 | 0 | 54 | 敵の攻撃。\nあなたは26ポイントのダメージを受けた。\nあなたはやられてしまった。\nあなたの負けです。 | あなたの攻撃。\n敵に26ポイントのダメージを与えた。\n敵を倒した\nあなたの勝ちです。 |
メインルーチンを書く
さきほどの基本的なルーチンを使用して、以下のようなCGIを書きます。
#!/usr/local/bin/perl
&fnMain;
sub fnMain {
#★各種設定
$strFileName = 's2.txt';
$iRowMax = 100; #最新何件分の対戦データを保存するか
#★データを受信
if ($ENV{'QUERY_STRING'} ne '') {
@strParam = split(/&/, $ENV{'QUERY_STRING'});
}
foreach $strIdx (@strParam) {
($strKey,$strVal) = split(/=/,$strIdx);
$strForm{$strKey} = $strVal;
}
$iAct = $strForm{'act'};
$iUid = $strForm{'uid'};
#★ファイル読み込み
$strData = fnGetFileText($strFileName);
#★自分の行を取得する
if (($strData =~ /^(.+?)\t($iUid)\t(.*?)\t(.+?)\t(.+?)\t(.*?)\t(.*?)$/m)
|| ($strData =~ /^(.+?)\t(.+?)\t($iUid)\t(.+?)\t(.+?)\t(.*?)\t(.*?)$/m)) {
$iTurn = $1;
$aiUid[0] = $2;
$aiUid[1] = $3;
$aiLife[0] = $4;
$aiLife[1] = $5;
$astrText[0] = $6;
$astrText[1] = $7;
} elsif ($strData =~ /^(.+?)\t(.+?)\t\t(.+?)\t(.+?)\t(.*?)\t(.*?)$/m) {
$aiUid[0] = $2;
$aiUid[1] = $iUid;
$aiLife[0] = $3;
$aiLife[1] = $4;
$iTurn = (int(rand(2)) == 1) ? $aiUid[0] : $aiUid[1];
$astrText[0] = ($iTurn == $iUid) ? 'あなたの番です。' : '相手の番です。';
$astrText[1] = ($iTurn != $iUid) ? 'あなたの番です。' : '相手の番です。';
#★該当行を更新
$strLine = "$iTurn\t$aiUid[0]\t$aiUid[1]\t$aiLife[0]\t$aiLife[1]\t$astrText[0]\t$astrText[1]";
$strData =~ s/^.+?\t$aiUid[0]\t\t.*$/$strLine/m;
#★新しい行を残して古い行を削除
@astrData = split("\n",$strData);
if ($#astrData >= $iRowMax) {
$strData = join("\n",splice(@astrData,$#astrData - $iRowMax + 1,$iRowMax)) . "\n";
}
#★保存
&fnSetFileText($strFileName,$strData);
} else {
$iTurn = $iUid;
$aiUid[0] = $iUid;
$aiUid[1] = '';
$aiLife[0] = 100;
$aiLife[1] = 100;
$astrText[0] = '対戦待ちです。';
$astrText[1] = '対戦待ちです。';
$strLine = "$iTurn\t$aiUid[0]\t$aiUid[1]\t$aiLife[0]\t$aiLife[1]\t$astrText[0]\t$astrText[1]\n";
&fnAddFileText($strFileName,$strLine);
}
#★自分が何番(0 or 1)か求める
$iMy = ($aiUid[0] == $iUid) ? 0 : 1;
$iYu = 1 - $iMy;
#★対戦
if ($aiUid[1] ne '' && $iAct >= 0 && $iTurn == $aiUid[$iYu]) {
if ($iAct == 0) {
$iRand = 10 + int(rand(31));
$astrText[$iMy] = 'あなたの攻撃。\n敵に%1%ポイントのダメージを与えた。';
$astrText[$iYu] = '敵の攻撃。\nあなたは%1%ポイントのダメージを受けた。';
$astrText[$iMy] =~ s/%1%/$iRand/g;
$astrText[$iYu] =~ s/%1%/$iRand/g;
$aiLife[$iYu] -= $iRand;
if ($aiLife[$iYu] <= 0) {
$aiLife[$iYu] = 0;
$astrText[$iMy] .= '\n敵を倒した\nあなたの勝ちです。';
$astrText[$iYu] .= '\nあなたはやられてしまった。\nあなたの負けです。';
}
} elsif ($iAct == 1) {
$iRand = 10 + int(rand(21));
if ($aiLife[$iMy] + $iRand > 100) {
$iRand = 100 - $aiLife[$iMy];
}
$astrText[$iMy] = 'お昼寝をした。\nあなたは%1%ポイント回復した。';
$astrText[$iYu] = '敵はお昼寝をした。\n敵は%1%ポイント回復した。';
$astrText[$iMy] =~ s/%1%/$iRand/g;
$astrText[$iYu] =~ s/%1%/$iRand/g;
$aiLife[$iMy] += $iRand;
}
$iTurn = ($iTurn == $aiUid[0]) ? $aiUid[1] : $aiUid[0];
$strLine = "$iTurn\t$aiUid[0]\t$aiUid[1]\t$aiLife[0]\t$aiLife[1]\t$astrText[0]\t$astrText[1]";
$strData =~ s/^.+?\t$aiUid[0]\t$aiUid[1]\t.*$/$strLine/m;
&fnSetFileText($strFileName,$strData);
}
#★レスポンス
print "Content-type: text/html\n";
print "\n";
print "$iTurn\n$aiLife[$iMy]\n$astrText[$iMy]";
}
これにより、クライアントから渡されたデータを用いて、クライアントが要求する結果を返します。
動作を確認する
実際の動作は以下の通りです。
新規ウィンドウで実行