2009年9月29日火曜日

第14回 for文③ 多重ループ

お題:
原点を通る一次関数(y=a*x)のグラフを■で表現する。グラフはx,y軸が正の領域(第一象限)のみ。
①初めにグラフの規模(n*n)を尋ね、設定する。nは整数で、n<100。
②一次関数の傾きaを尋ね、設定する。aは小数点にも対応する。
③グラフを描く。

プログラム実行例:
imageimageimage

必須事項:
・for文を2回以上使う事

注意事項:
・if文なども駆使してください
・全角記号□と■は半角数字の2個分のスペースです
・表現方法はたくさんあるので、上の実行例と全く同じにしなくても大丈夫です

解答は10月3日に掲載します。それまでにプログラムを作成し、
・プログラム文
・その実行ファイル
をメールに添付して以下のアドレスに送ってください。

解答、質問はこちらまで
cosmo-cleaner@za.pial.jp

---------------------------------------------------------------

解答例

1

2
3
4

5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32

#include <stdio.h>

int main () {
    int n,x,y;
    double a;

    puts("グラフの規模は? n×n");
    printf("n=");    scanf("%d",&n);
    printf("\n直線の傾きは?\n");
    printf("a=");    scanf("%lf",&a);

    for(y=n;y>=0;y--){
        if (y > 9)
            printf("%d",y);
        else
            printf(" %d",y);
       for(x=0;x<=n;x++){
            if (a*x >= y && a*x <y+1){
                printf("■");
            }
            else if (x >= y/a && x - 1< y/a)
                printf("■");
            else
                printf("□");
        }
        printf("\n");
    }

    printf("  ");
    for(x=0;x<=n;x++) {
        if (x < 10)
            printf("%d ",x);
        else
            printf("%d",x);
    }
}

実行例は上と同じです

解説

今回使った変数とその役割

n
x
y

a
グラフの規模(x,y軸の表示する範囲)
xの値
yの値
直線の傾き

紫のfor文はy軸で、青いfor文はx軸です。
グラフはy軸正方向(上)から描いていくので、for文も上からに設定します。なので9行目の通り、y=nから始まり、y=0になるまで1づつ降りて行きます。

青いfor文はx=0からx=nまで1づつ増やしながら■か□を1つづつ表示していきます。
考え方としては、下の図のようなイメージです。
image

現在紫のfor文で実行中のyの値とa*xがぶつかった所に■、それ以外には□を表示します。yは整数なのでa*xが小数の時にも対応するため、15行目のように、”1”の大きさの範囲を設けます。

18行目は直線が途切れなく表示されるためのif文です。これが無いと以下のようになります。

image

なぜ空白があくかというと、下の図のようなイメージです。

image

この時、現在のyに注目し、図の緑の点が現在のxの範囲に入っているかどうかを検討します。それが18行目です。
これさえあれば15行目はいらないのでは?と思うかもしれませんが、18行目だけだと傾きaが1以下の時に、同じような空白が出る現象が起こります。

答えられる範囲で質問いつでも受け付けます。
cosmo-cleaner@za.pial.jp

2 件のコメント:

  1. いつも勉強させていただいています。
    とてもいい例題ですね。とても勉強になりました。

    返信削除
  2. ありがとうございます
    これからの励みになります!
    C言語が着実に身に付くような問題と分かりやすい解答を
    心掛けていこうと思うので
    よろしくお願いします。

    返信削除