C語言實現(xiàn)掃雷游戲(含注釋詳解)
本文實例為大家分享了C語言實現(xiàn)掃雷游戲的具體代碼,供大家參考,具體內(nèi)容如下
前言
一、游戲規(guī)則介紹
掃雷是一個十分經(jīng)典的游戲,一張棋盤中有很多個不確定是雷還是安全區(qū)域的格子,當點擊之后若沒有雷則會在該區(qū)域顯示周圍八個格子雷的數(shù)目,若有雷則游戲結束。今天我就跟大家分享一下如何用c語言實現(xiàn)初階版掃雷。
二、基本思路流程介紹
1.創(chuàng)建一個用戶交互菜單
2.創(chuàng)建一個Show_Mines棋盤用來埋雷并初始化
3.創(chuàng)建一個Show_Table 棋盤用來和用戶交互并初始化
4.玩家選擇想要掃描的坐標
5.判定游戲是否結束
6.若沒有踩雷則在剛掃描的區(qū)域上顯示周圍八個區(qū)域的地雷數(shù)目并繼續(xù)游戲
7.繼續(xù)掃雷
8.判定游戲是否結束
…
9.若全部掃描完非雷區(qū)域則游戲結束
效果展示
三、代碼實現(xiàn)
1.用戶交互菜單(Menu函數(shù))
Menu(){ printf("########################\n"); printf("# 1. Play 0.Exit #\n"); printf("########################\n"); }
2. Game函數(shù)
void Game() { srand((unsigned long)time(NULL)); //生成隨機數(shù)種子 char show_board[ROW][COL]; char mines_board[ROW][COL]; memset(show_board, WHAT, sizeof(show_board));//生成并且初始化用戶顯示棋盤 memset(mines_board, '0', sizeof(mines_board));//生成并且初始化掃雷棋盤 SetMines(mines_board, ROW, COL);//放雷 int count = (ROW - 2)*(COL - 2) - NUM; //若掃完這些次 不觸雷則勝利 while (count){ system("cls"); ShowBoard(show_board, ROW, COL); printf("請選擇你要掃描的區(qū)域坐標 "); int x = 0; int y = 0; scanf("%d %d", &x, &y); if (x < 1 || x > ROW-2 || y < 1 || y > COL-2){ //非法性輸入判斷 printf("輸入錯誤!\n"); continue; } if (show_board[x][y] != WHAT){ printf("此處已經(jīng)被掃過了,請從新輸出\n"); continue; } if (mines_board[x][y] == '1'){ system("cls"); ShowBoard(mines_board, ROW, COL); printf("踩雷了!游戲結束!\n"); break; } show_board[x][y] = CountMines(mines_board, x, y); count--; } }
1.memset函數(shù)直接定義show_board函數(shù)并且初始化二維數(shù)組為全WHAT宏定義的*。
2.先向用戶展示用戶展示棋盤,用戶輸入一個坐標進行非法性判斷。
3.把用戶輸入的坐標拿給放置雷的棋盤中,若該區(qū)域有雷則游戲結束,反之則繼續(xù)
4.游戲勝利條件為掃描完所有非雷區(qū)域
3.放雷函數(shù)(SetMines函數(shù))
void SetMines(char board[][COL], int row, int col){ //放雷函數(shù) int count = NUM; while (count){ int x = rand() % (row - 2) + 1; int y = rand() % (col - 2) + 1; if (board[x][y] == '0'){ board[x][y] = '1'; count--; } } }
使用隨機數(shù)種子生成1到 棋盤大小長寬-2的隨機數(shù),這些隨機數(shù)組成的坐標放雷,循環(huán)次數(shù)就是雷的數(shù)目。因為隨機數(shù)可能生成一樣的,所以要進行一次非法性判斷,當棋盤這個位置沒有雷的情況下才能往里面放雷。
4.掃雷展示面板(ShowBoard函數(shù)和ShowLine函數(shù))
void ShowBoard(char board[][COL], int row, int col){//掃雷展示面板 printf(" "); for (int i = 1; i <= (col - 2); i++){ //打印表頭數(shù)字 printf("%d ", i); } printf("\n"); ShowLine(col);//顯示行線 for (int i = 1; i <= (row - 2); i++){ printf("%-3d|", i); for (int j = 1; j <= (col - 2); j++){ printf(" %c |", board[i][j]); } printf("\n"); ShowLine(col); } } void ShowLine(int col){ //顯示橫著的虛線,作為行間隔 for (int i = 0; i <= (col - 2); i++){ printf("----"); } printf("\n"); }
5.統(tǒng)計周圍雷的個數(shù)(CountMines函數(shù))
CountMines(char board[][COL], int x, int y){ //統(tǒng)計周圍雷的個數(shù) return board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + \ board[x][y + 1] + board[x + 1][y + 1] + board[x + 1][y] + \ board[x + 1][y - 1] + board[x][y - 1] - 7 * '0';//本來減八個零,但是整形轉字符加一個‘0' }
由于數(shù)組中存放的是字符'0',周圍是8個數(shù)字,所以-8*'0'才能返回雷數(shù)的int值,為了把數(shù)字也能打印出來,所以+‘0',否則打印的是數(shù)字作為的ASCLL碼的值,最終的結果為-7*‘0'.
6.mine函數(shù)
int main() { int quit = 0; int select = 0; while (!quit){ Menu(); printf("請輸入 "); scanf("%d", &select); switch (select){ case 1: Game(); break; case 0: quit = 1; break; default: printf("輸入錯誤,請重試!\n"); break; } } printf("byebye!\n"); system("pause"); return 0; }
四、總代碼
#ifndef __Test_H__ #define __Test_H__ #include<stdio.h> #include<Windows.h> #include <stdlib.h> #include <time.h> #define WHAT '*' #define NUM 20 #define COL 10 #define ROW 10 void Game(); #pragma warning(disable:4996) #endif //以上都是頭文件 int main() { int quit = 0; int select = 0; while (!quit){ Menu(); printf("請輸入 "); scanf("%d", &select); switch (select){ case 1: Game(); break; case 0: quit = 1; break; default: printf("輸入錯誤,請重試!\n"); break; } } printf("byebye!\n"); system("pause"); return 0; } void Game() { srand((unsigned long)time(NULL)); //生成隨機數(shù)種子 char show_board[ROW][COL]; char mines_board[ROW][COL]; memset(show_board, WHAT, sizeof(show_board)); memset(mines_board, '0', sizeof(mines_board)); SetMines(mines_board, ROW, COL); int count = (ROW - 2)*(COL - 2) - NUM; //若掃完這些次 不觸雷則勝利 while (count){ system("cls"); ShowBoard(show_board, ROW, COL); printf("請選擇你要掃描的區(qū)域坐標 "); int x = 0; int y = 0; scanf("%d %d", &x, &y); if (x < 1 || x > ROW-2 || y < 1 || y > COL-2){ //非法性輸入判斷 printf("輸入錯誤!\n"); continue; } if (show_board[x][y] != WHAT){ printf("此處已經(jīng)被掃過了,請從新輸出\n"); continue; } if (mines_board[x][y] == '1'){ system("cls"); ShowBoard(mines_board, ROW, COL); printf("踩雷了!游戲結束!\n"); break; } show_board[x][y] = CountMines(mines_board, x, y); count--; } } CountMines(char board[][COL], int x, int y){ //統(tǒng)計周圍雷的個數(shù) return board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + \ board[x][y + 1] + board[x + 1][y + 1] + board[x + 1][y] + \ board[x + 1][y - 1] + board[x][y - 1] - 7 * '0';//本來減八個零,但是整形轉字符加一個‘0' } void ShowBoard(char board[][COL], int row, int col){//掃雷展示面板 printf(" "); for (int i = 1; i <= (col - 2); i++){ printf("%d ", i); } printf("\n"); ShowLine(col);//顯示行線 for (int i = 1; i <= (row - 2); i++){ printf("%-3d|", i); for (int j = 1; j <= (col - 2); j++){ printf(" %c |", board[i][j]); } printf("\n"); ShowLine(col); } } oid SetMines(char board[][COL], int row, int col){ //放雷函數(shù) int count = NUM; while (count){ int x = rand() % (row - 2) + 1; int y = rand() % (col - 2) + 1; if (board[x][y] == '0'){ board[x][y] = '1'; count--; } } } void ShowLine(int col){ for (int i = 0; i <= (col - 2); i++){ printf("----"); } printf("\n"); } Menu(){ //用戶交互函數(shù) printf("########################\n"); printf("# 1. Play 0.Exit #\n"); printf("########################\n"); }
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。