[C言語ファンデーション7-アレイ(3)マインスイーパ]


序文

次に、この記事では、マインスイーパゲームを例として、以前に学んだ知識を確認します。


1.掃海とは何ですか?

Baidu百科事典:「Minesweeper」は、1992年にリリースされた人気のパズルゲームです。ゲームの目的は、クリックされたグリッドに表示される数字に従って、最短時間ですべての非地雷グリッドを見つけることです。同時に、雷を踏まないようにします。雷を踏むと、ゲーム全体が失われます。 。
ここに画像の説明を挿入

2.プログラムフレームワーク

プログラムの全体的なフレームワークは、前のセクションのフレームワークから適応させることができ、このフレームワークは一般的な形式としても使用できます。

2.1主な機能

int main()
{
    
    
	int input = 0;
	srand((unsigned int)time(NULL));//产生随机数
	do
	{
    
    
		menu();//菜单提示
		printf("请输入 ==> ");//输入1或0,
		scanf("%d", &input);
		switch (input)//根据输入选择是否玩游戏
		{
    
    
		case 1:
			game();//玩游戏的具体实现
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,重新选择!\n");
			break;
		}
	} while (input);

	return 0;
}

2.2機能メニュー

プロンプトメニューを出力して、プレーヤーに思い出させます。1はゲームをプレイすること、0はゲームを終了することです。

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

2.3ファンクションゲーム

配列鉱山、文字「0」で初期化

  • 地雷配列の後には10個の地雷が続き、地雷がある位置は文字「1」で表され、地雷がない位置は文字「0」のままです。
  • 10の鉱山の場所はランダムに生成されます

配列show、文字'*'で初期化

  • キャラクター「*」は、地雷が生成される位置をブロックして、プレイヤーがそれを見ることができないようにすることです。
  • show arrayは、特定の座標周辺の地雷に関する情報をチェス盤に配置します
  • 座標の周囲に地雷がある場合は、地雷の数がカウントされ、この座標に表示されます
void game()
{
    
    
	printf("开始玩游戏!\n");
	//扫雷游戏的实现
	//mine数组是用来存放布置好的雷的信息
	//就10个雷在什么位置
	char mine[ROWS][COLS] = {
    
     0 };//'0'
	//show数组是用来存放排查出的雷的信息
	//坐标周围有几个雷
	char show[ROWS][COLS] = {
    
     0 };//'*'

	//初始化棋盘
	init_board(mine, ROWS, COLS, '0');
	init_board(show, ROWS, COLS, '*');
	//打印棋盘
	//show_board(mine, ROW, COL);//全是字符'0'
	//show_board(mine, ROW, COL);//全是'*'
	//布置雷
	set_mine(mine, ROW, COL);//雷的数组
	//show_board(mine, ROW, COL);这是显示10个雷在哪里
	show_board(show, ROW, COL);//输出*暂时掩盖雷在哪里
	//排查雷
	find_mine(mine, show, ROW, COL);

	
}

2.3.2関数init_board

init_board初期化パラメータは、チェス盤全体が文字「0」と「*」を表示するようにチェス盤を初期化することです。

//初始化棋盘    参数:行数 列数  行数 列数 字符0或* 
void init_board(char arr[ROWS][COLS], int rows, int cols, char set)
{
    
    //set表示初始化传进来的字符是0 还是 *
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
    
    
		for (j = 0; j < cols; j++)
		{
    
    
			arr[i][j] = set;
		}
	}
}

2.3.3関数show_board

show_boardはチェス盤を表示するためのもので、チェス盤内の地雷の情報と、その後の掃海中のチェス盤の特定の状態を確認できます。

//展示棋盘
void show_board(char arr[ROWS][COLS], int row, int col)
{
    
    
	int i = 0;
	int j = 0;
	printf("------------扫雷------------\n");
	for (i = 0; i <= col; i++)
	{
    
    
		printf("%d ", i);//列号,棋盘首先打印列数
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
    
    
		printf("%d ", i);//行前面的数字,行号
		for (j = 1; j <= col; j++)
		{
    
    
			printf("%c ", arr[i][j]);//打印棋盘每个元素
		}
		printf("\n");
	}
	printf("------------扫雷------------\n");
}

2.3.4関数set_mine

関数set_mineは地雷を配置し、チェス盤の10の座標位置に地雷をランダムに生成します。

//布置雷
void set_mine(char mine[ROWS][COLS], int row, int col)
{
    
    
	int count = EASY_COUNT;//布置10个雷
	int x = 0;//行坐标
	int y = 0;//列坐标
	while (count)//直到10个雷布置完成,退出循环
	{
    
    
		x = rand() % row + 1;//取模是0-8,加1就是1-9
		y = rand() % col + 1;
		if (mine[x][y] == '0')//是空的,就放雷,否则重新随机产生坐标位置
		{
    
    
			mine[x][y] = '1';//布置雷
			count--;
		}
	}
}

2.3.5関数find_mine

関数find_mineは地雷をチェックすることで、プレイヤーが地雷をクリアするたびに、最初に座標を入力し、次に座標上のキャラクターが1であるかどうかを判断します。

  • 1は私のもので、ゲームは終了しました
  • 1ではなく、座標の周りの8つの位置にある地雷の数を数え、それらを文字の形式で座標に表示します
//排查雷
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
    
    
	int x = 0;
	int y = 0;
	int win = 0;//代表玩家排雷的次数
	while (win < row*col - EASY_COUNT)//小于雷的个数,说明雷还没排完
	{
    
    
		printf("请输入要排查的坐标 ==> ");
		scanf("%d %d", &x, &y);//玩家输入坐标
		if (x >= 1 && x <= row && y >= 1 && y <= col)//在1-9的坐标范围内
		{
    
    
			if (mine[x][y] == '1')//确定坐标为字符'1',就是雷
			{
    
    
				printf("很遗憾,被炸死了\n");
				show_board(mine, ROW, COL);//显示所有雷的位置
				break;
			}
			else//不是字符1,坐标就不是雷,显示坐标周围有雷的个数
			{
    
    
				int count = get_mine_count(mine, x, y);//函数计算类的个数
				show[x][y] = count + '0';//周围有雷的个数+'0'就转换成字符了
				show_board(show, ROW, COL);//打印出来,每次扫雷后的棋盘
				win++;//扫了一次雷就++
			}
		}
		else//超过坐标范围
		{
    
    
			printf("坐标非法,重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)//扫雷次数==9*9-10 71次就结束
	{
    
    
		printf("恭喜你,排雷成功\n");
		show_board(mine, ROW, COL);//显示雷的信息
	}
}

2.3.6関数get_mine_count

関数get_mine_countは、地雷の数をカウントします。

  • 文字「1」は雷があることを意味し、文字「0」はいいえを意味し、「1」-「0」は数字の1であり、1つの雷を表します
  • 座標の周りの8つの座標に文字を追加します-8*'0'、結果は地雷の数であり、整数です
//统计坐标周围有雷的个数
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
    
    //坐标周围的8个地方减去'0',再相加的个数就是类的个数
	return mine[x - 1][y] +
		mine[x - 1][y - 1] +
		mine[x][y - 1] +
		mine[x + 1][y - 1] +
		mine[x + 1][y] +
		mine[x + 1][y + 1] +
		mine[x][y + 1] +
		mine[x - 1][y + 1] - 8 * '0';
}

3.ヘッダーfile.h

#include <stdio.h>
#include <stdlib.h>//库函数
#include <time.h>//与系统时间相关

#define ROW 9//棋盘真实的行数
#define COL 9
#define ROWS ROW+2 //棋盘放大范围,便于棋盘边的位置遍历
#define COLS COL+2
#define EASY_COUNT 10 //10个雷的个数
//初始化
void init_board(char arr[ROWS][COLS], int rows, int cols, char set);
//打印
void show_board(char arr[ROWS][COLS], int row, int col);
//布置雷
void set_mine(char mine[ROWS][COLS], int row, int col);

4.ゲームをプレイする

実行結果を下図に示します。これは基本的にゲーム機能を満たしています。
ここに画像の説明を挿入

完全なコードはgiteeにあります:

C言語基盤7-配列(3)マインスイーパの完全なコード


要約する

この記事では、より基本的な掃海ゲームについてのみ説明します。後でより複雑な知識を学んだ後、掃海ゲームを改善することができます。マインスイーパゲームの全体的な執筆アイデアは、スリーピースゲームを参照して実現できます。

配列に関する知識は基本的に終わり、次の記事では演算子に関する知識を学び始めます。

おすすめ

転載: blog.csdn.net/taibudong1991/article/details/123906619