真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

掃雷游戲【C語言實(shí)現(xiàn)】【完美版】【非常詳細(xì)的講解,看完必會】-創(chuàng)新互聯(lián)

在這里插入圖片描述

在城中等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都做網(wǎng)站、成都網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作按需設(shè)計(jì),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計(jì),營銷型網(wǎng)站建設(shè),成都外貿(mào)網(wǎng)站制作,城中網(wǎng)站建設(shè)費(fèi)用合理。

本期介紹🍖

主要介紹:如何一步一步的把整個掃雷游戲的所有功能實(shí)現(xiàn),詳細(xì)的講解其中每一個功能從無到有的思考過程以及代碼上的實(shí)現(xiàn)👀。


文章目錄

  • 一、掃雷游戲🍖
  • 二、test.c文件的實(shí)現(xiàn)🍖
    • 2.1程序?qū)崿F(xiàn)思路 🍖
    • 2.2代碼 🍖
    • 2.3神來之筆的想法 🍖
  • 三、game.c文件的實(shí)現(xiàn)🍖
    • 3.1 棋盤初始化函數(shù)🍖
    • 3.2 設(shè)置地雷函數(shù)🍖
    • 3.3 打印棋盤函數(shù)🍖
    • 3.4 掃雷函數(shù)🍖
      • 3.4.1 計(jì)算四周地雷個數(shù)函數(shù)🍖
      • 3.4.2 顯示地雷函數(shù)🍖
      • 3.4.3 炸金花式展開函數(shù)🍖
        • 難題1🍖
        • 難題2🍖
        • 代碼實(shí)現(xiàn)🍖
      • 3.4.4 手動標(biāo)記地雷坐標(biāo)🍖
  • 四、完整的程序🍖
  • 五、最后實(shí)現(xiàn)效果🍖

一、掃雷游戲🍖

??掃雷是一款大眾類的益智小游戲,于1992年發(fā)行。游戲目標(biāo)是在最短的時(shí)間內(nèi)根據(jù)點(diǎn)擊格子出現(xiàn)的數(shù)字找出所有非雷格子,同時(shí)避免踩雷,踩到一個雷即全盤皆輸。這款游戲的玩法是在一個9 * 9(初級),16 * 16(中級),16 * 30(高級),或自定義大小的方塊矩陣中隨機(jī)布置一定量的地雷(初級為10個,中級為40個,高級為99個)。由玩家逐個翻開方塊,以找出所有地雷為最終游戲目標(biāo)。如果玩家翻開的方塊有地雷,則游戲結(jié)束。值得注意的是:若翻開的格子下沒有地雷,則會標(biāo)記其周圍一圈格子中包含雷的個數(shù),所以若想順利通關(guān)就必須利用好這些顯示出來的數(shù)字。如下圖所示。(而我們今天要實(shí)現(xiàn)的是9×9方格的掃雷游戲,棋盤上一共放置了10個地雷)
在這里插入圖片描述


二、test.c文件的實(shí)現(xiàn)🍖 2.1程序?qū)崿F(xiàn)思路 🍖

??首先,我們要思考一下怎樣才能實(shí)現(xiàn)的和計(jì)算機(jī)里的掃雷游戲一樣呢?進(jìn)入計(jì)算機(jī)里的掃雷游戲,首先映入眼簾的是9×9的棋盤上所有的格子都被掩蓋了。然后隨機(jī)去翻開一些格子,你肯定能發(fā)現(xiàn)會出現(xiàn)幾種情況:

1.當(dāng)翻開的是“地雷”時(shí),你會被炸死游戲結(jié)束。
2.當(dāng)翻開的格子周圍一圈當(dāng)中存在“地雷”時(shí),翻開的格子下面會顯示周圍一圈格子內(nèi)存在“地雷”的個數(shù)。
3.當(dāng)翻開的格子周圍沒有“地雷”時(shí),會一下子展開一大片區(qū)域。

??然后不斷地翻開格子,直到把所有的非“地雷”的格子全部翻開后,游戲提示:掃雷成功!那我們該怎么實(shí)現(xiàn)這里雙層結(jié)構(gòu)的棋盤呢?你會發(fā)現(xiàn)雙層結(jié)構(gòu)的第一層是用來覆蓋住第二層上顯示的內(nèi)容,一個想法就油然而生了:我們是不是只要創(chuàng)建兩個二維數(shù)組,其中一個隱藏在暗處用來存放這些地雷啊、數(shù)字的信息,用戶是看不見的;另一個則是專門向用戶展示的,是擺在明面上的棋盤(這期會實(shí)現(xiàn):可以自己標(biāo)注地雷位置的操作,還有炸金花式展開的功能)

??游戲菜單:選擇是否開始玩兒游戲,1:開始游戲,0:退出游戲。
??游戲流程:創(chuàng)建兩個格子棋盤(其中一個是隱與幕后存放地雷信息用的,另一個是向用戶展示的)→ 初始化兩個棋盤 → 隨機(jī)放置地雷 → 實(shí)現(xiàn)打印棋盤 → 開始掃雷(用戶輸入要查找的位置的坐標(biāo) → 判斷是否有雷 → 有則游戲結(jié)束,若沒有則顯示其周圍一圈中地雷的個數(shù)或者炸金花式展開一片)→ 直至掃完所有非雷區(qū) → 游戲結(jié)束。


2.2代碼 🍖

??代碼如下:

#include"game.h"

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

void game()
{//存放地雷的棋盤
	char mine[ROWS][COLS] = {0 };
	//展示給用戶看的棋盤
	char show[ROWS][COLS] = {0 };
	//初始化棋盤
	init_board(mine, ROWS, COLS, '0');
	init_board(show, ROWS, COLS, '*');
	//放置地雷
	set_mine(mine, ROW, COL);
	system("cls");//清空屏幕
	//打印棋盤
	//display_board(mine, ROW, COL);
	display_board(show, ROW, COL);
	//開始掃雷
	find_mind(mine, show, ROW, COL);
}

int main()
{//設(shè)置隨機(jī)數(shù)的起點(diǎn)
	srand((unsigned int)time(NULL));
	int input = 0;
	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;
}

??注意:仔細(xì)看上面的代碼,你會我并沒有引頭文件而是引了"game.h"文件,而且程序中出現(xiàn)了很多未定義的標(biāo)識符:如ROW、COL、ROWS、COLS(這里的ROW表示:行,COL表示:列)。那是因?yàn)槲野堰@些東西有放到頭文件"game.h"中去了,引用該頭文件就相當(dāng)于引用他們。還有就是上面的很多函數(shù)是沒有定義的,只不過事先說明其用處罷了。那為什么要把源文件分開來放置呢?這是很重要的一個知識點(diǎn),我之前有一期就是專門講這個點(diǎn)的,不懂的同學(xué)一定要了解一下再三重復(fù)真的很重要。下面讓我們來一 一實(shí)現(xiàn)這這些函數(shù)吧!??!鏈接:函數(shù)聲明和定義真正的用法

在這里插入圖片描述


2.3神來之筆的想法 🍖

??相信看到這肯定有同學(xué)問:“不是說實(shí)現(xiàn)的是9×9的掃雷嗎,為什么這里是用11×11的二維數(shù)組來存放噠???”這就得夸夸那些牛逼的大佬想出來的方法了。現(xiàn)在假設(shè)我用9×9的二維數(shù)組來存放信息,當(dāng)排查某個非雷的坐標(biāo)時(shí),我們知道這時(shí)是需要將該坐標(biāo)周圍一圈坐標(biāo)逐個排查一遍的。但當(dāng)你去排查最邊界的那一圈坐標(biāo)時(shí),你會發(fā)現(xiàn)你必須得以特殊的排查法來處理這些坐標(biāo),不然你就會越界訪問。就如下圖所示:
在這里插入圖片描述
??所以要在排查的時(shí)候不越界訪問你就必須給這最邊緣一圈的坐標(biāo)設(shè)計(jì)出專門的排查規(guī)則,這是一種解決的方法,但該方法的實(shí)現(xiàn)太過于麻煩了。所以一些大佬就思考:能不能從另一個角度以更加簡便的方法來解決這個問題呢?其中有些人就發(fā)現(xiàn),似乎只要把9×9的棋盤擴(kuò)張成11×11的棋盤,然后只拿該棋盤中間的9×9的格子用作和以前一樣的操作,問題不就迎刃而解了。這是為什么呢?因?yàn)槲也僮鲿r(shí)只會去排查中間那9行9列的格子,且就算我去排查最邊上的一圈坐標(biāo)也不會出現(xiàn)越界訪問的情況,如下圖所示。你看僅僅只需要把數(shù)組的大小改一改就能解決困擾你很久的問題,完全沒有必要在那限制這限制那的。所以有些時(shí)候不能硬想啊,一定要學(xué)會換一個角度來思考問題的解決之法?。?!
在這里插入圖片描述


三、game.c文件的實(shí)現(xiàn)🍖 3.1 棋盤初始化函數(shù)🍖

?? 該函數(shù)做到了可以任意對棋盤進(jìn)行初始化,想初始化什么就傳參傳進(jìn)來就行了。

//初始化棋盤
void init_board(char board[ROWS][COLS], int rows, int cols, char set)
{int i = 0;
	for (i = 0; i< rows; i++)
	{int j = 0;
		for (j = 0; j< cols; j++)
		{	board[i][j] = set;//set為外部傳進(jìn)來要初始化的字符
		}
	}
}

3.2 設(shè)置地雷函數(shù)🍖

??該函數(shù)是通過rand()隨機(jī)數(shù)函數(shù)來設(shè)置地雷的,如果我之前有一期是專門講解了如何去創(chuàng)建隨機(jī)數(shù),如果這里感覺不是很明確,建議先了解一下隨機(jī)數(shù)再來看下去。鏈接:如何創(chuàng)建隨機(jī)數(shù)。

//設(shè)置地雷
void set_mine(char mine[ROWS][COLS], int row, int col)
{int count = COUNT;//COUNT定義在頭文件中為常量10
	while (count)
	{int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (mine[x][y] == '0')
		{	mine[x][y] = '1';
			count--;
		}
	}
}

3.3 打印棋盤函數(shù)🍖

??該函數(shù)可以實(shí)時(shí)的打印出你想要的幾行幾列的棋盤,只需更改頭文件中的常量ROW和COL就行。

//打印棋盤
void display_board(char board[ROWS][COLS], int row, int col)
{printf("---------------掃雷游戲----------------\n");
	int i = 0;
	for (i = 0; i<= row; i++)//打印列號
	{printf(" %d  ", i);
	}
	printf("\n");
	printf("\n");
	for (i = 1; i<= row; i++)
	{int j = 0;
		printf(" %d  ", j);//打印行號
		//打印棋子行
		for (j = 1; j<= col; j++)
		{	printf(" %c ", board[i][j]);
			if (j<= col - 1)
			{		printf("|");
			}
		}
		printf("\n");
		//打印分隔行
		if (i<= row - 1)
		{	printf("    ");
			for (j = 1; j<= col; j++)
			{		printf("---");
				if (j<= col - 1)
				{printf("|");
				}
			}
			printf("\n");
		}
	}
	printf("---------------掃雷游戲----------------\n");

}

??演示一下效果,就如下圖所示。mine棋盤其中字符1代表設(shè)置的地雷,字符0表示該地沒有地雷,而show棋盤中字符 ‘ * ’ 表示方格還沒有被翻開,是未知的意思。
在這里插入圖片描述


3.4 掃雷函數(shù)🍖

??該函數(shù)是由很多子函數(shù)嵌套調(diào)用而成,總體實(shí)現(xiàn)的功能是:先創(chuàng)建一個循環(huán),然后要求用戶輸入要排查的下標(biāo),接著判斷用戶輸入下標(biāo)是否有效,再判斷是否排查到雷。若排到地雷則直接退出循環(huán)游戲結(jié)束,否則直接進(jìn)入炸金花式展開的遞歸調(diào)用,直到排查完所有的非雷方格則游戲勝利(炸金花式展開是啥,下面會仔細(xì)說明,不要著急)。

//開始掃雷
void find_mind(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0;
	int y = 0;
	int win = 0;//記錄排查出不是地雷位置的個數(shù)
	char ch = 0;
	while (win< row * col - COUNT)
	{printf("請輸入要排查的位置下標(biāo):");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x<= row && y >= 1 && y<= col)//判斷輸入下標(biāo)是否有效
		{	if (mine[x][y] == '1')//排查到了地雷
			{		break;
			}
			//此時(shí)沒有排查到地雷
			else
			{		//炸金花式展開
				explode_spread(mine, show, row, col, x, y);
				system("cls");
				//打印棋盤
				display_board(show, row, col);
				printf("需要標(biāo)注地雷就輸入:Y,不需要標(biāo)注地雷則輸入:N\n");
				//清空一下緩沖區(qū)
				while ((ch = getchar()) != '\n');
				scanf("%c", &ch);
				switch (ch)
				{		case 'Y':
					//標(biāo)記雷的位置
					sign_mine(show, row, col);
					break;
				default:
					break;
				}
			}
		}
		else
		{	printf("輸入下標(biāo)非法,請重新輸入:\n");
		}
	}
	//把所有mine中地雷全部顯示到show上
	show_all_mine(mine, show, row, col);
	system("cls");
	//打印棋盤
	display_board(show, row, col);
	//判斷是否排查成功
	if (win >= row * col - COUNT)
	{printf("恭喜你排查出所有的地雷?。?!\n");
	}
	else
	{printf("掃雷失敗,你被炸死了?。?!\n");
	}
}

3.4.1 計(jì)算四周地雷個數(shù)函數(shù)🍖

??該函數(shù)是實(shí)現(xiàn):當(dāng)我們在排查某個位置的時(shí)候,會計(jì)算該位置周圍一圈存在地雷的個數(shù),并返回給這個值。如下圖中的數(shù)字那樣:

//計(jì)算周圍一圈范圍內(nèi)存在地雷的個數(shù)
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{//把3×3方格內(nèi)所有的字符(‘1’或‘0’)加起來,
	//然后再統(tǒng)一減去9個字符‘0’得到的結(jié)果就是地雷的個數(shù)
	int i = 0;
	int sum = 0;
	for (i = x - 1; i<= x + 1; i++)
	{int j = 0;
		for (j = y - 1; j<= y + 1; j++)
		{	sum += mine[i][j];
		}
	}
	return (sum - 9 * '0');
}

3.4.2 顯示地雷函數(shù)🍖

??該函數(shù)若放到調(diào)用它的掃雷函數(shù)中去執(zhí)行,會實(shí)現(xiàn)下面這種情況:若我不小心掃到了地雷或掃雷成功時(shí)將會顯示曝光所有的地雷在用戶界面上向你展示。如下圖所示:
在這里插入圖片描述

//把所有mine中地雷全部顯示到show上
void show_all_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int i = 0;
	for (i = 1; i<= row; i++)
	{int j = 0;
		for (j = 1; j<= col; j++)
		{	if (mine[i][j] == '1')
			{		show[i][j] = '@';//地雷用字符‘@’在用戶界面表示
			}
		}
	}
}

3.4.3 炸金花式展開函數(shù)🍖

??這是一個遞歸函數(shù)(對于新手來水非常難,我估計(jì)光看我寫的代碼是很難理解透徹這個函數(shù)的,所以我會逐步的來分析這個代碼),該函數(shù)實(shí)現(xiàn)的功能是:若排查的位置周圍沒有雷則向四周爆炸式展開,直至遇到周圍有地雷的坐標(biāo)時(shí)停下來。如下圖所示:

在這里插入圖片描述
??那該怎么實(shí)現(xiàn)該遞歸函數(shù)呢?當(dāng)排查的位置沒有雷且該位置周圍沒有雷時(shí),就展開其周圍一圈的8個坐標(biāo),然后看這8個坐標(biāo)是否可以再逐個向其自身周圍接著展開,這樣一次就遞歸調(diào)用函數(shù)自身8次的展開速度就像爆炸了一樣,所以稱其為:炸金花式展開。


(1)難題1🍖

??如果按照這個思路去編寫代碼一定會出現(xiàn)一種情況“ 程序陷入死遞歸 ”。這個問題當(dāng)時(shí)也時(shí)困擾了我很久,代碼調(diào)試一直走不下去,直到我動手畫了張圖慢慢分析后才發(fā)現(xiàn)了問題的所在??聪聢D所示:
在這里插入圖片描述
??基于上面的所思所想:我們認(rèn)為當(dāng)排查某個周圍沒有雷的坐標(biāo)時(shí),該坐標(biāo)會向周圍一圈展開,然后展開的這些坐標(biāo)會繼續(xù)再向外圍展開,繼而把所有周圍沒有地雷的坐標(biāo)統(tǒng)統(tǒng)排查出來??墒聦?shí)真是如此嗎?你會發(fā)現(xiàn)不管你先展開哪一個位置你都將陷入死遞歸當(dāng)中。就拿上圖所示的這個坐標(biāo)為例,當(dāng)要展開(x,y)坐標(biāo)周圍的一圈坐標(biāo)時(shí),假如其首先會從(x-1,y+1)位置開始,然后又由該坐標(biāo)向其自身周圍的一圈展開時(shí),你會發(fā)現(xiàn)坐標(biāo)(x,y)也在需要展開的范圍內(nèi)。這樣一來不就會重復(fù)要求再次展開坐標(biāo)(x,y),然后在由(x,y)要求展開(x-1,y+1),兩個坐標(biāo)在那相互瘋狂調(diào)用,你不死遞歸誰死遞歸???
??解題思路:那該怎么解決呢,說難不難當(dāng)也不簡單,要看你自己在思考的過程中能不能靈光一現(xiàn)。你看,現(xiàn)在我們完全是站在存放地雷這個棋盤(mine_board)的角度在思考解決問題的辦法。這樣必然局限了我們的思維,不妨跳出來看看,換一個角度去尋求解題之法。不知道大家有沒有發(fā)現(xiàn)我們似乎略了用戶棋盤(show_board)了呀,可不能只認(rèn)為用戶棋盤只是用來展示的,如若這兩個棋盤配合的夠好,你會發(fā)現(xiàn)此法可以完美的解決上面的難題。
??如何實(shí)現(xiàn):若每次判斷一個坐標(biāo)上沒有雷且該坐標(biāo)周圍一圈同樣沒有雷時(shí),則將向我們展示的棋盤(show_board)上表示未知的字符 ‘ * ’ 改成空格。然后在之后的遞歸調(diào)用前給一個判斷:如果這個將要被遞歸調(diào)用的坐標(biāo)在(show_board)棋盤上存放的是字符 ‘ * ’ 時(shí)才能進(jìn)行下一步,否則將直接跳過此次遞歸。如此就可以限制住坐標(biāo)在那相互瘋狂調(diào)用,因?yàn)槌绦蜻@樣設(shè)計(jì)后每個坐標(biāo)向外展開的次數(shù)就只有一次了。


(2)難題2🍖

??解決了上面的難題后你還會遇到一種情況,程序調(diào)試時(shí)出現(xiàn)錯誤,編譯器給的理由是:非法訪問內(nèi)存空間。其實(shí)在很多情況下會導(dǎo)致這里出現(xiàn)“ 非法訪問內(nèi)存空間” ,但該處出現(xiàn)的原因是:數(shù)組越界訪問了??隙ㄓ型瑢W(xué)會問:怎么又會越界訪問呢?上面不是已經(jīng)解決這個問題了嗎?那就只能說明你思考問題的時(shí)候太片面。上面的確解決了這個問題,但你要知道這里可是出現(xiàn)了向外擴(kuò)張的遞歸啊,你那拓展出來最外圍的一圈坐標(biāo)完全無法起到限制的作用,無法阻止炸金花式的向外展開。所以當(dāng)然會出現(xiàn)越界訪問啦?。?!
在這里插入圖片描述

??那該怎么解決呢?其實(shí)很簡單只要能想到上面那層,就很容易得出:每次進(jìn)入遞歸函數(shù)后加一條限制不就行了。具體怎么做看下面的代碼自己領(lǐng)悟吧


(3)代碼實(shí)現(xiàn)🍖
//炸金花式展開函數(shù)
void explode_spread(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y)
{//限制非法坐標(biāo)的展開
	if (x >= 1 && x<= row && y >= 1 && y<= col)
	{//計(jì)算該位置附近四周地雷的個數(shù)
		int count = get_mine_count(mine, x, y);
		//若四周沒有一個地雷,則需要向該位置的四周展開,直到展開到某個位置附近存在地雷為止
		if (count == 0)
		{	//把附近沒有地雷的位置變成字符 “空格”
			show[x][y] = ' ';
			int i = 0;
			//向四周共8個位置遞歸調(diào)用
			for (i = x - 1; i<= x + 1; i++)
			{		int j = 0;
				for (j = y - 1; j<= y + 1; j++)
				{//限制對點(diǎn)位置的重復(fù)展開調(diào)用,使得每一個位置只能向四周展開一次
					if (show[i][j] == '*')
					{explode_spread(mine, show, row, col, i, j);
					}
				}
			}
		}
		//若四周存在地雷則應(yīng)該在這個位置上標(biāo)注上地雷的個數(shù)
		else
		{	show[x][y] = count + '0';
		}
	}
}

3.4.4 手動標(biāo)記地雷坐標(biāo)🍖

??該功能實(shí)現(xiàn)的是在每次排查后都有一次選擇的機(jī)會,是否要標(biāo)記地雷的位置。若要則輸入**‘ Y ’** ,之后需要輸入想要標(biāo)注的坐標(biāo)位置,只有當(dāng)方格還是未知符號 ‘ * ’ 時(shí)才能用字符 ‘ !’ 作為警告標(biāo)記的;若不要則輸入 ‘ N ’ ,程序接著執(zhí)行下一步。

//標(biāo)記地雷位置(方便排查游戲中的地雷)
void sign_mine(char show[ROWS][COLS], int row, int col)
{int x = 0;
	int y = 0;
	while (1)
	{printf("請輸入要標(biāo)記的坐標(biāo):");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x<= row && y >= 1 && y<= col)
		{	if (show[x][y] == '*')
			{		show[x][y] = '!';
				break;
			}
			else
			{		printf("該位置不能被標(biāo)記,請重新輸入:\n");
			}
		}
		else
		{	printf("輸入坐標(biāo)非法,請重新輸入:\n");
		}
	}
	system("cls");
	display_board(show, row, col);
}
}

四、完整的程序🍖

頭文件:

#include#include#include#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define COUNT 10

void init_board(char board[ROWS][COLS], int rows, int cols, char set);
void set_mine(char mine[ROWS][COLS], int row, int col);
void display_board(char board[ROWS][COLS], int row, int col);
void find_mind(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

源文件:

#include"game.h"

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

void game()
{//存放地雷的棋盤
	char mine[ROWS][COLS] = {0 };
	//展示給用戶看的棋盤
	char show[ROWS][COLS] = {0 };
	//初始化棋盤
	init_board(mine, ROWS, COLS, '0');
	init_board(show, ROWS, COLS, '*');
	//放置地雷
	set_mine(mine, ROW, COL);
	system("cls");//清空屏幕
	//打印棋盤
	//display_board(mine, ROW, COL);
	display_board(show, ROW, COL);
	//開始掃雷
	find_mind(mine, show, ROW, COL);
}

int main()
{//設(shè)置隨機(jī)數(shù)的起點(diǎn)
	srand((unsigned int)time(NULL));
	int input = 0;
	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;
}

源文件:

#include"game.h"

//初始化棋盤
void init_board(char board[ROWS][COLS], int rows, int cols, char set)
{int i = 0;
	for (i = 0; i< rows; i++)
	{int j = 0;
		for (j = 0; j< cols; j++)
		{	board[i][j] = set;
		}
	}
}

//設(shè)置地雷
void set_mine(char mine[ROWS][COLS], int row, int col)
{int count = COUNT;
	while (count)
	{int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (mine[x][y] == '0')
		{	mine[x][y] = '1';
			count--;
		}
	}
}

//打印棋盤
void display_board(char board[ROWS][COLS], int row, int col)
{int i = 0;
	printf("---------------掃雷游戲----------------\n");
	//打印列號
	for (i = 0; i<= row; i++)
	{printf(" %d  ", i);
	}
	printf("\n");
	printf("\n");
	for (i = 1; i<= row; i++)
	{int j = 0;
		//打印行號
		printf(" %d  ", i);
		//打印棋子行
		for (j = 1; j<= col; j++)
		{	printf(" %c ", board[i][j]);
			if (j<= col - 1)
			{		printf("|");
			}
		}
		printf("\n");
		//打印分隔行
		if (i<= row - 1)
		{	printf("    ");
			for (j = 1; j<= col; j++)
			{		printf("---");
				if (j<= col - 1)
				{printf("|");
				}
			}
			printf("\n");
		}
	}
	printf("---------------掃雷游戲----------------\n");
}

//計(jì)算周圍一圈范圍內(nèi)存在地雷的個數(shù)
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{//把3×3方格內(nèi)所有的字符(‘1’或‘0’)加起來,然后再統(tǒng)一減去9個字符‘0’,得到的結(jié)果就是地雷的個數(shù)
	int i = 0;
	int sum = 0;
	for (i = x - 1; i<= x + 1; i++)
	{int j = 0;
		for (j = y - 1; j<= y + 1; j++)
		{	sum += mine[i][j];
		}
	}
	return (sum - 9 * '0');
}

//把所有mine中地雷全部顯示到show上
void show_all_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int i = 0;
	for (i = 1; i<= row; i++)
	{int j = 0;
		for (j = 1; j<= col; j++)
		{	if (mine[i][j] == '1')
			{		show[i][j] = '@';//地雷用字符‘@’在用戶界面表示
			}
		}
	}
}

//炸金花式展開函數(shù)
void explode_spread(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y)
{//限制非法坐標(biāo)的展開
	if (x >= 1 && x<= row && y >= 1 && y<= col)
	{//計(jì)算該位置附近四周地雷的個數(shù)
		int count = get_mine_count(mine, x, y);
		//若四周沒有一個地雷,則需要向該位置的四周展開,直到展開到某個位置附近存在地雷為止
		if (count == 0)
		{	//把附近沒有地雷的位置變成字符 “空格”
			show[x][y] = ' ';
			int i = 0;
			//向四周共8個位置遞歸調(diào)用
			for (i = x - 1; i<= x + 1; i++)
			{		int j = 0;
				for (j = y - 1; j<= y + 1; j++)
				{//限制對點(diǎn)位置的重復(fù)展開調(diào)用,使得每一個位置只能向四周展開一次
					if (show[i][j] == '*')
					{explode_spread(mine, show, row, col, i, j);
					}
				}
			}
		}
		//若四周存在地雷則應(yīng)該在這個位置上標(biāo)注上地雷的個數(shù)
		else
		{	show[x][y] = count + '0';
		}
	}
}

//標(biāo)記地雷位置(方便排查游戲中的地雷)
void sign_mine(char show[ROWS][COLS], int row, int col)
{int x = 0;
	int y = 0;
	while (1)
	{printf("請輸入要標(biāo)記的坐標(biāo):");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x<= row && y >= 1 && y<= col)
		{	if (show[x][y] == '*')
			{		show[x][y] = '!';
				break;
			}
			else
			{		printf("該位置不能被標(biāo)記,請重新輸入:\n");
			}
		}
		else
		{	printf("輸入坐標(biāo)非法,請重新輸入:\n");
		}
	}
	system("cls");
	display_board(show, row, col);
}

//開始掃雷
void find_mind(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0;
	int y = 0;
	int win = 0;//記錄排查出不是地雷位置的個數(shù)
	char ch = 0;
	while (win< row * col - COUNT)
	{printf("請輸入要排查的位置下標(biāo):");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x<= row && y >= 1 && y<= col)//判斷輸入下標(biāo)是否有效
		{	if (mine[x][y] == '1')//排查到了地雷
			{		break;
			}
			//此時(shí)沒有排查到地雷
			else
			{		//炸金花式展開
				explode_spread(mine, show, row, col, x, y);
				system("cls");
				//打印棋盤
				display_board(show, row, col);
				printf("需要標(biāo)注地雷就輸入:Y,不需要標(biāo)注地雷則輸入:N\n");
				//清空一下緩沖區(qū)
				while ((ch = getchar()) != '\n');
				scanf("%c", &ch);
				switch (ch)
				{		case 'Y':
					//標(biāo)記雷的位置
					sign_mine(show, row, col);
					break;
				default:
					break;
				}
			}
		}
		else
		{	printf("輸入下標(biāo)非法,請重新輸入:\n");
		}
	}
	//把所有mine中地雷全部顯示到show上
	show_all_mine(mine, show, row, col);
	system("cls");
	//打印棋盤
	display_board(show, row, col);
	//判斷是否排查成功
	if (win >= row * col - COUNT)
	{printf("恭喜你排查出所有的地雷!?。n");
	}
	else
	{printf("掃雷失敗,你被炸死了!?。n");
	}
}

五、最后實(shí)現(xiàn)效果🍖

在這里插入圖片描述
??這就是我今天這一期所帶來的掃雷游戲的實(shí)現(xiàn),希望多多關(guān)注我的其他博客,我想你會收獲很多你完全不了解的新知識?。?!再次感謝你的捧場。


在這里插入圖片描述

這份博客👍如果對你有幫助,給博主一個免費(fèi)的點(diǎn)贊以示鼓勵歡迎各位🔎點(diǎn)贊👍評論收藏??,謝謝?。?!
如果有什么疑問或不同的見解,歡迎評論區(qū)留言歐👀。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


標(biāo)題名稱:掃雷游戲【C語言實(shí)現(xiàn)】【完美版】【非常詳細(xì)的講解,看完必會】-創(chuàng)新互聯(lián)
本文來源:http://weahome.cn/article/jogsg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部