C語言實現(xiàn)掃雷游戲(含注釋詳解)
本文實例為大家分享了C語言實現(xiàn)掃雷游戲的具體代碼,供大家參考,具體內容如下
前言
一、游戲規(guī)則介紹
掃雷是一個十分經典的游戲,一張棋盤中有很多個不確定是雷還是安全區(qū)域的格子,當點擊之后若沒有雷則會在該區(qū)域顯示周圍八個格子雷的數(shù)目,若有雷則游戲結束。今天我就跟大家分享一下如何用c語言實現(xiàn)初階版掃雷。
二、基本思路流程介紹
1.創(chuàng)建一個用戶交互菜單
2.創(chuàng)建一個Show_Mines棋盤用來埋雷并初始化
3.創(chuàng)建一個Show_Table 棋盤用來和用戶交互并初始化
4.玩家選擇想要掃描的坐標
5.判定游戲是否結束
6.若沒有踩雷則在剛掃描的區(qū)域上顯示周圍八個區(qū)域的地雷數(shù)目并繼續(xù)游戲
7.繼續(xù)掃雷
8.判定游戲是否結束
…
9.若全部掃描完非雷區(qū)域則游戲結束
效果展示




三、代碼實現(xiàn)
1.用戶交互菜單(Menu函數(shù))
Menu(){
printf("########################\n");
printf("# 1. Play 0.Exit #\n");
printf("########################\n");
}
2. Game函數(shù)
void Game()
{
srand((unsigned long)time(NULL)); //生成隨機數(shù)種子
char show_board[ROW][COL];
char mines_board[ROW][COL];
memset(show_board, WHAT, sizeof(show_board));//生成并且初始化用戶顯示棋盤
memset(mines_board, '0', sizeof(mines_board));//生成并且初始化掃雷棋盤
SetMines(mines_board, ROW, COL);//放雷
int count = (ROW - 2)*(COL - 2) - NUM; //若掃完這些次 不觸雷則勝利
while (count){
system("cls");
ShowBoard(show_board, ROW, COL);
printf("請選擇你要掃描的區(qū)域坐標 ");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
if (x < 1 || x > ROW-2 || y < 1 || y > COL-2){ //非法性輸入判斷
printf("輸入錯誤!\n");
continue;
}
if (show_board[x][y] != WHAT){
printf("此處已經被掃過了,請從新輸出\n");
continue;
}
if (mines_board[x][y] == '1'){
system("cls");
ShowBoard(mines_board, ROW, COL);
printf("踩雷了!游戲結束!\n");
break;
}
show_board[x][y] = CountMines(mines_board, x, y);
count--;
}
}
1.memset函數(shù)直接定義show_board函數(shù)并且初始化二維數(shù)組為全WHAT宏定義的*。
2.先向用戶展示用戶展示棋盤,用戶輸入一個坐標進行非法性判斷。
3.把用戶輸入的坐標拿給放置雷的棋盤中,若該區(qū)域有雷則游戲結束,反之則繼續(xù)
4.游戲勝利條件為掃描完所有非雷區(qū)域
3.放雷函數(shù)(SetMines函數(shù))
void SetMines(char board[][COL], int row, int col){ //放雷函數(shù)
int count = NUM;
while (count){
int x = rand() % (row - 2) + 1;
int y = rand() % (col - 2) + 1;
if (board[x][y] == '0'){
board[x][y] = '1';
count--;
}
}
}
使用隨機數(shù)種子生成1到 棋盤大小長寬-2的隨機數(shù),這些隨機數(shù)組成的坐標放雷,循環(huán)次數(shù)就是雷的數(shù)目。因為隨機數(shù)可能生成一樣的,所以要進行一次非法性判斷,當棋盤這個位置沒有雷的情況下才能往里面放雷。
4.掃雷展示面板(ShowBoard函數(shù)和ShowLine函數(shù))
void ShowBoard(char board[][COL], int row, int col){//掃雷展示面板
printf(" ");
for (int i = 1; i <= (col - 2); i++){ //打印表頭數(shù)字
printf("%d ", i);
}
printf("\n");
ShowLine(col);//顯示行線
for (int i = 1; i <= (row - 2); i++){
printf("%-3d|", i);
for (int j = 1; j <= (col - 2); j++){
printf(" %c |", board[i][j]);
}
printf("\n");
ShowLine(col);
}
}
void ShowLine(int col){ //顯示橫著的虛線,作為行間隔
for (int i = 0; i <= (col - 2); i++){
printf("----");
}
printf("\n");
}
5.統(tǒng)計周圍雷的個數(shù)(CountMines函數(shù))
CountMines(char board[][COL], int x, int y){ //統(tǒng)計周圍雷的個數(shù)
return 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] + \
board[x + 1][y - 1] + board[x][y - 1] - 7 * '0';//本來減八個零,但是整形轉字符加一個‘0'
}
由于數(shù)組中存放的是字符'0',周圍是8個數(shù)字,所以-8*'0'才能返回雷數(shù)的int值,為了把數(shù)字也能打印出來,所以+‘0',否則打印的是數(shù)字作為的ASCLL碼的值,最終的結果為-7*‘0'.
6.mine函數(shù)
int main()
{
int quit = 0;
int select = 0;
while (!quit){
Menu();
printf("請輸入 ");
scanf("%d", &select);
switch (select){
case 1:
Game();
break;
case 0:
quit = 1;
break;
default:
printf("輸入錯誤,請重試!\n");
break;
}
}
printf("byebye!\n");
system("pause");
return 0;
}
四、總代碼
#ifndef __Test_H__
#define __Test_H__
#include<stdio.h>
#include<Windows.h>
#include <stdlib.h>
#include <time.h>
#define WHAT '*'
#define NUM 20
#define COL 10
#define ROW 10
void Game();
#pragma warning(disable:4996)
#endif //以上都是頭文件
int main()
{
int quit = 0;
int select = 0;
while (!quit){
Menu();
printf("請輸入 ");
scanf("%d", &select);
switch (select){
case 1:
Game();
break;
case 0:
quit = 1;
break;
default:
printf("輸入錯誤,請重試!\n");
break;
}
}
printf("byebye!\n");
system("pause");
return 0;
}
void Game()
{
srand((unsigned long)time(NULL)); //生成隨機數(shù)種子
char show_board[ROW][COL];
char mines_board[ROW][COL];
memset(show_board, WHAT, sizeof(show_board));
memset(mines_board, '0', sizeof(mines_board));
SetMines(mines_board, ROW, COL);
int count = (ROW - 2)*(COL - 2) - NUM; //若掃完這些次 不觸雷則勝利
while (count){
system("cls");
ShowBoard(show_board, ROW, COL);
printf("請選擇你要掃描的區(qū)域坐標 ");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
if (x < 1 || x > ROW-2 || y < 1 || y > COL-2){ //非法性輸入判斷
printf("輸入錯誤!\n");
continue;
}
if (show_board[x][y] != WHAT){
printf("此處已經被掃過了,請從新輸出\n");
continue;
}
if (mines_board[x][y] == '1'){
system("cls");
ShowBoard(mines_board, ROW, COL);
printf("踩雷了!游戲結束!\n");
break;
}
show_board[x][y] = CountMines(mines_board, x, y);
count--;
}
}
CountMines(char board[][COL], int x, int y){ //統(tǒng)計周圍雷的個數(shù)
return 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] + \
board[x + 1][y - 1] + board[x][y - 1] - 7 * '0';//本來減八個零,但是整形轉字符加一個‘0'
}
void ShowBoard(char board[][COL], int row, int col){//掃雷展示面板
printf(" ");
for (int i = 1; i <= (col - 2); i++){
printf("%d ", i);
}
printf("\n");
ShowLine(col);//顯示行線
for (int i = 1; i <= (row - 2); i++){
printf("%-3d|", i);
for (int j = 1; j <= (col - 2); j++){
printf(" %c |", board[i][j]);
}
printf("\n");
ShowLine(col);
}
}
oid SetMines(char board[][COL], int row, int col){ //放雷函數(shù)
int count = NUM;
while (count){
int x = rand() % (row - 2) + 1;
int y = rand() % (col - 2) + 1;
if (board[x][y] == '0'){
board[x][y] = '1';
count--;
}
}
}
void ShowLine(int col){
for (int i = 0; i <= (col - 2); i++){
printf("----");
}
printf("\n");
}
Menu(){ //用戶交互函數(shù)
printf("########################\n");
printf("# 1. Play 0.Exit #\n");
printf("########################\n");
}
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

