欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

c語言實現含遞歸清場版掃雷游戲

 更新時間:2021年11月21日 14:55:20   作者:Shany-Ming  
掃雷大家應該都玩過,這是一個十分經典的游戲,下面這篇文章主要給大家介紹了關于c語言實現含遞歸清場版掃雷游戲的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下

一,設計思路

想必大家都玩過掃雷

?這便是一個標準的掃雷,換做代碼實現,我們需要考慮以下幾點:

1.棋盤的設計與初始化

2.在棋盤中放入雷

3.統(tǒng)計雷數

4.如何實現“一片”的效果

5.輸贏的判斷

接下來我們進行具體操作。

二.實現方式

1.菜單的打印

對任意一個游戲,菜單是必不可少的,也是最簡單的部分,直接上代碼

void menu()
{
	printf("------------------掃雷------------------\n");
	printf("---------------1.開始游戲---------------\n");
	printf("---------------0.退出游戲---------------\n");
}
int main()
{
	srand((unsigned int)time(NULL));
	int a = 0;
	do
	{
		menu();
		scanf("%d", &a);
		if (a == 0)
		{
			break;
		}
		game();
	} while (a);
	return 0;
}

其中srand是為了求隨機值,用來布置雷

2.game函數

主菜單完后進入game函數,在game函數里我們就要開始主要的游戲部分,如棋盤初始化與打印等,當然這些步驟都依靠函數完成,game函數只相當于集合了一系列的游戲模塊

void game()
{
	char mine[ROWS][COLS];
	char show[ROWS][COLS];
	initeboard(mine, ROWS, COLS, '0');
	initeboard(show, ROWS, COLS, '*');//初始棋盤
	displayboard(show, ROW, COL);//打印棋盤
	mine_make(mine, ROW, COL);//設置雷
	//displayboard(mine, ROW, COL);
	find_mine(mine, show, ROWS, COLS);//排查雷
 
}

3.棋盤的初始化與打印

可以看到,我在game函數里初始了兩個棋盤,為什么要兩個呢?

其實,一個是為了放置了雷,一個為了展示給玩家,為什么不用一個呢,我們要在放雷處用'1',表示不放雷處用‘0',這樣計算一個坐標周圍雷的數量就會更簡單,接下來看一段代碼:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 10
#define COL 10
#define ROWS ROW+2
#define COLS COL+2

這里我們看到定義了一個ROWS和COLS這又是為何呢?

回歸棋盤

?掃雷時當你確認一個點時,它會對此點周圍的八個點進行排查看是否有淚,當坐標位于紅線處時沒有無法判斷八個,因此有了ROWS與COLS,這時,有人就會問了:那埋雷的地方用ROW COL就可以了,還不用擔心雷跑到外邊我們加的框,想法很好,但我們有兩個棋盤,必須對應,而且也不存在跑出雷的情況,往下分析你就會知道

void initeboard(char board[ROWS][COLS], int cols, int rows,char s)//棋盤初始化,此處用了個節(jié)省步驟的方法,不用兩個棋盤依次初始化
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = s;
		}
	}
}
void displayboard(char board[ROWS][COLS], int row, int col)//棋盤打印
{
	int i = 0;
	int j = 0;
	printf(" ");//與行中打印的0%d對應
	for (j = 0; j <=col; j++)
	{
		printf(" %d  ", j);
	}
	printf("\n");
	printf("-");
	for (j = 1; j <= col + 1; j++)
	{
		printf("---");
		printf("|");
	}
	printf("\n");//列對應打印完成
	for (i = 1; i <= row; i++)
	{
		if (i <= 9)
		{
			printf(" 0%d ", i);
		}
		else
		printf(" %d ", i);
		printf("|");
		for (j = 1; j <= col; j++)
		{
			printf(" %c ", board[i][j]);
			printf("|");
		}
		printf("\n");
		printf("-");
		for (j = 1; j <= col+1; j++)
		{
			printf("---");
			printf("|");
		}
		printf("\n");//行對應嵌套在內部 打印的數前加0是為了讓當行數大于9時能夠對應 如09與10
	}
}

棋盤的打印做了行列對應,所以可能有點不明顯

?4.雷的放置,雷的個數

雷的放置很簡單,在棋盤‘0',處放置就行,因為我們對隨機數的算式使隨機數只會出現在0-9沒有跑出的情況

mine_make(char mine[ROWS][COLS], int row, int col)//設置雷
{
	int count = 10;
	while (count)
	{
		int x = rand() % 10;
		int y = rand() % 10;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

雷的個數就需要一定考慮了:

首先,我們需要把周圍八個位置是否有雷,有多少個雷判斷出來,這時我們設計‘0' ‘1'類型就排上用場了,但是注意,這是字符,不是數字

ASCII碼表

?一張表 讓我們知道如何轉型

當然返回的數字記得轉成字符類型

int get_mine(char mine[ROWS][COLS], int i, int j)//得到一個坐標附近雷的個數
{
	return mine[i - 1][j - 1] + mine[i - 1][j] + mine[i - 1][j + 1] +
		mine[i][j - 1] + mine[i][j + 1] +
		mine[i + 1][j - 1] + mine[i +1 ][j] + mine[i + 1][j + 1] - 8 * '0';//此處我們的數字其實是字符,用此方法可以轉為數字整形
}

5.遞歸實現一片效果

當不為雷是會展開附近一片不為雷,提高游戲效率

void spread(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y)//遞歸方法實現一大片
{
	show[x][y] = ' ';//先讓輸入金的坐標處變?yōu)榭崭?,因為已經判定過雷所以可以直接轉空格
	int i = 0;
	int j = 0;
	int ret = 0;
	for (i = x - 1; i <= x + 1; i++)
	{
		for (j = y - 1; j <= y + 1; j++)//嵌套for循環(huán)表示輸入坐標包括自生及周圍八個
		{
			if (i > 0 && i <= ROW && j > 0 && j <= COL && mine[i][j] != '1' && show[i][j] == '*')//防止出現負坐標,避免有雷,避免輸入重復
			{
				ret = get_mine(mine, i, j);//判斷ret是0或非0,并得出周圍雷數
				if (!ret)//如果ret=0,!ret便是非0;為真
				{
					spread(show, mine, i, j);//遞歸
				}
				if (ret)//ret!=0時為真,便打印數
				{
					show[i][j] = ret + '0';//使數字轉成對應字符
				}
			}
 
		}
	}
}

效果展示:

?6.排查雷

負責判斷是否被炸死及游戲勝利

void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//排查雷
{
	printf("請輸入坐標\n");
	int i = 0;
	int j = 0;
	int win = 0;
	while (row*col-10)//因為是十個雷,所以是—10,因為下總數減10就贏了,所以可以以此跳出循環(huán),當然要是雷部位10,定一個變量就行,此處就不改了
	{
		scanf("%d %d", &i, &j);
		if (mine[i][j] == '1')
		{
			printf("你掛了\n");
			displayboard(mine, ROW, COL);
			break;
		}
		else
		{
			show[i][j] = get_mine(mine, i, j)+'0';
			spread(show,mine, i, j);
			displayboard(show, ROW, COL);
			win++;
		}		
	}
	if (win ==row * col - 10)
	{
		printf("恭喜你,成功了\n");
		displayboard(mine, ROW, COL);
	}
}

具體注釋都在代碼里了

正常情況把打印雷盤注釋就行,就可以正常游戲了

?三.完整代碼

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 10
#define COL 10
#define ROWS ROW+2
#define COLS COL+2
void menu()
{
	printf("------------------掃雷------------------\n");
	printf("---------------1.開始游戲---------------\n");
	printf("---------------0.退出游戲---------------\n");
}
void initeboard(char board[ROWS][COLS], int cols, int rows,char s)//棋盤初始化,此處用了個節(jié)省步驟的方法,不用兩個棋盤依次初始化
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = s;
		}
	}
}
void displayboard(char board[ROWS][COLS], int row, int col)//棋盤打印
{
	int i = 0;
	int j = 0;
	printf(" ");//與行中打印的0%d對應
	for (j = 0; j <=col; j++)
	{
		printf(" %d  ", j);
	}
	printf("\n");
	printf("-");
	for (j = 1; j <= col + 1; j++)
	{
		printf("---");
		printf("|");
	}
	printf("\n");//列對應打印完成
	for (i = 1; i <= row; i++)
	{
		if (i <= 9)
		{
			printf(" 0%d ", i);
		}
		else
		printf(" %d ", i);
		printf("|");
		for (j = 1; j <= col; j++)
		{
			printf(" %c ", board[i][j]);
			printf("|");
		}
		printf("\n");
		printf("-");
		for (j = 1; j <= col+1; j++)
		{
			printf("---");
			printf("|");
		}
		printf("\n");//行對應嵌套在內部 打印的數前加0是為了讓當行數大于9時能夠對應 如09與10
	}
}
mine_make(char mine[ROWS][COLS], int row, int col)//設置雷
{
	int count = 10;
	while (count)
	{
		int x = rand() % 10;
		int y = rand() % 10;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}
int get_mine(char mine[ROWS][COLS], int i, int j)//得到一個坐標附近雷的個數
{
	return mine[i - 1][j - 1] + mine[i - 1][j] + mine[i - 1][j + 1] +
		mine[i][j - 1] + mine[i][j + 1] +
		mine[i + 1][j - 1] + mine[i +1 ][j] + mine[i + 1][j + 1] - 8 * '0';//此處我們的數字其實是字符,用此方法可以轉為數字整形
}
void spread(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y)//遞歸方法實現一大片
{
	show[x][y] = ' ';//先讓輸入金的坐標處變?yōu)榭崭?,因為已經判定過雷所以可以直接轉空格
	int i = 0;
	int j = 0;
	int ret = 0;
	for (i = x - 1; i <= x + 1; i++)
	{
		for (j = y - 1; j <= y + 1; j++)//嵌套for循環(huán)表示輸入坐標包括自生及周圍八個
		{
			if (i > 0 && i <= ROW && j > 0 && j <= COL && mine[i][j] != '1' && show[i][j] == '*')//防止出現負坐標,避免有雷,避免輸入重復
			{
				ret = get_mine(mine, i, j);//判斷ret是0或非0,并得出周圍雷數
				if (!ret)//如果ret=0,!ret便是非0;為真
				{
					spread(show, mine, i, j);//遞歸
				}
				if (ret)//ret!=0時為真,便打印數
				{
					show[i][j] = ret + '0';//使數字轉成對應字符
				}
			}
 
		}
	}
}
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//排查雷
{
	printf("請輸入坐標\n");
	int i = 0;
	int j = 0;
	int win = 0;
	while (row*col-10)//因為是十個雷,所以是—10,因為下總數減10就贏了,所以可以以此跳出循環(huán),當然要是雷部位10,定一個變量就行,此處就不改了
	{
		scanf("%d %d", &i, &j);
		if (mine[i][j] == '1')
		{
			printf("你掛了\n");
			displayboard(mine, ROW, COL);
			break;
		}
		else
		{
			show[i][j] = get_mine(mine, i, j)+'0';
			spread(show,mine, i, j);
			displayboard(show, ROW, COL);
			win++;
		}		
	}
	if (win ==row * col - 10)
	{
		printf("恭喜你,成功了\n");
		displayboard(mine, ROW, COL);
	}
}
void game()
{
	char mine[ROWS][COLS];
	char show[ROWS][COLS];
	initeboard(mine, ROWS, COLS, '0');
	initeboard(show, ROWS, COLS, '*');//初始棋盤
	displayboard(show, ROW, COL);//打印棋盤
	mine_make(mine, ROW, COL);//設置雷
	displayboard(mine, ROW, COL);
	find_mine(mine, show, ROWS, COLS);//排查雷
 
}
int main()
{
	srand((unsigned int)time(NULL));
	int a = 0;
	do
	{
		menu();
		scanf("%d", &a);
		if (a == 0)
		{
			break;
		}
		game();
	} while (a);
	return 0;
}
    

總結

到此這篇關于c語言實現含遞歸清場版掃雷游戲的文章就介紹到這了,更多相關c語言實現掃雷內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論