プログラミングⅡ 第3回

プログラミングⅡ 第3回
TicTacToe のバージョンアップ
TicTacToe4
コンピュータ VS 人 の対戦型にする
先手をどちらにするか訊いて決める
コンピュータの手をランダムに決める
メインルーチンを変更
今までメインルーチンのすぐ上にあった変数宣言を,
最上部の他の変数宣言と一緒にまとめる.
コンピュータが先手(○)か後手(×)かを示す変数
Computer : TPlayer を追加する.
var
Ban
Tesuu
Teban
Basyo
Katta
Computer
:
:
:
:
:
:
TBan;
Integer;
TPlayer;
TBangou;
Boolean;
TPlayer;
// コンピュータ(が○か×か)
メインルーチンを変更
begin {Main}
SenteWoKimeru;
BanSyokika;
BanWoKaku;
Tesuu := 0;
Teban := Batu;
repeat
Inc(Tesuu);
WriteLn;
Write(Tesuu, '手目: ');
TebanKoutai(Teban);
if Teban = Computer
then Basyo := ComputerNoTe
else Basyo := OkuBasyo;
Ban[Basyo] := Teban;
BanWoKaku;
Katta := Naranda(Basyo);
until (Tesuu = 9) or Katta;
if Katta
then WriteLn('勝ちました')
else WriteLn('引き分けです');
ReadLn;
end.
// どちらが先手か決める
// 手数を0に初期化する
// 手番を×(後手)とする
// 手数を+1する
// 手番を交代する
//
//
//
//
//
置く場所をコンピュータが決める
置く場所を訊く
置く
盤を書く
勝ったかどうか調べる
注意
これ以降,プロシージャやファンクションを追加
していきますが,どこに書くか考えて正しい位
置に追加してください.
プロシージャ SenteWoKimeru
コンピュータを先手にするか後手にするか,人に選んでもらう.
後手を選ぶことが多いので,
先手を選ぶときは y
後手を選ぶときは y以外
を入れればよいようにする.
procedure SenteWoKimeru;
(* どちらが先手か決める *)
var
YesNo : String;
begin
Write('コンピュータを先手(○)にしますか [y(Yes) / y以外(No)] ? ');
ReadLn(YesNo);
if YesNo = 'y'
then Computer := Maru
else Computer := Batu;
end; {SenteWoKimeru}
ファンクション ComputerNoTe
コンピュータが置く場所を決める.
とりあえず,ランダムに空桝を選ぶ.
function ComputerNoTe : TBangou;
{置く場所をコンピュータが選ぶ}
begin
Result := DetarameNiErabu;
end; {ComputerNoTe}
ファンクション DetarameNiErabu
1~n(残っている空桝の個数) の乱数をrとする.
1番目から桝を調べていき,空ならrを1減らす.
rが0になったときの桝を選ぶ.
function DetarameNiErabu : TBangou;
{でたらめに選ぶ}
var
R,K : TBangou;
begin
R := Random(10-Tesuu)+1;
K := 0;
repeat
Inc(K);
if Ban[K] = Kara
then Dec(R);
until R = 0;
Result := K;
end; {DetarameNiErabu}
// r=1~空枡の個数 の乱数
// 空枡のうちr番目を選ぼう
// k=0に初期設定する
// kを1増やす(次の枡を調べる)
// 空枡だったらrを1減らす
// r=0になるまで繰り返す
// Ban[k]がr番目の空枡
ファンクション DetarameNiErabu
前ページのプログラムの中で,変数 K,R の値が0にな
ることがあります.
0は実際の番号ではないのですが,TBangou に含め
ることにします.
type
TBangou
TYouso
TBan
TPlayer
=
=
=
=
0..9;
(Kara,Maru,Batu);
array [1..9] of TYouso;
Maru..Batu;
//
//
//
//
枡につけた通し番号,0は便宜上
枡の要素=(空,○,×)
盤=9つの枡(3×3)
選手=(○,×)
実行する
コンピュータはでたらめに置いていくので弱いでしょう.
ところで何回やってもコンピュータは同じ置き方をするのに気が
つきましたか.
「でたらめ」というのに変ですね.
いつも同じ乱数系列を使うからなのです.
乱数系列を変える Randomize をメインルーチンに追加します.
begin {Main}
Randomize;
SenteWoKimeru;
// どちらが先手か決める
TicTacToe5
3つ並ぶ場合を考慮して決める
優先度
1. 自分のこまが3つ並ぶように置ける場所があ
ればそこを選ぶ-勝つ手
2. 相手のこまが3つ並ぶように置ける場所があ
ればそこを選ぶ-負けない手
3. ランダムに選ぶ
プロシージャ TebanKoutai
配列定数 Aite を使って簡単にする.
定数を定義する.
type
TBangou
TYouso
TBan
TPlayer
=
=
=
=
0..9;
//
(Kara,Maru,Batu);
//
array [TBangou] of TYouso; //
Maru..Batu;
//
const
Aite : array [TPlayer] of TPlayer
= (Batu,Maru);
枡の通し番号,0は特殊
枡の要素=(空,○,×)
盤=9つの枡(3×3)
選手=(○,×)
// 配列定数
// Aite[Maru]=Batu,
// Aite[Batu]=Maru
プロシージャ TebanKoutai
配列定数 Aite を使って簡単にする.
TebanKoutai を変更する
procedure TebanKoutai(var Player : TPlayer);
{手番を交代する}
begin
Player := Aite[Player];
if Player = Batu
then WriteLn('×の番です')
else WriteLn('○の番です');
end; {TebanKoutai}
ファンクション ComputerNoTe
善い手を選ぶようにする.
function ComputerNoTe : TBangou;
{置く場所をコンピュータが選ぶ}
var
YoiBasyo : TBangou;
begin
YoiBasyo := YoiBasyoWoSagasu;
if YoiBasyo > 0
then Result := YoiBasyo
else Result := DetarameNiErabu;
end; {ComputerNoTe}
ファンクション YoiBasyoWoSagasu
勝つあるいは負けを防ぐ場所を探して,
あったらその場所を答えます.
なかったら0を答えます.
function YoiBasyoWoSagasu : TBangou;
{善い場所を探す}
var
Katu
: TBangou;
// 自分のこまが3つ並ぶ場所
Makenai : TBangou;
// 相手のこまが3つ並ぶ場所(を防ぐ)
Basyo : TBangou;
begin
Katu := 0;
Makenai := 0;
Basyo := 0;
repeat
Inc(Basyo);
if Ban[Basyo] = Kara
then begin
Ban[Basyo] := Computer;
// 自分のこまを置いてみる
if Naranda(Basyo)
// 3つ並べば勝ち
then Katu := Basyo;
Ban[Basyo] := Aite[Computer]; // 相手のこまを置いてみる
if Naranda(Basyo)
// 3つ並べば負け
then Makenai := Basyo;
Ban[Basyo] := Kara;
// 元に戻す
end;
until (Basyo = 9) or (Katu > 0);
// 勝つ手が見つかれば終わる
if Katu > 0
then Result := Katu
else Result := Makenai;
// 負けない手もなければ0
end; {YoiBasyoWoSagasu}
実行
このゲームは両者が最善手を選べば引き分け
になります.
しかし,コンピュータは最善手を選ぶようには
なっていないので,人が勝つ可能性がありま
す.
さあ,あなたはどのくらい勝てるでしょうか.
まさか負けることはないでしょうね.
問題
繰り返し実行できるように,メインルーチンを変
更してください.
1回ゲームが終わったら
終了しますか [y(Yes) / y以外(No)] ?
と訊いて,y以外を入れたら繰り返すようにしてく
ださい.
問題
勝負がついたとき(引き分けでないとき),今は,
勝ちました
と,主語(手番の選手)を省略して書きますが,
あなたが勝ちました
または
あなたが負けました
と,人を主語にして書くように変更してください.