C語(yǔ)言遞歸實(shí)現(xiàn)掃雷游戲
前言
首先要實(shí)現(xiàn)掃雷原理上同三子棋,都是通過(guò)一個(gè)二維數(shù)組來(lái)實(shí)現(xiàn)游戲主題功能那么這里有幾個(gè)值得注意的點(diǎn)
1、初級(jí)掃雷我們知道是九乘九數(shù)組實(shí)現(xiàn),那么在這里我們創(chuàng)建的是11乘11的數(shù)組,目的是方便后續(xù)判斷周圍九個(gè)格子的雷的數(shù)量!
2、而且我們需要?jiǎng)?chuàng)建兩個(gè)數(shù)組,一個(gè)用來(lái)存放字符1和0(1表示有雷,隨機(jī)數(shù)生成;0表示沒(méi)雷,初始化時(shí)自動(dòng)全放0);
另一個(gè)用來(lái)根據(jù)上邊的數(shù)組輸出顯示玩家是否被炸死,以及玩家選擇的坐標(biāo)周圍雷的數(shù)量
3、需要注意排雷時(shí)候如果附近沒(méi)有雷需要遞歸展開(kāi)?。?!
4、我們這里需要兩個(gè)源文件test.c game.c和頭文件game.h
一、菜單
這個(gè)游戲界面小伙伴自己設(shè)計(jì)就可老生常談我直接上代碼
void menu() { printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n"); printf("-*-*-*-*-*-*1.play 0.exit*-*-*-*-*-*-*-\n"); printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n"); } void test() { int input = 0; do { menu(); printf("請(qǐng)輸入:"); scanf("%d", &input); switch(input) { case 1:game(); break; case 0: printf("退出游戲!"); break; default:printf("輸入非法,請(qǐng)重新輸入:\n"); break; } } while (input); } int main() { srand((unsigned int)time(0)); test(); return 0; }
二、游戲數(shù)組的創(chuàng)建和初始化
那么在這里為了方便使用行數(shù)列數(shù)依然采用宏定義給出行數(shù)列數(shù)和雷的個(gè)數(shù)EASYCOUT
#define ROW 9 #define COL 9 #define ROWS 11 #define COLS 11 #define EASYCOUT 10
數(shù)組的創(chuàng)建
char mine[ROWS][COLS]; char show[ROWS][COLS];
數(shù)組初始化和打印
init(mine, ROWS, COLS, '0'); init(show, ROWS, COLS, '*'); display(mine, ROW, COL); display(show,ROW,COL);
void init(char board[ROWS][COLS], int rows, int cols, char ch) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { board[i][j] = ch; } } } void display(char board[ROWS][COLS], int rows, int cols) { printf(" "); for (int i = 1; i <= rows; i++) printf(" %d ",i); printf("\n"); for (int i = 1; i <= rows; i++) { printf("%d ",i); for (int j = 1; j <= cols; j++) { printf(" %c ", board[i][j]); }printf("\n"); } }
三、設(shè)置雷和掃雷
setmine(mine,ROWS,COLS); display(mine, ROW, COL);
1.設(shè)置雷
這里主要應(yīng)用隨機(jī)數(shù)的生成,之前的文章已經(jīng)介紹過(guò)。其次就是需要判斷隨機(jī)數(shù)的生成是否重復(fù),重復(fù)需要去重:
void setmine(char board[ROWS][COLS], int rows, int cols) { int x, y; for(int i=0;i < EASYCOUT;i++) { x = rand() % 9 + 1; y = rand() % 9 + 1; if (board[x][y] == '0') board[x][y] = '1';//1表示雷 else i--; } }
2.掃雷
在這個(gè)游戲主體部分我們需要用循環(huán)解決,循環(huán)次數(shù)則需要用
行數(shù)*列數(shù)-雷數(shù)量
同時(shí)需要注意輸入坐標(biāo)x y的范圍以及周圍的判斷!!
void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { // int x = 0, y = 0; int count = ROW* COL-EASYCOUT; int i = 0;//計(jì)算排雷次數(shù) while (count) { printf("請(qǐng)輸入排查的行數(shù)列數(shù):"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { i++; if (mine[x][y] == '1') { if (i == 1) { printf("很遺憾第一次你被炸死了,你還有最后機(jī)會(huì)!\n"); continue; } display(mine, ROW, COL); printf("很遺憾你被炸死了!\n"); break; } else { count--; //遞歸實(shí)現(xiàn) diguishow(mine,show,x,y, ROW, COL); display(show, ROW, COL); } } else { printf("輸入非法,重新輸入!\n"); } } if (!count) { printf("恭喜你獲得勝利!\n"); } }
3.周圍雷的數(shù)量的判斷
這里采用數(shù)值相減的方法字符1和字符0的值差1.
int getnum(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'; }
四、遞歸實(shí)現(xiàn)展示
這里注意兩個(gè)條件:
1、遞歸截止條件是該坐標(biāo)周圍的雷的數(shù)量非0
2、讓周圍8個(gè)坐標(biāo)依次遞歸
3、注意判斷過(guò)周圍8個(gè)格子沒(méi)有雷的坐標(biāo)需要標(biāo)記置空格?。?!來(lái)避免重復(fù)操作否則棧溢出
void diguishow(char mine[ROWS][COLS],char show[ROWS][COLS],int x,int y,int row,int col) { //截止條件該數(shù)字不是0 if (x >= 1 && x <= row && y >= 1 && y <= col) { if (show[x][y] == ' ') { return; } else if (getnum(mine, x, y) != 0) { show[x][y] = getnum(mine, x, y) + '0'; return; } else { show[x][y] = ' '; diguishow(mine, show, x - 1, y - 1,row,col); diguishow(mine, show, x - 1, y, row, col); diguishow(mine, show, x - 1, y + 1, row, col); diguishow(mine, show, x, y - 1, row, col); diguishow(mine, show, x, y + 1, row, col); diguishow(mine, show, x + 1, y - 1, row, col); diguishow(mine, show, x + 1, y, row, col); diguishow(mine, show, x + 1, y + 1, row, col); } } }
全代碼:
game.h
#pragma once #include<stdio.h> #include<Windows.h> #include<time.h> #include<stdlib.h> #define ROW 9 #define COL 9 #define ROWS 11 #define COLS 11 #define EASYCOUT 10 void init(char board[ROWS][COLS],int rows,int cols,char ch); void display(char board[ROWS][COLS],int rows,int cols); void setmine(char board[ROWS][COLS],int rows,int cols); void findmine(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col); int getnum(char mine[ROWS][COLS], int x, int y); void diguishow(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int row, int col);
test.c
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void game() { char mine[ROWS][COLS]; char show[ROWS][COLS]; init(mine, ROWS, COLS, '0'); init(show, ROWS, COLS, '*'); display(mine, ROW, COL); display(show,ROW,COL); //生成雷 setmine(mine,ROWS,COLS); display(mine, ROW, COL); //排雷 findmine(mine,show,ROW,COL); } void menu() { printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n"); printf("-*-*-*-*-*-*1.play 0.exit*-*-*-*-*-*-*-\n"); printf("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-\n"); } void test() { int input = 0; do { menu(); printf("請(qǐng)輸入:"); scanf("%d", &input); switch(input) { case 1:game(); break; case 0: printf("退出游戲!"); break; default:printf("輸入非法,請(qǐng)重新輸入:\n"); break; } } while (input); } int main() { srand((unsigned int)time(0)); test(); return 0; }
game.c
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void diguishow(char mine[ROWS][COLS],char show[ROWS][COLS],int x,int y,int row,int col) { //截止條件該數(shù)字不是0 if (x >= 1 && x <= row && y >= 1 && y <= col) { if (show[x][y] == ' ') { return; } else if (getnum(mine, x, y) != 0) { show[x][y] = getnum(mine, x, y) + '0'; return; } else { show[x][y] = ' '; diguishow(mine, show, x - 1, y - 1,row,col); diguishow(mine, show, x - 1, y, row, col); diguishow(mine, show, x - 1, y + 1, row, col); diguishow(mine, show, x, y - 1, row, col); diguishow(mine, show, x, y + 1, row, col); diguishow(mine, show, x + 1, y - 1, row, col); diguishow(mine, show, x + 1, y, row, col); diguishow(mine, show, x + 1, y + 1, row, col); } } } int getnum(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 findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { // int x = 0, y = 0; int count = ROW* COL-EASYCOUT; int i = 0;//計(jì)算排雷次數(shù) while (count) { printf("請(qǐng)輸入排查的行數(shù)列數(shù):"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { i++; if (mine[x][y] == '1') { if (i == 1) { printf("很遺憾第一次你被炸死了,你還有最后機(jī)會(huì)!\n"); continue; } display(mine, ROW, COL); printf("很遺憾你被炸死了!\n"); break; } else { count--; //遞歸實(shí)現(xiàn) diguishow(mine,show,x,y, ROW, COL); display(show, ROW, COL); } } else { printf("輸入非法,重新輸入!\n"); } } if (!count) { printf("恭喜你獲得勝利!\n"); } } void init(char board[ROWS][COLS], int rows, int cols, char ch) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { board[i][j] = ch; } } } void display(char board[ROWS][COLS], int rows, int cols) { printf(" "); for (int i = 1; i <= rows; i++) printf(" %d ",i); printf("\n"); for (int i = 1; i <= rows; i++) { printf("%d ",i); for (int j = 1; j <= cols; j++) { printf(" %c ", board[i][j]); }printf("\n"); } } void setmine(char board[ROWS][COLS], int rows, int cols) { int x, y; for(int i=0;i < EASYCOUT;i++) { x = rand() % 9 + 1; y = rand() % 9 + 1; if (board[x][y] == '0') board[x][y] = '1';//1表示雷 else i--; } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語(yǔ)言代碼實(shí)現(xiàn)簡(jiǎn)單的掃雷小游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言代碼實(shí)現(xiàn)簡(jiǎn)單的掃雷小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03通過(guò)先序遍歷和中序遍歷后的序列還原二叉樹(shù)(實(shí)現(xiàn)方法)
下面小編就為大家?guī)?lái)一篇通過(guò)先序遍歷和中序遍歷后的序列還原二叉樹(shù)(實(shí)現(xiàn)方法)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06