上一篇我們介紹了三子棋游戲小程序,
那這一篇我來介紹另一個簡單的游戲小程序——掃雷。
相信大家都玩過windows下的掃雷游戲,對其的規則也比較了解,
這里我們就不對規則做過多贅述了。
首先菜單和主函數的編寫和上一篇三子棋中的內容一致,
這里我們直接給出代碼:
void menu() { printf("********* Welcom to Mines *********\n"); printf("***************************************\n"); printf("* 1.play 0.exit *\n"); printf("***************************************\n"); } int main() { int choice; srand((unsigned int)time(NULL)); do { menu(); printf("Input your choice:"); scanf("%d", &choice); switch (choice) { case 1: game(); break; case 0: break; default: printf(" Input error!Please try again.\n"); break; } } while (choice); return 0; }
下面展示我的代碼寫出的菜單和主函數:
一樣,我們先定義一個game()函數,而后慢慢填充其中的內容。
和三子棋不同的是,這里需要創建兩個數組,其中一個是雷區數組,另一個是需要輸出在屏幕上的顯示數組。
為了便於區分兩個數組,雷區數組我用mines表示,顯示數組我用show_area來表示。
但這一步我們先跳過,先來完成初始化數組的功能函數。
這次我選擇使用memset()函數來進行初始化操作。
在init函數中,我們需要將雷區數組全部賦成“0”,“0”表示沒雷。
將顯示數組全部初始化為“.”,“.”表示未探索區域。
由於是掃雷程序,那么在雷區中一定要有雷才行,所以我們用上一篇提到的rand()來隨機生成坐標指向雷區數組的元素,
並將其賦值為“1”,“1”表示有雷。
代碼如下:
void init_mines(char mine[ROWS][COLS],char show[ROWS][COLS],int rows,int cols,int row,int col) { int i, x, y; memset(mine, '0', rows*cols*sizeof(char)); memset(show, '.', rows*cols*sizeof(char)); for (i = 0; i < MINES; i++) { while (1) { x = rand() % row + 1; y = rand() % col + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; break; } } } }
當用戶完成每次掃雷操作后,一定要打印出當前的狀況,這時就需要一個顯示功能函數display()。
代碼如下:
void display(char mine[ROWS][COLS],int row,int col) { int i, j; for (i = 1; i <= row; i++) { printf("%4d", i); } printf("\n"); for (i = 1; i <= col; i++) { printf("%2d", i); for (j = 1; j <= col; j++) { printf(" %c ", mine[i][j]); } printf("\n"); } }
為了用戶體驗,我們在打印出的雷區上方和左方加上了行數、列數,方便用戶觀察坐標。
下面展示用我的代碼打印出的雷區數組,和初始化后的顯示數組:
這時我們就需要利用掃雷規則來編寫完成checkwin()函數,以判斷是否勝利。
這里我們首先判斷其是不是雷,
如果不是雷,我們再編寫一個checkmine()函數,用來遍歷其周圍雷的個數,並將個數填入顯示數組中對應的元素中。
如果是雷,則返回一個值“*”,“*”表示被炸死。
最后判斷是否勝利。
我們先定義一個count變量,用來記錄未探索區域的個數,
如果未探索區域的個數和初始化時隨機生成的雷的個數相等,則表示雷排完了,
返回一個值“w”,“w”表示勝利。
代碼如下:
int checkwin(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col,int x,int y) { int count = 0; if (mine[x][y] == '0') show[x][y] = checkmine(mine, show, x, y); else return '*'; for (x = 1; x <= row; x++) { for (y = 1; y <= col; y++) { if (show[x][y] == '.') count++; } } if (count == MINES) return 'w'; return 0; }
接着我們給出上面提到的,用來遍歷該坐標周圍雷數的checkmine()函數。
static char checkmine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { int m, n; char mine_count = '0'; for (m = x - 1; m <= x + 1 ; m++) { for (n = y - 1; n <= y + 1; n++) { if (mine[m][n] == '1') mine_count++; } } return mine_count; }
由於該代碼只在該源文件中使用,所以我在其類型前加上了static。
這時我們就完成了掃雷各個功能函數的編寫,接着根據我們平時玩游戲的思路將上述函數引入game()中即可完成簡單掃雷的編寫。
game()函數的代碼如下:
void game() { char mines[ROWS][COLS], show_area[ROWS][COLS], ret; int x, y; init_mines(mines, show_area, ROWS, COLS, ROW, COL); display(show_area, ROW, COL); while (1) { printf("Input x and y(like x y):"); scanf("%d %d", &x, &y); if (x >= 1 && x <= ROW && y >= 1 && y <= COL) { ret = checkwin(mines, show_area, ROW, COL, x, y); if (ret == 'w') { display(mines, ROW, COL); printf("Congratulations!You win!\n"); break; } else if (ret == '*') { display(mines, ROW, COL); printf("You lose!Good luck next time!\n"); break; } else { display(show_area, ROW, COL); printf("\n"); } } else printf("Input error!Please try again.\n"); } }
和三子棋一樣,我這里定義數組時也運用了宏定義。
下面展示除勝利外的幾種情況:
1、在(1,2)周圍有1個雷。
2、被炸死。
最后放上我自己寫出的代碼:
代碼分為三部分,
第一部分是頭文件:
#ifndef __MINES_H__
#define __MINES_H__ #include<stdio.h> #include<time.h> #include<stdlib.h> #include<string.h> #define COLS 12 #define ROWS 12 #define COL 10 #define ROW 10 #define MINES 10 void init_mines(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols, int row, int col); void display(char mine[ROWS][COLS], int row, int col); int checkwin(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y); #endif//__MINES_H__
第二部分是源文件的函數部分:
#include"mines.h" void init_mines(char mine[ROWS][COLS],char show[ROWS][COLS],int rows,int cols,int row,int col) { int i, x, y; memset(mine, '0', rows*cols*sizeof(char)); memset(show, '.', rows*cols*sizeof(char)); for (i = 0; i < MINES; i++) { while (1) { x = rand() % row + 1; y = rand() % col + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; break; } } } } void display(char mine[ROWS][COLS],int row,int col) { int i, j; for (i = 1; i <= row; i++) { printf("%4d", i); } printf("\n"); for (i = 1; i <= col; i++) { printf("%2d", i); for (j = 1; j <= col; j++) { printf(" %c ", mine[i][j]); } printf("\n"); } } static char checkmine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { int m, n; char mine_count = '0'; for (m = x - 1; m <= x + 1 ; m++) { for (n = y - 1; n <= y + 1; n++) { if (mine[m][n] == '1') mine_count++; } } return mine_count; } int checkwin(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col,int x,int y) { int count = 0; if (mine[x][y] == '0') show[x][y] = checkmine(mine, show, x, y); else return '*'; for (x = 1; x <= row; x++) { for (y = 1; y <= col; y++) { if (show[x][y] == '.') count++; } } if (count == MINES) return 'w'; return 0; }
這部分內容,我並沒有完成關鍵的2點。 1、為了用戶體驗,在第一次用戶執行掃雷操作時,不會被炸死。
2、當用戶輸入的坐標周圍沒雷時,可以實現無雷區的展開。
第三部分是源文件的游戲測試部分:
#include"mines.h" void menu() { printf("********* Welcom to Mines *********\n"); printf("***************************************\n"); printf("* 1.play 0.exit *\n"); printf("***************************************\n"); } void game() { char mines[ROWS][COLS], show_area[ROWS][COLS], ret; int x, y; init_mines(mines, show_area, ROWS, COLS, ROW, COL); display(mines, ROW, COL); display(show_area, ROW, COL); while (1) { printf("Input x and y(like x y):"); scanf("%d %d", &x, &y); if (x >= 1 && x <= ROW && y >= 1 && y <= COL) { ret = checkwin(mines, show_area, ROW, COL, x, y); if (ret == 'w') { display(mines, ROW, COL); printf("Congratulations!You win!\n"); break; } else if (ret == '*') { display(mines, ROW, COL); printf("You lose!Good luck next time!\n"); break; } else { display(show_area, ROW, COL); printf("\n"); } } else printf("Input error!Please try again.\n"); } } int main() { int choice; srand((unsigned int)time(NULL)); do { menu(); printf("Input your choice:"); scanf("%d", &choice); switch (choice) { case 1: game(); break; case 0: break; default: printf(" Input error!Please try again.\n"); break; } } while (choice); return 0; }
希望各位能對我的代碼提出意見和建議,並能指導我完成第二部分鍾我未完成的兩點。