【C】C言語王国 マインスイーパ ゲーム

①はじめに

マインスイーパーは、あらゆる年齢層に適したゲームです。
ゲームプレイは、9×9 (初心者)、16×16 (中級)、16×30 (上級)、またはカスタム サイズの正方行列 (初心者) に特定の数の地雷をランダムに配置することです。 ). (中級者は 10、中級者は 40、上級者は 99) その後、プレイヤーはブロックを 1 つずつ裏返し、最終的なゲーム目標としてすべての地雷を見つけます。プレイヤーが地雷を含むブロックをひっくり返すと、ゲームは終了します。
仕組みを理解したら、C言語で実装する方法を考えてみましょう。(例として 9*9 を取り上げます)

ここに画像の説明を挿入します

②ゲーム実装手順

1. メニューメニューを作成します
2. 2 つの char 型配列、mine[ ] と show[ ] を定義します。mine
配列は地雷の位置情報を格納するために使用され、show 配列は地雷以外の周囲の地雷の数に関する情報を格納するために使用されます。 3.
右 鉱山と表示配列を初期化します。
鉱山配列はすべて文字 0に初期化され、表示配列はすべて文字* に初期化されます。
4. 鉱山を配置し、情報を鉱山配列に保存します。地雷は文字 0 から文字 1 に変更されます。
5. 地雷の除去
6. 配列の印刷

1. メニューメニューを作成する

メニュー画面はレストランでウェイターから渡されるメニューのようなもので、メニューの内容に応じて選択してください。1を選択すると
ゲームが開始され、0を選択するとゲームが終了します。

void menu()
{
    
    
	printf("**********************\n");
	printf("******  1. play  *****\n");
	printf("******  0. exit  *****\n");
	printf("**********************\n");
}

2. 多列多列地雷除去を実現

まず、2 つの char 型配列、mine[ ] と show[ ] を作成します。mine
配列は鉱山の位置情報を格納するために使用され、show 配列は鉱山以外の場所の周囲の鉱山の数に関する情報を格納するために使用されます。

    char mine[9][9] = {
    
     0 };
	char show[9][9] = {
    
     0 };

ただし、複数行および複数列の掃海を実装したいため、また将来的に行、列、および地雷の数を変更する際の利便性を考慮して、#define マクロ定義を使用することもできます

#define ROW 9//行
#define COL 9//列
#define LANDMINE 10//雷的个数

また、後で地雷以外の位置の周囲の情報を検索する際の便宜のため(たとえば、9*9 配列の最も外側の 2 行 2 列の周囲の位置は 8 個未満であるため、地雷以外の位置の周囲の情報を検索する際に、位置を後で決定するには、周囲の位置も決定する必要があります。範囲外かどうか)、元の配列に2 行 2 列を追加すること、特定の位置の周囲の位置が範囲外であるかどうかを判断する必要はありません)。

#define ROWS ROW+2
#define COLS COL+2

効果:
ここに画像の説明を挿入します

3.初期化

2 つの配列を定義した後、それらを初期化します。mine
配列はすべて文字 0 に初期化され、show 配列はすべて文字 * に初期化され、文字 0 と * は set によって受け取られます。

    Initiate_board(mine, ROWS, COLS, '0');
	Initiate_board(show, ROWS, COLS, '*');
void Initiate_board(char mine[ROWS][COLS], int rows, int cols, char set)
{
    
    
	int i, j;
	for (i = 0; i < rows; i++)
		for (j = 0; j < cols; j++)
			mine[i][j] = set;
}

4.地雷を配置する

	Set_mine(mine, ROW, COL);

1. レイアウト マインは、上の図の水色の 9*9 領域でのみ使用され、濃い青の領域では使用されないことに注意してください。そのため、パラメーターを渡すときは、元の行と列の代わりに row とcol渡さます 2 つの行を追加します。行と列からなる 2 つの列です。

2. 地雷を n 個配置するということは、要件を満たす n 個の異なるランダム座標を生成することを意味するため、rand() 関数を使用する必要がありますが、使用の前提は srand() 関数を使用するため、n 個のランダムな座標を生成するにmain 関数でsrand((unsigned int)time(NULL)) を 1 回呼び出すには、

void Set_mine(char mine[ROWS][COLS], int row, int col)
{
    
    
	int i = 0;
	while (i < LANDMINE)
	{
    
    
		int x = rand() % row + 1;//使得x的范围在1--row
		int y = rand() % col + 1;//使得y的范围在1--col
		if (mine[x][y] == '0')
		{
    
    
			mine[x][y] = '1';
			i++;
		}
	}
}

5. 配列を印刷する

	Display_board(mine, ROW, COL);

配列を出力する場合、上図の水色の部分のみが出力され、濃い青色の部分は出力する必要がないため、パラメータを渡す際には、行と列を2つ追加するのではなく、元の行と列のが渡されます。行と 2 列 行と列。

特定の位置がどの行と列であるかをすぐに知ることができるようにするには、次のコードを使用できます。

void Display_board(char mine[ROWS][COLS], int row, int col)
{
    
    
	int i, j;
	printf("\n----------扫雷----------\n");
	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 ", mine[i][j]);//打印数组
		printf("\n");
	}
	printf("----------扫雷----------\n");
	printf("\n");
}

レンダリング:
ここに画像の説明を挿入します

6.地雷除去を開始する

まず座標を入力し、その位置が地雷配列内の地雷であるかどうか(つまり、その位置が文字 1 であるかどうか) を判断します。そうである場合は、「残念ながら、殺されました。」というプロンプトが表示されます。そうでない場合は、周囲に地雷がいくつあるかを調べます。地雷がある位置を取得し、地雷の数をショー配列の対応する位置に渡します

	Search_mine(mine, show, ROW, COL);
int Search_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    
    
	int x, y;
	int i = 0;
	while (i < ROW * COL - LANDMINE)//ROW * COL - LANDMINE表示非雷的个数
	{
    
    
		printf("请输入想要查找的位置:");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
    
    
			if (mine[x][y] == '1')//踩到炸弹后,直接退出循环
			{
    
    
				printf("\n很遗憾,您被炸死了\n");
				Display_board(mine, ROW, COL);
				break;
			}
			else if (show[x][y] != '*')
			{
    
    
				printf("该位置已排雷,请重新输入:\n");
			}
			else
			{
    
    
				int count = landmine_count(mine, x, y);//landmine_count()函数在下面介绍
				show[x][y] = count + '0';//使得该位置的数字几变成字符几
				Display_board(show, ROW, COL);
				i++;
			}
		}
		else
		{
    
    
			printf("输入错误,请重新输入\n");
		}
	}
	if (i == ROW * COL - LANDMINE)//当数组中的非雷位置全都排出,即为排雷成功
	{
    
    
		printf("\n恭喜你,扫雷成功\n");
		Display_board(mine, ROW, COL);
	}
}

7. landmine_count() 関数

地雷配列はすべて文字 0 または 1 であり、文字 n から文字 0 を引いた値 = 数値 n であるため、地雷の数は、その位置の周囲の 8 つの位置にある文字の合計から 8*文字 0 を引いたものになります。

int landmine_count(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';
}

③モジュールコード実装

1.text.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

void menu()
{
    
    
	printf("**********************\n");
	printf("******  1. play  *****\n");
	printf("******  0. exit  *****\n");
	printf("**********************\n");
}

void game()
{
    
    
	char mine[ROWS][COLS] = {
    
     0 };
	char show[ROWS][COLS] = {
    
     0 };
	//初始化
	Initiate_board(mine, ROWS, COLS, '0');
	Initiate_board(show, ROWS, COLS, '*');
	//Display_board(mine, ROW, COL);
	Display_board(show, ROW, COL);
	//布置雷
	Set_mine(mine, ROW, COL);
	Display_board(mine, ROW, COL);
	//扫雷
	Search_mine(mine, show, ROW, COL);
}

int main()
{
    
    
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
    
    
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
    
    
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

2.ゲーム.h

#pragma once

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

#define LANDMINE 10

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

//初始化
void Initiate_board(char mine[ROWS][COLS], int rows, int cols, char set);
//打印
void Display_board(char mine[ROWS][COLS], int row, int col);
//布置雷
void Set_mine(char mine[ROWS][COLS], int row, int col);
//扫雷
int Search_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);


3.ゲーム.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

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

void Display_board(char mine[ROWS][COLS], int row, int col)
{
    
    
	int i, j;
	printf("\n----------扫雷----------\n");
	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 ", mine[i][j]);
		printf("\n");
	}
	printf("----------扫雷----------\n");
	printf("\n");
}

void Set_mine(char mine[ROWS][COLS], int row, int col)
{
    
    
	int i = 0;
	while (i < LANDMINE)
	{
    
    
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
    
    
			mine[x][y] = '1';
			i++;
		}
	}
}

int landmine_count(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';
}

int Search_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    
    
	int x, y;
	int i = 0;
	while (i < ROW * COL - LANDMINE)
	{
    
    
		printf("请输入想要查找的位置:");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
    
    
			if (mine[x][y] == '1')
			{
    
    
				printf("\n很遗憾,您被炸死了\n");
				Display_board(mine, ROW, COL);
				break;
			}
			else if (show[x][y] != '*')
			{
    
    
				printf("该位置已排雷,请重新输入:\n");
			}
			else
			{
    
    
				int count = landmine_count(mine, x, y);
				show[x][y] = count + '0';
				Display_board(show, ROW, COL);
				i++;
			}
		}
		else
		{
    
    
			printf("输入错误,请重新输入\n");
		}
	}
	if (i == ROW * COL - LANDMINE)
	{
    
    
		printf("\n恭喜你,扫雷成功\n");
		Display_board(mine, ROW, COL);
	}
}

おすすめ

転載: blog.csdn.net/qq_75000174/article/details/132045526