【C言語】2次元配列を回転して表示させよう

2次元配列を回転して表示する方法の解説ページアイキャッチ

この記事はC言語演習問題集の問題の回答です。まだ問題読んでないという方は下記記事の「二次元配列を回転して表示させよう」をぜひ見てから読んでください。

C言語練習問題のアイキャッチC言語応用問題集

考え方

まず2次元配列を90度・180度・270度回転させて表示する考え方について解説しておきます。

配列を90度の倍数の回転した上での表示は、複雑な計算は必要なく、回転した状態で表示できるように表示する順番を変更するだけで実現することができます。

例えば1次元配列を180度回転して表示することを考えると、単に配列を逆順に表示してやれば良いだけです。

1次元配列の180度回転

2次元配列の回転も同様です。

ただし、1次元配列とは異なり、2次元の配列である、つまり縦方向と横方向に広がる配列なので、この2つの方向を考慮しながら表示順を決定する必要があります。ここが難しいです…。

解答例

2次元配列を回転して表示させるプログラム例は下記のようになります。

2次元配列の回転
#include <stdio.h>

#define M 5 /* 列数 */
#define N 2 /* 行数 */

int main(void){

  int m;
  int n;

  int a[N][M] = {
    {1, 2, 3, 4, 5},
    {6, 7, 8, 9, 10}
  };

  /* 回転なし */
  printf("回転角度:0度\n");

  for(n = 0; n < N; n++){
    for(m = 0; m < M; m++){
      printf("%d " , a[n][m]);
    }
    printf("\n");
  }
  printf("\n");

  /* 90度回転 */
  /* 行数と列数が入れ替わる */
  printf("回転角度:90度\n");

  for(n = 0; n < M; n++){
    for(m = 0; m < N; m++){
      printf("%d " , a[N - 1 - m][n]);
    }
    printf("\n");
  }
  printf("\n");

  /* 180度回転 */
  printf("回転角度:180度\n");

  for(n = 0; n < N; n++){
    for(m = 0; m < M; m++){
      printf("%d " , a[N - 1 - n][M - 1 - m]);
    }
    printf("\n");
  }
  printf("\n");

  /* 270度回転 */
  /* 行数と列数が入れ替わる */
  printf("回転角度:270度\n");

  for(n = 0; n < M; n++){
    for(m = 0; m < N; m++){
      printf("%d " , a[m][M - 1 - n]);
    }
    printf("\n");
  }
  printf("\n");

  return 0;
}

スポンサーリンク

表示例

実行すると下記のように表示されます。90度、180度、270度回転して表示されていることが確認できると思います。

回転角度:0度
1 2 3 4 5 
6 7 8 9 10 

回転角度:90度
6 1 
7 2 
8 3 
9 4 
10 5 

回転角度:180度
10 9 8 7 6 
5 4 3 2 1 

回転角度:270度
5 10 
4 9 
3 8 
2 7 
1 6 

解説

プログラムとしては、配列にアクセスを行い、アクセスした順に数字を出力していくものになっています。そして、そのアクセスする順序を変更することで、配列の回転を実現しています。

頭で考えると難しいので図を書いて、配列にどういう順でアクセスしていくかをみてみましょう。

0度回転

まずは一番わかりやすい0度からみていきましょう。回転後の配列(0度回転なので実際には回転はしない)の並びは下のようになります。

0度回転時の配列の並び

したがって、この並び順で表示するためには、配列 a に下図の順でアクセスし、この順で数値を出力すれば良いです。

0度回転時の配列へのアクセス順序

回転なしの場合はまずは配列の一番左上から右方向に一つずつアクセスして出力し、右端まで出力したら、1つ下の要素の左端に移動。さらにこれを配列の一番下の要素を出力し終わるまで繰り返すことで表示することが可能です。

プログラムで書くと下のようなループ文になります。

0度回転時のループ
  for(n = 0; n < N; n++){
    for(m = 0; m < M; m++){
      printf("%d " , a[n][m]);
    }
    printf("\n");
  }
  printf("\n");

スポンサーリンク

90度回転

90度回転の場合、回転後の配列 a の並びは下のようになります。

90度回転時の配列の並び

したがって、この並び順で表示するためには、配列 a へ下図の順でアクセスし、この順で数値を出力すれば良いです。

90度回転時の配列へのアクセス順序

90度回転の場合は配列 a の左下からアクセスして出力するようになります。そこから上方向に移動して、上端に来たら右に方向に一つ移動して下から出力するのを繰り返します。

これを行うためのポイントは二つあります。

一つ目はアクセス方向が下ではなく上方向であることです。0度の時は上から下方向に移動していましたがここでは反対向きに移動させる必要があります。配列の添字として具体的に考えると、通常の反対向きの順でアクセスするためには、N - 1 から 0 まで 1 ずつ減らしながらアクセスします。

ポイントの二つ目は、2重ループのうち、内側のループは横方向ではなく縦方向のループになることです。これにより、まず縦方向にアクセスし、1列分アクセス完了後に横方向へ移動することが可能になります。これはループ文ではまず内側のループが実行されますためです。ですので、内側のループに用いる識別子を配列の縦方向の添字として考える必要があります。

これら二つのポイントを踏まえて作成したループ文が下記です。

ループの内側でインクリメントしている m が、配列 a の縦方向へアクセスする添字になっていること、縦方向へアクセスする添字は N - 1 から減らすようにすることで上方向への移動を実現していることに注目してください。

90度回転時のループ
  for(n = 0; n < M; n++){
    for(m = 0; m < N; m++){
      printf("%d " , a[N - 1 - m][n]);
    }
    printf("\n");
  }
  printf("\n");

180度回転

180度回転の場合、回転後の配列 a の並びは下のようになります。

180度回転時の配列の並び

したがって、この並び順で表示するためには、配列 a に下図の順でアクセスし、この順で数値を出力すれば良いです。

180度回転時の配列へのアクセス順序

180度回転では0度回転時の逆順でアクセスする必要があります。つまり右下から左上方向にアクセスをしていくことになります。

逆順でアクセスするために、90度回転時に説明した1つ目のポイントを考慮してプログラムを作成する必要があります。90度回転時は縦方向のみ逆順アクセスになりましたが、180度回転では縦方向だけでなく横方向も逆順にアクセスする必要があります。なのでループ文は下記のようになります。

180度回転時のループ
  for(n = 0; n < N; n++){
    for(m = 0; m < M; m++){
      printf("%d " , a[N - 1 - n][M - 1 - m]);
    }
    printf("\n");
  }
  printf("\n");

270度回転

270度回転の場合、回転後の配列 a の並びは下のようになります。

270度回転時の配列の並び

したがって、この並び順で表示するためには、配列 a へ下図の順でアクセスし、この順で数値を出力すれば良いです。

270度回転時の配列へのアクセス順序

90度回転のときに説明したポイント2つ両方を考慮してプログラミングする必要があります。270度回転の場合は縦方向に関しては上から下の順(つまり順方向)にアクセスすれば良いですが、横方向に関しては右から左の順(つまり逆方向)にアクセスする必要がありますので、配列 a の2つ目の添え字は M - 1 から 0 に変化するようにする必要があります。

これらを考慮して作成したループ文が下のようになります。

270度回転時のループ
  for(n = 0; n < M; n++){
    for(m = 0; m < N; m++){
      printf("%d " , a[m][M - 1 - n]);
    }
    printf("\n");
  }
  printf("\n");

スポンサーリンク

まとめ

このページでは2次元配列を回転して表示する方法について解説しました。

90度の倍数の回転であれば、今回解説したように表示する配列の要素の順を変更するだけで実現することができます。

また、今回は表示のみを行いましたが、回転後の配列を作成することも今回の考え方で行うことができます。

つまり、今回紹介した順序に従って、表示ではなく配列に値を格納するようにすれば回転後の配列の作成を行うこともできます。

ただし、90度や270度回転後の配列は元々の配列に比べて縦横のサイズが逆になる点に注意してください。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です