最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言實現(xiàn)經(jīng)典掃雷小游戲完整代碼(遞歸展開?+?選擇標記)

 更新時間:2022年05月11日 14:57:02   作者:野豬佩奇`  
這篇文章主要介紹了C語言小項目之掃雷游戲帶遞歸展開?+?選擇標記效果,本代碼中,我們用字符?!?來標識雷,文中附有完整代碼,需要的朋友可以參考下

大家好,今天我們將一起用C語言實現(xiàn)一個經(jīng)典小游戲 – 掃雷,Let is go !

游戲介紹

掃雷游戲相信大家都玩過,上圖就是一個網(wǎng)頁版的掃雷,它的規(guī)則是玩家選擇一個方格,若此方格沒有地雷,那么該方格會顯示與它相鄰的八個方格中雷的個數(shù),若此方格有地雷,那么游戲失敗,當玩家把除了有地雷的方格外的其他方格都成功翻開時,游戲勝利。

游戲整體框架

對于一個代碼量還算可以的小游戲我們還是利用多文件來進行編程,養(yǎng)成良好習慣,為以后在公司團隊合作編程打下基礎(chǔ),因此我們把掃雷游戲分成三個文件來編寫:

test.c:游戲邏輯的測試,包含游戲菜單的打印,游戲設(shè)計的基本邏輯的展示。

game.c:游戲功能的具體實現(xiàn),這部分是整個游戲的核心代碼,一般不會展示給用戶。

game.h:相關(guān)頭文件的包含、符號的聲明以及函數(shù)的聲明。

游戲具體功能及實現(xiàn)

1、雷盤的定義

對于掃雷游戲,我們遇到的第一個問題就是:應(yīng)該如何表示掃雷的雷盤及如何存放布雷、排雷的數(shù)據(jù);我們發(fā)現(xiàn),二維數(shù)組可以很好的解決這個問題。

如上圖:我們定義了兩個棋盤,分別用來保存布置雷的信息和排查雷的信息,這樣就可以避免二者相互干擾或者相互覆蓋;

同時,我們使用宏來定義雷盤的大小以及雷的個數(shù),這樣做的好處是當我們以后想使用更大的雷盤或者想增加掃雷的難度的時候,我們只需要改動這里一次即可,增加了代碼的可維護性。

另外,很多小伙伴可能會疑惑為什么我這里會定義兩個不同ROW和COL,這其實是為后面的排雷做鋪墊:

如圖:當我們排查1位置時,如果1處不是雷,那么我們就會依次檢查1周圍8個坐標是否有地雷,如果有,就會把地雷的數(shù)量顯示在1位置處;但是當我們排查2位置時,我們發(fā)現(xiàn), 數(shù)組排查雷時會發(fā)生越界,所以為了避免數(shù)組越界,我們就需要增加一系列限制條件,這樣做無疑是比較麻煩的,所以有的大佬就想出了這樣一種辦法:在定義數(shù)組長度時我們直接在上下左右四個方向各多給一行的空間,并把這些空間中的數(shù)據(jù)初始化為非雷,這樣,就輕松解決了數(shù)組越界的問題,不得不說,這種方法實在巧妙!

2、雷盤的初始化

最開始的時候我們把mine數(shù)組元素全部初始化為字符0,把show數(shù)組元素全部初始化為字符*(給用戶一種神秘的感覺)。

3、布置雷

對于布置雷我們有兩個需要注意的地方:

第一是用于隨機生成坐標的rand函數(shù)的種子srand函數(shù)只需要在main函數(shù)中聲明一次即可。

第二是我們在布置雷的時候需要檢查該位置是否已經(jīng)有雷,避免重復(fù)布置。

4、排查雷

排查雷的時候我們首先需要讓用戶輸入需要排查的坐標,然后判斷坐標的合法性及該坐標是否已被排查,其次再判斷該坐標是否有雷,如果沒有,就遞歸檢查它周圍的坐標,直到遇到有雷的坐標才停止遞歸,再讓用戶選擇是否需要標記雷的信息,最后檢查是否滿足游戲勝利的條件。

5、遞歸式展開一片

觀察網(wǎng)頁版的掃雷我們可以發(fā)現(xiàn),當用戶點擊一個坐標,如果該坐標及其周圍的坐標都沒有雷,那么雷盤就會一次性展開一片,而這樣設(shè)計也是比較合理的,因為如果每一個非雷坐標都需要玩家排查的話十分影響游戲體驗;所以,這里我們就利用遞歸的實現(xiàn)模擬實現(xiàn)了這個功能。

6、獲取周圍雷的個數(shù)

7、標記特定位置

同樣:在網(wǎng)頁版的掃雷中,如果我們確定某一位置一定是雷時,我們可以利用標記功能來標識該坐標,方便我們后面的判斷。

本代碼中,我們用字符 ! 來標識雷。

8、打印雷盤

游戲完整代碼 

1、test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
	printf("*****************************************\n");
	printf("*********  1.play      0.exit   *********\n");
	printf("*****************************************\n");
}
void game()
{
	//定義用于存放雷和顯示雷的數(shù)組
	char mine[ROWS][COLS];
	char show[ROWS][COLS];
	//數(shù)組初始化
	BoardInit(mine, ROWS, COLS, '0');
	BoardInit(show, ROWS, COLS, '*');
	//埋雷
	SetMine(mine, ROW, COL);
	system("cls");   //清除菜單,美觀整潔
	//打印雷盤
	//BoardPrint(mine, ROW, COL);   //用于自己調(diào)試觀察,在發(fā)布時注釋掉
	BoardPrint(show, ROW, COL);
	//排雷
	FindMine(mine, show, ROW, COL);
}
int main()
{
	//設(shè)置隨機數(shù)的種子
	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;
}

2、game.h

#pragma once
#include<stdio.h>
#include<windows.h>
#include<time.h>
#include<stdlib.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define MINE_COUNT 10
//數(shù)組初始化
void BoardInit(char board[ROWS][COLS], int rows, int cols, char set);
//埋雷
void SetMine(char board[ROWS][COLS], int row, int col);
//排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//打印雷盤
void BoardPrint(char board[ROWS][COLS], int row, int col);

3、game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//數(shù)組初始化
void BoardInit(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;   //set表示要初識化的字符
		}
	}
}
//埋雷
void SetMine(char board[ROWS][COLS], int row, int col)
{
	int count = MINE_COUNT;
	while (count)
	{
		int x = rand() % row + 1;      //隨機生成雷的坐標
		int y = rand() % col + 1;
		if (board[x][y] == '0')        //檢查該位置是否已經(jīng)有雷
		{
			board[x][y] = '1';
			count--;
		}
	}
}
//打印雷盤
void BoardPrint(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("------掃雷游戲------\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 ", board[i][j]);
		}
		printf("\n");
	}
	printf("------掃雷游戲------\n");
}
//標記雷的位置
void MarkMine(char board[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("請輸入你想要標記位置的坐標->");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)    //判斷該坐標是否合法
		{
			if (board[x][y] == '*')        //判斷該坐標是否被排查
			{
				board[x][y] = '!';
				break;
			}
			else
			{
				printf("該位置不能被標記,請重新輸入!\n");
			}
		}
		else
		{
			printf("輸入錯誤,請重新輸入!\n");
		}
	}
}
//獲取坐標周圍雷的個數(shù)
int GetMineCount(char board[ROWS][COLS], int x, int y)
{
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = x - 1; i <= x + 1; i++)
	{
		for (j = y - 1; j <= y + 1; j++)
		{
			if (board[i][j] == '1')
			{
				count++;
			}
		}
	}
	return count;
}
//遞歸爆炸式展開一片
void ExplosionSpread(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y, int* pw)
{
	if (x >= 1 && x <= row && y >= 1 && y <= col)  //判斷坐標是否為排查范圍內(nèi)
	{
		int num = GetMineCount(mine, x, y);   //獲取坐標周圍雷的個數(shù)
		if (num == 0)
		{
			(*pw)++;
			show[x][y] = ' ';   //如果該坐標周圍沒有雷,就把該坐標置成空格,并向周圍八個坐標展開
			int i = 0;
			int j = 0;
			for (i = x - 1; i <= x + 1; i++)
			{
				for (j = y - 1; j <= y + 1; j++)
				{
					if (show[i][j] == '*')    //限制遞歸條件,防止已經(jīng)排查過的坐標再次遞歸,從而造成死遞歸
						ExplosionSpread(mine, show, row, col, i, j, pw);
				}
			}
		}
		else
		{
			(*pw)++;
			show[x][y] = num + '0';
		}
	}
}
//排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;  //用來標記是否取得勝利
	int* pw = &win;
	char ch = 0;   //用來接受是否需要標記雷
	while (win < row * col - MINE_COUNT)
	{
		printf("請輸入你想要排查的坐標->");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)   //判斷坐標合法性
		{
			if (mine[x][y] == '1')
			{
				system("cls");
				printf("很遺憾,你被炸死了!\n");
				BoardPrint(mine, row, col);   //被炸死了就打印mine數(shù)組,讓用戶知道自己怎么死的
				break;
			}
			else
			{
				if (show[x][y] != '*')   //判斷是否重復(fù)排查
				{
					printf("該坐標已被排查,請重新輸入!\n");
					continue;  //直接進入下一次循環(huán)
				}
				else
				{
					ExplosionSpread(mine, show, row, col, x, y, pw);  //爆炸展開一片
					system("cls");  //清空屏幕
					BoardPrint(show, row, col);  //打印棋盤
					printf("需要標記雷的位置請輸入y/Y,否則請按任意鍵->");
					while ((ch = getchar()) != '\n');  //清理緩沖區(qū)
					scanf("%c", &ch);
					if (ch == 'Y' || ch == 'y')
					{
						MarkMine(show, row, col);   //標記雷
						system("cls");
						BoardPrint(show, row, col);
					}
					else
					{
						continue;
					}
				}
			}
		}
		else
		{
			printf("輸入錯誤,請重新輸入!\n");
		}
	}
	if (win == row * col - MINE_COUNT)
	{
		system("cls");
		printf("恭喜你,排雷成功!\n");
		BoardPrint(show, row, col);
		return;
	}
}

游戲效果展示

到此這篇關(guān)于C語言小項目之掃雷游戲完整代碼(遞歸展開 + 選擇標記)的文章就介紹到這了,更多相關(guān)C語言掃雷游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++中?‘=default?’及‘?=delete?’的使用

    C++中?‘=default?’及‘?=delete?’的使用

    這篇文章主要介紹了C++中?=default?及?=delete?使用,使用=default和=delete可以控制編譯器默認函數(shù)體的使用,下面我們就來看看具體的室友方法吧,需要的朋友也可以參考一下
    2021-12-12
  • c語言合并兩個已排序數(shù)組的示例(c語言數(shù)組排序)

    c語言合并兩個已排序數(shù)組的示例(c語言數(shù)組排序)

    如何將兩個已排序數(shù)組合并成一個排序數(shù)組,下面我們給出使用c語言合并兩個已排序數(shù)組的示例,需要的朋友可以參考下
    2014-03-03
  • C++內(nèi)存管理詳細解析

    C++內(nèi)存管理詳細解析

    這篇文章主要給大家分享的是C++內(nèi)存管理的詳細內(nèi)容學習,下面文章圍繞C++內(nèi)存管理的相關(guān)資料展開具體學習內(nèi)容,需要的朋友可以參考一下,希望對你有所幫助
    2021-11-11
  • 如何在C++類的外部調(diào)用類的私有方法

    如何在C++類的外部調(diào)用類的私有方法

    這篇文章主要介紹了如何在C++類的外部調(diào)用類的私有方法,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下
    2022-09-09
  • C語言數(shù)據(jù)結(jié)構(gòu)遞歸之斐波那契數(shù)列

    C語言數(shù)據(jù)結(jié)構(gòu)遞歸之斐波那契數(shù)列

    這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)遞歸之斐波那契數(shù)列的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-10-10
  • VC中Tab control控件的用法詳細解析

    VC中Tab control控件的用法詳細解析

    以下是對VC中Tab control控件的用法進行了詳細的介紹,需要的朋友可以過來參考下哦
    2013-09-09
  • 詳解C#byte數(shù)組怎么傳入C

    詳解C#byte數(shù)組怎么傳入C

    在本篇內(nèi)容里小編給大家整理了關(guān)于C#byte數(shù)組怎么傳入C的相關(guān)知識點內(nèi)容,有興趣的朋友們學習參考下。
    2019-03-03
  • C/C++讀寫JSON數(shù)據(jù)的詳細過程記錄

    C/C++讀寫JSON數(shù)據(jù)的詳細過程記錄

    JSON文件無論是在web開發(fā)、客戶端開發(fā)、服務(wù)端等開發(fā)中都是應(yīng)用比較廣泛的的第一種輕量級數(shù)據(jù)交換格式,非常方便閱讀和編寫,下面這篇文章主要給大家介紹了關(guān)于C/C++讀寫JSON數(shù)據(jù)的詳細過程,需要的朋友可以參考下
    2023-04-04
  • C語言用Easyx繪制圍棋和象棋的棋盤

    C語言用Easyx繪制圍棋和象棋的棋盤

    這篇文章主要為大家詳細介紹了C語言用Easyx繪制圍棋和象棋的棋盤,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Qt實現(xiàn)簡單TCP服務(wù)器

    Qt實現(xiàn)簡單TCP服務(wù)器

    這篇文章主要為大家詳細介紹了Qt實現(xiàn)簡單TCP服務(wù)器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08

最新評論

平利县| 太保市| 澜沧| 堆龙德庆县| 馆陶县| 拉萨市| 无棣县| 桐梓县| 呼伦贝尔市| 深圳市| 黎平县| 玉树县| 遵化市| 卓资县| 马公市| 都江堰市| 永和县| 弥渡县| 托里县| 娱乐| 综艺| 耒阳市| 宜章县| 丹江口市| 湖南省| 乌什县| 通海县| 黄浦区| 南川市| 镇沅| 全南县| 山东省| 略阳县| 四会市| 南岸区| 郧西县| 临城县| 尼木县| 遂溪县| 三台县| 桑日县|