この記事では、9x9サイズのマインスイーパーゲームの設計と実装方法について説明します。ゲームは以下の3つのファイルで構成されます。
- test.c: テストロジックの実装
- game.c: ゲーム関数の実装
- game.h: データ型や関数宣言
まず、ゲームボードを9x9に設定し、10個の地雷を配置します。ただし、配列の境界問題を避けるため、実際には11x11の配列を使用します。
ゲームの流れは以下の通りです:
- 2つの盤面を作成する:地雷を保存する盤面とプレイヤーが操作する盤面。
- 地雷をランダムに配置する。
- プレイヤーが座標を入力して地雷を探し、その周囲の地雷数を表示する。
- すべての安全なセルを開くまでゲームを続ける。
コードの実装
以下に、各ファイルの内容を示します。
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;
}