9x9 サイズのマインスイーパーゲームの設計と実装

この記事では、9x9サイズのマインスイーパーゲームの設計と実装方法について説明します。ゲームは以下の3つのファイルで構成されます。

  • test.c: テストロジックの実装
  • game.c: ゲーム関数の実装
  • game.h: データ型や関数宣言

まず、ゲームボードを9x9に設定し、10個の地雷を配置します。ただし、配列の境界問題を避けるため、実際には11x11の配列を使用します。

ゲームの流れは以下の通りです:

  1. 2つの盤面を作成する:地雷を保存する盤面とプレイヤーが操作する盤面。
  2. 地雷をランダムに配置する。
  3. プレイヤーが座標を入力して地雷を探し、その周囲の地雷数を表示する。
  4. すべての安全なセルを開くまでゲームを続ける。

コードの実装

以下に、各ファイルの内容を示します。

game.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define MINE_COUNT 10

void InitializeBoard(char board[ROWS][COLS], int rows, int cols, char set);
void DisplayBoard(char board[ROWS][COLS], int row, int col);
void PlaceMines(char board[ROWS][COLS], int row, int col);
int CountAdjacentMines(char mine[ROWS][COLS], int x, int y);
void RevealCell(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

void InitializeBoard(char board[ROWS][COLS], int rows, int cols, char set) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            board[i][j] = set;
        }
    }
}

void DisplayBoard(char board[ROWS][COLS], int row, int col) {
    for (int i = 0; i <= col; i++) {
        printf("%d ", i);
    }
    printf("\n");
    for (int i = 1; i <= row; i++) {
        printf("%d ", i);
        for (int j = 1; j <= col; j++) {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }
}

void PlaceMines(char board[ROWS][COLS], int row, int col) {
    int count = MINE_COUNT;
    while (count) {
        int x = rand() % row + 1;
        int y = rand() % col + 1;
        if (board[x][y] == '0') {
            board[x][y] = '1';
            count--;
        }
    }
}

int CountAdjacentMines(char mine[ROWS][COLS], int x, int y) {
    return (mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] +
            mine[x][y - 1] + mine[x][y + 1] +
            mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0');
}

void RevealCell(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
    int x, y;
    int win = 0;
    while (win < row * col - MINE_COUNT) {
        printf("座標を入力してください: ");
        scanf("%d %d", &x, &y);
        if (x >= 1 && x <= row && y >= 1 && y <= col) {
            if (mine[x][y] == '1') {
                printf("残念ながら、あなたは爆発しました\n");
                DisplayBoard(mine, ROW, COL);
                break;
            } else {
                int count = CountAdjacentMines(mine, x, y);
                show[x][y] = count + '0';
                DisplayBoard(show, ROW, COL);
                win++;
            }
        } else {
            printf("入力が間違っています。再度入力してください。\n");
        }
    }
    if (win == row * col - MINE_COUNT) {
        printf("おめでとうございます!地雷を全て見つけました。\n");
        DisplayBoard(mine, ROW, COL);
    }
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

void PlayGame() {
    char mine[ROWS][COLS];
    char show[ROWS][COLS];
    InitializeBoard(mine, ROWS, COLS, '0');
    InitializeBoard(show, ROWS, COLS, '*');
    DisplayBoard(show, ROW, COL);
    PlaceMines(mine, ROW, COL);
    RevealCell(mine, show, ROW, COL);
}

void ShowMenu() {
    printf("**********************\n");
    printf("*******1.プレイ*********\n");
    printf("*******0.終了*********\n");
    printf("**********************\n");
}

int main() {
    int input;
    do {
        ShowMenu();
        printf("選択してください: ");
        scanf("%d", &input);
        switch (input) {
            case 1:
                PlayGame();
                break;
            case 0:
                printf("ゲームを終了します。\n");
                break;
            default:
                printf("入力が間違っています。再度入力してください。\n");
                break;
        }
    } while (input);
    return 0;
}

タグ: C マインスイーパー ゲーム開発 コンソールアプリケーション

6月8日 20:23 投稿