「早くゲーム作らせろ!」って思ってる人、いるかもしれませんが、基本をおさえるまでゲームには入りません。次の章まで待ちましょう。
今回は、「じゃんけん」を作ります。
いままで文字を表示する方法はShowMessageしかやってませんでした。しかし、タイトルロゴとかを表示するのにShowMessageとかを使うのはどうなのって感じですよね?そこで、わざわざメッセージダイアログを表示させずにFormに直接文字を表示させる方法としてTLabelを使うというのがあります。
「じゃんけんゲーム」と表示させるためにTLabelを使ってみましょう。
まず、TButtonの三つ左の「A」と書かれたコンポーネントをクリックして、Tbuttonと同じ要領で貼り付けてください。これでTLabelが使えるようになりました。
最初は小さな文字で「Label1」と表示されてるだけだと思いますので、Captionプロパティを「じゃんけん」とでもしてください。次に、文字の大きさを変更するためにFontプロパティのところをダブルクリックして文字の大きさの設定をしてください。
ボタンを三個用意して、Captionをそれぞれ「グー」「チョキ」「パー」にしてください。また、判りやすくするためにNameプロパティを「guu」「tyoki」「paa」にしてください。
次に、イベントの処理になります。じゃんけんにはいわゆる「三竦み」(さんすくみ)があり、相手との勝敗をif文で判定しなければならないのですが、とりあえずまず「ShowMessage('貴方の勝ちです')」と表示させるようにしてください。やり方はわかりますね?
とりあえず実行してみるわけですが、絶対勝ってしまうためじゃんけんになっていません。勝敗の判定はどうすればいいのでしょうか?とりあえず構想を練ってみると
///じゃんけん構想…これは実行できません。
//グーを出した時
procedure TForm1.guuClick(Sender: TObject);
begin
if <相手> = <グー> then ShowMessage('あいこです');
if <相手> = <チョキ> then ShowMessage('貴方の勝ちです');
if <相手> = <パー> then ShowMessage('貴方の負けです');
end;
//チョキを出した時
procedure TForm1.tyokiClick(Sender: TObject);
begin
if <相手> = <グー> then ShowMessage('貴方の負けです');
if <相手> = <チョキ> then ShowMessage(あいこです');
if <相手> = <パー> then ShowMessage('貴方の勝ちです');
end;
//パーを出した時
procedure TForm1.paaClick(Sender: TObject);
begin
if <相手> = <グー> then ShowMessage('貴方の勝ちです');
if <相手> = <チョキ> then ShowMessage('貴方の負けです');
if <相手> = <パー> then ShowMessage('あいこです');
end;
まあ、大体こんなんだろうという構想は立てられます。
ところで今回いきなり「//グーを出した時」などといったものが出てきましたが、これはコメントです。行中で//を書くとコンパイラはその後の文字は無視してくれます。{と}や、(*と*)で囲んでも同様です。(一部無視されない文字もあります)あとでみてもだれがみてもわかるプログラムにするために、コメントはまめに書きましょう。まあ書きすぎるのも問題ですが…
さて、これを作るに当たって一つの問題があります。それは「じゃんけんの時相手の手を記憶するコンポーネント、プロパティが存在しない」ということです。相手の出した手を記憶するものを自分で作る必要があります。そこで出てくるのが「変数」というものです。
変数とは数字や文字を入れる箱のようなもので、いわゆる一時記憶の役割をします。
用途に沿って整数用、実数用、文字用などさまざまなタイプの変数が存在します。
このじゃんけんゲームでは相手の手を記憶するためにInteger型の変数を使います。
変数を利用するには使う前にコンピューターに対して「この型をした、こんな名前の変数を使います」と宣言しなければなりません。
宣言は
Var
変数名,変数名:変数の型;
このように行います。(変数名の間にカンマを書けば複数の変数を同時に宣言することができます)
はじめのうちは{$R *.dfm}
の下で宣言するのが良いでしょう。
{$R *.dfm}
Var
Mario_Hp,Mario_X,Mario_Y : integer;
ただ、procedureの後、beginの前にも書く事ができることを知っておいた方がいいです。(これをローカル変数といいます)主な用途は後で述べるFor文ですね。
procedure TForm1(〜略〜)
var
Mario_Hp,Mario_X,Mario_Y : integer;
begin (〜略〜)
スプーではありません。スコープです。
Wikipediaに結構わかりやすい説明が載ってたんで転載しときます。
プログラミングで、ある変数や関数が特定の名前で参照される範囲のこと。スコープ外にある名前は言語上存在しないのと同じ事である。このとき名前は「見えない」といわれる。プログラミングで予期しない誤作動を避けるためにも、必要のない名前はできるだけ参照されないことが望ましい(大域変数の危険性)。適切なスコープの判断は正しいプログラムを構成する上で重要である。
Delphiだと
var
a:integer;
implementation
{$R *.dfm}
var
b:integer;
procedure TForm1.Button1Click(Sender: TObject);
var
c:integer;
begin
end;
var
d:integer;
procedure TForm1.Button2Click(Sender: TObject);
var
e:integer;
begin
end;
aはこのユニットにリンクしてるユニットすべてで使えます。bはButton1ClickとButton2Click等で使えますが、cはButton1Clickでしか使えません。dはこれが宣言された後の場所…つまりButton2Click等でしかつかえません。eはButton2Clickだけです。
自分が作った変数を他人が間違えて使わないように、スコープには常に気をつける必要があります。
右辺の計算結果を左辺の変数に代入します。右辺の計算結果を左辺の変数に対してに代入するためx+10:=152-51;
などといったことはできません。
A:=100+A;
こうすればAにはA+100が代入され、結果的にAは100増えます。
代入をする時は、原則として同じ型同士のものでなければなりません(代入元の型が代入先の型に含まれる場合…小数型に整数を代入する場合等を除く)。
Mario_Hp:='ルイージ'
Mario_Hp:=0;
ちなみに、代入先が整数である場合、X:=X + 5;
はInc(X,5);
と書き換えができて、X:=X - 5;
はDec(X,5);
と書き換えられます。IncやDecを使った方がスマートになります。
name:='マリ'+'オ';
)。D:=15 div 7
《D=2
となります。》)M:=15 mod 7
《D=1
となります。》)いきなりバーッって書いちゃいましたが大丈夫ですかね?じゃんけんの話にもどります。
まず、はじめのうちは
と書いたように、{$R *.dfm}
の下で宣言するのが良いでしょう。{$R *.dfm}
の下に
{$R *.dfm}
var
Teki:integer;
と書いてください。これで「Teki」という名の変数ができました。練った構想を実際に書いてみましょう。
//0=グー、1=チョキ、2=パーとなっています。
//グーを出した時
procedure TForm1.guuClick(Sender: TObject);
begin
if Teki = 0 then ShowMessage('あいこです');
if Teki = 1 then ShowMessage('貴方の勝ちです');
if Teki = 2 then ShowMessage('貴方の負けです');
end;
//チョキを出した時
procedure TForm1.tyokiClick(Sender: TObject);
begin
if Teki = 0 then ShowMessage('貴方の負けです');
if Teki = 1 then ShowMessage(あいこです');
if Teki = 2 then ShowMessage('貴方の勝ちです');
end;
//パーを出した時
procedure TForm1.paaClick(Sender: TObject);
begin
if Teki = 0 then ShowMessage('貴方の勝ちです');
if Teki = 1 then ShowMessage('貴方の負けです');
if Teki = 2 then ShowMessage('あいこです');
end;
このプログラムを実行してみましょう。うまく実行できたものの、毎回相手の手がグーになってしまったかと思います。
何故毎回グーになったのかというと、Tekiに一度も代入してないため、初期値の0になってしまっているのです。これを防ぐためには、ボタンを押すたびにTekiに適当なランダムな数字を代入する必要があります。
ランダムな数字を呼び出すためにはRandom関数を使います。Random関数にランダムを呼び出す範囲を指定すれば、0からその長さぶんの間の数の乱数が選ばれます。
Random関数を付け加えると
//0=グー、1=チョキ、2=パーとなっています。
//グーを出した時
procedure TForm1.guuClick(Sender: TObject);
begin
Teki:=Random(3);///0から3の長さ…つまり0,1,2
if Teki = 0 then ShowMessage('あいこです');
if Teki = 1 then ShowMessage('貴方の勝ちです');
if Teki = 2 then ShowMessage('貴方の負けです');
end;
//チョキを出した時
procedure TForm1.tyokiClick(Sender: TObject);
begin
Teki:=Random(3);
if Teki = 0 then ShowMessage('貴方の負けです');
if Teki = 1 then ShowMessage('あいこです');
if Teki = 2 then ShowMessage('貴方の勝ちです');
end;
//パーを出した時
procedure TForm1.paaClick(Sender: TObject);
begin
Teki:=Random(3);
if Teki = 0 then ShowMessage('貴方の勝ちです');
if Teki = 1 then ShowMessage('貴方の負けです');
if Teki = 2 then ShowMessage('あいこです');
end;
こうなります。これでじゃんけんが完成しました。
このプログラムを何度も実行すればわかるかと重いますが、起動してから相手が出すパターンが毎回同じです。これはコンピュータが命令されたとおりにしか動かないため「適当な数字をえらぶ」ということができず、呼び出した回数を元に数を選んでしまうため完全なランダムにならないのです。
この問題を解決するためにはForm1のOnCreateイベントに「Randomize;」と一行付け足すだけで解決できます。Randomizeは呼び出した時刻によって乱数を初期化するもので、コンピュータが時間を元に数字を選ぶ→起動ごとにちゃんと違った数が選び出される…となるのです。
このプログラム、case文で次のようにまとめることができます。case文を使えばプログラムが読みやすくなるので、使える時は使った方が得です。跡で使わないといけない時も出てきます。
//グーを出した時
procedure TForm1.guuClick(Sender: TObject);
begin
case Random(3) of
0:ShowMessage('あいこです');
1:ShowMessage('貴方の勝ちです');
2:ShowMessage('貴方の負けです');
end;
end;
//チョキを出した時
procedure TForm1.tyokiClick(Sender: TObject);
begin
case Random(3) of
0:ShowMessage('貴方の負けです');
1:ShowMessage('あいこです');
2:ShowMessage('貴方の勝ちです');
end;
end;
//パーを出した時
procedure TForm1.paaClick(Sender: TObject);
begin
case Random(3) of
0:ShowMessage('貴方の勝ちです');
1:ShowMessage('貴方の負けです');
2:ShowMessage('あいこです');
end;
end;