C語言C++學習交流群496926338
掃雷應該屬於一款大眾遊戲, 從我初中使用電腦開始, 它就被集成到了windows系統中, 雖然他是這麼經典, 我還是要介紹一下他的玩法,
1 遊戲的主介面, 是一個一個小方格, 在小方格上按一下左鍵, 可以翻開小方格看看後面有什麼。
2 在這些小方格的背後隱藏著雷, 如果不幸點中了雷, 那麼就GameOver了。
2 如果點中的不是一個雷, 那麼就是一塊空地, 這個時候會出現兩種情況:
1)用滑鼠點中的空地周圍八個點內有雷, 那麼就顯示雷的個數
2)用滑鼠點中的空地周圍沒有雷, 這個時候就將周圍的空地全部顯示出來, 遇到該顯示數位的空地, 就將數字顯示出來。 (仔細觀察你會發現, 數字會將空地圍起來, 這是一句廢話, 但是也值得想一想這是為什麼)
3 在小方格上, 點擊滑鼠的右鍵, 可以將一個空地標記為雷,
4 當空地上剩餘的格子數和雷的個數一樣多, 那麼這個時候就應該算是勝利啦。
OK~遊戲流程說完了, 這個時候該談談如何實現了。
1 首先需要一張地圖, 一般情況下我們都可以用一個二維陣列表示一個地圖, 每一個元素代表著掃雷中的一個小方格。 相應元素存儲0, 那麼地圖上的這個位置就是空地, 相應元素存儲1, 那麼就代表這個位置就一顆雷。
2 在控制台上依照二維陣列長度和寬度, 列印相應的小方塊。
3 然後就用滑鼠點擊那些小方塊, 對於控制台來講, 在黑框框的區域中是有座標的, 可以使用一些函數捕獲到你點擊了螢幕的哪一個座標。
4 對於控制台來說, 列印一個字元, 有的字元橫向占一個位置比如普通的字母數位, 有的字元橫向占兩個位置比如一些圖形字元: ①②③■◆等等,這點在控制台程式設計的時候要注意。
5 當點擊螢幕的時候,獲取到點擊的座標後,去二維陣列中查看相應的位置是雷還是空地,從而做相應的處理。
1)假如點擊到了雷, 那麼就控制遊戲結束
2)假如點擊到了空地有兩種情況
1)點擊的空地周圍有雷, 那麼就將雷的個數顯示出來
2)假如點擊的空地周圍沒有雷, 那麼就使用遞迴的方法去探測周圍的點, 探測出與其相連的所有周圍有雷的點。
這個是我實現的效果:
下面就是代碼啦:
// saolei.cpp : 定義控制台應用程式的入口點。
//
#include "stdafx.h"
#include
#include
#include
#define Boom 10
int a[10][10] = {0};
COORD TempPos[100] ={0};
int nSign = 0;
/************************************
函數名 : WriteWchar
函數作用: 在控制台相應的座標上顯示一串字元
返回值 : void
參數 : int x 橫坐標
參數 : int y 縱坐標
參數 : char szString[] 要顯示的字串
說明 :
************************************/
void WriteWchar(int x,int y,char szString[])
{
HANDLE hOut= GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = {x*2,y};
SetConsoleCursorPosition(hOut,pos);
printf("%s",szString);
}
/************************************
函數名 : DrawNumber
函數作用: 在相應的座標上, 根據傳入的數位, 列印相應的數位字元
返回值 : void
參數 : COORD pos 要列印的位置
參數 : int nNumber 要列印的數字
說明 :
************************************/
void DrawNumber(COORD pos,int nNumber)
{
switch (nNumber)
{
case 1:
WriteWchar(pos.X,pos.Y,"①");
break;
case 2:
WriteWchar(pos.X,pos.Y,"②");
break;
case 3:
WriteWchar(pos.X,pos.Y,"③");
break;
case 4:
WriteWchar(pos.X,pos.Y,"④");
break;
case 5:
WriteWchar(pos.X,pos.Y,"⑤");
break;
case 6:
WriteWchar(pos.X,pos.Y,"⑥");
break;
case 7:
WriteWchar(pos.X,pos.Y,"⑦");
break;
case 8:
WriteWchar(pos.X,pos.Y,"⑧");
break;
default:
break;
}
}
/************************************
函數名 : GetNumber
函數作用: 獲取一個點的四周有幾顆雷
返回值 : int
參數 : COORD pos 要探測的點的座標
說明 :
************************************/
int GetNumber(COORD pos)
{
int nCount = 0;
for(int i = pos.X-1;i
for (int j = pos.Y-1;j
{
if (a[j][i] == Boom)
{
nCount++;
}
}
return nCount;
}
/************************************
函數名 : Drawmap
函數作用: 列印一下地圖
返回值 : void
說明 :
************************************/
void Drawmap()
{
for (int i =0;i
{
for (int j =0;j
{
WriteWchar(j,i,"■");
}
}
}
/************************************
函數名 : Init
函數作用: 隨機生成10個地雷, 然後存到陣列中
返回值 : void
說明 :
************************************/
void Init()
{
srand(time(NULL));
for (int i =0;i
{
int Temp_x = rand()%10;
int Temp_y = rand()%10;
//判斷這個地方是不是已經生成一個雷了, 如果沒有, 賦值為雷
if (a[Temp_x][Temp_y]!=Boom)
{
a[Temp_x][Temp_y] = Boom;
}
//如果是雷, 就相當於本次生成沒有發生過。 。 。 。 。
else
{
i--;
}
}
Drawmap();
}
/************************************
函數名 : IsClose
函數作用: 判斷是不是已經探測過的點, 由於使用的8方向遞迴的探測,
返回值 : bool
參數 : COORD posTemp
說明 :
************************************/
bool IsClose(COORD posTemp)
{
for (int i =0;i
{
if(TempPos[i].X == posTemp.X&&TempPos[i].Y == posTemp.Y)
return true;
}
return false;
}
/************************************
函數名 : IsKongdi
函數作用: 判斷一個點是空地, 還是雷, 如果是空地, 需要做其他處理
返回值 : void
參數 : COORD pos
說明 :
************************************/
bool IsKongdi(COORD pos)
{
int nNumber = 0;
//1 如果是雷, 就直接返回一個false說明要掛了
if (a[pos.Y][pos.X] == Boom)
{
return false;
}
//2 如果不是雷, 那麼就做後續處理
else
{
//2.1先判斷一下周圍有幾顆雷
nNumber = GetNumber(pos);
if (nNumber!=0){
//有幾顆雷, 就列印這個數字
DrawNumber(pos,nNumber);
return true;
}
else
{
//如果沒有雷, 那就先畫空地出來, 然後向周圍擴散去探測其他點
WriteWchar(pos.X,pos.Y," ");
}
}
//2.2點到了空地, 但是周圍沒有雷的情況的處理, 繼續去探測周圍8個點
for(int i = -1;i
for (int j = -1;j
{
COORD posTemp = {pos.X+i,pos.Y+j};
//是不是越界了
if (i==0&&j==0||posTemp.X==-1||posTemp.Y==-1||posTemp.X==10||posTemp.Y==10)
continue;
//這個點是不是已經探測過了
if (IsClose(posTemp))
continue;
//這個點沒有探測過, 就將其加入到陣列中, 然後使其在以後的探測中, 存入
TempPos[nSign++] =posTemp;
IsKongdi(posTemp);
}
return true;
}
/************************************
函數名 : GetMousePosition
函數作用: 獲取滑鼠點擊的位置, 假如沒有獲取到, 就返回(-1,-1)
返回值 : COORD 滑鼠點擊的座標
說明 :
************************************/
COORD GetMousePosition()
{
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
INPUT_RECORD stcInput = {0};
DWORD buffer;
COORD pos = {-1,-1};
ReadConsoleInput(hIn,&stcInput,1,&buffer);
if (stcInput.EventType == MOUSE_EVENT)
{
MOUSE_EVENT_RECORD stcMouseEnent = stcInput.Event.MouseEvent;
if (stcMouseEnent.dwButtonState ==FROM_LEFT_1ST_BUTTON_PRESSED )
{
pos = stcMouseEnent.dwMousePosition;
pos.X/=2;
}
}
return pos;
}
int _tmain(int argc, _TCHAR* argv[])
{
Init();
COORD pos;
//開始遊戲
while(1)
{
//獲取滑鼠點擊位置
pos = GetMousePosition();
if (pos.X!=-1)
{
//如果滑鼠點擊的位置被探測過了,就開始下一次迴圈
if (IsClose(pos))
{
continue;
}
TempPos[nSign++] =pos;
bool bIskongdi = IsKongdi(pos);
//點到雷了,就直接退出遊戲了。
if (false ==bIskongdi)
{
system("cls");
WriteWchar(20,10,"you lose");
getchar();
break;
}
//檢測是不是贏了,贏的條件就是沒有被探測的點的個數和雷的個數相等
if (nSign ==90)
{
system("cls");
WriteWchar(20,10,"you win");
}
}
}
return 0;
}
項目不是很長,但是注釋我寫的還算明白,估計大家都可以看得懂,希望對於新手們有一定的幫助最後,謝謝大家的支持!!!
喜歡的話關注收藏評論轉發一波 比心麼麼噠!加入我們C語言C++學習交流 壹 496926338群內有大量的專案開發和新手教學視頻千人大群等著你來加入。pos = GetMousePosition();
if (pos.X!=-1)
{
//如果滑鼠點擊的位置被探測過了,就開始下一次迴圈
if (IsClose(pos))
{
continue;
}
TempPos[nSign++] =pos;
bool bIskongdi = IsKongdi(pos);
//點到雷了,就直接退出遊戲了。
if (false ==bIskongdi)
{
system("cls");
WriteWchar(20,10,"you lose");
getchar();
break;
}
//檢測是不是贏了,贏的條件就是沒有被探測的點的個數和雷的個數相等
if (nSign ==90)
{
system("cls");
WriteWchar(20,10,"you win");
}
}
}
return 0;
}
項目不是很長,但是注釋我寫的還算明白,估計大家都可以看得懂,希望對於新手們有一定的幫助最後,謝謝大家的支持!!!
喜歡的話關注收藏評論轉發一波 比心麼麼噠!加入我們C語言C++學習交流 壹 496926338群內有大量的專案開發和新手教學視頻千人大群等著你來加入。