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

C語言二維數(shù)組運用實現(xiàn)掃雷游戲

 更新時間:2022年06月07日 14:18:33   作者:多喝苦瓜身體好  
這篇文章主要為大家詳細(xì)介紹了C語言二維數(shù)組運用實現(xiàn)掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

作為80后、90后的老年人,想必對掃雷游戲都不陌生。
掃雷,是微軟在win8版本之前系統(tǒng)自帶的一款游戲——現(xiàn)在已經(jīng)被下架了,童年的回憶,很難受。
游戲操作很簡單,首先初始化一個m×n的方塊矩陣,然后玩家不斷地翻開方塊,直到所有沒有雷的方塊都被翻開,游戲勝利。
在玩家進行操作的時候,游戲會適當(dāng)?shù)慕o予玩家一些提示:分布在雷周圍的方塊會顯示出數(shù)字提示周圍八個小方塊里有幾個雷,這樣,玩家就可以根據(jù)提示來排除那些藏了雷的小方塊。
現(xiàn)在,我們根據(jù)游戲規(guī)則來整理一下程序的思路:

1、創(chuàng)建兩個二維數(shù)組,分別保存雷的分布地圖和顯示給玩家的地圖;
2、分別初始化這兩個數(shù)組;
3、打印初始地圖
4、讀取玩家輸入的坐標(biāo)并對其進行合法性判定;
5、若玩家的輸入合法, 對地圖進行更新, 否則, 提示玩家重新輸入;
6、判定游戲是否結(jié)束, 若結(jié)束轉(zhuǎn)到6, 否則重復(fù)3~6
7、輸出游戲結(jié)果.

現(xiàn)在根據(jù)思路來寫一下程序大致的框架了.
首先, 要兩個二維數(shù)組, 那么問題來了, 數(shù)組要多大才合適呢? 顯然, 數(shù)組的大小要和游戲的規(guī)模大小相同——也就是方塊矩陣的大小和雷的數(shù)量,而這個矩陣多大、雷有多少,我們不知道,為了方便修改,我們使用宏定義來定義:

#define MAX_ROW 10?? ?//矩陣行數(shù)
#define MAX_COL 10?? ?//矩陣列數(shù)
#define MAX_MINE 10?? ?//雷的數(shù)量

然后創(chuàng)建兩個二維數(shù)組:

char mine_map[MAX_ROW][MAX_COL];
char game_map[MAX_ROW][MAX_COL];

mine_map是保存雷的分布數(shù)據(jù)的地圖,game_map則是顯示給用戶的地圖。
然后分別對這兩個地圖進行初始化,game_map的初始化比較簡單:

void init_map(char a[MAX_ROW][MAX_COL])
{
?? ?for (int i = 0; i < MAX_ROW; i++)
?? ??? ?for (int j = 0; j < MAX_COL; j++)
?? ??? ??? ?a[i][j] = '#';
}

而mine_map的初始化則比較復(fù)雜了。首先,需要隨機生成MAX_MINE個雷,這里我們使用rand()函數(shù)來生成,并在初始化之前生成一個隨機種子。接著,在生成完MAX_MINE個雷之后,對mine_map掃描一次,在雷的周圍的小方塊里生成提示數(shù)字:

//計算一個小方塊的周圍有幾個雷的函數(shù)
void cal_mine(char a[MAX_ROW][MAX_COL], int row, int col)
{
?? ?for (int r = row - 1; r < row + 2; r++)
?? ??? ?for (int c = col - 1; c < col + 2; c++)
?? ??? ?{
?? ??? ??? ?if (r >= 0 && r < MAX_ROW
?? ??? ??? ??? ?&& c >= 0 && c < MAX_COL
?? ??? ??? ??? ?&& a[r][c] != '*')
?? ??? ??? ??? ?a[r][c] = a[r][c] + 1;
?? ??? ?}
}
//生成游戲地圖
void create_map(char map[MAX_ROW][MAX_COL])
{
?? ?int count = 0;
?? ?int row;
?? ?int col;
?? ?for (int i = 0; i < MAX_ROW; i++)
?? ??? ?for (int j = 0; j < MAX_COL; j++)
?? ??? ??? ?map[i][j] = '0';
?? ?while (count < MAX_MINE)
?? ?{
?? ??? ?row = rand() % MAX_ROW;
?? ??? ?col = rand() % MAX_COL;
?? ??? ?if (map[row][col] != '*')
?? ??? ??? ?map[row][col] = '*';
?? ??? ?else
?? ??? ??? ?continue;
?? ??? ?count += 1;
?? ?}
?? ?for (int i = 0; i < MAX_ROW; i++)
?? ??? ?for (int j = 0; j < MAX_COL; j++)
?? ??? ?{
?? ??? ??? ?if (map[i][j] == '*')
?? ??? ??? ??? ?cal_mine(map, i, j);
?? ??? ?}
}

之后就是更新地圖和打印地圖的函數(shù)了,為了方便調(diào)試上面這兩個初始化函數(shù),我們先寫打印地圖函數(shù):

void display_map(char gmap[MAX_ROW][MAX_COL])
{
?? ?system("cls");
?? ?for (int r = MAX_ROW - 1; r >= 0; r--)
?? ?{
?? ??? ?printf(" %2d|", r + 1);
?? ??? ?for (int c = 0; c < MAX_COL; c++)
?? ??? ??? ?printf(" %c", gmap[r][c]);
?? ??? ?printf("\n");
?? ?}
?? ?printf(" ? |");
?? ?for (int i = 0; i < MAX_COL; i++)
?? ??? ?printf("__");
?? ?printf("\n ? ? ");
?? ?for (int i = 0; i < MAX_COL; i++)
?? ??? ?printf("%-2d", i + 1);
?? ?printf("\n");
}

這個函數(shù)的可讀性并不好,因為這個地圖長啥樣完全是根據(jù)我的喜好來定的,雖然用控制臺寫的程序都丑,但是它丑得有多別致由我決定······這個函數(shù)不同的人能玩出不同的花,以上僅供參考。
最后就是更新地圖函數(shù)了,先寫一個函數(shù)框架吧:

int renew_map(char game[MAX_ROW][MAX_COL],?
?? ??? ??? ?char mine[MAX_ROW][MAX_COL],
?? ??? ??? ? int row, int col)
{
?? ?int count;
?? ?game[row][col] = mine[row][col];
?? ?if (mine[row][col] == '*')
?? ??? ?return 0;
?? ?else if (mine[row][col] != '0')
?? ??? ?return 1;
?? ?count = continues_map(game, mine, row, col);
?? ?return count;
}

如果讀到了雷,返回0;如果讀到了非零區(qū)域,則將其翻開;若讀到了周圍沒有雷的區(qū)域,則將其周圍的方塊自動翻開,直到不為0為止,這里我使用了一個叫continues_map的函數(shù)。
那么問題來了,要如何實現(xiàn)自動翻開的功能呢?
要回答這個問題,首先就要清楚連續(xù)翻的規(guī)則:在掃雷游戲中,提示數(shù)為0的方塊表示周圍沒有雷,因此這個方塊周圍的八個方塊都是可以翻開的,而且如果這八個方塊之中有提示數(shù)為0的方塊,則繼續(xù)將該方塊的周圍八個方塊翻開,直到碰到提示數(shù)不為0的方塊為止,并將其翻開······這樣來看,能否用循環(huán)語句來實現(xiàn)呢?我們想想算法思路:

1、判斷該方塊是否是“0”方塊. 如果是,則掃描該方塊的周圍8個小方塊;如果不是,則將該提示數(shù)錄入game_map中;
2、對這8個方塊分別執(zhí)行步驟1.

考慮一下極端情況,若這8個方塊也都是“0”方塊,那么是否能用循環(huán)繼續(xù)對這八個方塊分別掃描?就算可以,繼續(xù)考慮極端情況,能否繼續(xù)用循環(huán)對周圍16個方塊進行掃描?隨著問題規(guī)模的增加,循環(huán)逐漸乏力,也就是說使用循環(huán)處理該問題并不好——就算用循環(huán)實現(xiàn)了,代碼也將會非常復(fù)雜,可讀性非常之差,不利于后期的維護和修改。
那應(yīng)該使用什么方法來實現(xiàn)?我們接著看算法思路,首先進行判斷,如果條件滿足,則將原問題分解為8個子問題,再對這8個子問題進行之前的操作,直到將所有滿足判斷條件的子問題處理完為止——這樣來看,這不就是遞歸調(diào)用的特性嘛。
于是,只要將該函數(shù)寫成遞歸形式不就行了嘛:

int continues_map(char game[MAX_ROW][MAX_COL], char mine[MAX_ROW][MAX_COL], int row, int col)
{
?? ?int count = 1;
?? ?int left = col - 1, right = col + 1, up = row + 1, down = row - 1;
?? ?if (left >= 0 && game[row][left] == '#' && mine[row][left] == '0')
?? ?{
?? ??? ?game[row][left] = '0';
?? ??? ?count = count + continues_map(game, mine, row, left);
?? ?}
?? ?else if (left >= 0 && game[row][left] == '#')
?? ?{
?? ??? ?game[row][left] = mine[row][left];
?? ??? ?count++;
?? ?}
?? ?if (right < MAX_COL && game[row][right] == '#' && mine[row][right] == '0')
?? ?{
?? ??? ?game[row][right] = '0';
?? ??? ?count = count + continues_map(game, mine, row, right);
?? ?}
?? ?else if (right < MAX_COL && game[row][right] == '#')
?? ?{
?? ??? ?game[row][right] = mine[row][right];
?? ??? ?count++;
?? ?}
?? ?if (up < MAX_ROW && game[up][col] == '#' && mine[up][col] == '0')
?? ?{
?? ??? ?game[up][col] = '0';
?? ??? ?count = count + continues_map(game, mine, up, col);
?? ?}
?? ?else if (up < MAX_ROW && game[up][col] == '#')
?? ?{
?? ??? ?game[up][col] = mine[up][col];
?? ??? ?count++;
?? ?}
?? ?if (down >= 0 && game[down][col] == '#' && mine[down][col] == '0')
?? ?{
?? ??? ?game[down][col] = '0';
?? ??? ?count = count + continues_map(game, mine, down, col);
?? ?}
?? ?else if (down >= 0 && game[down][col] == '#')
?? ?{
?? ??? ?game[down][col]= mine[down][col];
?? ??? ?count++;
?? ?}
?? ?if (left >= 0 && game[up][left] == '#' && mine[up][left] == '0')
?? ?{
?? ??? ?game[up][left] = '0';
?? ??? ?count = count + continues_map(game, mine, up, left);
?? ?}
?? ?else if (left >= 0 && game[up][left] == '#')
?? ?{
?? ??? ?game[up][left] = mine[up][left];
?? ??? ?count++;
?? ?}
?? ?if (right < MAX_COL && game[up][right] == '#' && mine[up][right] == '0')
?? ?{
?? ??? ?game[up][right] = '0';
?? ??? ?count = count + continues_map(game, mine, up, right);
?? ?}
?? ?else if (right < MAX_COL && game[up][right] == '#')
?? ?{
?? ??? ?game[up][right] = mine[up][right];
?? ??? ?count++;
?? ?}
?? ?if (left >= 0 && game[down][left] == '#' && mine[down][left] == '0')
?? ?{
?? ??? ?game[down][left] = '0';
?? ??? ?count = count + continues_map(game, mine, down, left);
?? ?}
?? ?else if (left >= 0 && game[down][left] == '#')
?? ?{
?? ??? ?game[down][left] = mine[down][left];
?? ??? ?count++;
?? ?}
?? ?if (right < MAX_COL && game[down][right] == '#' && mine[down][right] == '0')
?? ?{
?? ??? ?game[down][right] = '0';
?? ??? ?count = count + continues_map(game, mine, down, right);
?? ?}
?? ?else if (right < MAX_COL && game[down][right] == '#')
?? ?{
?? ??? ?game[down][right] = mine[down][right];
?? ??? ?count++;
?? ?}
?? ?return count;
}

一共八種情況和終止條件,寫成遞歸都挺復(fù)雜的,更不用說循環(huán)了······
寫到這里,一個用以實現(xiàn)掃雷游戲功能的程序大致就寫得差不多了,再加上一個主函數(shù)就可以玩了。主函數(shù)的功能主要就是對以上的函數(shù)進行調(diào)用來實現(xiàn)游戲功能,并對玩家輸入的合法性進行判斷,代碼如下:

int main()
{
?? ?srand((unsigned)time(0));
?? ?char mine_map[MAX_ROW][MAX_COL];
?? ?char game_map[MAX_ROW][MAX_COL];
?? ?int input_row = 0;
?? ?int input_col = 0;
?? ?int count = 0;
?? ?int increase = 0;
?? ?display_map(game_map);
?? ?while (count < MAX_ROW*MAX_COL - MAX_MINE)
?? ?{?? ??? ?
?? ??? ?//讀取坐標(biāo)并效驗
?? ??? ?printf("輸入您將要翻開的格子的坐標(biāo)(row, col): \n");
?? ??? ?scanf("%d %d", &input_row, &input_col);
?? ??? ?if (input_row<1 || input_row>MAX_ROW
?? ??? ??? ?|| input_col<1 || input_col>MAX_COL
?? ??? ??? ?|| game_map[input_row - 1][input_col - 1] != '#')
?? ??? ?{
?? ??? ??? ?printf("輸入有誤,請重新輸入...\n");
?? ??? ??? ?continue;
?? ??? ?}
?? ??? ?input_row -= 1;
?? ??? ?input_col -= 1;
?? ??? ?increase = renew_map(game_map, mine_map, input_row, input_col);
?? ??? ?display_map(game_map);
?? ??? ?if (increase == 0)
?? ??? ??? ?break;
?? ??? ?count = count + increase;
?? ?}
?? ?if (count == 0)
?? ??? ?printf("你是來自非洲的黑人朋友?\n");
?? ?else if (count == MAX_ROW * MAX_COL - MAX_MINE)
?? ??? ?printf("YOU WIN!\n");
?? ?else
?? ??? ?printf("游戲結(jié)束!\n");
?? ?system("pause");
?? ?return 0;
}

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C語言實現(xiàn)動態(tài)鏈表的示例代碼

    C語言實現(xiàn)動態(tài)鏈表的示例代碼

    本文主要介紹了C語言實現(xiàn)動態(tài)鏈表的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • C++通過共享內(nèi)存ShellCode實現(xiàn)跨進程傳輸

    C++通過共享內(nèi)存ShellCode實現(xiàn)跨進程傳輸

    在計算機安全領(lǐng)域,ShellCode是一段用于利用系統(tǒng)漏洞或執(zhí)行特定任務(wù)的機器碼,本文主要為大家介紹了C++如何通過共享內(nèi)存ShellCode實現(xiàn)跨進程傳輸,需要的可以參考下
    2023-12-12
  • C++中“#”號的使用技巧

    C++中“#”號的使用技巧

    本篇文章是對C++中“#”號的使用技巧進行了分析介紹,需要的朋友參考下
    2013-05-05
  • C語言菜鳥基礎(chǔ)教程之條件判斷

    C語言菜鳥基礎(chǔ)教程之條件判斷

    本文給大家簡單介紹了下C語言中的條件判斷語句的語法和用法示例,非常簡潔實用,有需要的小伙伴可以參考下
    2017-10-10
  • C++編程中__if_exists與__if_not_exists語句的用法

    C++編程中__if_exists與__if_not_exists語句的用法

    這篇文章主要介紹了C++編程中__if_exists與__if_not_exists語句的用法,是C++中用于判斷指定的標(biāo)識符是否存在的基礎(chǔ)的條件判斷語句,需要的朋友可以參考下
    2016-01-01
  • c++核心編程之函數(shù)的重載

    c++核心編程之函數(shù)的重載

    這篇文章主要介紹了c++核心編程之函數(shù)的重載,函數(shù)可以重復(fù)使用,提高了復(fù)用性,但前提是必須在一個作用域并且函數(shù)名稱相同,下面附代碼詳細(xì)介紹,需要的小伙伴可以參考一下
    2022-03-03
  • C++超詳細(xì)講解拷貝構(gòu)造函數(shù)

    C++超詳細(xì)講解拷貝構(gòu)造函數(shù)

    我們經(jīng)常會用一個變量去初始化一個同類型的變量,那么對于自定義的類型也應(yīng)該有類似的操作,那么創(chuàng)建對象時如何使用一個已經(jīng)存在的對象去創(chuàng)建另一個與之相同的對象呢
    2022-06-06
  • OpenCV實戰(zhàn)之基于Hu矩實現(xiàn)輪廓匹配

    OpenCV實戰(zhàn)之基于Hu矩實現(xiàn)輪廓匹配

    這篇文章主要介紹了利用C++ OpenCV實現(xiàn)基于Hu矩的輪廓匹配,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)OpenCV有一定的幫助,感興趣的可以學(xué)習(xí)一下
    2022-01-01
  • 新手socket編程入門詳解指南

    新手socket編程入門詳解指南

    本文,將一步一步引導(dǎo)初學(xué)者來學(xué)習(xí)socket,所有編程思路都結(jié)合在socket API里面,以及提供socket的疑問和基礎(chǔ)知識點,同時在最后給出多個例程,下面可以和小編一起學(xué)習(xí)
    2019-05-05
  • C++?std::chrono庫使用示例(實現(xiàn)C++?獲取日期,時間戳,計時等功能)

    C++?std::chrono庫使用示例(實現(xiàn)C++?獲取日期,時間戳,計時等功能)

    std::chrono是C++標(biāo)準(zhǔn)庫中的一個組件,用于表示和處理時間,這篇文章主要介紹了C++?std::chrono庫使用指南(實現(xiàn)C++?獲取日期,時間戳,計時等功能),需要的朋友可以參考下
    2023-06-06

最新評論

新化县| 江口县| 徐闻县| 比如县| 柳州市| 德阳市| 隆化县| 深圳市| 丹巴县| 马公市| 临沭县| 交口县| 六枝特区| 调兵山市| 青铜峡市| 永丰县| 西乌珠穆沁旗| 六枝特区| 青神县| 房产| 铜鼓县| 宾阳县| 博兴县| 措勤县| 磐石市| 元阳县| 斗六市| 芦溪县| 万源市| 梁河县| 从江县| 云安县| 潢川县| 阜宁县| 民权县| 安福县| 达孜县| 福安市| 东辽县| 宁海县| 栾城县|