CGIを書く

クライアントから受け取ったデータを使ってサーバ側で処理を行い、結果をクライアントに返します。
そこで、CGIを使ってサーバ側で処理を行うためのスクリプトを書きます。

データの内容を決める

ゲームを作る上で、サーバ側にどのようなデータが保存されるべきかを考えます。
ここでは一人のユーザに関するゲーム状況を、以下のような項目を使って一行で表します。

  • ユーザID
  • 自分の体力
  • 相手の体力

他のクライアントとデータを共有する必要が無いため、これが必要最低限のデータとなります。

455673240
838840100100
97551806
5457228383

基本的なルーチンを書く

ここでは、基本的なファイル処理として以下のルーチンを使用するのでご了承下さい。

指定したファイル名の中身を返すルーチン。

sub fnGetFileText {
    ($strFilePath) = @_;
    
    @strText = ();
    if (! -f $strFilePath){
        @strText = split(/$/m, "");
        return("");
    }
    
    open (IN,"$strFilePath");
    @strText = <IN>;
    close (IN);
    
    $strData = join('',@strText);
    return($strData);
}

指定したファイル名に指定した中身を保存するルーチン。

sub fnSetFileText {
    ($strFilePath, $strData) = @_;
    
    @strText = split(/$/m, $strData);
    if (! -f $strFilePath){
        open(OUT,">$strFilePath");
        close(OUT);
    }
    
    open (OUT,">$strFilePath");
    flock(OUT, 2);
    print OUT (@strText);
    close (OUT);
}

指定したファイル名に指定した中身を追記するルーチン。

sub fnAddFileText {
    ($strFilePath, $strText) = @_;
    
    if (! -f $strFilePath){
        open(OUT,">$strFilePath");
        close(OUT);
    }
    
    open(OUT, ">>$strFilePath");
    flock(OUT, 2);
    print OUT $strText;
    close(OUT);
}

メインルーチンを書く

基本ルーチンを使用して、CGIを書きます。

#!/usr/local/bin/perl
&fnMain;
sub fnMain {
    #★各種設定
    $strFileName = 's1.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 =~ /^$iUid\t(.+?)\t(.+?)$/m) {
        $iMyLife = $1;
        $iYuLife = $2;
    } else {
        $iMyLife = 100;
        $iYuLife = 100;
        
        #★新しい行を残して古い行を削除
        @astrData = split("\n",$strData);
        if ($#astrData >= $iRowMax) {
            $strData = join("\n",splice(@astrData,$#astrData - $iRowMax + 1,$iRowMax)) . "\n";
        }
        &fnSetFileText($strFileName,$strData);
        
        #★自分の行を追加
        $strLine = "$iUid\t$iMyLife\t$iYuLife\n";
        &fnAddFileText($strFileName,$strLine);
    }
    
    #★対戦
    if ($iAct >= 0) {
        #★自分の攻撃
        if ($iAct == 0) {
            $iRand = 10 + int(rand(31));
            $strMsg = 'あなたの攻撃。\n敵に%1%ポイントのダメージを与えた。';
            $strMsg =~ s/%1%/$iRand/g;
            $iYuLife -= $iRand;
            if ($iYuLife <= 0) {
                $iYuLife = 0;
                $strMsg .= '\n敵を倒した\nあなたの勝ちです。';
            }
        } elsif ($iAct == 1) {
            $iRand = 10 + int(rand(21));
            if ($iMyLife + $iRand > 100) {
                $iRand = 100 - $iMyLife;
            }
            $strMsg = 'お昼寝をした。\nあなたは%1%ポイント回復した。';
            $strMsg =~ s/%1%/$iRand/g;
            $iMyLife += $iRand;
        }
        #★相手の攻撃
        if ($iYuLife > 0) {
            $iRand = 10 + int(rand(31));
            $strMsg .= '\n\n敵の攻撃。\nあなたは%1%ポイントのダメージを受けた。';
            $strMsg =~ s/%1%/$iRand/g;
            $iMyLife -= $iRand;
            if ($iMyLife <= 0) {
                $iMyLife = 0;
                $strMsg .= '\nあなたはやられてしまった。\nあなたの負けです。';
            }
        }
        #★保存
        $strLine = "$iUid\t$iMyLife\t$iYuLife";
        $strData =~ s/^$iUid\t.*$/$strLine/m;
        &fnSetFileText($strFileName,$strData);
    } else {
        $strMsg  = '行動を選んで下さい。';
    }
    
    #★レスポンス
    print "Content-type: text/html\n";
    print "\n";
    print "$iMyLife\n$iYuLife\n$strMsg";
}

これにより、クライアントから渡されたデータを用いて、クライアントが要求する結果を返します。

動作を確認する

実際の動作は以下の通りです。
新規ウィンドウで実行

Copyright © 2006 Hikijishi All Rights Reserved.
[] [ajax][0.00273990631103516]