この記事はC言語演習問題集の問題の回答です。まだ問題読んでないという方は下記記事の「二次元配列を回転して表示させよう」をぜひ見てから読んでください。
C言語応用問題集考え方
まず2次元配列を90度・180度・270度回転させて表示する考え方について解説しておきます。
配列を90度の倍数の回転した上での表示は、複雑な計算は必要なく、回転した状態で表示できるように表示する順番を変更するだけで実現することができます。
例えば1次元配列を180度回転して表示することを考えると、単に配列を逆順に表示してやれば良いだけです。
2次元配列の回転も同様です。
ただし、1次元配列とは異なり、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度回転なので実際には回転はしない)の並びは下のようになります。
したがって、この並び順で表示するためには、配列 a
に下図の順でアクセスし、この順で数値を出力すれば良いです。
回転なしの場合はまずは配列の一番左上から右方向に一つずつアクセスして出力し、右端まで出力したら、1つ下の要素の左端に移動。さらにこれを配列の一番下の要素を出力し終わるまで繰り返すことで表示することが可能です。
プログラムで書くと下のようなループ文になります。
for(n = 0; n < N; n++){
for(m = 0; m < M; m++){
printf("%d " , a[n][m]);
}
printf("\n");
}
printf("\n");
スポンサーリンク
90度回転
90度回転の場合、回転後の配列 a
の並びは下のようになります。
したがって、この並び順で表示するためには、配列 a
へ下図の順でアクセスし、この順で数値を出力すれば良いです。
90度回転の場合は配列 a
の左下からアクセスして出力するようになります。そこから上方向に移動して、上端に来たら右に方向に一つ移動して下から出力するのを繰り返します。
これを行うためのポイントは二つあります。
一つ目はアクセス方向が下ではなく上方向であることです。0度の時は上から下方向に移動していましたがここでは反対向きに移動させる必要があります。配列の添字として具体的に考えると、通常の反対向きの順でアクセスするためには、N - 1
から 0
まで 1
ずつ減らしながらアクセスします。
ポイントの二つ目は、2重ループのうち、内側のループは横方向ではなく縦方向のループになることです。これにより、まず縦方向にアクセスし、1列分アクセス完了後に横方向へ移動することが可能になります。これはループ文ではまず内側のループが実行されますためです。ですので、内側のループに用いる識別子を配列の縦方向の添字として考える必要があります。
これら二つのポイントを踏まえて作成したループ文が下記です。
ループの内側でインクリメントしている m
が、配列 a
の縦方向へアクセスする添字になっていること、縦方向へアクセスする添字は N - 1
から減らすようにすることで上方向への移動を実現していることに注目してください。
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
の並びは下のようになります。
したがって、この並び順で表示するためには、配列 a
に下図の順でアクセスし、この順で数値を出力すれば良いです。
180度回転では0度回転時の逆順でアクセスする必要があります。つまり右下から左上方向にアクセスをしていくことになります。
逆順でアクセスするために、90度回転時に説明した1つ目のポイントを考慮してプログラムを作成する必要があります。90度回転時は縦方向のみ逆順アクセスになりましたが、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
の並びは下のようになります。
したがって、この並び順で表示するためには、配列 a
へ下図の順でアクセスし、この順で数値を出力すれば良いです。
90度回転のときに説明したポイント2つ両方を考慮してプログラミングする必要があります。270度回転の場合は縦方向に関しては上から下の順(つまり順方向)にアクセスすれば良いですが、横方向に関しては右から左の順(つまり逆方向)にアクセスする必要がありますので、配列 a
の2つ目の添え字は M - 1
から 0
に変化するようにする必要があります。
これらを考慮して作成したループ文が下のようになります。
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度回転後の配列は元々の配列に比べて縦横のサイズが逆になる点に注意してください。
オススメの参考書(PR)
C言語学習中だけど分からないことが多くて挫折しそう...という方には、下記の「スッキリわかるC言語入門」がオススメです!
まず学習を進める上で、参考書は2冊持っておくことをオススメします。この理由は下記の2つです。
- 参考書によって、解説の仕方は異なる
- 読み手によって、理解しやすい解説の仕方は異なる
ある人の説明聞いても理解できなかったけど、他の人からちょっと違った観点での説明を聞いて「あー、そういうことね!」って簡単に理解できた経験をお持ちの方も多いのではないでしょうか?
それと同じで、1冊の参考書を読んで理解できない事も、他の参考書とは異なる内容の解説を読むことで理解できる可能性があります。
なので、参考書は2冊持っておいた方が学習時に挫折しにくいというのが私の考えです。
特に上記の「スッキリわかるC言語入門」は、他の参考書とは違った切り口での解説が豊富で、他の参考書で理解できなかった内容に対して違った観点での解説を読むことができ、オススメです。題名の通り「なぜそうなるのか?」がスッキリ理解できるような解説内容にもなっており、C言語入門書としてもかなり分かりやすい参考書だと思います。
もちろんネット等でも色んな観点からの解説を読むことが出来ますので、分からない点は別の人・別の参考書の解説を読んで解決していきましょう!もちろん私のサイトも参考にしていただけると嬉しいです!
入門用のオススメ参考書は下記ページでも紹介していますので、こちらも是非参考にしていただければと思います。
https://daeudaeu.com/c_reference_book/