プログラミングⅡ 第2回

プログラミングⅡ 第2回
第1回(プログラミングⅠの復習)
の解説
プログラムの作り方
いきなり完全版を作るのではなく,だんだんふく
らませていきます.
TicTacToe1
プログラムの作り方
いきなり完全版を作るのではなく,だんだんふく
らませていく.
TicTacToe1
TicTacToe2
プログラムの作り方
いきなり完全版を作るのではなく,だんだんふく
らませていく.
TicTacToe1
TicTacToe2
TicTacToe3
盤のデータ構造
2次元配列で表す場合
type TBan = array [1..3,1..3] of ~;
1,1
1,2
1,3
2,1
2,2
2,3
3,1
3,2
3,3
盤のデータ構造
1次元配列で表す場合
type TBan = array [1..9] of ~;
1
2
3
4
5
6
7
8
9
盤のデータ構造
今回は1次元配列を使うことにします.
盤の枡を指す番号は 1~9 で,integer 型のほん
の一部に過ぎません.
一部の範囲だけを動くデータのために,固有の
型名をつけると,わかりやすくなります.
type TBangou = 1..9;
これを部分範囲型といいます.
盤のデータ構造
から
盤の枡の状態は,空,○,× の3つあります.
それぞれを 0,1,2 で表すことにして
type TYouso = 0..2;
としてもよいのですが,
名前で表すとわかりやすくなります.
type TYouso = (Kara,Maru,Batu);
これを列挙型といいます.
盤のデータ構造
合わせて次のようになります.
type
TBangou = 1..9;
TYouso = (Kara,Maru,Batu);
TBan
= array [TBangou] of TYouso;
var
Ban : TBan;
盤の表示
枠の線を +-|を使って書きます.
+-+-+-+
| |×| |
+-+-+-+
| |○| |
+-+-+-+
|○| | |
+-+-+-+
1行目
2行目
3行目
4行目
5行目
6行目
7行目
盤の表示
9つの空の枡を一直線に書くのは簡単です.
for N := 1 to 9 do
begin
Write(‘|’); //左の線
Write(‘ ’);
end;
WriteLn(‘|’);
//最後の線
実行すると
| | |
|
|
|
|
|
|
|
盤の表示
空白の代わりにN番目の要素を書くようにします.
for N := 1 to 9 do
begin
Write(‘|’);
YousoWoKaku(N);
end;
WriteLn(‘|’);
実行すると
|
|×|
|
|○|
|○|
|
|
盤の表示
3枡書いたら右の線を書いて改行
するようにします.
for N := 1 to 9 do
begin
Write(‘|’);
YousoWoKaku(N);
if N mod 3 = 0
then WriteLn(‘|’);
end;
実行すると
| |×|
| |○|
|○| |
|
|
|
盤の表示
横の線を書くようにします.
WriteLn(‘+-+-+-+’);
for N := 1 to 9 do
begin
Write(‘|’);
YousoWoKaku(N);
if N mod 3 = 0
then begin
WriteLn(‘|’);
WriteLn(‘+-+-+-+’);
end;
end;
実行すると
+-+-+-+
| |×| |
+-+-+-+
| |○| |
+-+-+-+
|○| | |
+-+-+-+
要素を書く
要素は3種類あるので,場合分け(case分岐)
を使います.
case Ban[N] of
Kara : Write(‘ ’);
Maru : Write(‘○’);
Batu : Write(‘×’);
end;
どこに置くか
手番のプレイヤーに,どこに置くか訊きます.
正しい番号を入れるまで,繰り返し訊かないと
いけません.
どこに置くか
repeatループを使った例
repeat
Write(‘どこに置きますか [1~9] ? ’);
ReadLn(N);
until (N in [1..9]) and (Ban[N] = Kara);
Result := N;
実行すると
どこに置きますか [1~9] ? 0
どこに置きますか [1~9] ?
どこに置くか
whileループを使った例
Write(‘どこに置きますか [1~9] ? ’);
ReadLn(N);
while not (N in [1..9]) or (Ban[N] <> Kara) do
begin
WriteLn(‘そこは置けません’);
Write(‘どこに置きますか [1~9] ? ’);
ReadLn(N);
end;
Result := N;
実行すると
どこに置きますか [1~9] ? 0
そこは置けません
どこに置きますか [1~9] ?
集合を使うと便利
整数Nが 1~9 の数であるかの判定.
不等式を使うと
(1 <= N) and (N <= 9)
集合を使うと
N in [1..9]
これは,数学での式
N ∈ {1,2,3,4,5,6,7,8,9}
と同じ意味です.
集合を使うと便利
「M月が大の月(31日まである月)か」を
不等式で書くと
(M=1) or (M=3) or (M=5) or (M=7) or
(M=8) or (M=10) or (M=12)
ですが,集合で書くと
M in [1,3,5,7,8,10,12]
と簡潔でわかりやすくなります.
集合を使うと便利
「M月とN月が両方とも大の月か」を
不等式で書くと,とても長くなります.
集合で書くと
[M,N] <= [1,3,5,7,8,10,12]
と簡単です.
これは,数学での式
{M,N}⊆{1,3,5,7,8,10,12}
と同じ意味です.
繰り返しの条件
repeatループでは終了条件を書き,
whileループでは継続条件を書きます.
ちょうど反対(否定)になります.
 repeat
~
until (N in [1..9]) and (Ban[N] = Kara);
 while not (N in [1..9]) or (Ban[N] <> Kara) do
begin
~
end;
ゲームの終了条件
とりあえず,勝敗は気にしないで,すべての
枡が埋まるまで(9手)続けるとします.
Tesuu := 0;
repeat
Inc(Tesuu); // Tesuu := Tesuu+1; と同じ
~
until Tesuu = 9;
Boolean(論理値)
次のプログラムを実行してみてください.
var
Tesuu : Integer;
begin {Main}
Tesuu := 0;
repeat
Inc(Tesuu);
WriteLn(Tesuu:2, (Tesuu=9):6);
until Tesuu=9;
ReadLn;
end.
Boolean(論理値)
実行しましたか.
Tesuu の値は
Tesuu=9 の値は
1 2 …9
9=1 9=2 … 9=9
で,整数値(Integer)です. すなわち
False False … True
で,論理値(Boolean)です.
ゲームの終了条件
勝敗は,今○か×を置いたことによって,それ
が3つ並んだら「勝った」とわかります.
変数 Katta : Boolean を使うことにします.
Tesuu := 0;
repeat
Inc(Tesuu);
~
Katta := Naranda(Basyo);
until (Tesuu = 9) or Katta;
ゲームの終了条件
function Naranda(N : TBangou) : Boolean;
は,今 Ban[N] に○か×を置いたところで,それ
が3つ並んだか調べる論理値関数です.
Nによって並ぶ筋が異なるので場合分けして調べ
ます.
case N of
1 : Onaji(1,2,3) or Onaji(1,4,7)
or Onaji(1,5,9);
~
end;
ゲームの終了条件
関数 Naranda を完成させてください.
問題
procedure TebanKoutai(var Player : TPlayer);
は case分岐を使っていますが,二分岐なので
if分岐でも書けます.
if分岐に書き換えてください.
問題
盤の線を罫線(┌ ─ など)を使うともっときれいに
書けます.
┌─┬─┬─┐
| |×| |
├─┼─┼─┤
| |○| |
├─┼─┼─┤
|○| | |
└─┴─┴─┘
1行目
2行目
3行目
4行目
5行目
6行目
7行目
罫線を使うように改良してください.
「けいせん」を変換していろいろな線が選べます.
7行目が3,5行目と異なるので,ちょっと工夫しないと
いけません.