🚀 シューティングゲーム - 解答と解説

課題4-2の要件

1. プログラムの実装 (shooting_game.c)

#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> #include <time.h> // 画面サイズ #define SCREEN_WIDTH 40 #define SCREEN_HEIGHT 20 // ゲーム要素の最大数 #define MAX_BULLETS 50 #define MAX_ENEMIES 10 // ゲームオブジェクトの構造体 typedef struct { int x, y; int active; } GameObject; // ゲーム状態の構造体 typedef struct { GameObject player; GameObject bullets[MAX_BULLETS]; GameObject enemies[MAX_ENEMIES]; int score; int gameOver; } GameState; // 関数プロトタイプ void initGame(GameState* game); void handleInput(GameState* game); void updateGame(GameState* game); void renderGame(GameState* game); void spawnEnemy(GameState* game); void fireBullet(GameState* game); int checkCollision(GameObject* obj1, GameObject* obj2); void clearScreen(); int main() { system("chcp 65001"); srand((unsigned int)time(NULL)); GameState game; initGame(&game); while (!game.gameOver) { if (_kbhit()) { handleInput(&game); } updateGame(&game); renderGame(&game); Sleep(50); // 20FPS } printf("\nGame Over!\nScore: %d\n", game.score); return 0; } void initGame(GameState* game) { // プレイヤーの初期化 game->player.x = SCREEN_WIDTH / 2; game->player.y = SCREEN_HEIGHT - 2; game->player.active = 1; // 弾と敵の初期化 for (int i = 0; i < MAX_BULLETS; i++) { game->bullets[i].active = 0; } for (int i = 0; i < MAX_ENEMIES; i++) { game->enemies[i].active = 0; } game->score = 0; game->gameOver = 0; } void handleInput(GameState* game) { char key = _getch(); switch (key) { case 'a': if (game->player.x > 0) game->player.x--; break; case 'd': if (game->player.x < SCREEN_WIDTH - 1) game->player.x++; break; case ' ': fireBullet(game); break; case 'q': game->gameOver = 1; break; } } void updateGame(GameState* game) { // 敵の生成 if (rand() % 20 == 0) { spawnEnemy(game); } // 弾の移動 for (int i = 0; i < MAX_BULLETS; i++) { if (game->bullets[i].active) { game->bullets[i].y--; if (game->bullets[i].y < 0) { game->bullets[i].active = 0; } } } // 敵の移動 for (int i = 0; i < MAX_ENEMIES; i++) { if (game->enemies[i].active) { game->enemies[i].y++; if (game->enemies[i].y >= SCREEN_HEIGHT) { game->enemies[i].active = 0; game->gameOver = 1; } } } // 衝突判定 for (int i = 0; i < MAX_BULLETS; i++) { if (game->bullets[i].active) { for (int j = 0; j < MAX_ENEMIES; j++) { if (game->enemies[j].active) { if (checkCollision(&game->bullets[i], &game->enemies[j])) { game->bullets[i].active = 0; game->enemies[j].active = 0; game->score += 100; } } } } } } void renderGame(GameState* game) { clearScreen(); // 画面バッファの作成と初期化 char buffer[SCREEN_HEIGHT][SCREEN_WIDTH + 1]; for (int y = 0; y < SCREEN_HEIGHT; y++) { for (int x = 0; x < SCREEN_WIDTH; x++) { buffer[y][x] = ' '; } buffer[y][SCREEN_WIDTH] = '\0'; } // オブジェクトの描画 buffer[game->player.y][game->player.x] = 'A'; for (int i = 0; i < MAX_BULLETS; i++) { if (game->bullets[i].active) { buffer[game->bullets[i].y][game->bullets[i].x] = '|'; } } for (int i = 0; i < MAX_ENEMIES; i++) { if (game->enemies[i].active) { buffer[game->enemies[i].y][game->enemies[i].x] = 'V'; } } // 画面の描画 printf("Score: %d\n", game->score); for (int y = 0; y < SCREEN_HEIGHT; y++) { printf("%s\n", buffer[y]); } } void spawnEnemy(GameState* game) { for (int i = 0; i < MAX_ENEMIES; i++) { if (!game->enemies[i].active) { game->enemies[i].x = rand() % SCREEN_WIDTH; game->enemies[i].y = 0; game->enemies[i].active = 1; break; } } } void fireBullet(GameState* game) { for (int i = 0; i < MAX_BULLETS; i++) { if (!game->bullets[i].active) { game->bullets[i].x = game->player.x; game->bullets[i].y = game->player.y - 1; game->bullets[i].active = 1; break; } } } int checkCollision(GameObject* obj1, GameObject* obj2) { return obj1->x == obj2->x && obj1->y == obj2->y; } void clearScreen() { system("cls"); }

2. プログラムの解説

2.1 データ構造