C語言實現(xiàn)簡單的掃雷小游戲
本文實例為大家分享了C語言實現(xiàn)掃雷小游戲的具體代碼,供大家參考,具體內(nèi)容如下
在編寫掃雷小游戲之前,第一,我們應(yīng)該列出我們想要實現(xiàn)的掃雷小游戲的功能:
1.顯示選中的坐標周圍的雷的個數(shù)。
2.保證第一次選中的坐標不是雷。
3.選中的坐標周圍8個格子中沒有雷,則展開。
第二,我們應(yīng)該明白我們需要兩個棋盤來實現(xiàn)掃雷游戲:一個棋盤用來展示給玩家,初始界面全為“ * ” (未翻開的格子),這個頁面就是我們常見的掃雷頁面。另一個棋盤用來給編寫者看,棋盤內(nèi)只有字符‘1'和字符‘0' ?!?'代表雷,‘0'代表非雷。使用字符‘1'‘0'來代表雷和非雷有利于我們下一步計算坐標周圍雷的個數(shù)。
1.初始化棋盤
nitboard(show_board, ROWS, COLS,'*'); //‘*'代表未翻開的坐標
Initboard(mine_board, ROWS, COLS, '0'); //‘0'代表非雷
void Initboard(char board[ROWS][COLS], int row, int col, char set)
{
memset(board, set, row*col * sizeof(board[0][0]));
}
2.打印棋盤
void DisPlayboard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf(" ");
for (i = 1; i <= row; i++) //打印行
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i); //打印列
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("\n");
}
3.在棋盤中埋入雷。(因為每一次重新開始游戲雷的位置不能重復(fù),所以選擇用隨機數(shù)來埋雷)
void GetBoom(char board[ROWS][COLS], int row, int col) //埋雷
{
int x = 0;
int y = 0;
int sum = 0;
while(1)
{
x = rand() % row +1; //雷放在1-9的范圍里
y = rand() % col +1;
if (1)
{
board[x][y] = '1';
sum++;
if (sum == M) //埋入雷后跳出循環(huán)
{
break;
}
}
}
4.確保第一次不踩到雷,如果第一次踩到雷,我們就將此位置改為非雷,然后將此處的雷移動到別處未放置雷的位置。
(還要考慮一種特殊情況,即如果第一次落子就獲得勝利的情況時后面函數(shù)就不用再執(zhí)行了,所以此函數(shù)要改為有返回值的函數(shù),這樣在調(diào)用此函數(shù)時就可以判斷是否為一次就獲得勝利的情況)
int Judge_first(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int m;
int n;
printf("請輸入要排查的坐標:");
scanf("%d%d", &x, &y);
while (1)
{
if (mine_board[x][y] == '1') //如果第一次踩雷,將此坐標改為非雷
{
mine_board[x][y] = '0';
show_board[x][y] = ' ';
while (1)
{
m = rand() % 9 + 1;
n = rand() % 9 + 1;
if (m != x && n != y && mine_board[m][n] != '1')
{
mine_board[m][n] = '1';
}
Open(mine_board, show_board, x, y);
if (Full(show_board, ROW, COL) == 1) //展開后判斷是否一次獲得勝利
{
printf("游戲勝利\n");
DisPlayboard(mine_board, ROW, COL);
return 2; //一次獲得勝利返回2 不再執(zhí)行PlayerMove函數(shù)
break;
}
DisPlayboard(show_board, row, col);
break;
}
break;
}
else if (mine_board[x][y] == '0')
{
show_board[x][y] = ' ';
Open(mine_board, show_board, x, y);
if (Full(show_board, ROW, COL) == 1)
{
printf("游戲勝利\n");
DisPlayboard(mine_board, ROW, COL);
return 2;
break;
}
DisPlayboard(show_board, row, col);
break;
}
}
}
5.當坐標周圍雷個數(shù)為0時,展示周圍格子,再以X和Y周圍八個坐標分別為中心展開,當坐標周圍有雷時不再遞歸展開,并將雷的個數(shù)放在該坐標。
void Open(char mine_board[ROWS][COLS],char show_board[ROWS][COLS], int x, int y)
{
int ret = 0;
ret = Num(mine_board, x, y);
if (ret == 0) //當坐標周圍雷個數(shù)為0時 打開周圍格子 再以X和Y周圍八個坐標為中心展開 重復(fù)即為遞歸展開
{
show_board[x][y] = ' ';
if (x - 1 > 0 && y - 1 > 0 && show_board[x - 1][y - 1] == '*')
{
Open(mine_board, show_board, x - 1, y - 1);
}
if (x - 1 > 0 && y > 0 && show_board[x - 1][y] == '*')
{
Open(mine_board, show_board, x - 1, y);
}
if (x - 1 > 0 && y + 1 <= COL && show_board[x - 1][y + 1] == '*')
{
Open(mine_board, show_board, x - 1, y + 1);
}
if (x > 0 && y + 1 <= COL && show_board[x][y + 1] == '*')
{
Open(mine_board, show_board, x, y + 1);
}
if (x + 1 < ROW && y + 1 <= COL && show_board[x + 1][y + 1] == '*')
{
Open(mine_board, show_board, x + 1, y + 1);
}
if (x + 1 <= ROW && y > 0 && show_board[x + 1][y] == '*')
{
Open(mine_board, show_board, x + 1, y);
}
if (x + 1 <= ROW && y - 1 > 0 && show_board[x + 1][y - 1] == '*')
{
Open(mine_board, show_board, x + 1, y - 1);
}
if (x > 0 && y - 1 > 0 && show_board[x][y - 1] == '*')
{
Open(mine_board, show_board, x, y - 1);
}
}
else if (ret != 0)
show_board[x][y] = Num(mine_board, x, y) + 48;
}
6.計算坐標周圍一圈中所含雷的個數(shù)。
int Num(char board[ROWS][COLS], int x, int y)
{
int sum = 0; //sum為坐標周圍雷的個數(shù)
sum = board[x - 1][y - 1]
+ board[x][y - 1] + board[x + 1][y - 1]
+ board[x + 1][y] + board[x + 1][y + 1]
+ board[x][y + 1] + board[x - 1][y + 1]
+ board[x - 1][y] - (8 * '0');
return sum;
}
7.判斷玩家是否排完所有雷。
int Full(char board[ROWS][COLS], int row, int col)
{
int i;
int j;
int sum = 0; //sum為棋盤未翻開格子的個數(shù)
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (board[i][j] == '*')
sum++;
}
}
if (sum == M) //當未翻開的格子數(shù)為雷數(shù)時 返回1
return 1;
}
8.玩家輸入坐標掃雷。
void PlayerMove(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int ret = 0;
while (1)
{
if (Full(show_board, ROW, COL) == 1) //棋盤未翻開格子等于雷數(shù)時玩家勝利
{
printf("游戲勝利\n");
DisPlayboard(mine_board, ROW, COL);
break;
}
printf("請輸入坐標:");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine_board[x][y] == '1') //玩家踩到雷,游戲結(jié)束
{
printf("游戲結(jié)束\n");
DisPlayboard(mine_board, ROW, COL);
break;
}
ret = Num(mine_board, x, y);
if (ret == 0) //周圍沒有雷時,展開周圍格子
{
Open(mine_board, show_board, x, y);
DisPlayboard(show_board, ROW, COL);
}
else if (ret != 0) //周圍有雷時打印雷的個數(shù)
{
show_board[x][y] = ret + 48;
DisPlayboard(show_board, ROW, COL);
}
}
else
printf("輸入錯誤,請重新輸入");
}
}
9.函數(shù)聲明,宏定義,函數(shù)的定義實現(xiàn),測試。
源文件:test.c //主要負責(zé)測試整個代碼
頭文件:game.h //包含函數(shù)各種聲明,宏定義
源文件:game.c //包含各種函數(shù)的定義
test.c
#include"game.h"
void menu()
{
printf("************************************\n");
printf("************************************\n");
printf("******* 1.play *******\n");
printf("******* 0.exit *******\n");
printf("************************************\n");
}
int game()
{
char show_board[ROWS][COLS] = { 0 };
char mine_board[ROWS][COLS] = { 0 };
//
Initboard(show_board, ROWS, COLS,'*'); //初始化數(shù)組
Initboard(mine_board, ROWS, COLS, '0');
printf("游戲開始\n");
DisPlayboard(show_board, ROW, COL); //打印玩家雷盤
//
GetBoom(mine_board, ROW, COL); //埋雷
printf("\n\n\n");
DisPlayboard(mine_board, ROW, COL); //打印雷盤
//
if (Judge_first(mine_board, show_board, ROW, COL) == 2) //如果一次勝利,就不再執(zhí)行PlayerMove函數(shù)
return 2;
//
PlayerMove(mine_board, show_board, ROW, COL);
}
void test()
{
int n;
menu();
do
{
printf("請輸入選項按鈕: ");
scanf("%d", &n);
switch (n)
{
case 1:
game();
break;
case 0:
printf("游戲退出\n");
break;
default:
printf("輸入錯誤,請重新輸入\n");
break;
}
}while(1);
}
int main()
{
srand((unsigned int)time(NULL));
test();
}
game.c
#include"game.h"
void Initboard(char board[ROWS][COLS], int row, int col, char set)
{
memset(board, set, row*col * sizeof(board[0][0]));
}
void DisPlayboard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf(" ");
for (i = 1; i <= row; i++) //打印行
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i); //打印列
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("\n");
}
void GetBoom(char board[ROWS][COLS], int row, int col) //埋雷
{
int x = 0;
int y = 0;
int sum = 0;
while(1)
{
x = rand() % row +1; //雷放在1-9的范圍里
y = rand() % col +1;
if (1)
{
board[x][y] = '1';
sum++;
if (sum == M) //埋入所需的雷后跳出循環(huán)
{
break;
}
}
}
}
int Judge_first(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int m;
int n;
printf("請輸入要排查的坐標:");
scanf("%d%d", &x, &y);
while (1)
{
if (mine_board[x][y] == '1') //如果第一次踩雷,將此坐標改為非雷
{
mine_board[x][y] = '0';
show_board[x][y] = ' ';
while (1)
{
m = rand() % 9 + 1;
n = rand() % 9 + 1;
if (m != x && n != y && mine_board[m][n] != '1')
{
mine_board[m][n] = '1';
}
Open(mine_board, show_board, x, y);
if (Full(show_board, ROW, COL) == 1) //展開后判斷是否一次獲得勝利
{
printf("游戲勝利\n");
DisPlayboard(mine_board, ROW, COL);
return 2; //一次獲得勝利返回2 不再執(zhí)行PlayerMove函數(shù)
break;
}
DisPlayboard(show_board, row, col);
break;
}
break;
}
else if (mine_board[x][y] == '0')
{
show_board[x][y] = ' ';
Open(mine_board, show_board, x, y);
if (Full(show_board, ROW, COL) == 1)
{
printf("游戲勝利\n");
DisPlayboard(mine_board, ROW, COL);
return 2;
break;
}
DisPlayboard(show_board, row, col);
break;
}
}
}
void PlayerMove(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int ret = 0;
while (1)
{
if (Full(show_board, ROW, COL) == 1) //棋盤下滿玩家勝利
{
printf("游戲勝利\n");
DisPlayboard(mine_board, ROW, COL);
break;
}
printf("請輸入坐標:");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine_board[x][y] == '1')
{
printf("游戲結(jié)束\n");
DisPlayboard(mine_board, ROW, COL);
break;
}
ret = Num(mine_board, x, y);
if (ret == 0) //周圍沒有雷時,展開周圍格子
{
Open(mine_board, show_board, x, y);
DisPlayboard(show_board, ROW, COL);
}
else if (ret != 0) //周圍有雷時打印雷的個數(shù)
{
show_board[x][y] = ret + 48;
DisPlayboard(show_board, ROW, COL);
}
}
else
printf("輸入錯誤,請重新輸入");
}
}
void Open(char mine_board[ROWS][COLS],char show_board[ROWS][COLS], int x, int y)
{
int ret = 0;
ret = Num(mine_board, x, y);
if (ret == 0) //當坐標周圍雷個數(shù)為0時 打開周圍格子 再以X和Y周圍八個坐標為中心展開 重復(fù)即為遞歸展開
{
show_board[x][y] = ' ';
if (x - 1 > 0 && y - 1 > 0 && show_board[x - 1][y - 1] == '*')
{
Open(mine_board, show_board, x - 1, y - 1);
}
if (x - 1 > 0 && y > 0 && show_board[x - 1][y] == '*')
{
Open(mine_board, show_board, x - 1, y);
}
if (x - 1 > 0 && y + 1 <= COL && show_board[x - 1][y + 1] == '*')
{
Open(mine_board, show_board, x - 1, y + 1);
}
if (x > 0 && y + 1 <= COL && show_board[x][y + 1] == '*')
{
Open(mine_board, show_board, x, y + 1);
}
if (x + 1 < ROW && y + 1 <= COL && show_board[x + 1][y + 1] == '*')
{
Open(mine_board, show_board, x + 1, y + 1);
}
if (x + 1 <= ROW && y > 0 && show_board[x + 1][y] == '*')
{
Open(mine_board, show_board, x + 1, y);
}
if (x + 1 <= ROW && y - 1 > 0 && show_board[x + 1][y - 1] == '*')
{
Open(mine_board, show_board, x + 1, y - 1);
}
if (x > 0 && y - 1 > 0 && show_board[x][y - 1] == '*')
{
Open(mine_board, show_board, x, y - 1);
}
}
else if (ret != 0)
show_board[x][y] = Num(mine_board, x, y) + 48;
}
int Num(char board[ROWS][COLS], int x, int y)
{
int sum = 0;
sum = board[x - 1][y - 1]
+ board[x][y - 1] + board[x + 1][y - 1]
+ board[x + 1][y] + board[x + 1][y + 1]
+ board[x][y + 1] + board[x - 1][y + 1]
+ board[x - 1][y] - (8 * '0');
return sum;
}
int Full(char board[ROWS][COLS], int row, int col)
{
int i;
int j;
int sum = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (board[i][j] == '*')
sum++;
}
}
if (sum == M)
return 1;
}
game.h
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include <stdlib.h> #include<time.h> #define ROW 9 #define COL 9 #define ROWS ROW + 2 #define COLS COL + 2 #define M 10 //所需雷的個數(shù) void test(); int game(); void Initboard(char board[ROWS][COLS], int row, int col, int set); //初始化數(shù)組 void DisPlayboard(char board[ROWS][COLS], int row, int col); //打印雷盤 void GetBoom(char board[ROWS][COLS], int row, int col); //安放炸彈 int Judge_first(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col); //保證第一次不是雷 void PlayerMove(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col); //玩家排雷 void Open(char mine_board[ROWS][COLS],char show_board[ROWS][COLS], int x, int y); //展開函數(shù) int Num(char mine_board[ROWS][COLS], int x, int y); //計算坐標周圍雷的數(shù)量 int Full(char board[ROWS][COLS], int row, int col); //判斷雷是否下滿
更多有趣的經(jīng)典小游戲?qū)崿F(xiàn)專題,分享給大家:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++編程中break語句和continue語句的學(xué)習(xí)教程
這篇文章主要介紹了C++編程中break語句和continue語句的學(xué)習(xí)教程,break和continue是C++循環(huán)控制中的基礎(chǔ)語句,需要的朋友可以參考下2016-01-01
JS調(diào)用C++函數(shù)拋出異常及捕捉異常詳解
這篇文章主要介紹了js調(diào)用C++函數(shù)的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2021-08-08

