第2章21 for文で繰り返し処理を作る@イチからゲーム作りで覚えるC言語

イチからゲーム作りで覚えるC言語
連載ページ一覧へ
2章22 繰り返し処理のネスト構造と break、continue などのジャンプ文
NEXT : 2章22 繰り返し処理のネスト構造と break、continue などのジャンプ文
2章20 do~while文で繰り返し処理を作る : PREV

この記事でやること

前回はプロジェクト「0160_doWhile」を新しく作り、do~while文についてお話ししました。
今回は、新しくプロジェクト「0170_for」を作り、繰り返し処理を行うfor文についてお話します。この書き方を知っていることで、特定の処理をループ(繰り返し)させることで同じ処理を何度も書く必要がなくなります。

なお、繰り返し処理はC言語で幾つかあります。下の順番でお話をしたいと思います。

  1. while ( 繰り返す条件 ) {… 繰り返す内容 …}
  2. do { … 繰り返す内容 … } while ( 繰り返す条件 )
  3. for ( 最初の処理 ; 繰り返し条件 ; 繰り返し完了時の処理 ) {…繰り返す内容… } ←ココのお話
  4. 繰り返し処理の多重構造と break、continue などのジャンプ文
この記事はゆる~くC言語でコンソールゲームを作りながらプログラミングを学ぶための連載記事です。シリーズものですので記事の一覧はこちらを参照してくださいね。

繰り返し処理を行うプログラム

繰り返し処理をくみこんだソースコードを実際にプログラムを動かして結果を見てみましょう。

#include <stdio.h>
int main() {
 int tairyoku;
 int lv = 5;
 char namae[] = "ぷらんく";
 printf("%s は現在レベル %d です。", namae );
 printf("今後の成長はこんな感じ。\n", lv);
 for (int i = lv; i < lv + 5; i++) {
   tairyoku = i * 5 + 50;
   printf("レベル %d で体力が %d になります。\n", i, tairyoku );
 }
}

コピペなりして、実行してみて下さい。

ぷらんく は現在レベル 5 です。今後の成長はこんな感じ。
レベル 5 で体力が 75 になります。
レベル 6 で体力が 80 になります。
レベル 7 で体力が 85 になります。
レベル 8 で体力が 90 になります。
レベル 9 で体力が 95 になります。

こんな結果になりました。
プレイヤーの今のレベルと、今のレベル +5 未満(未満なので、レベル9まで)の体力を計算して成長具合を出しています。

for文を使った繰り返し処理の書き方

C言語ではプログラムの処理を繰り返すための for という文が用意されています。書き方はこんな感じ。

for ( 初期化処理 ; 繰り返し条件 ; 繰り返し完了時の処理 ) {…繰り返し処理…}

または、内容が一つだけであれば、下のように書くことができます。

for ( 初期化処理 ; 繰り返し条件 ; 繰り返し完了時の処理 } 繰り返す1文;

初期化処理には、繰り返しに関連する変数の初期化をしたりすることがおおいです。for 文に入るときに1回だけ実行されます。
今回のサンプルプログラムでは、変数 i に lv(プレイヤーのレベル)を代入しています。

繰り返し条件が合っている(偽、0、false 以外の数が入っている)ときに「繰り返し処理」を実行すべきと判定されます。もしここで、条件に合っていない場合は、for 文の終わりまでジャンプします。

※また特殊な例ですが、何もここに書かないときも「繰り返す」べしと判定されます。if 文の条件や、while文の繰り返し条件では何も書かないと文法エラーとなりますが、 for の繰り返し条件は書くことを省略することもできます。後の方で補足としてお話したいと思います。

「繰り返し完了時の処理」は、for文の{…繰り返し時の処理…}が終わったときに実行されます。ですので、次の繰り返し条件チェックが行われれる前に実行されます。

処理の流れはこんな感じです。

for文の処理の流れ

for文の処理の流れ

ソースコードを追ってみる

今回のサンプルコードを一行一行追ってみましょう!
6行目までは変数の宣言と初期化をしているだけですね。

 printf("%s は現在レベル %d です。", namae , lv);
 printf("今後の成長はこんな感じ。\n");

6~7行目でプレイヤーのステータス(レベル)を表示しています。
この時点では、それぞれの変数はこんな内容になっています。

  • int 型変数の tairyoku は宣言のみで初期化されていない。体力。
  • int 型変数の lv には 整数 5 が入っている。レベル。
  • char型配列の変数 namae には “ぷらんく” という文字列が入っている。プレイヤーの名前。

8 行目からが for文 (繰り返し文)となっています。

 for (int i = lv; i < lv + 5; i++) {
   tairyoku = i * 5 + 50;
   printf("レベル %d で体力が %d になります。\n", i, tairyoku );
 }

8行目で、まず 「for ( 初期化処理 ; 繰り返し条件 ; 繰り返し完了時の処理 )」のうち、初期化処理が実行されます。
ここでは、int型で変数 i に lv を代入しており、 i の中身は整数の 5 となります。

続いて、「for ( 初期化処理 ; 繰り返し条件 ; 繰り返し完了時の処理 )」のうち、繰り返し条件がチェックされます。
条件は「 i < lv + 5」ですので、「5 < 10」となり条件はあっています。
ここの条件が正しい(偽、0、false でない)ので、for (){…繰り返し処理…}の{ … 繰り返し処理 … }部分が実行されます。

 for (int i = lv; i < lv + 5; i++) {
   tairyoku = i * 5 + 50;
   printf("レベル %d で体力が %d になります。\n", i, tairyoku );
 }

9 行目では変数 tairyoku(体力)に i * 5 + 50 を代入しています。
初めてここに到達した時点では i は 5 ですので、式は 5 × 5 + 50 となり、
tairyoku には 75 が代入されます。

10行目は 9 行目で計算された体力を表示しています。

11行目で for 文の繰り返し処理が終わりとなります。
このとき、「for ( 初期化処理 ; 繰り返し条件 ; 繰り返し完了時の処理 )」の、「繰り返し完了時の処理」が実行されます。
今回は i++ と記載されており、これは i = i + 1 と同じ計算となります。
変数 i の中身を 1 増やしており、変数 i の中身は 5 から 6 になります。

その後、再びfor文の繰り返し条件チェックが行われます。
繰り返し条件のチェックのみ行い、合致するなら for 文の {…繰り返し処理…}がまた実行されます。
今回も「i < lv + 5」は「6 < 10」となり、繰り返し処理が始まりますね。

for文のループを繰り返した時の変数の動き

以下、繰り返した数と変数の中身の移り変わりを表にしてみます。

for 繰り返しと、変数の中身
for ループ回数コードの行i
計算するレベル
lv + 5
計算の上限
はじめて9行目 for開始510
12行 for{} 終了610
1回目9行目 for開始610
12行 for{} 終了710
2回目9行目 for開始710
12行 for{} 終了810
3回目9行目 for開始810
12行 for{} 終了910
4回目9行目 for開始910
12行 for{} 終了1010

ループの4回目で、レベル 9 の計算を行い、繰り返し処理を終えた時、for文の「繰り返し完了時の処理」が実行され i++ されます。
この後、for 文の条件「i < lv + 5」は「10 < 10」となり正しくない(偽)のため、for文のループ処理は終了し、for文の直後の13行目にジャンプし、プログラムは終了となります。

プレイヤーの体力計算式(デバッグ)

ちなみに、今回のプログラムで lv = 5 の箇所を 1 に、
for文の条件「 i < lv + 5 」を「i  < lv + 100」などとすると、プレイヤーがレベル 1 から 100 の間でどのように変化していくのかを出すことができます。
エクセルやGoogle Sphread Sheet などで、グラフにすることで体力の計算式がゲームバランスとして良さそうか、視覚的に確認ができるかと思います。

ぷらんくちゃん のレベルと体力の計算表

ぷらんくちゃん のレベルと体力の計算表

補足:for 文の初期化、条件、繰り返し完了時の処理の省略

この補足の項目はちょっとしたまとめです。このシリーズの中では実際にはこの書き方はあまりしない予定ですので、もうちょっと深く仕様をしりたいという方向けです。飛ばしてもらっても大丈夫です。
for 文は下のように書くことができると、このページの頭でお話したかと思います。

for ( 初期化処理 ; 繰り返し条件 ; 繰り返し完了時の処理 ) {…繰り返し処理…}

初期化処理も、繰り返し条件も、繰り返し完了時の処理も、いずれも省略することができます。

初期化処理の省略

初期化処理を for 文の前で別に行っているときや、特に初期化処理が必要ないときなどは、書かずに省略することができます。こんな風に書けます。

for (  ; 繰り返し条件 ; 繰り返し完了時の処理 ) {…繰り返し処理…}

簡単な例をみてみましょう。

for ( int i = 0 ; i < 100 ; i ++ ) { 繰り返し処理 }

などの場合は、下のようにも書くことができます。

int i = 0;
for ( ; i < 100 ; i ++ ) { 繰り返し処理 }

初期化処理を書くべき箇所には、なにも書いていませんね。

厳密には変数 i が使用できるスコープ(範囲)が違うなど差がありますが、スコープの話はまた今度したいと思います。

繰り返し条件の省略

無条件に繰り返しをするときは、条件を書く必要はありません。
繰り返し条件が 0 以外(偽以外、false以外)の時に繰り返し処理が実行されるので、下のように書くことで無条件に繰り返しができます。

for ( 初期化処理 ;  ; 繰り返し完了時の処理 ) {…繰り返し処理…}

for ( int i = 0 ; 1 ; i ++ ) { 繰り返し処理 }

これは下でも同じ意味となります。

for ( int i = 0 ; ; i ++ ) { 繰り返し処理 }

のように書くことで、for のループが繰り返されます。
無限ループが発生しないように、なにかの条件で break文などで、for 文から抜け出す処理などを書くなどすることが多いです。

繰り返し完了時の処理の省略

for 文の繰り返し完了時の処理についても省略することができます。
自分で for 文の{…繰り返し処理… } の最後に書くなどすることで、「繰り返し完了時の処理」を省略することがあります。

for ( 初期化処理 ; 繰り返し条件 ;  ) {…繰り返し処理…}

こちらも簡単な例を見てみましょう。

for ( int i = 0 ; i < 100 ; i++ ) { 繰り返し処理A }

こちらは、下のように書くこともできます。

for ( int i = 0 ; i < 100 ; ) {
 繰り返し処理A;
 i++;
}
もし、 for 文の{…繰り返し処理… } の最後に、i++ などの「繰り返し完了時の処理」を書いている時、continue 文でジャンプしたときは実行されないので注意しましょう。

while 文と同じ書き方

for 文の初期化処理と繰り返し完了時の処理を省略すると、 while 文と同じようなループ処理をさせることができます。

while ( 繰り返し条件 ) { … 繰り返し処理 … }

こちらは、下のようにも書くことができます。

for ( ; 繰り返し条件 ; ) { … 繰り返し処理 … }

for 文の中で使うジャンプ文

for の繰り返し処理の中で使えるジャンプ文のうち、break 文と continue 文をお話します。
といっても、前のページでお話した、while 文と同じです。

break 文

break 文は for文が終わった後にジャンプします。
処理の流れのイメージはこんな感じ。

for 文の中で break 文を使った時の流れ

for 文の中で break 文を使った時の流れ

continue文

continue 文は for 文の繰り返し処理の終了地点にジャンプします。
処理の流れのイメージはこんな感じ。

for 文の中で continue文 を使った時の流れ

for 文の中で continue文 を使った時の流れ

continue 文が実行されたときも、for 文の「繰り返し完了時の処理」は実行されるので注意しましょう。

あとがき

繰り返し処理の中では一番使うことが多い気がする for 文についてまとめました。
for 文と同じような機能は他のさまざまなプログラミング言語でも持っていることが非常に多いかと思います。

今回はここまで。おつかれさまでした。

イチからゲーム作りで覚えるC言語
連載ページ一覧へ
2章22 繰り返し処理のネスト構造と break、continue などのジャンプ文
NEXT : 2章22 繰り返し処理のネスト構造と break、continue などのジャンプ文
2章20 do~while文で繰り返し処理を作る : PREV

非常に参考になったサイトさまや、参考文献など

ページの更新履歴

更新日更新内容
更新なし