みなさん、こんにちは。私の名前は sy です。今日はマインスイーパ ゲーム (初級レベル) をお届けします。スリーピース チェス ゲームと同様に、マインスイーパ ゲームも C 言語の初心者が試してみるべき小さなプロジェクトです。プロジェクトには次の 2 つが含まれます。次元配列. マクロ定義の使用、関数呼び出し、分岐選択ループ ステートメントの使用なども非常に興味深いので、見てみましょう。~
まずは掃海ゲームのルールと仕組みをご紹介します 皆さんも子供の頃に遊んだことがあると思います 基本的な掃海ゲームは9*9の正方形の配列です 配列の中に10個の機雷がランダムに格納されており、プレイヤーはランダムに座標を選択します。地雷の有無を確認する場合、選択した座標が地雷でない場合はその位置の周囲8箇所の地雷の総数が表示され、選択した位置が地雷の場合はプレイヤーが表示されます。
爆弾で死亡。今日書いた小さなゲームは、9*9 のマインスイーパー正方配列を実装するもので、使用環境は Visual Studio 2019 です。
以下に、いくつかのブロック コードに従って実装プロセスを説明します。
1. 印刷メニューのファンクションメニュー()
この関数は、switch 分岐ステートメントを使用して選択します。scanf 関数を使用して数値を入力し、それをスイッチ選択変数式に渡します。プレイヤーが「1」を入力するとゲームに参加します。「0」を選択すると、ゲームに参加します。ゲームを終了します。他の数字を選択すると、選択エラーが表示されます。選択をやり直してください。
void menu()
{
printf("***************************************\n");
printf("********** 请选择是否开始游戏:**********\n");
printf("*********** 1.开始游戏 **************\n");
printf("*********** 0.退出游戏 **************\n");
printf("***************************************\n");
}
2. ゲーム処理関数game()の実装
「1」を選択した後、この関数を入力します。ボードとショーという 2 つの文字タイプの 2 次元配列を定義します。ボード配列は背景に地雷を配置する役割を果たし、ショー配列はプレイヤーに表示され、一緒に表示されます。ボードアレイにより、地雷を検出するタスクが完了します。ここでは、2 つの 2 次元配列の行と列を定義するためにマクロが使用され、マクロのセットが 2 つ定義されていますが、このうち ROWS と COLS のセットは主に正方行列の初期化に使用されます。 ROWS と COLS の列は 11*11 を表します。これは、今後地雷をチェックするときに座標が境界を越えないようにするためです (下図に示すように、1、2、3 は境界を越えます)。InitBoard 関数は 2 つの正方行列を初期化し、それぞれ 2 つの文字「0」と「*」を渡し、char ret パラメータを使用してそれらを受け取ります。これにより、1 つの関数で 2 つの正方行列を定義できます。DispalyBoard 関数は show array を印刷して表示し、SetMine 関数は地雷を配置し、FingMine 関数は地雷のトラブルシューティングを行います。
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void game()
{
char board[ROWS][COLS];
char show[ROWS][COLS];
InitBoard(board, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
DisplayBoard(show, ROW, COL);
//布置雷
SetMine(board, ROW, COL);
//排查雷
FindMine(board, show, ROW, COL);
}
3. 主な機能
main関数では、srand((unsigned int)time(NULL))でランダム関数シードを初期化します。ここではランダムシードとして時間を取り上げます。時間は常に変化するため、異なるランダム値を生成できます。その後、コンピュータは雷をランダムに配置し、値の展開は、ランダム値ジェネレータ srand() を通じてタイム シードを生成し、次に rand() を使用して乱数を生成します。ここで、unsigned int は強制変換型であり、パラメータ シードを符号なし整数型に強制することを意味します。通常、rand() の開始値を初期化するシードとして time(NULL) の戻り値を使用します。do...while() ループを使用して、判定する前に 1 回実行します。
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:>\n");
scanf("%d", &input);
switch (input)
{
case 1:
printf("开始游戏!\n");
game();
break;
case 0:
printf("退出游戏!\n");
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
} while (input);
return 0;
}
以下では、関数ブロックの具体的な実装を実装します。
1. InitBoard() 関数を使用して 2 つの正方行列を初期化します。
for ループを使用して 2 次元配列を走査します。将来座標が範囲外になるのを避けるため、初期化中は行と列が 11*11 であることに注意してください。ret は受信文字の受信に使用されます。下の図は、「0」に初期化されたボード配列を示しています。
void InitBoard(char board[ROWS][COLS],int rows,int cols,char ret)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = ret;
}
}
}
2. DisplayBoard() 関数を使用して、2 次元配列 show を表示および印刷します。
プレイヤーが座標を入力しやすくするために、for ループを使用して水平座標と垂直座標を出力し、プレイヤーが地雷除去ポイントを選択するために表示される配列正方行列を出力します。
void DisplayBoard(char show[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i <= row; i++)//打印横坐标
{
printf(" %d ", i);
}
printf("\n");
for (i = 1; i <=row; i++)
{
printf(" %d ", i);//打印竖坐标
for (j = 1; j <= col; j++)
{
printf(" %c ", show[i][j]);//遍历打印‘*’
}
printf("\n");
}
}
3. SetMine() 関数を使用して地雷を配置します
ボード配列で実行し、x 座標と y 座標を定義し、マクロを使用してサンダーの数をカウンタ カウントに割り当て、while ループを使用します。x=rand()%row+1 は、x がサンダーをランダムに配置することを意味します。 1 と 9。横軸 (rand()%5 は、ランダムに生成された数値が 0 ~ 4 であることを意味し、地雷を 9*9 の正方行列に配置するには +1 が必要です。) if ステートメントは、次の座標が指すかどうかを決定します。 x と y は文字「0」 (空の意味) で、地雷を保存し、ゼロに減ってサイクルが停止するまで数えることができます。下の図は10個の地雷を配置する方法を示しています
void SetMine(char board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = MINE_COUNT;//计数器
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';//赋值字符‘1’
}
count--;//布置完一个雷减一
}
}
4. FindMine() 関数を使用して地雷のトラブルシューティングを行う
2次元配列基板を渡して表示 行と列は9*9を確認するだけ 継続的に座標を確認する必要があるためwhileループを使用 残りの行から雷の数を引く Winループに入り、必要な検索対象の座標を入力します。座標が有効な範囲内で、指定された座標の内容が '1' の場合は、強制終了に関する情報が出力されます。地雷が配置されているボードの正方形の配列を表示します。「1」でない場合は地雷を踏んでいません。この位置に周囲 8 か所の地雷の合計数を表示します (GetMineCount() 関数はここで計算に使用します)、計算の戻り値をcに代入し、文字番号(ASCIIで表現、文字番号は数値そのもの+文字'0')を表示し、位置を確認してwin+1します。入力された座標が不正な場合は再入力が表示され、勝利数が正方配列の総数 - 地雷の数に等しい場合、地雷除去が成功したことが証明されます。
void FindMine(char board[ROWS][COLS],char show[ROWS][COLS],int row, int col)
{
int win = 0;
while (win<row*col-MINE_COUNT)
{
int x = 0;
int y = 0;
printf("请输入要查找的坐标:\n");
scanf("%d %d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (board[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
DisplayBoard(board, ROW, COL);
break;
}
else
{
//如果没有碰到雷,则计算它周围的雷个数
int c = GetMineCount(board, x, y);
show[x][y] = c + '0';//在当前处显示周围雷的个数
DisplayBoard(show, ROW, COL);
win++;
}
}
else
{
printf("输入坐标非法,请重新输入!\n");
break;
}
if (win == row * col - MINE_COUNT)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(board, ROW, COL);
}
}
}
5. GetMineCount() 関数を使用して、選択した座標の周囲の地雷の数を計算します。
'0'-'0'=0; '1'-'0'=1; したがって、周囲の 8 つの座標を確認するには、8 文字の 0 を減算する必要があります。下の図では、3 5 の座標を入力すると 2 と表示され、周囲に地雷が 2 つあることを意味します。
int GetMineCount(char board[ROWS][COLS], int x, int y)
{
return board[x - 1][y] + board[x - 1][y - 1] +
board[x][y - 1] + board[x + 1][y - 1] +
board[x + 1][y] + board[x + 1][y + 1] +
board[x][y + 1] + board[x - 1][y + 1] - 8 * '0';
}
コードは以下の別のファイルに示されています。
test.c ファイル
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("***************************************\n");
printf("********* 请选择是否开始游戏:**********\n");
printf("*********** 1.开始游戏 **************\n");
printf("*********** 0.退出游戏 **************\n");
printf("***************************************\n");
}
void game()
{
char board[ROWS][COLS];
char show[ROWS][COLS];
InitBoard(board, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
DisplayBoard(show, ROW, COL);
//布置雷
SetMine(board, ROW, COL);
//排查雷
FindMine(board, show, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:>\n");
scanf("%d", &input);
switch (input)
{
case 1:
printf("开始游戏!\n");
game();
break;
case 0:
printf("退出游戏!\n");
break;
default:
printf("选择错误,请重新选择!\n");
break;
}
} while (input);
return 0;
}
game.c ファイル
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char board[ROWS][COLS],int rows,int cols,char ret)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = ret;
}
}
}
void DisplayBoard(char show[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i <= row; i++)//打印横坐标
{
printf(" %d ", i);
}
printf("\n");
for (i = 1; i <=row; i++)
{
printf(" %d ", i);//打印竖坐标
for (j = 1; j <= col; j++)
{
printf(" %c ", show[i][j]);//遍历打印‘*’
}
printf("\n");
}
}
void SetMine(char board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = MINE_COUNT;//计数器
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';//赋值字符‘1’
}
count--;//布置完一个雷减一
}
}
void FindMine(char board[ROWS][COLS],char show[ROWS][COLS],int row, int col)
{
int win = 0;
while (win<row*col-MINE_COUNT)
{
int x = 0;
int y = 0;
printf("请输入要查找的坐标:\n");
scanf("%d %d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (board[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
DisplayBoard(board, ROW, COL);
break;
}
else
{
//如果没有碰到雷,则计算它周围的雷个数
int c = GetMineCount(board, x, y);
show[x][y] = c + '0';//在当前处显示周围雷的个数
DisplayBoard(show, ROW, COL);
win++;
}
}
else
{
printf("输入坐标非法,请重新输入!\n");
break;
}
if (win == row * col - MINE_COUNT)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(board, ROW, COL);
}
}
}
int GetMineCount(char board[ROWS][COLS], int x, int y)
{
return board[x - 1][y] + board[x - 1][y - 1] +
board[x][y - 1] + board[x + 1][y - 1] +
board[x + 1][y] + board[x + 1][y + 1] +
board[x][y + 1] + board[x - 1][y + 1] - 8 * '0';
}
game.h ファイル
#pragma once
#include<stdio.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define MINE_COUNT 10
void InitBoard(char board[ROWS][COLS], int rows, int cols, char ret);
void DisplayBoard(char show[ROWS][COLS], int row, int col);
void SetMine(char board[ROWS][COLS], int row, int col);
void FindMine(char board[ROWS][COLS], char show[ROWS][COLS], int row, int col);
読んでくださった皆様、ありがとうございました!コメントエリアで提案や技術サポートを提供してくれる偉人や友人の皆さんを歓迎します~! !!