掃雷
- 1 掃雷介紹
- 2 效果演示
- 3 步驟實作
- 4 模塊代碼講解
- 5 相關檔案代碼分享
1 掃雷介紹

相信大家小時候都玩過掃雷小游戲,哈哈哈,爺青回,這里先簡單介紹下掃雷的游戲規則吧,首先隨便點一個位置就會出現一系列的數字,每個數字代表的就是以這個數字為中心的九宮格里面有幾個雷,通過不斷的推理計算當最后我們標記的地雷數量和游戲設定的數量相同且其余的方塊都被點過那么我們就獲得了勝利,如果我們不小心點到了地雷游戲就會直接結束,

2 效果演示
下面我們開始一步一步用代碼自己實作掃雷游戲,首先看一下效果,




3 步驟實作
第一步是顯示棋盤,如果我們把雷的資訊和要呈現給玩家的資訊放在一個棋盤上的話,那么同時列印就會將雷的資訊也暴露了,所以我們選擇用兩個棋盤,一個放雷的資訊,一個呈現給玩家看和進行游戲,
注意:這里由于我們后面要進行一個周圍九宮格是否有雷的判斷,所以我們定義的棋盤陣列要比我們實際玩的要大一圈,否則會造成陣列的越界訪問,
第二步是隨機在放雷的棋盤中隨機放入我們設定的雷的數量,
第三步是進行雷的排查,同時每選擇一次都列印一次棋盤方便玩家進行選擇,同時需要進行判斷輸贏從而退出游戲,
4 模塊代碼講解
主函式我們用do while回圈加上swith陳述句來實作
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("請輸入:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("輸入錯誤,請重新輸入\n");
break;
}
} while(input);
return 0;
}
這樣我們的程式框架就搭建好了,接下來進行細節(也就是函式的補充)
顯示選單函式
void menu()
{
printf("****************************\n");
printf("**********1.開始游戲********\n");
printf("**********0.不玩了**********\n");
printf("****************************\n");
}
玩游戲函式
void game()
{
//定義兩個陣列分別存放雷和用來排查的界面
char mine[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};
//初始化兩個陣列
InitBoard(mine, ROWS, COLS, '0');//'0'
InitBoard(show, ROWS, COLS, '*');//'*'
//在mine陣列中放置雷
Putmine(mine, ROW, COL);
//顯示排雷陣列
Display(show, ROW, COL);
//在show陣列中排查雷
Findmine(mine, show, ROW, COL);
}
到這里我們就可以對我們需要的函式進行一個宣告和定義了,首先我們建立一個game.h檔案放入我們的函式宣告加上宏定義
#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROWS 11
#define COLS 11
#define MINES 10
#define ROW ROWS-2
#define COL COLS-2
void InitBoard(char arr[ROWS][COLS],int row,int col, char ch);
void Putmine(char arr[ROWS][COLS], int row,int col);
void Display(char arr[ROWS][COLS], int row,int col);
void Findmine(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int row, int col);
int Count(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int x, int y);
void Extendmine(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int x, int y);
int Is_win(char arr1[ROWS][COLS], int row, int col);
然后我們建立一個game.c的檔案放函式的定義
初始化棋盤函式,
void InitBoard(char arr[ROWS][COLS], int row, int col, char ch)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
arr[i][j] = ch;
}
}
}
在放雷的資訊的棋盤陣列里面隨機放入我們設定的雷的函式,
void Putmine(char arr[ROWS][COLS], int row, int col)
{
int count = 0;
while (count < MINES)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (arr[x][y] != '1')
{
arr[x][y] = '1';
count++;
}
}
}
列印我們的棋盤陣列的函式,
void Display(char arr[ROWS][COLS], int row, int col)
{
int i = 0;
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
printf(" ");
for (i = 0; i < col; i++)
{
if (i == col - 1)
{
printf("-");
}
else
{
printf("--");
}
}
printf("\n");
for (i = 1; i <=row; i++)
{
int j = 0;
printf("%d|", i);
for (j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
計算我們我們輸入的資料周圍雷的個數的函式,
int Count(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int x, int y)
{
int i = 0;
int count = 0;
for (i = x - 1; i <= (x + 1); i++)
{
int j = 0;
for (j = y - 1; j <= (y + 1); j++)
{
if ('1' == arr1[i][j])
{
count++;
}
}
}
return count;
}
接下來就是最重要的函式,找雷的函式,在找雷的程序中我們需要不斷根據玩家的輸入進行判斷是否為雷,
void Findmine(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int ret = 0;
while (1)
{
printf("####################\n");
printf("請輸入本次排查的坐標:");
scanf("%d %d", &x, &y);
printf("####################\n");
if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
{
if ('1' == arr1[x][y])
{
printf("很不幸,你踩到雷了\n");
break;
}
else
{
arr2[x][y] = Count(arr1, arr2, x, y) + '0';
Extendmine(arr1, arr2, x, y);
Display(arr2, ROW, COL);
}
ret = Is_win(arr2, ROW, COL);
if (ret == MINES)
{
printf("恭喜你贏啦!!!!!\n");
}
}
else
{
printf("輸入錯誤,請再次輸入一次吧:");
}
}
}
在找雷的函式中我們又用到了一個實作“炸開”效果的函式,這里用到了遞回的方法,后面再詳細講解遞回中我會跟大家來詳細解釋這段代碼,
void Extendmine(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int x, int y)
{
char n = '0';
n = Count(arr1, arr2, x, y)+'0';
if ('0' == n)
{
arr2[x][y] = ' ';
int i = 0;
for (i = x - 1; i <= x + 1; i++)
{
int j = 0;
for (j = y - 1; j <= y + 1; j++)
{
if (i == x && j == y)
{
continue;
}
if (arr1[i][j] == '0' && arr2[i][j] == '*')
{
Extendmine(arr1, arr2, i, j);
}
}
}
}
else
{
arr2[x][y] = n;
}
}
最后就是我們判斷輸贏的函式,我們只需要在每一次輸入后玩家的陣列中’*'的個數即可,若個數剛好為雷的數量,則玩家獲勝,
int Is_win(char arr[ROWS][COLS], int row, int col)
{
int count_mine = 0;
int i = 0;
for (i = 1; i <= row; i++)
{
int j = 0;
for (j = 1; j <= col; j++)
{
if (arr[i][j] == '*')
{
count_mine++;
}
}
}
return count_mine;
}
5 相關檔案代碼分享
test.c
#include <stdio.h>
#include "game.h"
void menu()
{
printf("****************************\n");
printf("**********1.開始游戲********\n");
printf("**********0.不玩了**********\n");
printf("****************************\n");
}
void game()
{
//定義兩個陣列分別存放雷和用來排查的界面
char mine[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};
//初始化兩個陣列
InitBoard(mine, ROWS, COLS, '0');//'0'
InitBoard(show, ROWS, COLS, '*');//'*'
//在mine陣列中放置雷
Putmine(mine, ROW, COL);
//顯示排雷陣列
Display(show, ROW, COL);
//在show陣列中排查雷
Findmine(mine, show, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("請輸入:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("輸入錯誤,請重新輸入\n");
break;
}
} while(input);
return 0;
}
game.h
#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROWS 11
#define COLS 11
#define MINES 10
#define ROW ROWS-2
#define COL COLS-2
void InitBoard(char arr[ROWS][COLS],int row,int col, char ch);
void Putmine(char arr[ROWS][COLS], int row,int col);
void Display(char arr[ROWS][COLS], int row,int col);
void Findmine(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int row, int col);
int Count(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int x, int y);
void Extendmine(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int x, int y);
int Is_win(char arr1[ROWS][COLS], int row, int col);
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void InitBoard(char arr[ROWS][COLS], int row, int col, char ch)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
arr[i][j] = ch;
}
}
}
void Putmine(char arr[ROWS][COLS], int row, int col)
{
int count = 0;
while (count < MINES)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (arr[x][y] != '1')
{
arr[x][y] = '1';
count++;
}
}
}
void Display(char arr[ROWS][COLS], int row, int col)
{
int i = 0;
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
printf(" ");
for (i = 0; i < col; i++)
{
if (i == col - 1)
{
printf("-");
}
else
{
printf("--");
}
}
printf("\n");
for (i = 1; i <=row; i++)
{
int j = 0;
printf("%d|", i);
for (j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
int Count(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int x, int y)
{
int i = 0;
int count = 0;
for (i = x - 1; i <= (x + 1); i++)
{
int j = 0;
for (j = y - 1; j <= (y + 1); j++)
{
if ('1' == arr1[i][j])
{
count++;
}
}
}
return count;
}
void Extendmine(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int x, int y)
{
char n = '0';
n = Count(arr1, arr2, x, y)+'0';
if ('0' == n)
{
arr2[x][y] = ' ';
int i = 0;
for (i = x - 1; i <= x + 1; i++)
{
int j = 0;
for (j = y - 1; j <= y + 1; j++)
{
if (i == x && j == y)
{
continue;
}
if (arr1[i][j] == '0' && arr2[i][j] == '*')
{
Extendmine(arr1, arr2, i, j);
}
}
}
}
else
{
arr2[x][y] = n;
}
}
void Findmine(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int ret = 0;
while (1)
{
printf("####################\n");
printf("請輸入本次排查的坐標:");
scanf("%d %d", &x, &y);
printf("####################\n");
if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
{
if ('1' == arr1[x][y])
{
printf("很不幸,你踩到雷了\n");
break;
}
else
{
arr2[x][y] = Count(arr1, arr2, x, y) + '0';
Extendmine(arr1, arr2, x, y);
Display(arr2, ROW, COL);
}
ret = Is_win(arr2, ROW, COL);
if (ret == MINES)
{
printf("恭喜你贏啦!!!!!\n");
}
}
else
{
printf("輸入錯誤,請再次輸入一次吧:");
}
}
}
int Is_win(char arr[ROWS][COLS], int row, int col)
{
int count_mine = 0;
int i = 0;
for (i = 1; i <= row; i++)
{
int j = 0;
for (j = 1; j <= col; j++)
{
if (arr[i][j] == '*')
{
count_mine++;
}
}
}
return count_mine;
}
本人水平有限,如有錯誤歡迎指正!!!
有更好的方法也歡迎討論!!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/292810.html
標籤:其他
