[C語言初階]掃雷小游戲

目錄

  • 一、原理及問題分析
  • 二、代碼實現
    • 2.1 分文件結構設計
    • 2.2 棋盤初始化與打印
    • 2.3 布置雷與排查雷
    • 2.4 游戲主流程實現
  • 三、后期優化方向

在上一篇文章中,我們實現了我們的第二個游戲——三子棋小游戲。這次我們繼續結合我們之前所學的所有內容,制作出我們的第三個項目——掃雷小游戲。
在這里插入圖片描述

一、原理及問題分析

說起掃雷,這是一個非常經典的小游戲。掃雷游戲的核心邏輯是通過玩家輸入的坐標排查雷的位置,若踩雷則游戲結束,否則顯示周圍雷的數量。接下來我們先以結構化的方式來宏觀分析整個掃雷游戲中的關鍵要點:

  1. 雙棋盤設計

    • mine數組:存儲雷的位置(1為雷,0為非雷)。
    • show數組:存儲玩家可見的信息(初始為*,排查后顯示周圍雷數,因為是字符,所以兩個數組都是char類型)。
    • 設計意義:若只創建一個數組,雷為1,不是雷為0,若這個坐標周圍只有1個雷,則分不清是雷,還是排查出的雷的信息,有歧義,所以再創建一個額外數組,專門用來存放排查出的雷的信息,只打印這個數組即可,用%c打印。
  2. 邊界處理

    • 實際使用11x11的數組(通過ROWSCOLS定義),但只操作中間的9x9區域(通過ROWCOL定義)。
    • 目的:排查雷時邊界容易越界,所以要實現9x9棋盤實際是創建11x11的數組才不會越界,。 但不要直接寫數字,而是定義行和列的符號,方便后期修改。
  3. 模塊化設計

    • test.c:處理菜單、循環流程和用戶輸入。
    • game.c:實現游戲核心邏輯(初始化、布置雷、排查雷)。
    • game.h:聲明函數和定義常量。
  4. 游戲流程(在三子棋和之前的猜數字小游戲中已實現過)

    • 使用do-while循環支持重復游玩。
    • 玩家輸入坐標后,通過遞歸展開無雷區域(進階功能需自行實現)。

二、代碼實現

2.1 分文件結構設計

文件分工與核心函數

  • game.h:定義常量、聲明函數。
// game.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>// 常量定義:實際操作的棋盤大小為9x9,擴展為11x11避免越界
#define ROW 9    
#define COL 9    
#define ROWS ROW+2
#define COLS COL+2
#define EASY 10  // 默認雷的數量// 函數聲明
void Start(char arr[ROWS][COLS], int rows, int cols, char get); // 初始化棋盤
void Display(char arr[ROWS][COLS], int row, int col);           // 打印棋盤
void Set(char arr[ROWS][COLS], int row, int col);               // 布置雷
int Choose(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); // 排雷邏輯
  • test.c:主流程和菜單邏輯。
  • game.c:核心功能實現。

2.2 棋盤初始化與打印

1. 初始化函數 Start

  • 功能:將棋盤所有位置初始化為指定字符(mine初始為'0'show初始為'*')因為一個函數要實現兩種不同內容初始化,所以多加一個參數。
// game.c
void Start(char arr[ROWS][COLS], int rows, int cols, char get) 
{for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {arr[i][j] = get; // 將每個元素設置為傳入的字符('0'或'*')}}
}

2. 打印函數 Display

  • 功能:打印棋盤,為了美化棋盤顯示,優化玩家體驗,我們添加了行列號和分隔線。
// game.c
void Display(char arr[ROWS][COLS], int row, int col){printf("--------掃雷游戲--------\n");// 打印列號(頂部標簽)printf("   "); // 對齊行號for (int i = 1; i <= col; i++){printf("%d ", i);}printf("\n");// 打印分隔線printf("   ");for (int i = 1; i <= col; i++) {printf("--");}printf("\n");// 打印棋盤內容(帶行號)for (int i = 1; i <= row; i++) {printf("%d |", i); // 行號+左側豎線for (int j = 1; j <= col; j++) {printf("%c ", arr[i][j]); // 打印棋盤元素}printf("\n");}printf("--------掃雷游戲--------\n");
}

運行效果

--------掃雷游戲--------1 2 3 4 5 6 7 8 9 -------------------
1 |* * * * * * * * * 
2 |* * * * * * * * * 
...(略)

2.3 布置雷與排查雷

1. 布置雷函數 Set

  • 功能:在9x9區域內隨機生成雷。(關于rand函數的用法以及取余的技巧在之前的三子棋和猜數字小游戲中已經詳細介紹過,這里不再贅述)
// game.c
void Set(char arr[ROWS][COLS], int row, int col){int count = EASY; // 雷的數量while (count) {int x = rand() % row + 1; // 生成1~9的隨機坐標int y = rand() % col + 1;if (arr[x][y] == '0') {   // 僅當該位置無雷時布置arr[x][y] = '1';      // 標記為雷count--;}}
}

2. 計算周圍雷數 get_mine

  • 功能:計算坐標(x,y)周圍8個位置的雷數總和。 這個函數可以不用在game.h中聲明,因為只是為了在排查雷的函數中臨時用的,不會用在其他地方。
// game.c
int get_mine(char arr[ROWS][COLS], int x, int y) 
{// 周圍8個坐標的字符值相加('0'或'1'),再減去8*'0'得到實際數字return arr[x-1][y-1] + arr[x-1][y] + arr[x-1][y+1] +arr[x][y-1]   +               arr[x][y+1]   +arr[x+1][y-1] + arr[x+1][y] + arr[x+1][y+1] - 8 * '0';
}

3. 排雷邏輯 Choose

  • 功能:處理玩家輸入的坐標,判斷是否踩雷或顯示周圍雷數。
// game.c
int Choose(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col){int x = 0, y = 0;int Win = 0; // 記錄已排查的非雷區域數量while (Win < ROW * COL - EASY) // 勝利條件:所有非雷區域均被排查{ printf("請選擇排雷坐標(如2 3表示第二行第三列):>");scanf("%d %d", &x, &y);if (x >= 1 && y >= 1 && x <= row && y <= col)// 坐標合法性檢查{ if (mine[x][y] == '1') // 踩雷{ printf("很遺憾,你被炸死了!\n");Display(mine, ROW, COL); // 展示雷的位置break; // 游戲結束} else  // 安全坐標{ int count = get_mine(mine, x, y); // 計算周圍雷數show[x][y] = count + '0'; // 轉換為字符存儲(例如3 -> '3')Display(show, ROW, COL);Win++;}} else {printf("坐標非法!\n");}}if (Win == ROW * COL - EASY) // 勝利條件達成{ printf("恭喜通關!\n");Display(mine, ROW, COL); // 展示雷的位置}
}

2.4 游戲主流程實現

test.c:菜單和主循環邏輯。

// test.c
#include "game.h"void menu() {printf("*********************************\n");printf("*********************************\n");printf("***********掃雷小游戲************\n");printf("*********************************\n");printf("***********1.開始游戲************\n");printf("***********0.退出游戲************\n");printf("*********************************\n");printf("**********版本:Beta1.0***********\n");printf("**********作者:Yang210***********\n");printf("*********************************\n");printf("*********************************\n");printf("*********************************\n");
}void game() {char mine[ROWS][COLS]; // 存儲雷的棋盤char show[ROWS][COLS]; // 顯示給玩家的棋盤Start(mine, ROWS, COLS, '0'); // 初始化雷棋盤為全'0'Start(show, ROWS, COLS, '*'); // 初始化顯示棋盤為全'*'Set(mine, ROW, COL);          // 布置雷Display(show, ROW, COL);      // 打印初始棋盤Choose(mine, show, ROW, COL); // 進入排雷邏輯
}int main() {srand((unsigned int)time(NULL)); // 設置隨機數種子int input = 0;int add = 0; // 記錄游戲次數do {menu();if (add == 0) {printf("請選擇(輸入1開始游戲,輸入0退出游戲):>");} else {printf("是否繼續游玩(輸入1繼續游玩,輸入0退出游戲):>");}scanf("%d", &input);switch (input) {case 1:game();add++;break;case 0:printf("已退出游戲\n");break;default:printf("輸入錯誤!\n");}} while (input); // input為0時退出循環return 0;
}

三、后期優化方向

  1. 遞歸展開:若排查坐標周圍無雷(即雷數為0),自動展開相鄰區域。
  2. 標記雷:允許玩家輸入特殊指令(如m 3 4)標記可能為雷的位置。
  3. 難度調整:通過修改EASY的值實現不同難度的雷數設置。
  4. 界面優化:使用Windows API或第三方庫(如EasyX)添加圖形界面。

簡單地總結一下,在這篇文章中,我們通過分文件設計和模塊化的運用,將掃雷游戲的邏輯逐一地理清并且給出了后期擴展的方向。我們在代碼中通過定義符號常量(如ROWEASY)提高可維護性,方便后期修改,這是一種很重要的編程習慣。我們通過我們現階段所學的知識,做出了這個經典的游戲,這是對我們所學知識的肯定,也是我們對經典跨越時間的致敬。最后,我想送給大家一句話:"人生沒有白走的路,每一步都算數。"我們的決定,決定了我們。在介紹完了兩個C語言的項目之后,下一章,我們將回歸C語言的知識學習,介紹一下操作符的相關知識,敬請期待。
請添加圖片描述

作者其他文章鏈接:
[C語言初階]三子棋小游戲
[C語言初階]數組
[C語言初階]遞歸
Gitee詳細使用教程

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/84383.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/84383.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/84383.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ROS云課三分鐘-破壁篇GCompris-一小部分支持Edu應用列表-2025

開啟藍橋云課ROS ROS 機器人操作系統初級教程_ROS - 藍橋云課 安裝和使用GCompris 終端輸入&#xff1a;sudo apt install gcompris sudo apt install gcompris ok&#xff0c;完成即可。 sudo apt install gcompris 如果是平板&#xff0c;秒變兒童學習機。 啟動 流暢運…

Linux系統基礎——是什么、適用在哪里、如何選

一、Linux是什么 Linux最初是由林納斯托瓦茲&#xff08;Linus Torvalds&#xff09;基于個人興趣愛好開發的個人項目&#xff0c;他編寫了最核心的內核&#xff1b;后面為了發展壯大Linux系統他將整個項目開源到GitHub上&#xff0c;可以讓全世界的人都參與到項目的開發維護中…

26、AI 預測性維護 (燃氣輪機軸承) - /安全與維護組件/ai-predictive-maintenance-turbine

76個工業組件庫示例匯總 AI 預測性維護模擬組件 (燃氣輪機軸承) 概述 這是一個交互式的 Web 組件,旨在模擬基于 AI 的預測性維護 (Predictive Maintenance, PdM) 概念,應用于工業燃氣輪機的關鍵部件(例如軸承)。它通過模擬傳感器數據、動態預測剩余使用壽命 (RUL),并根…

el-form 使用el-row el-col對齊 注意事項

1.el-form 使用inline&#xff0c;el-form-item寬度會失效。 2.為了保證el-form-item 和 它內部的el-input 能在一行&#xff0c;要設置el-form-item的label-width <el-form :model"editInspectform"><el-row style"margin-bottom: 20px"><…

mac 安裝 mysql 和 mysqlshell

1. 安裝 mysql https://dev.mysql.com/downloads/mysql/?spma2c6h.12873639.article-detail.4.37474f4dTHdszC 默認mysql未配置環境變量&#xff0c;可以在設置中找到 2. 安裝 mysqlshell https://dev.mysql.com/downloads/shell/ #啟動mysql-shell mysqlsh 3. 使用 mysq…

漏洞檢測與滲透檢驗在功能及范圍上究竟有何顯著差異?

漏洞檢測與滲透檢驗是確保系統安全的重要途徑&#xff0c;這兩種方法各具特色和功效&#xff0c;它們在功能上有著顯著的差異。 目的不同 漏洞掃描的主要任務是揭示系統內已知的安全漏洞和隱患&#xff0c;這就像是對系統進行一次全面的健康檢查&#xff0c;看是否有已知的疾…

機器學習模型度量指標(混淆矩陣、準確率、精確率、召回率、F1分數、ROC曲線、AUC、平均精度均值)

我們研究的是多分類問題&#xff0c;下面所有例子以多分類問題舉例 混淆矩陣&#xff08;Confusion Matrix&#xff09; 混淆矩陣&#xff08; Confusion Matrix &#xff09;是一個表格&#xff0c;用于可視化機器學習模型在分類問題上 的性能。混淆矩陣的行表示實際類別&…

打卡day35

一、模型結構可視化 理解一個深度學習網絡最重要的2點&#xff1a; 了解損失如何定義的&#xff0c;知道損失從何而來----把抽象的任務通過損失函數量化出來了解參數總量&#xff0c;即知道每一層的設計才能退出—層設計決定參數總量 為了了解參數總量&#xff0c;我們需要知…

時序數據庫 TDengine × Superset:一鍵構建你的可視化分析系統

如果你正在用 TDengine 管理時序數據&#xff0c;寫 SQL 查詢沒問題&#xff0c;但一到展示環節就犯難——圖表太基礎&#xff0c;交互不夠&#xff0c;甚至連團隊都看不懂你辛苦分析的數據成果&#xff1f;別擔心&#xff0c;今天要介紹的這個組合&#xff0c;正是為你量身打造…

C# 初學者的 3 種重構模式

(Martin Fowlers Example) 1. 積極使用 Guard Clause&#xff08;保護語句&#xff09; "如果條件不滿足&#xff0c;立即返回。將核心邏輯放在最少縮進的地方。" 概念定義 Guard Clause&#xff08;保護語句&#xff09; 是一種在函數開頭檢查特定條件是否滿足&a…

基于51單片機和8X8點陣屏、獨立按鍵的滑動躲閃類小游戲

目錄 系列文章目錄前言一、效果展示二、原理分析三、各模塊代碼1、8X8點陣屏2、獨立按鍵3、定時器04、定時器1 四、主函數總結 系列文章目錄 前言 用的是普中A2開發板。 【單片機】STC89C52RC 【頻率】12T11.0592MHz 【外設】8X8點陣屏、獨立按鍵 效果查看/操作演示&#xff…

Java面向對象 一

系列文章目錄 Java面向對象 二-CSDN博客 Java面向對象 三-CSDN博客 目錄 系列文章目錄 前言 一、初步認識面向對象 1.類和對象的簡單理解 2.類的構成 二、類的實例化 1.對象的創建 2.對象的初始化 三、this引用的作用 四、構造方法 1.構造方法的提供 2.對象的構…

深度學習Y8周:yolov8.yaml文件解讀

&#x1f368; 本文為&#x1f517;365天深度學習訓練營中的學習記錄博客&#x1f356; 原作者&#xff1a;K同學啊 本周任務&#xff1a;根據yolov8n、yolov8s模型的結構輸出&#xff0c;手寫出yolov8l的模型輸出、 文件位置&#xff1a;./ultralytics/cfg/models/v8/yolov8.…

【RocketMQ 生產者和消費者】- 生產者啟動源碼 - MQClientInstance 定時任務(4)

文章目錄 1. 前言2. startScheduledTask 啟動定時任務2.1 fetchNameServerAddr 拉取名稱服務地址2.2 updateTopicRouteInfoFromNameServer 更新 topic 路由信息2.2.1 topic 路由信息2.2.2 updateTopicRouteInfoFromNameServer 獲取 topic2.2.3 updateTopicRouteInfoFromNameSer…

解決Docker容器內yum: not found、apt: not found、apk: command not found等命令找不到問題

Linux有很多發行版&#xff0c;各發行版的包管理工具不一定相同。 Alpine的包管理工具是 apk Debian/Ubuntu的包管理工具是 apt Centos/RHEL的包管理工具是 yum 在安裝軟件之前&#xff0c;需要先查看Docker容器內的Linux是什么發行版&#xff0c;可使用 cat /etc/os-rele…

每日c/c++題 備戰藍橋杯(修理牛棚 Barn Repair)

修理牛棚 Barn Repair 題解 問題背景與挑戰 在一個暴風雨交加的夜晚&#xff0c;Farmer John 的牛棚遭受了嚴重的破壞。屋頂被掀飛&#xff0c;大門也不翼而飛。幸運的是&#xff0c;許多牛正在度假&#xff0c;牛棚并未住滿。然而&#xff0c;為了保護那些還在牛棚里的牛&am…

鴻蒙版Flutter庫torch_light手電筒功能深度適配

鴻蒙版Flutter庫torch_light手電筒功能深度適配&#xff1a;跨平臺開發者的光明之路 本項目作者&#xff1a;kirk/堅果 適配倉庫地址 作者倉庫&#xff1a;https://github.com/svprdga/torch_light# 在數字化浪潮的推動下&#xff0c;跨平臺開發框架如 Flutter 憑借其高效、…

【信息系統項目管理師】一文掌握高項常考題型-項目進度類計算

更多內容請見: 備考信息系統項目管理師-專欄介紹和目錄 文章目錄 一、進度類計算的基本概念1.1 前導圖法1.2 箭線圖法1.3 時標網絡圖1.4 確定依賴關系1.5 提前量與滯后量1.6 關鍵路徑法1.7 總浮動時間1.8 自由浮動時間1.9 關鍵鏈法1.10 資源優化技術1.11 進度壓縮二、基本公式…

深入了解linux系統—— 操作系統的路徑緩沖與鏈接機制

前言 在之前學習當中&#xff0c;我們了解了被打開的文件是如何管理的&#xff1b;磁盤&#xff0c;以及ext2文件系統是如何存儲文件的。 那我們要打開一個文件&#xff0c;首先要先找到這個文件&#xff0c;操作系統又是如何去查找的呢&#xff1f; 理解操作系統搜索文件 …

Docker Hub倉庫介紹

Docker Hub倉庫全解析&#xff1a;從公共市場到私有化部署指南 一、Docker Hub公共鏡像市場 1.1 核心功能解析 全球最大容器鏡像庫&#xff1a;累計托管超500萬鏡像核心服務矩陣&#xff1a; #mermaid-svg-CAMkhmtSWKEUw7z0 {font-family:"trebuchet ms",verdana,a…