29_構造体の練習課題

構造体の練習課題(C言語・コンソール)

構造体を利用する練習問題を2問提示します。 どちらも「構造体を使う前のコード」を確認し、構造体で書き換える内容です。


練習課題 1 ショップ在庫(構造体前 → 構造体へ)

構造体を使う前のコード

ファイル名: shop_before.c

#include <stdio.h>

int main(void) {
    char name0[20] = "ポーション";
    int  price0 = 50;
    int  stock0 = 5;

    char name1[20] = "ハーブ";
    int  price1 = 30;
    int  stock1 = 3;

    char name2[20] = "エーテル";
    int  price2 = 120;
    int  stock2 = 2;

    int choice;
    int qty;
    int total = 0;

    printf("=== お店 ===\n");
    printf("0:%s(%dG) 在庫:%d\n", name0, price0, stock0);
    printf("1:%s(%dG) 在庫:%d\n", name1, price1, stock1);
    printf("2:%s(%dG) 在庫:%d\n", name2, price2, stock2);

    printf("買う番号(0-2): ");
    if (scanf("%d", &choice) != 1) return 0;
    printf("個数: ");
    if (scanf("%d", &qty) != 1) return 0;

    if (choice == 0) {
        if (qty > 0 && qty <= stock0) {
            stock0 = stock0 - qty;
            total  = total  + price0 * qty;
        } else { printf("在庫不足\n"); }
    } else if (choice == 1) {
        if (qty > 0 && qty <= stock1) {
            stock1 = stock1 - qty;
            total  = total  + price1 * qty;
        } else { printf("在庫不足\n"); }
    } else if (choice == 2) {
        if (qty > 0 && qty <= stock2) {
            stock2 = stock2 - qty;
            total  = total  + price2 * qty;
        } else { printf("在庫不足\n"); }
    } else {
        printf("番号が不正です\n");
    }

    printf("合計=%dG\n", total);
    return 0;
}

課題:構造体で書き換えなさい
提出ファイル名(構造体版):shop_struct.c

ヒント(困ったときに開く)
模範解答(完成後に確認すること)
#include <stdio.h>
#include <string.h>

typedef struct {
    char name[20];
    int  price;
    int  stock;
} Item;

void print_menu(Item a[], int n) {
    int i;
    printf("=== お店 ===\n");
    for (i = 0; i < n; i++) {
        printf("%d:%s(%dG) 在庫:%d\n", i, a[i].name, a[i].price, a[i].stock);
    }
}

/* 購入処理:更新後の Item を返す */
Item buy(Item it, int qty, int *total) {
    if (qty > 0 && qty <= it.stock) {
        it.stock  = it.stock - qty;
        *total   = *total + it.price * qty;
    } else {
        printf("在庫不足\n");
    }
    return it;
}

int main(void) {
    Item items[3];
    int choice, qty, total;

    strcpy(items[0].name, "ポーション");  items[0].price = 50;  items[0].stock = 5;
    strcpy(items[1].name, "ハーブ");      items[1].price = 30;  items[1].stock = 3;
    strcpy(items[2].name, "エーテル");    items[2].price = 120; items[2].stock = 2;
    total = 0;

    while (1) {
        print_menu(items, 3);
        printf("買う番号(0-2, -1で終了): ");
        if (scanf("%d", &choice) != 1) break;
        if (choice == -1) break;
        if (choice < 0 || choice > 2) { printf("番号が不正です\n"); continue; }
        printf("個数: ");
        if (scanf("%d", &qty) != 1) break;
        items[choice] = buy(items[choice], qty, &total);
    }

    printf("合計=%dG\n", total);
    return 0;
}

練習課題 2 5×5フィールドの移動(構造体前 → 構造体へ)

構造体を使う前のコード

ファイル名: field_before.c

#include <stdio.h>

int main(void) {
    int width  = 5;
    int height = 5;
    int px, py;  /* プレイヤー座標 */
    int ex, ey;  /* 敵の座標 */
    char key;
    int x, y;

    px = 0;  py = 0;
    ex = 4;  ey = 4;

    printf("w/a/s/d で1歩移動\n");
    printf("入力: ");
    if (scanf(" %c", &key) != 1) return 0;

    if      (key == 'w') py = py - 1;
    else if (key == 's') py = py + 1;
    else if (key == 'a') px = px - 1;
    else if (key == 'd') px = px + 1;

    if (px < 0)          px = 0;
    if (px > width  - 1) px = width  - 1;
    if (py < 0)          py = 0;
    if (py > height - 1) py = height - 1;

    for (y = 0; y < height; y++) {
        for (x = 0; x < width; x++) {
            if      (x == px && y == py) printf("P");
            else if (x == ex && y == ey) printf("E");
            else printf(".");
        }
        printf("\n");
    }

    if (px == ex && py == ey) {
        printf("遭遇!\n");
    }
    return 0;
}

課題:構造体で書き換えなさい
提出ファイル名(構造体版):field_struct.c

構造体のネスト: ActorPos 型のメンバ pos を持ちます。 プレイヤーの x 座標へのアクセスは player.pos.x と2段階のドットで辿ります。
ヒント(困ったときに開く)
模範解答(完成後に確認すること)
#include <stdio.h>
#include <string.h>

typedef struct { int x; int y; } Pos;

typedef struct {
    char name[16];
    Pos  pos;
} Actor;

/* 移動処理:更新後の Actor を返す */
Actor move(Actor a, char key, int w, int h) {
    if      (key == 'w') a.pos.y--;
    else if (key == 's') a.pos.y++;
    else if (key == 'a') a.pos.x--;
    else if (key == 'd') a.pos.x++;
    if (a.pos.x < 0)     a.pos.x = 0;
    if (a.pos.x > w - 1) a.pos.x = w - 1;
    if (a.pos.y < 0)     a.pos.y = 0;
    if (a.pos.y > h - 1) a.pos.y = h - 1;
    return a;
}

/* 盤面描画 */
void draw(int w, int h, Actor p, Actor e) {
    int x, y;
    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            if      (x == p.pos.x && y == p.pos.y) printf("P");
            else if (x == e.pos.x && y == e.pos.y) printf("E");
            else printf(".");
        }
        printf("\n");
    }
}

int main(void) {
    Actor player, enemy;
    char key;
    int w = 5, h = 5;

    strcpy(player.name, "player");  player.pos.x = 0;  player.pos.y = 0;
    strcpy(enemy.name,  "enemy");   enemy.pos.x  = 4;  enemy.pos.y  = 4;

    printf("w/a/s/d で1歩移動\n");
    printf("入力: ");
    if (scanf(" %c", &key) != 1) return 0;

    player = move(player, key, w, h);
    draw(w, h, player, enemy);

    if (player.pos.x == enemy.pos.x && player.pos.y == enemy.pos.y) {
        printf("遭遇!\n");
    }
    return 0;
}