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

C語(yǔ)言實(shí)現(xiàn)掃雷小游戲的全過程記錄

 更新時(shí)間:2021年04月08日 10:37:15   作者:JunFengYiHan  
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言實(shí)現(xiàn)掃雷小游戲的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

第一步思考要實(shí)現(xiàn)的功能

想必大家都知道掃雷這個(gè)小游戲,今天我們來(lái)用C語(yǔ)言實(shí)現(xiàn)一下,首先要掃雷,我們首先就需要有一個(gè)布置了雷的棋盤,然后開始掃雷,玩過掃雷的小伙伴都知道,如果選中的格子旁邊沒有雷,那么旁邊的格子就會(huì)自動(dòng)清空,大概的思路有了,現(xiàn)在我們開始實(shí)現(xiàn)。

第二步實(shí)現(xiàn)

初級(jí)版掃雷

首先創(chuàng)建棋盤的作用是用來(lái)存儲(chǔ)雷的信息,這時(shí)我們思考一下,一個(gè)棋盤到底夠不夠用?棋盤多大才合適?我們打印出來(lái)的棋盤肯定是不能出現(xiàn)雷的信息的,不然游戲就無(wú)法正常進(jìn)行了,但是我們雷的信息又需要棋盤存儲(chǔ),這樣一想,一個(gè)棋盤似乎做不到,那么我們就可以再創(chuàng)建一個(gè)棋盤以達(dá)到既能存儲(chǔ)雷的信息也能打印一個(gè)不含雷的棋盤,保證游戲的正常進(jìn)行。

char mineboard[ROWS][COLS] = { 0 };//存放雷的數(shù)組
char showboard[ROWS][COLS] = { 0 };//展示信息的數(shù)組

讀者可以思考一下為什么這里創(chuàng)建的是字符數(shù)組,現(xiàn)在棋盤有了,但是里面放了什么我們并不確定放了些什么,所有我們將它初始化一下

initboard(mineboard, ROWS, COLS, '0');
initboard(showboard, ROWS, COLS, '*');
void initboard(char board[ROWS][COLS], int rows, int cols, char ret)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for(j = 0; j < cols; j++)
		{
			board[i][j] = ret;//ret為要初始化字符
		}
	}
}

有些讀者看到ROWS和COLS可能就會(huì)疑惑了,下標(biāo)怎么是符號(hào),其實(shí)這是因?yàn)椴┲魍ㄟ^#define將這兩個(gè)符號(hào)定義成了兩個(gè)數(shù)字

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

這樣做的好處就是,當(dāng)需要修改棋盤的大小時(shí),只需要改變這一處即可,至于MINE_NUM為要布置的雷的個(gè)數(shù),暫時(shí)用不上,我們先繼續(xù)實(shí)現(xiàn),既然棋盤有了,也初始化了,那么我們先打印出來(lái)看一下,是不是和我們預(yù)想的一樣,我們封裝一個(gè)打印函數(shù)實(shí)現(xiàn)打印

void printboard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 1; i <= row; i++)
	{
		if (1 == i)
		{
			for (j = 0; j <= col; j++)
			{
				printf(" %d", j);
			}
			printf("\n");
		}
		for (j = 1; j <= col; j++)
		{
			if (1 == j)
			{
				printf(" %d", i);
			}
			printf(" %c", board[i][j]);
		}
		printf("\n");
	}
}
printboard(mineboard, ROW, COL);//調(diào)用函數(shù)打印雷的信息
printboard(showboard, ROW, COL);//調(diào)用函數(shù)打印展示的的信息

接下來(lái)我們布置雷,同樣封裝一個(gè)布雷函數(shù),但是布雷,總不能人為布置吧,不然雷都知道了就沒得完了,所以我們應(yīng)該讓電腦幫我們布雷,而且多次游戲的話,雷的位置肯定不能一樣,所以我們就需要一個(gè)庫(kù)函數(shù)來(lái)幫我們實(shí)現(xiàn)隨機(jī)布雷

		srand((unsigned int)time(NULL));//生成隨機(jī)數(shù)的種子
void setmine(char board[ROWS][COLS], int mine_num, int row, int col)
{
	while (mine_num)
	{
		int x = rand() % row + 1;//生成隨機(jī)數(shù)
		int y = rand() % col + 1;//生成隨機(jī)數(shù)
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			mine_num--;
		}
	}
}
	setmine(mineboard, MINE_NUM, ROW, COL);//調(diào)用布雷函數(shù)布雷

我們可以看到我們傳遞參數(shù)的時(shí)候就用到了MINE_NUM雷的個(gè)數(shù)這個(gè)符號(hào)常量,因?yàn)槌A坎豢杀恍薷?,所以我們將它放在?shí)參的位置上而不是直接用它,布置好雷之后,我們調(diào)用打印函數(shù)將雷盤信息打印一下。

printboard(mineboard, ROW, COL);

確認(rèn)信息無(wú)誤后,我們接著實(shí)現(xiàn)游戲,同樣封裝成一個(gè)函數(shù)

void play(char mineboard[ROWS][COLS], char showboard[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int n = 0;//記錄已排除的格子
	
	while (row * col - MINE_NUM - n)
	{
		printf("請(qǐng)輸入坐標(biāo),以空格隔開輸入>:");
		scanf("%d %d", &x, &y);
		if (x > ROW || y > COL || x < 1 || y < 1)
		{
			printf("坐標(biāo)非法,請(qǐng)重新輸入\n");
			continue;
		}
		if (mineboard[x][y] != '1')
		{
			int ret = find(mineboard, x, y);
			if (ret != 0)
			{
				showboard[x][y] = ret + '0';
				//n++;
			}
			else
			{
				showboard[x][y] = ' ';
				//spread(showboard, mineboard, x, y);
				
			}
			n = Isblank(showboard, row, col);//檢查已經(jīng)有多少格子已經(jīng)排除
			system("cls");
			printboard(showboard, row, col);
		}
		else
		{
			break;
		}
	}
	if (row * col - MINE_NUM - n)
	{
		printf("很遺憾,你被炸死了\n");	
	}
	else
	{
		printf("恭喜你,掃雷成功\n");
	}
	printboard(mineboard, row, col);
}
	play(mineboard, showboard, ROW, COL);//調(diào)用函數(shù),開始游戲

在開始游戲之前無(wú)疑我們要先要先將展示的棋盤和提示信息打印出來(lái),讓玩家看到,從而進(jìn)行游戲,所以我們?cè)陂_始游戲之前調(diào)用一下打印函數(shù)

printboard(showboard, ROW, COL);

接下來(lái)就是游戲的實(shí)現(xiàn)了,可以看到游戲函數(shù)中有很多函數(shù)的接口比如find,Isblank等這就是我們接下來(lái)要實(shí)現(xiàn)的功能函數(shù),開始游戲給與提示,讀入坐標(biāo),并對(duì)坐標(biāo)進(jìn)行判斷,是否合法,不合法則提示玩家重新輸入,如果合法,則判斷斷當(dāng)前坐標(biāo)是不是雷如果是則退出循環(huán),游戲結(jié)束,并給與提示,如果不是雷則判斷附近有沒有雷,沒有則置為空也就是空格,有雷則放入附近雷的信息,然后判斷是不是所有不是雷的空格都找到了,如果不是則繼續(xù)游戲,重復(fù)剛才的判斷,是則游戲結(jié)束,掃雷成功,排雷功能在上面代碼已經(jīng)實(shí)現(xiàn),接下來(lái)實(shí)現(xiàn)判斷功能,其實(shí)很簡(jiǎn)單,遍歷棋盤,看看是不是所有不是雷的元素都被找出來(lái)即可

查找輸入坐標(biāo)附近雷的信息

int find(char board[ROWS][COLS], int x, int y)
{
	int i = 0;
	int j = 0;
	int count = 0;
	if (x > 0 && x < ROW && y > 0 && y < COL)
	{
		for (i = x - 1; i <= x + 1; i++)
		{
			for (j = y - 1; j <= y + 1; j++)
			{
				if (board[i][j] == '1')
					count++;
			}
		}
	}
	return count;
}

統(tǒng)計(jì)已排除的坐標(biāo)個(gè)數(shù)

int Isblank(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int n = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (board[i][j] != '*')
			{
				n++;
			}
		}
	}
	return n;
}

返回值就是我們需要的已經(jīng)被排查的坐標(biāo)個(gè)數(shù)了,判斷一下總的坐標(biāo)個(gè)數(shù)和雷的個(gè)數(shù)加已排除的坐標(biāo)個(gè)數(shù)即可,所以我們將這個(gè)條件作為循環(huán)停止的條件,如play函數(shù)中的while即可。

因?yàn)橥顺鲅h(huán)的原因有兩個(gè),所以我們對(duì),退出的條件進(jìn)行一下判斷,用如下代碼即可

if (row * col - MINE_NUM - n)
	{
		printf("很遺憾,你被炸死了\n");	
	}
	else
	{
		printf("恭喜你,掃雷成功\n");
	}

到此初級(jí)的簡(jiǎn)單掃雷游戲就實(shí)現(xiàn)了。

掃雷進(jìn)階—遞歸實(shí)現(xiàn)自動(dòng)清空

初級(jí)版本的掃雷游戲只能輸入一個(gè)坐標(biāo)判斷一次,完成掃雷無(wú)疑是巨大的挑戰(zhàn),甚至說完全憑運(yùn)氣,所以我們來(lái)實(shí)現(xiàn)一下自動(dòng)清空附近沒有一個(gè)雷的坐標(biāo),來(lái)降低游戲的難度,接下來(lái)我們來(lái)實(shí)現(xiàn)這個(gè)功能,細(xì)心的小伙伴們會(huì)發(fā)現(xiàn)我在play函數(shù)中我留了一個(gè)名為spread的函數(shù)接口,而這個(gè)接口就是我們調(diào)用自動(dòng)清空函數(shù)的入口,因?yàn)樯厦鏇]有實(shí)現(xiàn)這個(gè)函數(shù),所以我就將它注釋掉了,現(xiàn)在我們將它還原即可。

void spread(char showboard[ROWS][COLS], char mineboard[ROWS][COLS], int x, int y)
{
	showboard[x][y] = ' ';
	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++)
		{
			if (i > 0 && i <= ROW && j > 0 && j <= COL && mineboard[i][j] != '1' && showboard[i][j] == '*')
			{
				ret = find(mineboard, i, j);
				if (!ret)
				{
					spread(showboard, mineboard, i, j);
				}
				if (ret)
				{
					showboard[i][j] = ret + '0';
				}
				else if (showboard[i][j] == '*')
				{
					showboard[i][j] = ' ';
				}
			}
			
		}
	}
}

到此我們的掃雷就很好的實(shí)現(xiàn)了。小伙伴們趕緊試試吧。

完整的源碼

頭文件

#pragma once

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

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

//打印菜單
void menu();
//提示
void playgame();
//初始化雷盤
void initboard(char board[ROWS][COLS], int rows, int cols, char ret);
//打印雷盤
void printboard(char board[ROWS][COLS], int row, int col);
//布置雷
void setmine(char board[ROWS][COLS], int mine_num, int row, int col);
//掃雷
void play(char mineboard[ROWS][COLS], char showboard[ROWS][COLS], int row, int col);

函數(shù)定義的源文件

#define _CRT_SECURE_NO_WARNINGS

#include"game.h"

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

void playgame()
{
	printf("游戲開始");
	Sleep(650);
	system("cls");
}

void initboard(char board[ROWS][COLS], int rows, int cols, char ret)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for(j = 0; j < cols; j++)
		{
			board[i][j] = ret;
		}
	}
}

void printboard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 1; i <= row; i++)
	{
		if (1 == i)
		{
			for (j = 0; j <= col; j++)
			{
				printf(" %d", j);
			}
			printf("\n");
		}
		for (j = 1; j <= col; j++)
		{
			if (1 == j)
			{
				printf(" %d", i);
			}
			printf(" %c", board[i][j]);
		}
		printf("\n");
	}
}

void setmine(char board[ROWS][COLS], int mine_num, int row, int col)
{
	while (mine_num)
	{
		int x = rand() % row + 1;//生成隨機(jī)數(shù)
		int y = rand() % col + 1;//生成隨機(jī)數(shù)
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			mine_num--;
		}
	}
}

int find(char board[ROWS][COLS], int x, int y)
{
	int i = 0;
	int j = 0;
	int count = 0;
	if (x > 0 && x < ROW && y > 0 && y < COL)
	{
		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 spread(char showboard[ROWS][COLS], char mineboard[ROWS][COLS], int x, int y)
{
	//if (x > 0 && x <= ROW && y > 0 && y <= COL)
	//{
		showboard[x][y] = ' ';
		//*pn += 1;
		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++)
			{
				if (i > 0 && i <= ROW && j > 0 && j <= COL && mineboard[i][j] != '1' && showboard[i][j] == '*')
				{
					ret = find(mineboard, i, j);
					if (!ret)
					{
						spread(showboard, mineboard, i, j);
					}
					if (ret)
					{
						showboard[i][j] = ret + '0';
						//*pn += 1;
					}
					else if (showboard[i][j] == '*')
					{
						showboard[i][j] = ' ';
						//*pn += 1;
					}
				}
				
			}
		}
	//}
}
int Isblank(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int n = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <= col; j++)
		{
			if (board[i][j] != '*')
			{
				n++;
			}
		}
	}
	return n;
}

void play(char mineboard[ROWS][COLS], char showboard[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int n = 0;//記錄已排除的格子
	
	while (row * col - MINE_NUM - n)
	{
		printf("請(qǐng)輸入坐標(biāo),以空格隔開輸入>:");
		scanf("%d %d", &x, &y);
		if (x > ROW || y > COL || x < 1 || y < 1)
		{
			printf("坐標(biāo)非法,請(qǐng)重新輸入\n");
			continue;
		}
		if (mineboard[x][y] != '1')
		{
			int ret = find(mineboard, x, y);
			if (ret != 0)
			{
				showboard[x][y] = ret + '0';
				//n++;
			}
			else
			{
				//showboard[x][y] = ' ';
				spread(showboard, mineboard, x, y);
				
			}
			n = Isblank(showboard, row, col);//檢查已經(jīng)有多少格子已經(jīng)排除
			system("cls");
			printboard(showboard, row, col);
		}
		else
		{
			break;
		}
	}
	if (row * col - MINE_NUM - n)
	{
		printf("很遺憾,你被炸死了\n");	
	}
	else
	{
		printf("恭喜你,掃雷成功\n");
	}
	printboard(mineboard, row, col);
}

測(cè)試的源文件

#define _CRT_SECURE_NO_WARNINGS

#include"game.h"

void game()
{
	playgame();
	char mineboard[ROWS][COLS] = { 0 };//存放雷的數(shù)組
	char showboard[ROWS][COLS] = { 0 };//展示信息的數(shù)組
	initboard(mineboard, ROWS, COLS, '0');
	//printboard(mineboard, ROW, COL);
	initboard(showboard, ROWS, COLS, '*');
	printboard(showboard, ROW, COL);
	setmine(mineboard, MINE_NUM, ROW, COL);
	//printboard(mineboard, ROW, COL);
	play(mineboard, showboard, ROW, COL);

}

int main()
{
	int Input = 0;
	do 
	{
		srand((unsigned int)time(NULL));//隨機(jī)數(shù)的種子
		menu();
		printf("請(qǐng)選擇>:");
		scanf("%d", &Input);
		switch (Input)
		{
		case 1:game(); 
			break;
		case 0:printf("退出游戲\n");
			break;
		default:printf("選擇錯(cuò)誤,請(qǐng)重新選擇\n");
			break;
		}
	} while (Input);
	return 0;
}

寫在最后的話

現(xiàn)在我們來(lái)解釋一下,之前留下的問題,為什么要用字符數(shù)組,因?yàn)樽址麛?shù)組的打印可以更多形式可以是#,*,!等等比數(shù)字無(wú)疑多出很多可能,而且字符也有數(shù)字可以表示,玩家看上去并無(wú)區(qū)別,棋盤為什么是11 * 11的呢,那是因?yàn)檫@樣輸入的下標(biāo)就可以直接當(dāng)作棋盤的下標(biāo)使用了,也可以防止遍歷的時(shí)候越界,這樣說小伙伴們可以理解嗎?

到此這篇關(guān)于C語(yǔ)言實(shí)現(xiàn)掃雷小游戲的文章就介紹到這了,更多相關(guān)C語(yǔ)言掃雷小游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C/C++讀取配置文件的方式小結(jié)

    C/C++讀取配置文件的方式小結(jié)

    這篇文章主要為大家詳細(xì)介紹了C/C++中讀取配置文件的幾種常見方式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-04-04
  • C++全面覆蓋內(nèi)存管理知識(shí)講解

    C++全面覆蓋內(nèi)存管理知識(shí)講解

    本章主要介紹C語(yǔ)言與C++的內(nèi)存管理,以C++的內(nèi)存分布作為引入,介紹C++不同于C語(yǔ)言的內(nèi)存管理方式(new delete對(duì)比 malloc free),感興趣的朋友來(lái)看看吧
    2022-06-06
  • C++中std::vector的6種初始化方式

    C++中std::vector的6種初始化方式

    這篇文章主要介紹了C++中std::vector的6種初始化方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • MacOS下C++使用WebRTC注意事項(xiàng)及問題解決

    MacOS下C++使用WebRTC注意事項(xiàng)及問題解決

    這篇文章主要介紹了MacOS下C++使用WebRTC注意事項(xiàng),對(duì)于iOS/macOS平臺(tái),開啟openh264,去除test,使用一些命令可以輕松解決,下面小編給大家?guī)?lái)了問題及解決方法,需要的朋友可以參考下
    2022-09-09
  • C++多態(tài)的示例詳解

    C++多態(tài)的示例詳解

    多態(tài)按字面的意思就是多種形態(tài)。當(dāng)類之間存在層次結(jié)構(gòu),并且類之間是通過繼承關(guān)聯(lián)時(shí),就會(huì)用到多態(tài)。本文將通過三個(gè)小案例讓大家更深入的了解一下C++的多態(tài),感興趣的可以了解一下
    2022-06-06
  • C++中l(wèi)ist容器的實(shí)現(xiàn)

    C++中l(wèi)ist容器的實(shí)現(xiàn)

    本文主要介紹了C++中l(wèi)ist容器的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • C++語(yǔ)言實(shí)現(xiàn)拼圖游戲詳解

    C++語(yǔ)言實(shí)現(xiàn)拼圖游戲詳解

    這篇文章主要為大家詳細(xì)介紹了C++基于EasyX庫(kù)實(shí)現(xiàn)拼圖小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • C++實(shí)現(xiàn)酒店管理系統(tǒng)

    C++實(shí)現(xiàn)酒店管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)酒店管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • C語(yǔ)言實(shí)現(xiàn)enum枚舉

    C語(yǔ)言實(shí)現(xiàn)enum枚舉

    在實(shí)際編程中,有些數(shù)據(jù)的取值往往是有限的,只能是非常少量的整數(shù),并且最好為每個(gè)值都取一個(gè)名字,以方便在后續(xù)代碼中使用,比如一個(gè)星期只有七天,一年只有十二個(gè)月,一個(gè)班每周有六門課程等。 以每周七天為例,我們可以使用#define命令來(lái)給每天指定一個(gè)名字
    2021-06-06
  • 合并排序(C語(yǔ)言實(shí)現(xiàn))

    合并排序(C語(yǔ)言實(shí)現(xiàn))

    遞歸算法是把一個(gè)問題分解成和自身相似的子問題,然后再調(diào)用自身把相應(yīng)的子問題解決掉。這些算法用到了分治思想。
    2013-02-02

最新評(píng)論