- チックタックトウ(○×ゲーム)のプログラムを作りながら,
プログラミングTで習った諸事項の復習をする.
- チックタックトウ
- 3×3の枡からなる盤に,2人のプレイヤーが交互に○と×を置いていく.
- 先に3つ一直線に並べた方が勝ちである.
-
- どちらも一直線に並べられなかったら,引き分けである.
-
- プログラムは一度に完全なものを作るのではなく,徐々に組み立てていく.
-
- まずは,盤を表すデータ構造を定義し,盤の初期状態をを書く.
- データ構造を定義する.
type
TBangou = 1..9; // 部分範囲型
TYouso = (Kara,Maru,Batu); // 列挙型
TBan = array [TBangou] of TYouso; // 配列型
var
Ban : TBan;
- 盤は3×3の枡からなるが,9つの枡に1〜9の通し番号をつけて表している.
-
- メインルーチン 大まかな流れをプロシージャの名前を並べて書く.
begin {Main}
BanSyokika;
BanWoKaku;
ReadLn;
end.
- 個々のプロシージャを細かく(メインルーチンの上に)書く.
- 盤を初期化する(すべて空にする)プロシージャ
procedure BanSyokika; // プロシージャ
{盤を初期化する}
var
N : TBangou;
begin
for N := 1 to 9 do // for ループ
Ban[N] := Kara;
end; {BanSyokika}
- 盤全体を書くプロシージャ
procedure BanWoKaku;
{盤を書く}
var
N : TBangou;
begin
WriteLn;
WriteLn('+−+−+−+');
for N := 1 to 9 do
begin
Write('|');
YousoWoKaku(N);
if N mod 3 = 0 // if 分岐
then begin
WriteLn('|');
WriteLn('+−+−+−+');
end;
end;
end; {BanWoKaku}
- この中で使っているプロシージャをさらに細かく(この上に)書く.
- 1つの枡の要素を書くプロシージャ
procedure YousoWoKaku(N : TBangou);
{Ban[N]を書く}
begin
case Ban[N] of // case 分岐
Maru : Write('○':2);
Batu : Write('×':2);
Kara : Write(' ':2);
end;
end; {YousoWoKaku}
- 実行して空の盤が書かれることを確認する.
- 初期化ルーチンに,次の文を仮に追加して,○や×も書かれることを確認しよう.
Ban[3] := Maru;
Ban[7] := Batu;
-
- 2人のプレイヤーに,どこに置くか訊いて○と×を置いていく.
- データ構造を追加する.
type
TBangou = 1..9;
TYouso = (Kara,Maru,Batu);
TBan = array [TBangou] of TYouso;
TPlayer = Maru..Batu; // 部分範囲型
- メインルーチンを変更.
var
Tesuu : Integer; // 何手目か
Teban : TPlayer; // 手番のプレイヤー,○,×
Basyo : TBangou; // 置く場所,1〜9
begin {Main}
BanSyokika;
BanWoKaku;
Tesuu := 0; // 手数を0に初期化する
Teban := Batu; // 手番を×(後手)とする
repeat // repeat ループ
Inc(Tesuu); // 手数を+1する
WriteLn;
Write(Tesuu, '手目: ');
TebanKoutai(Teban); // 手番を交代する
Basyo := OkuBasyo; // 置く場所を訊く
Ban[Basyo] := Teban; // 置く
BanWoKaku; // 盤を書く
until Tesuu = 9;
ReadLn;
end.
- ここで使われているプロシージャ,ファンクションを書く.
- 手番を交代するプロシージャ
procedure TebanKoutai(var Player : TPlayer);
{手番を交代する}
begin
case Player of
Maru : begin
Player := Batu;
WriteLn('×の番です');
end;
Batu : begin
Player := Maru;
WriteLn('○の番です');
end;
end;
end; {TebanKoutai}
- 置く場所を人に訊いて,その場所を返すファンクション
function OkuBasyo : TBangou;
{どこに置くか人に訊く}
var
N : TBangou;
begin
Write('どこに置きますか [1〜9] ? ');
ReadLn(N);
while not (N in [1..9]) or (Ban[N] <> Kara) do // while ループ
begin // 集合 [1..9]
WriteLn('そこには置けません');
Write('どこに置きますか [1〜9] ? ');
ReadLn(N);
end;
Result := N; // 返す値
end; {OkuBasyo}
- 実行する.まだ,勝ち負けの判定をしないので,必ず9手するまで行う.
-
- 勝ち負けの判定を加える.
- メインルーチンを変更
var
Tesuu : Integer;
Teban : TPlayer;
Basyo : TBangou;
Katta : Boolean; // 勝ちが決まったかどうか
begin
BanSyokika;
BanWoKaku;
Tesuu := 0;
Teban := Batu;
repeat
Inc(Tesuu);
WriteLn;
Write(Tesuu, '手目: ');
TebanKoutai(Teban);
Basyo := OkuBasyo;
Ban[Basyo] := Teban;
BanWoKaku;
Katta := Naranda(Basyo); // 勝ったかどうか調べる
until (Tesuu = 9) or Katta;
if Katta
then WriteLn('勝ちました')
else WriteLn('引き分けです');
ReadLn;
end.
- 新しく使われたファンクションを書く.
- 勝ったかどうか調べるファンクション
function Naranda(N : TBangou) : Boolean;
{N 番を含む列に同じマークが3つ並んだか調べる}
begin
case N of
1 : Result := Onaji(1,2,3) or Onaji(1,4,7) or Onaji(1,5,9);
2 : Result := Onaji(1,2,3) or Onaji(2,5,8);
3 : ; // 完成させてください
4 : ; // 完成させてください
5 : ; // 完成させてください
6 : ; // 完成させてください
7 : ; // 完成させてください
8 : ; // 完成させてください
9 : ; // 完成させてください
end;
end; {Naranda}
- さらに,この中で使われているファンクションを書く.
- 3つの枡に同じマークが入っているか調べるファンクション.
function Onaji(I,J,K : TBangou) : Boolean;
{Ban[I],Ban[J],Ban[K] に同じマークが入っているか調べる}
begin
Result := (Ban[J] = Ban[I]) and (Ban[K] = Ban[I]);
end; {Onaji}
- 実行する.今度は,3つ並ぶと終了する.
- このように,本格的なプログラムを書くときは,つぎのように作っていくことを心がけよう.
- 少しずつ徐々にふくらませていく.
- 1つのルーチンが何十行にもなると理解しにくくなるので,
プロシージャ,ファンクションをうまく使ってコンパクトにまとめる.
|