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

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)被下架了,童年的回憶,很難受。
游戲操作很簡單,首先初始化一個(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的初始化比較簡單:

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è)地圖長啥樣完全是根據(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;
}

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

相關(guān)文章

  • C/C++ 數(shù)組和指針及引用的區(qū)別

    C/C++ 數(shù)組和指針及引用的區(qū)別

    這篇文章主要介紹了C/C++ 數(shù)組和指針及引用的區(qū)別的相關(guān)資料,這里從匯編的角度來分析他們之間的區(qū)別,需要的朋友可以參考下
    2017-07-07
  • 最新評(píng)論