リバーシ(ボードゲーム)
#! /usr/local/bin/perl loadForm(); #フォームデータ取り込み loadData(); #データ処理 printData(); #HTML出力 exit; #====================================================================#データ処理 sub loadData { my ($i, $max, $no, $color); if($FORM{'lv'} eq "") { $FORM{'lv'} = "1"; } if($FORM{'data'}) { $DATA = $FORM{'data'}; if($FORM{'no'} eq "" or $FORM{'no'} eq "pass") { #コンピュータの一手 $NEXT = "use"; if($FORM{'no'} eq "pass") { #パスの場合 手詰りチェック for($i = 0 ; $i < length($DATA) ; $i++) { if(substr($DATA, $i, 1) eq "0" and changeData($i, $FORM{'color'})) { $MSG = "エラー:パスできません。"; return; } } } if($FORM{'color'} eq "1") { $color = "2"; } else { $color = "1"; } for($i = 0 ; $i < length($DATA) ; $i++) { if(substr($DATA, $i, 1) eq "0") { #反転枚数チェック my $count = changeData($i, $color); if($count > 0) { $count = checkLv($i, $color, $count); #レベルごとの評価 $count += (rand 0.1); if($count > $max) { #反転枚数最大チェック $max = $count; $no = $i; } } } } if($no eq "") { #手詰りの場合 パス if($FORM{'no'} eq "pass") { gameOver(); #互いにパスの場合 ゲームオーバー } else { $MSG = "コンピュータ:パス"; } return; } else { changeData($no, $color, 1); #ひっくり返す } } else { #プレイヤーの一手 $NEXT = "com"; if(!changeData($FORM{'no'}, $FORM{'color'}, 1)) { #ひっくり返す(枚数チェック) $NEXT = "use"; #0枚の場合 エラー $DATA = $FORM{'data'}; $MSG = "エラー:手詰りの場合パスしてください。"; return; } } if(!($DATA =~ /0/) or !($DATA =~ /1/) or !($DATA =~ /2/)) { gameOver(); #ゲームオーバー } } else { #ゲームスタート $DATA = "0000000000000000000000000001200000021000000000000000000000000000"; $FORM{'color'} = int(rand 2) + 1; #色を決める if($FORM{'color'} == 1) { #2が先手(白) $NEXT = "com"; } else { $NEXT = "use"; } } } #====================================================================レベルごとの評価 sub checkLv { my ($i, $j); my @check = ( [0, 1, 8, 9], [7, 6, 14, 15], [56, 48, 49, 57], [63, 54, 55, 62] ); #チェック箇所 if($FORM{'lv'} eq "2" or $FORM{'lv'} eq "3") { #レベル2・3 for($i = 0 ; $i < @check ; $i++) { if($_[0] == $check[$i][0]) { $_[2] += 4; #プラス評価 return $_[2]; } if($FORM{'lv'} eq "3") { #レベル3 for($j = 1 ; $check[$i][$j] ; $j++) { if($_[0] == $check[$i][$j]) { if(substr($DATA, $check[$i][0], 1) eq $_[1]) { $_[2] += 3; #プラス評価 } elsif(substr($DATA, $check[$i][0], 1) eq "0") { $_[2] /= 5; #マイナス評価 } else { $_[2] /= 2; #マイナス評価 } return $_[2]; } } } } } return $_[2]; } #====================================================================反転・枚数チェック sub changeData { my ($i, $n, $count); my @check = (-9, -1, 7, 8, -8, -7, 1, 9); #チェック箇所 if($_[2]) { substr($DATA, $_[0], 1, $_[1]); #反転 } for($i = 0 ; $i < @check ; $i++) { #反転箇所を探す for($n = $_[0] + $check[$i] ;; $n += $check[$i]) { if($i <= 2 and $n % 8 == 7) { last; } if($i >= 5 and $n % 8 == 0) { last; } if($n < 0 or $n >= length($DATA)) { last; } if(substr($DATA, $n, 1) eq "0") { last; } if(substr($DATA, $n, 1) eq $_[1]) { for($n -= $check[$i] ; $n != $_[0] ; $n -= $check[$i]) { if($_[2]) { substr($DATA, $n, 1, $_[1]); #反転 } $count++; #反転枚数+1 } last; } } } return $count; #反転枚数を返す } #====================================================================ゲームオーバー・点数集計 sub gameOver { my ($i, $com, %point); my $use = $FORM{'color'}; $NEXT = "end"; if($use eq "1") { $com = "2"; } else { $com = "1"; } for($i = 0 ; $i < length($DATA) ; $i++) { #点数集計 $point{substr($DATA, $i, 1)}++; } if($point{$use} > $point{$com}) { #勝敗チェック $MSG = "WIN" } elsif($point{$use} < $point{$com}) { $MSG = "LOSE" } else { $MSG = "DRAW" } $MSG .= sprintf(" %d − %d", $point{$use}, $point{$com}); } #====================================================================HTML出力 sub printData { if($FORM{'color'} eq "1") { $USE = "●"; $COM = "<font color=\"#ffffff\">●</font>"; } else { $USE = "<font color=\"#ffffff\">●</font>"; $COM = "●"; } print qq(Content-type: text/html; charset=Shift_JIS\n\n); print <<" END"; <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> END if($NEXT eq "com") { print <<" END"; <meta http-equiv="refresh" content="2;url=$ENV{'SCRIPT_NAME'}?data=$DATA&color=$FORM{'color'}&lv=$FORM{'lv'}"> END } print <<" END"; <title>リバーシ</title> <style type="text/css"> <!-- table { margin-bottom:10px; width:400px; background:#6c6; border:1px solid #666 } th { padding:3px; background:#99f } td { width:12%; height:50px; font-size:40px; text-align:center; border:1px solid #666 } td a { width:100%; height:100% } a { text-decoration:none } .msg { padding:3px; color:red; font-size:25px; font-weight:bold; text-align:center } //--> </style> </head> <body> <table cellspacing="0" align="center"> <tr> <th colspan="4" align="left"></th> <th colspan="4" align="right"> END if($NEXT eq "com") { print <<" END"; <a href="$ENV{'SCRIPT_NAME'}?data=$DATA&color=$FORM{'color'}&lv=$FORM{'lv'}">コンピュータ</a> END } else { print <<" END"; コンピュータ END } print <<" END"; [ Lv$FORM{'lv'} ] $COM </th> </tr> </table> <table cellspacing="0" align="center"> END for($i = 0 ; $i < length($DATA) ; $i++) { if($i % 8 == 0) { print qq(<tr>\n); } if(substr($DATA, $i, 1) eq "0") { if($NEXT eq "use") { print <<" END"; <td> <a href="$ENV{'SCRIPT_NAME'}?data=$DATA&color=$FORM{'color'}&lv=$FORM{'lv'}&no=$i"> </a> </td> END } else { print <<" END"; <td> </td> END } } elsif(substr($DATA, $i, 1) eq $FORM{'color'}) { print qq(<td>$USE</td>\n); } else { print qq(<td>$COM</td>\n); } if(($i + 1) % 8 == 0) { print qq(</tr>\n); } } print <<" END"; </table> <table cellspacing="0" align="center"> <tr> <th colspan="4" align="left">$USE プレイヤー</th> <th colspan="4" align="right"> [ END if($NEXT eq "use") { print <<" END"; <a href="$ENV{'SCRIPT_NAME'}?data=$DATA&color=$FORM{'color'}&lv=$FORM{'lv'}&no=pass"> パス </a> END } else { print <<" END"; パス END } print <<" END"; ] [再スタート <a href="$ENV{'SCRIPT_NAME'}">Lv1</a> <a href="$ENV{'SCRIPT_NAME'}?lv=2">Lv2</a> <a href="$ENV{'SCRIPT_NAME'}?lv=3">Lv3</a> ] </th> </tr> </table> <div class="msg">$MSG</div> </body> </html> END } #====================================================================フォームデータ取り込み sub loadForm { my ($query, $pair); if($ENV{'REQUEST_METHOD'} eq 'POST') { read(STDIN, $query, $ENV{'CONTENT_LENGTH'}); } else { $query = $ENV{'QUERY_STRING'}; } foreach $pair (split(/&/, $query)) { my ($key, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([0-9a-fA-F][0-9a-fA-F])/chr(hex($1))/eg; $FORM{$key} = $value; } }
〔 実行する 〕