幾段代碼,讓你用遞回解決C語言擴展排雷(掃雷)
- 前言
- 一、遞回是什么?
- 二、如何使用遞回將周圍無雷的棋子排除?
- 1.遞回和掃雷的關系
- 2.代碼實作
- 附錄
前言
幾段話,讓你用遞回解決C語言擴展排雷,熟悉我的人都知道,我是一個善于將程序寫的很詳細的精通人性的男“講師”,

今天給大家整個遞回擴展排雷!
一、遞回是什么?
程式呼叫自身的編程技巧稱為遞回,遞回做為一種演算法在程式設計語言中廣泛應用,一個程序或函式在其定義或說明中有直接或間接呼叫自身的一種方法,它通常把一個大型復雜的問題層層轉化為一個與原問題相似的規模較小的問題求解,遞回策略只需少量的程式就可描述出解題程序所需要的多次重復計算,大大地減少了程式的代碼量,
遞回的主要思考方式就在于:把大事化小,(自己呼叫自己)
要撰寫一個函式要確定遞回的兩個條件
1. 遞回結束的條件
2. 遞回的呼叫的公式
二、如何使用遞回將周圍無雷的棋子排除?
1.遞回和掃雷的關系
遞回在掃雷中可以解決擴展排雷的問題,當用戶排除掉一個棋子,該棋子周圍沒有雷,則展開,再從該九宮格依次排查,周圍是否有雷,無雷則繼續展開,有雷則輸出周圍有幾顆雷,我們不必去考慮遞回到底執行了幾次,最主要的目的就是將問題簡化,
當周圍有雷,該坐標排查結束,繼續排查其他坐標,遞回的終止條件即為當排查坐標不為字符’0’(這里我定義為0,代表坐標不是雷)或該坐標被排查過(為*字符)則遞回終止,
那么當排查坐標為字符’0’且該坐標未被排查過,遞回繼續執行,
if (mine[i][j] == '0' && showboard[i][j] == '*')
{
extendmine(mine, showboard, i, j);//遞回函式
}
如果該條件成立,則執行遞回,
這里函式中的i和j來不斷遞回等價于x和y,并求出該坐標周圍九宮格范圍內的雷數,
我們可以將這個遞回函式的實作分為兩個步驟:
1. 求出這個坐標周圍的雷數,如果為0,則將其變為空白,
2. 排查在該坐標九宮格范圍內的其他坐標,(這里我用了回圈,也可以使用很多個if陳述句來實作)
2.代碼實作
代碼如下(示例):
void extendmine(char mine[ROWS][COLS], char showboard[ROWS][COLS], int x, int y)
{
int n = 0;
n = howmanymine(mine, x, y);
if (n == 0)
{
showboard[x][y] = ' ';//如果周圍沒有雷,將中心賦值為空格
int i = 0;
int j = 0;
for (i = x - 1; i <= x + 1 && i >= 0 && i <= ROW; i++)
{
for (j = y - 1; j <= y + 1 && j >= 0 && j <= COL; j++)
{
if (i == x && j == y)//跳出(x,y)的位置
{
continue;
}
if (mine[i][j] == '0' && showboard[i][j] == '*')//坐標自身不是雷且還是初始化字符,進入遞回再次擴展排雷
{
extendmine(mine, showboard, i, j);//遞回函式
}
}
}
}
else
showboard[x][y] = n + '0';//如果附近有雷,展示雷的個數
}
那么掃雷游戲中較難的部分——如何使用遞回擴展排雷就可以解決了,
實作效果如下

附錄
主程式.c#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void menu()
{
printf("********************************\n");
printf("*************1.paly*************\n");
printf("*************2.exit*************\n");
printf("********************************\n");
}
void game()
{
char mine[ROWS][COLS] = { 0 };//布置雷的資訊
char showboard[ROWS][COLS] = { 0 };//排查出雷的資訊
init(mine, ROWS, COLS, '0');//初始化函式
init(showboard, ROWS, COLS, '*');
setmine(mine, ROW, COL);
display(mine, ROW, COL);
display(showboard, ROW, COL);
playgame(mine,showboard,ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 2:
printf("退出游戲\n");
break;
default:
printf("輸入錯誤,請重新輸入\n");
}
} while (input!=2);
}
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化棋盤
void init(char showboard[ROWS][COLS], int rows, int cols,char c)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
showboard[i][j] = c;
}
}
}
//放置地雷
void setmine(char mine[ROWS][COLS], int row, int col)
{
int x, y = 0;
int count = easy_game;
while (count)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
//列印棋盤
void display(char showboard[ROWS][COLS], int row, int col)
{
int i = 0;
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
int j = 0;
for (j = 1; j <= col; j++)
{
printf("%c ",showboard[i][j]);
}
printf("\n");
}
printf("\n");
}
//求出該坐標周圍有多少雷
int howmanymine(char mine[ROWS][COLS], int x, int y)
{
int i, j = 0;
int count = 0;
for (i = x - 1; i <= x + 1; i++)//x-1<=i<=x+1
{
for (j = y - 1; j <= y + 1; j++)//y-1<=i<=y+1
{
count += mine[i][j];
}
}
count = count - mine[x][y] - 8 * '0';//轉換為字符數字
return count;
}
//空白擴展
void extendmine(char mine[ROWS][COLS], char showboard[ROWS][COLS], int x, int y)
{
int n = 0;
n = howmanymine(mine, x, y);
if (n == 0)
{
showboard[x][y] = ' ';//如果周圍沒有雷,將中心賦值為空格
int i = 0;
int j = 0;
for (i = x - 1; i <= x + 1 && i >= 0 && i <= ROW; i++)
{
for (j = y - 1; j <= y + 1 && j >= 0 && j <= COL; j++)
{
if (i == x && j == y)//跳出(x,y)的位置
{
continue;
}
if (mine[i][j] == '0' && showboard[i][j] == '*')//坐標自身不是雷且還是初始化字符,進入遞回再次擴展排雷
{
extendmine(mine, showboard, i, j);//遞回函式
}
}
}
}
else
showboard[x][y] = n + '0';//如果附近有雷,展示雷的個數
}
//判斷是否獲勝
int is_win(char showboard[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
int count = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (showboard[i][j] == '*')
{
count++;
}
}
}
return count;
}
//主體程式
void playgame(char mine[ROWS][COLS], char showboard[ROWS][COLS], int row, int col)
{
int x, y = 0;
int n = 0;//判斷回圈是否繼續
while (1)
{
printf("請輸入你要排雷的坐標");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("你被炸死了,游戲結束!\n");
display(mine, row, col);
break;
}
else
{
int count = howmanymine(mine, x, y);
showboard[x][y] = count + '0';
extendmine(mine, showboard, x, y);
display(showboard, row, col);
n = is_win(showboard, row, col);
if (n == easy_game)
{
printf("恭喜你排雷成功!");
display(mine, row, col);
break;
}
}
}
else
{
printf("輸入錯誤,請重新輸入");
}
}
}
game.h
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS ROW+2
#define easy_game 9
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
void init(char mine[ROWS][COLS], int rows, int cols,char c);
void setmine(char mine[ROWS][COLS], int row, int col);
void display(char showboard[ROWS][COLS], int row, int col);
void playgame(char mine[ROWS][COLS],char showboard[ROWS][COLS],int row, int col);

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/291686.html
標籤:其他
