第2章22 繰り返し処理のネスト構造と break、continue などのジャンプ文@イチからゲーム作りで覚えるC言語

イチからゲーム作りで覚えるC言語
連載ページ一覧へ
2章23 疑似乱数を使おう
NEXT : 2章23 疑似乱数を使おう
2章21 for文で繰り返し処理を作る : PREV

この記事でやること

前回はプロジェクト「0170_for」を新しく作り、繰り返し処理を行うfor文についてお話ししました。
今回は、新しくプロジェクト「0180_nested_loop」を作り、繰り返し処理を入れ子にして書いたときの処理の流れについてお話します。この書き方を知っていることで、2Dや3Dゲームのデータ処理によくある、地形などの処理の流れの基礎がわかるかと思います。

なお、C言語の繰り返し処理は下の順番でお話ししています。

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

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

繰り返し処理をくみこんだソースコードを実際にプログラムを動かして結果を見てみましょう。プロジェクト「0180_nested_loop」を新しく作成し、ソースコード「NestedLoop.c」を作成してみてください。

#include <stdio.h>
int main() {
 for (int y = 0; y < 4; y++) {
   for (int x = 0; x < 10; x++) {
     printf("#");
   }
   printf("\n");
 }
}

このコードを実行してみるとこんな結果になったかと思います。

##########
##########
##########
##########

横方向に 10 個、縦方向に 4 個ぶんの「#」が表示されたかと思います。

繰り返し文の中に、さらに繰り返し文

前回までで for 文などの繰り返し文をお話しました。繰り返し文の中にさらに繰り返し文が入っています。このように繰り返し処理の中に繰り返し処理が入っているような構造をネスト構造(Nest)呼びます。

どのような処理の流れになるか、見てみましょう。
まず2つの for 文の実行範囲を赤と青で分けてみましょう。

for 文のネスト構造

for 文のネスト構造

赤色で囲んだ外側の for 文の中に、青色の for 文が入っています。
青色の for 文はどのような処理をしているかを確認してみます。

4~6行目までの for の中身は下の部分ですね。

   for (int x = 0; x < 10; x++) {
     printf("#");
   }

まず for 文に入るとき、変数 x に 0 を代入しています。
条件は「x < 10」で、その間は繰り返し処理を実行することになります。
そして、繰り返し完了時に、「x++」を行い、 x の中身を 1 増やしています。
つまり、このfor文は、printf(“#”); を 10 回行う処理となっていますね。

先のどの赤色と青色で分けたループ処理の中身に当てはめてみるとわかりやすくなるかと思います。

for文のネスト構造を見やすく置き換え

for文のネスト構造を見やすく置き換え

赤色の for 文の繰り返し処理の中身は、
「printf(“#”); で 記号#シャープを 10 回表示する処理」と「printf(“\n”); で改行する処理」
となります。これを y < 4 の間繰り返すことになります。
for の繰り返し完了時の処理で y++ しているので、4 回繰り返していることになりますね。

これで、横に 10 個 、縦に 4 個のシャープ記号(#)が表示されるプログラムができました。

ネスト構造の中での break や continue文

ネスト構造の中で break や continue 文を使った時はどのような流れになるでしょうか。

break でループ処理、Switch文からの脱出

break文は while文や for文などの繰り返し文や switch 文の中で使うことができます。
これらの文がネスト構造になっているとき、break 文を使うと、今いる場所の while や for の処理から一つ外側に抜けることができます。
下のようなイメージです。

for文のネスト構造の中でbreak文

for文のネスト構造の中でbreak文

今回のサンプルプログラムで見てみましょう。ハイライトの行(5~8行目)に if 文と break を追加しています。

#include <stdio.h>
int main() {
 for (int y = 0; y < 4; y++) {
   for (int x = 0; x < 10; x++) {
     if (y == 1) {
       printf("<-break!");
       break;
     }
     printf("#");
   }
   printf("\n");
 }
}

実行すると以下のような結果になります。

##########
<-break!
##########
##########

結果の2行目が変わっていますね。
5~8行目は if 文で囲まれています。 if ( y == 1 ) { ‥‥ } とあるので、 y が 1 の時のみ実行される処理となります。
外側の for ループ(3~12行)が 2 回目に入ったとき、 y は 1 になっていますね。
そして、内側の for ループ(4~10行)を実行しようとしたとき、 if ( y == 1 ) { ‥‥ } の条件に合致され、実行されます。
if 文の中で printf関数により「<-break!」というメッセージが表示されたのち、break文により、内側の for ループから抜け出します。
その後、11行目の printf関数で改行され、外側の for ループが継続されます。

continue でループ処理の継続

continue文についても break 文と同じで、今いる場所の for文や while文に対しての処理となります。こちらも、今回のサンプルプログラムに continue を追記したものをご参考までにのせておきます。

#include <stdio.h>
int main() {
 for (int y = 0; y < 4; y++) {
   for (int x = 0; x < 10; x++) {
     if (y == 1) {
       printf("<-break!");
       break;
     }
     if (x == 5) {
       printf("-");
       continue;
     }
     printf("#");
   }
   printf("\n");
 }
}

9~12行目のハイライトした箇所に新しく if 文と continue文を追加しています。
実行するとこのような結果になります。

#####-####
<-break!
#####-####
#####-####

結果で表示されている 10列 × 4行の「#」について、の6列目が「-」になっています。
今回追加した「if ( x == 5 )」の条件に合致するような箇所だけ、「-」を表示し、continue 文を実行しているためこのような結果となっています。

あとがき

ネスト構造を重ねて書く必要のあるプログラムはたくさんあります。ゲームでも2Dや3Dの画像関連のプログラムや、データのチェックなどで頻繁に使われます。
例えば、3Dのデータで存在する (x,y,z) 領域全てに対しての処理などは for 文を3つ重ねて書いたりすることが多いですし、Unity等のゲームエンジン画面表示時の Shader (描画の加工をする機能)の部分でも頻繁に使われたりします。

深~いネスト構造の中で、重たい処理をすると、それだけ繰り返し実行される処理が増えるのでゲーム全体がカクカクで重たくなったりします。

また、ソースコードが人間の目で読みづらくなるので、深いネスト構造を作るときは本当に必要なのかを考える必要がありますので、便利なのですが注意して扱う必要があります。

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

イチからゲーム作りで覚えるC言語
連載ページ一覧へ
2章23 疑似乱数を使おう
NEXT : 2章23 疑似乱数を使おう
2章21 for文で繰り返し処理を作る : PREV

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

ページの更新履歴

更新日更新内容
更新なし