目錄
1、需求分析
2、程式架構
3、代碼實作(分函式呈現)
(1)主函式代碼實作
分析:
例外處理:
(2)游戲主函式實作
分析:
(3)初始化函式的實作
分析:
(4)展示函式的實作
分析:
(5)埋雷函式的實作
分析:
(6)掃雷函式的實作
分析:
(7)頭檔案的引入、函式宣告、難度的提高
分析:
4、代碼實作(分檔案呈現)
test.c代碼
game.h代碼
game.c代碼
1、需求分析
通過C語言實作簡單的掃雷小游戲,由于創作者水平有限,未在該游戲中實作圖形化界面,同時在真正掃雷游戲中點一個位置成功掃雷多個坐標的功能也未實作,功能較為簡單,敬請原諒!
2、程式架構
程式分為test.c、game.c兩個源檔案和game.h一個頭檔案,
test.c:主函式介面引入,
game.c:游戲的相關函式實作,
game.h:頭檔案引入、函式宣告,
3、代碼實作(分函式呈現)
(1)主函式代碼實作
void test() { srand((unsigned int)time(NULL)); int input = 0; do { menu(); printf("請輸入->"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戲!\n"); break; } } while (input); } int main() { test(); return 0; }分析:
1.主函式中引入了隨機種子,生成亂數來方便后續的雷的生成
2.在通過menu()選單呈現后,通過switch進行介面接入,當用戶輸入1時可以進行游戲,當用戶輸入0時即退出游戲,
3.總體是通過do while回圈實作的,但巧妙的利用了將用戶輸入的資料填入while后面的括號中,即當用戶輸入0時while條件判斷失敗,游戲就終止,
例外處理:
在switch中雖然沒有通過default可以進行例外處理,但當用戶輸入只要不為0的資料時,回圈仍舊自動進行,在輸入非0和非1的資料后,程式會要求玩家進行重新輸入,會再次進入回圈,實際上就已經相當于另類的例外處理,
(2)游戲主函式實作
void game() { char mine[ROWS][COLS] = { 0 };//存取放置好雷的資訊的雷盤 char show[ROWS][COLS] = { 0 };//存取展示給用戶的資訊的雷盤 Init_board(mine, ROWS, COLS, '0');//初始化雷盤 Init_board(show, ROWS, COLS, '*');//初始化展示的雷盤 Set_mine(mine, ROW, COL,EASY_COUNT);//埋雷 Display_board(show, ROW, COL);//展示想要展示雷盤 Find_mine(mine, show, ROWS, COLS);//排雷游戲開始 }分析:
1.為什么要建立兩個雷盤?第一個雷盤是我們用來初始化雷的,即埋雷的,第二個雷盤是用來顯示給玩家的,即顯示玩家在哪個位置排雷了,并且以這個位置為中心的3*3的格子里有多少雷,也許大家會問,一個雷盤不好嗎?一個雷盤當然也沒有問題,但兩個雷盤能夠更好的對后續操作進行更好的處理,特別是我們在計算以我們要掃的格子為中心3*3范圍內有多少雷時,第一個雷盤我們初始化了為1*11,這樣是為了我們更好的計算我們要掃的位置處周圍有多少雷,
給大家展示一下兩個雷盤:
左邊的雷盤為埋好雷的雷盤,右邊的雷盤為呈現給玩家的雷盤,
2、初始化的第一個雷盤(11*11),我們將其全部都初始化為0,在后續的埋雷的程序中,將雷的位置的資料賦值為1,初始化展示的雷盤是將所有的位置的資料初始化為字符'*',后面我們排雷后將其賦值為我們排的地方的周圍存在的雷的數量,
3.展示雷盤和初始化雷盤不一樣,展示雷盤只需要用9*9即可,并不需要將11*11都展示出來,11*11只是為了我們更好的計算掃雷的位置周圍的雷的數量,
(3)初始化函式的實作
void Init_board(char board[ROWS][COLS], int rows, int cols, char set) { int i = 0; int j = 0; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { board[i][j] = set; } } }分析:
雷盤初始化函式并不復雜,簡單的運用for回圈即可,需要注意的是,我們要根據初始化的雷盤不同在函式的最后一個引數的位置填入不同的字符,
(4)展示函式的實作
void Display_board(char board[ROWS][COLS], int row, int col) { int i = 0; int j = 0; for (i = 0; i <=row; i++) { printf("%d ", i); } printf("\n"); for (i = 1; i <= row; i++) { printf("%d ", i); for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } }分析:
1.該展示函式中,第一個for回圈是為了顯示出列坐標來,方便玩家后續進行輸出想要掃雷的坐標,
2.內層for回圈前面的printf("%d",i)是為了顯示出橫坐標來坐標來,
3.需要注意的是不要忘了換行操作!
4.展示函式從1到9展示即可,因為不需要展示0下標和10下標的,這兩個下標只是為了我們方便計算周圍雷的數量,因為我們不需要考慮邊緣位置的特殊性,
(5)埋雷函式的實作
void Set_mine(char mine[ROWS][COLS], int row, int col,int count) { while (count) { int x = rand() % 9 + 1; int y = rand() % 9 + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } }分析:
1.這個函式中count為我們想要埋雷的數量,每成功埋一個雷,count就會減1,當count為0時,埋雷全部結束,此時也將跳出回圈,
2.這個函式中我們在生成雷的位置時之所以要+1的原因是因為,在前面我們開辟的是一個11*11的雷盤,我們想要埋雷的位置或者說我們想要在陣列中對應的埋雷的位置是1到9,而對8取模得到的結果范圍為0到8,加1之后為1到9,
3.為什么要將雷的位置的資料賦值為1?是為了在后面計算周圍雷得數量,即將周圍坐標的資料加起來即可得到周圍雷的數量之和,
(6)掃雷函式的實作
void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols) { int x = 0; int y = 0; int win = 0; while (win < (rows - 2) * (cols - 2) - EASY_COUNT) { printf("請輸入你要排查的坐標:"); scanf("%d %d", &x, &y); if (x > ROW || x<0 || y>COL || y < 0) { printf("輸入錯誤,請重新輸入!\n"); } else { if (mine[x][y] == '1') { printf("很遺憾,你被炸死了!\n"); Display_board(mine, ROW, COL); break; } else { show[x][y] = count_num(mine, x, y)+'0'; Display_board(show, ROW, COL); win++; } } } if (win == (rows - 2) * (cols - 2) - EASY_COUNT) { printf("排雷成功!\n"); } } static int count_num(char mine[ROWS][COLS], int x, int y) { return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x + 1][y] + mine[x + 1][y - 1] + mine[x + 1][y + 1] + mine[x - 1][y + 1] + mine[x][y + 1] + mine[x][y - 1]-8*'0'; }分析:
1.while后面的括號的意義:就是當我們掃完全部的雷后就跳出回圈并通過后面的if條件進行判斷是否將雷完全掃完,如果掃完就輸出掃雷成功,
2.在輸入坐標后,有兩個分支,第一個分支就是如果坐標對應的位置是1,即雷,就會顯示掃雷失敗,,如果不是雷,就跳轉到定義的count_num()計算該坐標周圍雷的數量,該函式的實作就是將周圍坐標所存盤的值相加,減去8*‘0’,至于為什么需要減去字符0呢?因為我們在開辟雷盤時定義的資料型別是字符型,此處通過計算得到的資料是整型,減去‘0’之后得到的資料即為字符型真正對應的整型,后面存入要展示的雷盤時加上‘0’,也是為了將其由整型轉換為字符型,方便存入雷盤中,
(7)頭檔案的引入、函式宣告、難度的提高
#include<stdio.h> #include<time.h> #include<stdlib.h> #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define EASY_COUNT 10 void menu();//選單函式宣告 void game();//游戲主初始化函式宣告 void Init_board(char board[ROWS][COLS], int rows, int cols, char ch);//初始化函式宣告 void Set_mine(char mine[ROWS][COLS], int row, int col,int count);//埋雷函式宣告 void Display_board(char board[ROWS][COLS], int row, int col);//展示函式宣告 void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols);//掃雷函式宣告分析:
ROW即為雷盤的真正行數,COL即為雷盤的真正列數,EASY_COUNT即為雷的數量,如果大家想要提高游戲的難度,可以通過改變ROW、COL、EASY_COUNT即可,
4、代碼實作(分檔案呈現)
test.c代碼
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" //游戲函式 void game() { char mine[ROWS][COLS] = { 0 };//存取放置好雷的資訊的雷盤 char show[ROWS][COLS] = { 0 };//存取展示給用戶的資訊的雷盤 Init_board(mine, ROWS, COLS, '0');//初始化雷盤 Init_board(show, ROWS, COLS, '*');//初始化展示的雷盤 Set_mine(mine, ROW, COL,EASY_COUNT);//埋雷 Display_board(show, ROW, COL);//展示想要展示雷盤 Find_mine(mine, show, ROWS, COLS);//排雷游戲開始 } void test() { srand((unsigned int)time(NULL)); int input = 0; do { menu(); printf("請輸入->"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戲!\n"); break; } } while (input); } int main() { test(); return 0; }
game.h代碼
#pragma once #include<stdio.h> #include<time.h> #include<stdlib.h> #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define EASY_COUNT 10 void menu();//選單函式宣告 void game();//游戲主初始化函式宣告 void Init_board(char board[ROWS][COLS], int rows, int cols, char ch);//初始化函式宣告 void Set_mine(char mine[ROWS][COLS], int row, int col,int count);//埋雷函式宣告 void Display_board(char board[ROWS][COLS], int row, int col);//展示函式宣告 void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols);//掃雷函式宣告
game.c代碼
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" //選單 void menu() { printf("***********************\n"); printf("******* 1.play ******\n"); printf("******* 0.exit ******\n"); printf("***********************\n"); } //初始化函式 void Init_board(char board[ROWS][COLS], int rows, int cols, char set) { int i = 0; int j = 0; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { board[i][j] = set; } } } //展示函式 void Display_board(char board[ROWS][COLS], int row, int col) { int i = 0; int j = 0; for (i = 0; i <=row; i++) { printf("%d ", i); } printf("\n"); for (i = 1; i <= row; i++) { printf("%d ", i); for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } } //埋雷函式 void Set_mine(char mine[ROWS][COLS], int row, int col,int count) { while (count) { int x = rand() % 9 + 1; int y = rand() % 9 + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } } //掃雷函式 void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols) { int x = 0; int y = 0; int win = 0; while (win < (rows - 2) * (cols - 2) - EASY_COUNT) { printf("請輸入你要排查的坐標:"); scanf("%d %d", &x, &y); if (x > ROW || x<0 || y>COL || y < 0) { printf("輸入錯誤,請重新輸入!\n"); } else { if (mine[x][y] == '1') { printf("很遺憾,你被炸死了!\n"); Display_board(mine, ROW, COL); break; } else { show[x][y] = count_num(mine, x, y)+'0'; Display_board(show, ROW, COL); win++; } } } if (win == (rows - 2) * (cols - 2) - EASY_COUNT) { printf("排雷成功!\n"); } } static int count_num(char mine[ROWS][COLS], int x, int y) { return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x + 1][y] + mine[x + 1][y - 1] + mine[x + 1][y + 1] + mine[x - 1][y + 1] + mine[x][y + 1] + mine[x][y - 1]-8*'0'; }
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/355416.html
標籤:其他
下一篇:請回答c語言-掃雷游戲


