.
??write in front??
??大家好,我是gugugu。希望你看完之后,能對你有所幫助,不足請指正!共同學(xué)習(xí)交流??
??本文由 gugugu 原創(chuàng) CSDN首發(fā)?? 如需轉(zhuǎn)載還請通知?
??個人主頁:gugugu—CSDN博客
??歡迎各位→點贊?? + 收藏?? + 留言???
??系列專欄:gugugu的系列專欄——CSDN博客
??我們并非登上我們所選擇的舞臺,演出并非我們所選擇的劇本??
前言
在學(xué)完數(shù)組和函數(shù)之后,今天帶來C語言的第二個小游戲——掃雷。
本程序?qū)Τ鯇W(xué)者來說存在一定難度,多次反復(fù)練習(xí),加強理解即可。
本文將從設(shè)計思路,功能實現(xiàn)等角度進(jìn)行詳細(xì)教學(xué)分析。
注意:本游戲是多文件編程
一.介紹掃雷。
1.掃雷的規(guī)則
游戲規(guī)則:點擊方格,如果是地雷,游戲失敗,找到所有方格,而不踩到地雷游戲勝利。游戲初始,所有的方格都是被覆蓋的。點開的“空”會標(biāo)識數(shù)字,中心的“空”標(biāo)識數(shù)字“1”,即表示其周圍8個方格內(nèi)僅有1顆雷,玩家需要通過這樣的信息來判斷正確的雷區(qū)位置并予以標(biāo)識。最終排除所有地雷獲勝。
看看掃雷游戲的原版是啥樣的吧。
本文將介紹初階的掃雷,進(jìn)階版將在不久之后繼續(xù)更新。
2.掃雷功能模板
掃雷游戲主要由以下幾個板塊組成
a.菜單
b.初始化
c.打印游戲界面
d.布置雷
e.排除雷
二、掃雷功能分析
首先本游戲依舊采用do while循環(huán)的結(jié)構(gòu)實現(xiàn)多次進(jìn)行游戲的功能。
1.確定棋盤的大小和雷的個數(shù)
在這里我們需要使用宏來確定棋盤的大小和雷的個數(shù)
使用宏可以方便隨時更改,而不會把程序給寫死,也就是說,我們想要多大的棋盤,想要多少顆雷都可以隨時更改
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2//棋盤大小
#define BOOM 10//10課雷
2.菜單
掃雷游戲的菜單和猜數(shù)字游戲菜單的實現(xiàn)是一個道理,詳細(xì)可見猜數(shù)字游戲博客
…鏈接…
創(chuàng)建一個變量,用1表示開始游戲,用0表示結(jié)束游戲,設(shè)計一個菜單進(jìn)行選擇即可。
void main()
{
printf("#####################\n");
printf("########1.play#######\n");
printf("########0.exit#######\n");
printf("#####################\n");
}
3.初始化
棋盤初始化就是將界面清空,放上我們想讓界面存在的東西。
void init(char board[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++)
{
board[i][j]=set;
}
}
}
4.打印
我們玩游戲的時候肯定要看到游戲界面啊,所以需要寫一個函數(shù)來打印游戲界面。
也就是打印數(shù)組的內(nèi)容。
但是打印的時候不能只有*啊
我們還得打印行號和列號來輔助玩家確定坐標(biāo)。
void Display(char board[ROWS][COLS],int row,int col)//這個地方使用rows和cols也可以,代碼差別不大
{
//分割線
printf("########掃雷########\n");
//打印列號
int i=0;
for(i=0;i<=col;i++)
{
printf("%d ",i);
}
//換行
printf("\n");
//打印棋盤內(nèi)容
for(i=1;i<=row;i++)
{
int j=0;
for(j=0;j<=col;j++)//一行
{
if(j=0)
{
printf("%d ",i);//打印行號
}
else
{
printf("%c ",board[i][j]);
}
}
printf("\n");
}
printf("########掃雷########\n");
}
5.布置雷
首先我們確定雷的個數(shù)
使用宏來確定雷的個數(shù),比較方便,易于更改
#define BOOM 10
但是記住雷的數(shù)量要布置的合理,不能出現(xiàn)9*9的棋盤,出現(xiàn)100顆雷,對吧。
- 那么雷的位置如何確定呢?
這就需要創(chuàng)建兩個隨機數(shù)分別放在x和y中,作為行號和列號。
布置雷肯定是把數(shù)組某一個位置上放雷,我們把雷記作‘1’,注意,這里的1是字符1,而不是數(shù)字1.
-
但是肯定不止布置一顆雷啊,所以需要用到循環(huán),創(chuàng)建一個變量int count=BOOM;
把count作為while的判斷條件,每進(jìn)行一次循環(huán)count–,那么當(dāng)count=0,也就是當(dāng)雷布置完的時候,會自動退出循環(huán)。 -
注意,每次布置雷的時候,要確定這個地方是否已經(jīng)布置過雷了,如果布置過雷的話,重新產(chǎn)生隨機數(shù),重新布置這顆雷。
look look!!
void getboom(char board[ROWS][COLS],int row,int col)
{
int x=0;
int y=0;
int count=BOOM;
while(count)
{
int x=rand()%row+1;
int y=rand()%col+1;
if(board[x][y]=='0')
{
board[x][y]='1';
count--;
}
}
}
6.排雷
布置好雷之后要進(jìn)行排查雷,每次排查完一次之后都要進(jìn)行一次排查完之后的展示
如果排到的地方是雷的話,你會被炸死,游戲結(jié)束;
如果不是雷,則在該處計算并輸出旁邊的八個格子內(nèi)有多少顆雷;
一直循環(huán),知道炸死,或者雷被排完。
void outboom(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
int x=0;
int y=0;
int count=row*col-BOOM;
while(count)
{
printf("請輸入坐標(biāo)\n");
scanf("%d %d",&x,&y);
if(x>=1&&x<=row&&y>=1&&y<=col)
{
if(show[x][y]!='*')
{
printf("該位置已被排查,請重新輸入\n”);
}
if(mine[x][y]=='1')
{
printf("很遺憾,你被炸死了\n");
break;
}
else
{
char num=getnum(mine,x,y);//需要再引入一個函數(shù)
show[x][y]=num;
display(show,ROW,COL);
}
}
else
{
printf("坐標(biāo)非法,請重新輸入\n");
}
7.數(shù)雷的個數(shù)
這里就需要另寫一個函數(shù)來實現(xiàn)這個功能了,因為我們的數(shù)組show和mine都是字符數(shù)組,所以我們返回的雷的個數(shù)也需要是字符,所以將返回類型定義為char
char getnum(char board[ROWS][COLS], int x,int y)
{
return (board[x-1][y-1]+
board[x-1][y]+
board[x-1][y+1]+
board[x][y-1]+
board[x][y+1]+
board[x+1][y-1]+
board[x+1][y]+
board[x+1][y+1]-8*48+48);
}
-
來分析一下為什么會這么寫
-
首先我們先解釋一下為什么可以字符加減
-
每一個字符會對應(yīng)一個ASCII碼表, 字符會先轉(zhuǎn)化為ASCII碼值,用ASCII碼值進(jìn)行加減,再返回ASCII碼表對應(yīng)的字符
-
-
為什么要先減8*48呢?
-
因為0的ASCII碼值為48,這里就是相當(dāng)于8個位置都減了一個字符0
-
那為什么要加48呢?
-
如果不加48的話,那運算結(jié)果就是從ASCII值0開始,可以看上表,ASCII碼值0對應(yīng)的字符是不顯示字符,但是字符0對應(yīng)的ASCII值為48,之后加上48之后,才能從字符0開始輸出。
三、效果演示
大致就是這些功能啦,更高級的功能將在下一次博客—進(jìn)階版掃雷更新,敬請期待!
四、源碼
1、頭文件(game.h)
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define BOOM 10
void init(char board[ROWS][COLS], int rows, int cols, char set);
void display(char board[ROWS][COLS], int row, int col);
void getboom(char board[ROWS][COLS], int row, int col);
void outboom(char board[ROWS][COLS], int row, int col);
2、函數(shù)實現(xiàn)部分(game.c)
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
char numboom(char board[ROWS][COLS], int x, int y)
{
return board[x - 1][y - 1] +
board[x - 1][y] +
board[x - 1][y + 1] +
board[x][y - 1] +
board[x][y + 1] +
board[x + 1][y - 1] +
board[x + 1][y] +
board[x + 1][y + 1] - 8 * 48 + 48;
}
//初始化
void init(char board[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++)
{
board[i][j] = set;
}
}
}
//打印
void display(char board[ROWS][COLS], int row, int col)
{
printf("-------掃雷--------\n");
int i = 0;
//列號
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
//打印內(nèi)容
for (i = 1; i <= row; i++)
{
int j = 0;
for (j = 0; j <= col; j++)//一行
{
if (j == 0)
{
printf("%d ", i);//行號
}
else
{
printf("%c ", board[i][j]);
}
}
printf("\n");
}
printf("-------掃雷--------\n");
}
//布置雷
void getboom(char board[ROWS][COLS], int row, int col)
{
int count = BOOM;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
//排查雷
void outboom(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = row * col - BOOM;
while (count)
{
printf("請輸入坐標(biāo)\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] != '*')
{
printf("位置已經(jīng)排查,請重新輸入\n");
}
if (mine[x][y] == '1')
{
printf("很遺憾,你被炸死了\n");
display(mine, ROW, COL);
break;
}
else
{
char num = numboom(mine, x, y);
show[x][y] = num;
display(show, ROW, COL);
count--;
}
}
else
{
printf("輸入的坐標(biāo)非法,請重新輸入\n");
}
}
if (count == 0)
{
printf("游戲獲勝\n");
}
}
3、主函數(shù)部分(test.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 game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化
init(mine, ROWS, COLS, '0');
init(show, ROWS, COLS, '*');
//打印
display(mine, ROW, COL);
display(show, ROW, COL);
//布置雷
getboom(mine, ROW, COL);
display(mine, ROW, COL);
//排查雷
outboom(mine, show, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("請選擇\n");
scanf("%d", &input);
switch (input)
{
case 1:
printf("###### 掃雷 ########\n");
game();
break;
case 0:
printf("安全退出\n");
break;
default :
printf("選擇錯誤,請重新選擇\n");
break;
}
} while (input);
return 0;
}
好了,到這里本期分享就結(jié)束了,不知道各位小伙伴有沒有學(xué)會,可以在評論區(qū)留言哦,博主看到就會回答的。下一期進(jìn)階版掃雷將很快更新?。?!敬請期待?。。。?!
?。。。。。。。。。。。。?!求關(guān)注!?。。。。。。。。。。。。。。。?br> ?。。。。。。。。。。。。?mark>一鍵三連吧?。。。。。。。。。。。。。。?!文章來源:http://www.zghlxwxcb.cn/news/detail-624697.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-624697.html
到了這里,關(guān)于【C語言】掃雷小游戲詳細(xì)分析(模塊化編程)——內(nèi)附源碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!