コンピュータに手を選択させるように変更してみましょう。
単純な選択方法として、乱数を使って選択させる方法があります。知能のかけらもありませんが。^^;
手順としては
となります。
サブルーチン# 手の選択サブルーチン sub select { my $b=@_; while (1) { $number=int(rand(8)); # 0から8の乱数を発生 if ($b[$number]==0) { return $number } # 重複チェック } }メインルーチンの修正# 乱数初期化(Perlのバージョンによっては必要ない srand(time());# メインループ for ($i=0; $i<9; $i++) { if ( ($i % 2) ==0 ) { $b[&select(@b)]=1; # 先手を&selectで選ぶように変更 } else { $b[&input(@b)]=-1; # 後手 } &print_board(@b); if (&check_winner(@b)!=0) { last; } }
ゲームの勝敗のルールから、「3目並べれば勝ち。3目並べられれば負け。」なのですから、戦略として
- 自分で3目並べられる場所には、その場所に置く。
- 相手に3目並べられる場所には、その場所に置く。
の2つが上げられます。このような規則を戦略的規則といいます。
手順としては
- 勝ちになるマスがあるかマス目を順に調べる。
- 空きマスかどうか調べ、空いてなければ次のマスに。
- ○を置いた状態で勝敗チェックをし、ボードから取り除く。勝ちならばマス目の番号を返す。
- 次のマスに。
- 負けになるマスがあるかマス目を順に調べる。
- 空きマスかどうか調べ、空いてなければ次のマスに。
- ×を置いた状態で勝敗チェックをし、ボードから取り除く。負けならばマス目の番号を返す。
- 次のマスに。
- 1.、2.で決まらなければとりあえず乱数で。^^;
となります。
# 手の選択サブルーチン sub select { my @b=@_; my $i; for ($i=0; $i<9; $i++) { # 勝ちマスチェック if ($b[$i]==0) { $b[$i]=1; if (&check_winner(@b)==1) { $b[$i]=0; return $i; } else { $b[$i]=0; } } } for ($i=0; $i<9; $i++) { # 負けマスチェック if ($b[$i]==0) { $b[$i]=-1; if (&check_winner(@b)==-1) { $b[$i]=0; return $i; } else { $b[$i]=0; } } } while (1) { $number=int(rand(8)); # 0から8の乱数を発生 if ($b[$number]==0) { return $number } # 重複チェック } }
# 盤面初期化 for ($i=0; $i<9; $i++) { $b[$i]=0; } # メインループ for ($i=0; $i<9; $i++) { if ( ($i % 2) ==0 ) { $b[&select(@b)]=1; # 先手 } else { $b[&input(@b)]=-1; # 後手 } &print_board(@b); if (&check_winner(@b)!=0) { last; } } # 勝敗表示 if (&check_winner(@b)==1) { print "○の勝ち!\n"; } elsif (&check_winner(@b)==-1) { print "×の勝ち!\n"; } else { print "引き分け!\n"; } # 手の選択サブルーチン sub select { my @b=@_; my $i; for ($i=0; $i<9; $i++) { # 勝ちマスチェック if ($b[$i]==0) { $b[$i]=1; if (&check_winner(@b)==1) { $b[$i]=0; return $i; } else { $b[$i]=0; } } } for ($i=0; $i<9; $i++) { # 負けマスチェック if ($b[$i]==0) { $b[$i]=-1; if (&check_winner(@b)==-1) { $b[$i]=0; return $i; } else { $b[$i]=0; } } } while (1) { $number=int(rand(8)); # 0から8の乱数を発生 if ($b[$number]==0) { return $number } # 重複チェック } } # 盤面表示サブルーチン sub print_board { my @b=@_; my $i; for ( $i=0; $i<9; $i++ ) { if ( $b[$i]==1 ) { print "○"; } elsif ( $b[$i]==-1 ) { print "×"; } else { print " "; } if ( ($i==2) || ($i==5) || ($i==8) ) { print "\n"; } } } # 勝敗チェックサブルーチン sub check_winner { my @b=@_; my $i; for ( $i=0; $i<3; $i++ ) { if ( $b[$i*3+0]+$b[$i*3+1]+$b[$i*3+2]==3 ) { return 1; } elsif ( $b[$i*3+0]+$b[$i*3+1]+$b[$i*3+2]==-3 ) { return -1; } } for ( $i=0; $i<3; $i++ ) { if ( $b[0+$i]+$b[3+$i]+$b[6+$i]==3 ) { return 1; } elsif ( $b[0+$i]+$b[3+$i]+$b[6+$i]==-3 ) { return -1; } } if ( $b[0]+$b[4]+$b[8]==3 ) { return 1; } elsif ( $b[0]+$b[4]+$b[8]==-3 ) { return -1; } if ( $b[2]+$b[4]+$b[6]==3 ) { return 1; } elsif ( $b[2]+$b[4]+$b[6]==-3 ) { return -1; } return 0; } # 入力サブルーチン sub input { my @b=@_; my $number; while () { # 無限ループ print "012\n"; print "345\n"; print "678\n"; print "0-8の数字をいれてください。"; $number=<stdin>; chomp($number); if ($number>=0 && $number<=8) { # 数字チェック。文字列も0として通ってしまう。TT if ($b[$number]!=0) { # 重複チェック print "そのマスはすでに入力済みです。\n"; } else { return $number; } } else { print "入力が正しくありません。"; } } }