C語(yǔ)言輕松實(shí)現(xiàn)掃雷小游戲
前言
掃雷是一款經(jīng)典的小游戲,那么如何用c語(yǔ)言來(lái)實(shí)現(xiàn)呢?下面我將帶你搞定掃雷小游戲。
注:本此游戲所用到的文件與上篇三子棋類似,最后附有代碼展示。
1.游戲設(shè)計(jì)邏輯
1.布置雷—10個(gè)
2.掃雷
輸入坐標(biāo);
如果是雷—就炸死了,游戲結(jié)束;
如果不是雷—就告訴你這個(gè)坐標(biāo)周?chē)?個(gè)坐標(biāo)上總共有多少個(gè)雷;
直到把所有非雷區(qū)的位置全部找到,游戲結(jié)束,掃雷成功。
2.游戲思考及實(shí)現(xiàn)過(guò)程
2.1符號(hào)與棋盤(pán)的建立
我們就拿9*9的棋盤(pán)來(lái)舉例,那么這樣我們就需要用一個(gè)字符型的二維數(shù)組來(lái)實(shí)現(xiàn)。這當(dāng)中要用到兩個(gè)字符數(shù)組的想法是實(shí)現(xiàn)邏輯不想那么麻煩。只是想一個(gè)mine數(shù)組打印布置好的雷的信息,一個(gè)show數(shù)組打印排查出雷的信息。
用‘1’- 雷,‘0’- 非雷 。用‘*’- 已排查的位置,數(shù)字字符來(lái)表示未排查的位置。
在數(shù)字字符顯示的周?chē)?個(gè)坐標(biāo)上,如果是靠近邊緣的位置,有的坐標(biāo)則會(huì)超出坐標(biāo)范圍,會(huì)發(fā)生數(shù)組越界的現(xiàn)象。我們所要寫(xiě)的是一個(gè)9*9的棋盤(pán),那么我們就將行列各自加一,成為11*11的棋盤(pán)我們只用中間的9*9的棋盤(pán)。那么我們的數(shù)組就要變成這樣了。
在game.h中宏定義二維數(shù)組的行列。
#define ROW 9 #define COL 9 ? #define ROWS ROW+2 #define COLS COL+2
創(chuàng)建二維數(shù)組,也就是掃雷所需要的棋盤(pán)
char mine[ROWS][COLS] = { 0 }; char show[ROWS][COLS] = { 0 };
2.2棋盤(pán)的初始化與打印
初始化棋盤(pán),我們想要的效果是mine數(shù)組中一開(kāi)始全是‘0’,show數(shù)組中全是‘*’
函數(shù)的具體實(shí)現(xiàn)是在game.c中
init_board(mine, ROWS, COLS,'0'); init_board(show, ROWS, COLS, '*');
void init_board(char arr[][], int rows, int cols, char set) { ?? ?int i = 0; ?? ?for (i = 0; i < rows; i++) ?? ?{ ?? ??? ?int j = 0; ?? ??? ?for (j = 0; j < cols; j++) ?? ??? ?{ ?? ??? ??? ?arr[i][j] = set; ?? ??? ?} ?? ?} }
打印棋盤(pán),我們?nèi)绻胍焖僦老碌奈恢檬悄睦铮梢詫⑿辛刑?hào)給打印出來(lái),
show_board(mine, ROW, COL); show_board(show, ROW, COL);
void show_board(char arr[ROWS][COLS], int row, int col) { ?? ?int i = 0; ?? ?printf("------------掃雷------------\n"); ?? ?for (i = 0; i<= col; i++)//打印列號(hào) ?? ?{ ?? ??? ?printf("%d ", i); ?? ?} ?? ?printf("\n"); ?? ?for (i = 1; i <= row; i++) ?? ?{ ?? ??? ?printf("%d ",i);//打印行號(hào) ?? ??? ?int j = 0; ?? ??? ?for (j = 1; j <=col; j++) ?? ??? ?{ ?? ??? ??? ?printf("%c ", arr[i][j]); ?? ??? ?} ?? ??? ?printf("\n"); ?? ?} ?? ?printf("------------掃雷------------\n"); }
2.3布置雷
set_mine(mine, ROW, COL);
#define EASY_COUNT 10
void set_mine(char mine[ROWS][COLS], int row, int col) { ?? ?int x = 0; ?? ?int y = 0; ?? ?int count = EASY_COUNT; ?? ?while (count) ?? ?{ ?? ??? ?x = rand() % 9 + 1; ?? ??? ?y = rand() % 9 + 1; ?? ??? ?if (mine[x][y] == '0') ?? ??? ?{ ?? ??? ??? ?mine[x][y] = '1'; ?? ??? ??? ?count--; ?? ??? ?} ?? ?} }
使用了一個(gè)宏定義常量是為了以后可以為了方便修改。有了方面的打印函數(shù),你可以嘗試著將棋盤(pán)打印出來(lái)看看,就明白是否把雷給布置好了。
2.4 排查雷并設(shè)置結(jié)束標(biāo)志
排查雷的時(shí)候,我們要弄清楚這要用到兩個(gè)數(shù)組,我們是將mine數(shù)組中的信息放到show數(shù)組中去,排查是兩個(gè)數(shù)組都要涉及到。
find_mine(mine, show, ROW, COL);
因?yàn)?’- 雷,‘0’- 非雷,我們要顯示出周?chē)睦椎臄?shù)量,首先要選一個(gè)坐標(biāo)落子,然后在遍歷周?chē)陌藗€(gè)坐標(biāo)
我們要知道一件事 ‘1’-‘0’ == 1。這也是為什么我們要用‘1’和‘0’來(lái)表示雷的信息,很方便我們排查雷。我們要返回周?chē)藗€(gè)坐標(biāo)的信息,只要將周?chē)藗€(gè)坐標(biāo)的字符(ascll值)加在一起,再減去8*‘0’,即可以得到周?chē)袔最w雷的信息了。我們還知道這個(gè)游戲我們一共設(shè)置10個(gè)雷,當(dāng)我們把所有非雷的位置找到我們就贏了。我用了一個(gè)win來(lái)標(biāo)記游戲贏了的狀態(tài)。教你一個(gè)游戲測(cè)試的方法,我們知道將宏定義常量EASY_COUNT改成80,在布好雷區(qū)后,先將mine數(shù)組打印出來(lái),照著排就可以了,因?yàn)檫@時(shí)我們?cè)O(shè)置了80個(gè)雷,只有一個(gè)位置沒(méi)有雷,我們可以很快地就測(cè)試出贏了的結(jié)果。
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { ?? ?int x = 0; ?? ?int y = 0; ?? ?int win = 0; ?? ?while (win<row*col-EASY_COUNT) ?? ?{ ?? ??? ?printf("請(qǐng)輸入坐標(biāo):>"); ?? ??? ?scanf("%d %d", &x, &y); ? ?? ??? ?if (x >= 1 && x <= row && y >= 1 && y <= col) ?? ??? ?{ ?? ??? ??? ?if (mine[x][y] == '1') ?? ??? ??? ?{ ?? ??? ??? ??? ?printf("你被炸死了\n"); ?? ??? ??? ??? ?show_board(mine, ROW, COL); ?? ??? ??? ??? ?break; ?? ??? ??? ?} ?? ??? ??? ?else ?? ??? ??? ?{ ?? ??? ??? ??? ?int count = get_mine_count(mine, x, y); ?? ??? ??? ??? ?show[x][y] = count + '0'; ?? ??? ??? ??? ?show_board(show, ROW, COL); ?? ??? ??? ??? ?win++; ?? ??? ??? ?} ?? ??? ?} ?? ??? ?else ?? ??? ?{ ?? ??? ??? ?printf("坐標(biāo)非法,請(qǐng)重新輸入\n"); ?? ??? ?} ?? ?} ? ?? ?if (win == row * col - EASY_COUNT) ?? ?{ ?? ??? ?printf("恭喜你,你贏了\n"); ?? ??? ?show_board(mine, ROW, COL); ?? ?} }
int get_mine_count(char mine[ROWS][COLS], int x, int y) { ?? ?return mine[x - 1][y - 1] + ?? ??? ?mine[x - 1][y] +? ?? ??? ?mine[x - 1][y + 1] +? ?? ??? ?mine[x][y - 1] +? ?? ??? ?mine[x][y + 1] +? ?? ??? ?mine[x + 1][y - 1] + ?? ??? ?mine[x + 1][y] +? ?? ??? ?mine[x + 1][y + 1] - 8 * '0'; }
3.代碼展示
test.c
#include "game.h" ? void menu() { ?? ?printf("******************\n"); ?? ?printf("***** 1.play *****\n"); ?? ?printf("***** 0.exit *****\n"); ?? ?printf("******************\n"); } //掃雷游戲的實(shí)現(xiàn) void game() { ?? ?char mine[ROWS][COLS] = { 0 }; ?? ?char show[ROWS][COLS] = { 0 }; ?? ?//初始化 ?? ?init_board(mine, ROWS, COLS, '0'); ?? ?init_board(show, ROWS, COLS, '*'); ? ?? ?//打印棋盤(pán) ? ?? ?//show_board(show, ROW, COL); ?? ?//? ?? ?//布置雷 ?? ?set_mine(mine, ROW, COL); ?? ?//show_board(mine, ROW, COL); ?? ?show_board(show, ROW, COL); ? ?? ?//排查雷 ?? ?find_mine(mine, show, ROW, COL); ? } ? ? int main() { ?? ?srand((unsigned int)time(NULL)); ?? ?int input = 0; ?? ?do ?? ?{ ?? ??? ?menu(); ?? ??? ?printf("請(qǐng)輸入:>"); ?? ??? ?scanf("%d", &input); ?? ??? ?switch (input) ?? ??? ?{ ?? ??? ?case 1: ?? ??? ??? ?game(); ?? ??? ??? ?break; ?? ??? ?case 0: ?? ??? ??? ?printf("退出游戲\n"); ?? ??? ??? ?break; ?? ??? ?default: ?? ??? ??? ?printf("選擇錯(cuò)誤,重新選擇\n"); ?? ??? ??? ?break; ? ?? ??? ?} ?? ?} while (input); ?? ?return 0; }
game.c
#include "game.h" //初始化棋盤(pán) void init_board(char arr[ROWS][COLS], int rows, int cols, char set) { ?? ?int i = 0; ?? ?for (i = 0; i < rows; i++) ?? ?{ ?? ??? ?int j = 0; ?? ??? ?for (j = 0; j < cols; j++) ?? ??? ?{ ?? ??? ??? ?arr[i][j] = set; ?? ??? ?} ?? ?} } //打印棋盤(pán) void show_board(char arr[ROWS][COLS], int row, int col) { ?? ?int i = 0; ?? ?printf("------------掃雷------------\n"); ?? ?for (i = 0; i <= col; i++)//打印列號(hào) ?? ?{ ?? ??? ?printf("%d ", i); ?? ?} ?? ?printf("\n"); ?? ?for (i = 1; i <= row; i++) ?? ?{ ?? ??? ?printf("%d ",i);//打印行號(hào) ?? ??? ?int j = 0; ?? ??? ?for (j = 1; j <= col; j++) ?? ??? ?{ ?? ??? ??? ?printf("%c ", arr[i][j]); ?? ??? ?} ?? ??? ?printf("\n"); ?? ?} ?? ?printf("------------掃雷------------\n"); } ? //布置雷 void set_mine(char mine[ROWS][COLS], int row, int col) { ?? ?int x = 0; ?? ?int y = 0; ?? ?int count = EASY_COUNT; ?? ?while (count) ?? ?{ ?? ??? ?x = rand() % 9 + 1; ?? ??? ?y = rand() % 9 + 1; ?? ??? ?if (mine[x][y] == '0') ?? ??? ?{ ?? ??? ??? ?mine[x][y] = '1'; ?? ??? ??? ?count--; ?? ??? ?} ?? ?} } ? int get_mine_count(char mine[ROWS][COLS], int x, int y) { ?? ?return mine[x - 1][y - 1] + ?? ??? ?mine[x - 1][y] +? ?? ??? ?mine[x - 1][y + 1] +? ?? ??? ?mine[x][y - 1] +? ?? ??? ?mine[x][y + 1] +? ?? ??? ?mine[x + 1][y - 1] + ?? ??? ?mine[x + 1][y] +? ?? ??? ?mine[x + 1][y + 1] - 8 * '0'; } ? //排查雷 void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { ?? ?int x = 0; ?? ?int y = 0; ?? ?int win = 0; ?? ?while (win<row*col-EASY_COUNT) ?? ?{ ?? ??? ?printf("請(qǐng)輸入坐標(biāo):>"); ?? ??? ?scanf("%d %d", &x, &y); ? ?? ??? ?if (x >= 1 && x <= row && y >= 1 && y <= col) ?? ??? ?{ ?? ??? ??? ?if (mine[x][y] == '1') ?? ??? ??? ?{ ?? ??? ??? ??? ?printf("你被炸死了\n"); ?? ??? ??? ??? ?show_board(mine, ROW, COL); ?? ??? ??? ??? ?break; ?? ??? ??? ?} ?? ??? ??? ?else ?? ??? ??? ?{ ?? ??? ??? ??? ?int count = get_mine_count(mine, x, y); ?? ??? ??? ??? ?show[x][y] = count + '0'; ?? ??? ??? ??? ?show_board(show, ROW, COL); ?? ??? ??? ??? ?win++; ?? ??? ??? ?} ?? ??? ?} ?? ??? ?else ?? ??? ?{ ?? ??? ??? ?printf("坐標(biāo)非法,請(qǐng)重新輸入\n"); ?? ??? ?} ?? ?} ? ?? ?if (win == row * col - EASY_COUNT) ?? ?{ ?? ??? ?printf("恭喜你,你贏了\n"); ?? ??? ?show_board(mine, ROW, COL); ?? ?} }
game.h
#pragma once ? #include <stdio.h> ? #define ROW 9 #define COL 9 ? #define ROWS ROW+2 #define COLS COL+2 ? #define EASY_COUNT 10 ? //初始化 void init_board(char arr[ROWS][COLS], int rows, int cols, char set); ? //打印棋盤(pán) void show_board(char arr[ROWS][COLS], int row, int col); ? //布置雷 void set_mine(char arr[ROWS][COLS], int row, int col); ? //排查雷 void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
這就是一個(gè)簡(jiǎn)單的掃雷游戲的實(shí)現(xiàn)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++ std::initializer_list 實(shí)現(xiàn)原理解析及遇到問(wèn)題
這篇文章主要介紹了C++ std::initializer_list 實(shí)現(xiàn)原理勘誤,本文通過(guò)源碼解析給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02C++ Boost MetaStateMachine定義狀態(tài)機(jī)超詳細(xì)講解
Boost是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱。Boost庫(kù)是一個(gè)可移植、提供源代碼的C++庫(kù),作為標(biāo)準(zhǔn)庫(kù)的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開(kāi)發(fā)引擎之一,是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱2022-12-12C語(yǔ)言深入了解自定義數(shù)據(jù)類型的使用
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言自定義數(shù)據(jù)類型的結(jié)構(gòu)體、枚舉和聯(lián)合的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04C語(yǔ)言實(shí)現(xiàn)運(yùn)動(dòng)會(huì)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)運(yùn)動(dòng)會(huì)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05