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

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

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

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

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

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

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

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

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

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

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ù)雜了。首先,需要隨機(jī)生成MAX_MINE個(gè)雷,這里我們使用rand()函數(shù)來生成,并在初始化之前生成一個(gè)隨機(jī)種子。接著,在生成完MAX_MINE個(gè)雷之后,對(duì)mine_map掃描一次,在雷的周圍的小方塊里生成提示數(shù)字:

//計(jì)算一個(gè)小方塊的周圍有幾個(gè)雷的函數(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)試上面這兩個(gè)初始化函數(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");
}

這個(gè)函數(shù)的可讀性并不好,因?yàn)檫@個(gè)地圖長(zhǎng)啥樣完全是根據(jù)我的喜好來定的,雖然用控制臺(tái)寫的程序都丑,但是它丑得有多別致由我決定······這個(gè)函數(shù)不同的人能玩出不同的花,以上僅供參考。
最后就是更新地圖函數(shù)了,先寫一個(gè)函數(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ū)域,則將其周圍的方塊自動(dòng)翻開,直到不為0為止,這里我使用了一個(gè)叫continues_map的函數(shù)。
那么問題來了,要如何實(shí)現(xiàn)自動(dòng)翻開的功能呢?
要回答這個(gè)問題,首先就要清楚連續(xù)翻的規(guī)則:在掃雷游戲中,提示數(shù)為0的方塊表示周圍沒有雷,因此這個(gè)方塊周圍的八個(gè)方塊都是可以翻開的,而且如果這八個(gè)方塊之中有提示數(shù)為0的方塊,則繼續(xù)將該方塊的周圍八個(gè)方塊翻開,直到碰到提示數(shù)不為0的方塊為止,并將其翻開······這樣來看,能否用循環(huán)語句來實(shí)現(xiàn)呢?我們想想算法思路:

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

考慮一下極端情況,若這8個(gè)方塊也都是“0”方塊,那么是否能用循環(huán)繼續(xù)對(duì)這八個(gè)方塊分別掃描?就算可以,繼續(xù)考慮極端情況,能否繼續(xù)用循環(huán)對(duì)周圍16個(gè)方塊進(jìn)行掃描?隨著問題規(guī)模的增加,循環(huán)逐漸乏力,也就是說使用循環(huán)處理該問題并不好——就算用循環(huán)實(shí)現(xiàn)了,代碼也將會(huì)非常復(fù)雜,可讀性非常之差,不利于后期的維護(hù)和修改。
那應(yīng)該使用什么方法來實(shí)現(xiàn)?我們接著看算法思路,首先進(jìn)行判斷,如果條件滿足,則將原問題分解為8個(gè)子問題,再對(duì)這8個(gè)子問題進(jìn)行之前的操作,直到將所有滿足判斷條件的子問題處理完為止——這樣來看,這不就是遞歸調(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)了······
寫到這里,一個(gè)用以實(shí)現(xiàn)掃雷游戲功能的程序大致就寫得差不多了,再加上一個(gè)主函數(shù)就可以玩了。主函數(shù)的功能主要就是對(duì)以上的函數(shù)進(jìn)行調(diào)用來實(shí)現(xiàn)游戲功能,并對(duì)玩家輸入的合法性進(jì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)并效驗(yàn)
?? ??? ?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("輸入有誤,請(qǐng)重新輸入...\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;
}

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

相關(guān)文章

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

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

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

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

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

    C++中“#”號(hào)的使用技巧

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

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

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

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

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

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

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

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

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

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

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

    新手socket編程入門詳解指南

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

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

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

最新評(píng)論

营口市| 镇江市| 枣庄市| 屯门区| 若尔盖县| 米林县| 新野县| 景宁| 大同县| 普兰店市| 亚东县| 高阳县| 蛟河市| 武川县| 新和县| 彭州市| 乐陵市| 海伦市| 成武县| 杨浦区| 岫岩| 监利县| 柳河县| 满城县| 聊城市| 叙永县| 马边| 招远市| 伊金霍洛旗| 大理市| 舒兰市| 平湖市| 鄂温| 阿图什市| 桂平市| 南郑县| 望谟县| 苍梧县| 石门县| 九台市| 思茅市|