今天發布源代碼,由於寫在一個文件里非常亂,所以分三個文件寫
繪圖和鼠標函數graph.h
/*繪圖與鼠標相關函數*/
#include<graphics.h>
#include <easyx.h>
void DrawEmpty(int, int, int, int);//初始化空格子界面的函數
void DrawSmile(void);//畫笑臉的函數
void DrawRedFlag(int, int);//右鍵畫紅旗的函數
int MouseX, MouseY;//鼠標的x,y坐標
MOUSEMSG m;//鼠標結構變量,接受鼠標消息
void DrawSmile(void)
{
setfillstyle(BS_SOLID);
setfillcolor(YELLOW);
fillellipse(90, 5, 110, 25);//繪制橢圓(笑臉)函數,參數為橢圓外切矩形的左上右下角坐標
setfillstyle(BS_SOLID);
setfillcolor(BLACK);//畫眼睛
fillellipse(93, 13, 97, 17);
fillellipse(103, 13, 107, 17);
bar(97, 20, 103, 21);//畫嘴巴
}
void DrawRedFlag(int i, int j)
{
setfillstyle(BS_SOLID);
setfillcolor(RED);
bar(8 + j * 20, 35 + i * 20, 8 + j * 20 + 5, 35 + i * 20 + 5);
setcolor(BLACK);
line(8 + j * 20, 35 + i * 20, 8 + j * 20, 35 + i * 20 + 10);
}
void DrawEmpty(int i, int j, int mode, int color) //畫出16*16的小格
{
setfillstyle(BS_SOLID);
setfillcolor(color);
if (mode == 0)
{
bar(10 + j * 20 - 8, 40 + i * 20 - 8, 10 + j * 20 + 8, 40 + i * 20 + 8);
}
else if (mode == 1)
{
bar(10 + j * 20 - 7, 40 + i * 20 - 7, 10 + j * 20 + 7, 40 + i * 20 + 7);
}
}
void MouseGetXY(void)//獲得鼠標的位置
{
m = GetMouseMsg();
MouseX = m.x;
MouseY = m.y;
}
輔助計算函數auxiliary.h
/*輔助函數*/
#include <conio.h> //_kbhit()
struct
{
int num;//格子當前狀態,1表示有雷,0表示無雷或已經顯示數字
int roundnum;//統計格子周圍的雷數
int flag;//右鍵按下顯示紅旗標志,0表示沒有,1表示有
}Mine[10][10];
int mineNUM;//統計處理過的格子數
TCHAR randmineNUM[100];//顯示數字的字符串
/*統計每個格子周圍的雷數*/
int MineStatistics(int i, int j)
{
int nNUM = 0;
if (i == 0 && j == 0)//左上角格子的統計
{
if (Mine[0][1].num == 1)
nNUM++;
if (Mine[1][0].num == 1)
nNUM++;
if (Mine[1][1].num == 1)
nNUM++;
}
else
if (i == 0 && j == 9)//右上角格子的統計
{
if (Mine[0][8].num == 1)
nNUM++;
if (Mine[1][9].num == 1)
nNUM++;
if (Mine[1][8].num == 1)
nNUM++;
}
else
if (i == 9 && j == 0)//左下角格子的統計
{
if (Mine[8][0].num == 1)
nNUM++;
if (Mine[9][1].num == 1)
nNUM++;
if (Mine[8][1].num == 1)
nNUM++;
}
else
if (i == 9 && j == 9)//右下角格子的統計
{
if (Mine[9][8].num == 1)
nNUM++;
if (Mine[8][9].num == 1)
nNUM++;
if (Mine[8][8].num == 1)
nNUM++;
}
else if (j == 0)//左邊第一列格子的統計
{
if (Mine[i][j + 1].num == 1)
nNUM++;
if (Mine[i + 1][j].num == 1)
nNUM++;
if (Mine[i - 1][j].num == 1)
nNUM++;
if (Mine[i - 1][j + 1].num == 1)
nNUM++;
if (Mine[i + 1][j + 1].num == 1)
nNUM++;
}
else if (j == 9)//右邊第一列格子的統計
{
if (Mine[i][j - 1].num == 1)
nNUM++;
if (Mine[i + 1][j].num == 1)
nNUM++;
if (Mine[i - 1][j].num == 1)
nNUM++;
if (Mine[i - 1][j - 1].num == 1)
nNUM++;
if (Mine[i + 1][j - 1].num == 1)
nNUM++;
}
else if (i == 0)//第一行格子的統計
{
if (Mine[i + 1][j].num == 1)
nNUM++;
if (Mine[i][j - 1].num == 1)
nNUM++;
if (Mine[i][j + 1].num == 1)
nNUM++;
if (Mine[i + 1][j - 1].num == 1)
nNUM++;
if (Mine[i + 1][j + 1].num == 1)
nNUM++;
}
else if (i == 9)//最后一行格子的統計
{
if (Mine[i - 1][j].num == 1)
nNUM++;
if (Mine[i][j - 1].num == 1)
nNUM++;
if (Mine[i][j + 1].num == 1)
nNUM++;
if (Mine[i - 1][j - 1].num == 1)
nNUM++;
if (Mine[i - 1][j + 1].num == 1)
nNUM++;
}
else//普通格子的統計
{
if (Mine[i - 1][j].num == 1)
nNUM++;
if (Mine[i - 1][j + 1].num == 1)
nNUM++;
if (Mine[i][j + 1].num == 1)
nNUM++;
if (Mine[i + 1][j + 1].num == 1)
nNUM++;
if (Mine[i + 1][j].num == 1)
nNUM++;
if (Mine[i + 1][j - 1].num == 1)
nNUM++;
if (Mine[i][j - 1].num == 1)
nNUM++;
if (Mine[i - 1][j - 1].num == 1)
nNUM++;
}
return nNUM;//把格子周圍一共有多少雷數的統計結果返回
}
void ShowWhite(int i, int j)//顯示無雷區的空白部分
{
if (Mine[i][j].flag == 1 || Mine[i][j].num == 0)//如果有紅旗或該格處理過就不對該格進行任何判斷
return;
mineNUM--;//顯示過數字或者空格的格子就表示多處理了一個格子,當所有格子都處理過了表示勝利
if (Mine[i][j].roundnum == 0 && Mine[i][j].num != 1)//顯示空格
{
DrawEmpty(i, j, 1, WHITE);
Mine[i][j].num = 0;
}
else
if (Mine[i][j].roundnum != 0)//輸出雷數
{
DrawEmpty(i, j, 1, WHITE);
_stprintf_s(randmineNUM, _T("%d"), Mine[i][j].roundnum);
setcolor(RED);
outtextxy(6 + j * 20, 32 + i * 20, randmineNUM);
Mine[i][j].num = 0;//已經輸出雷數的格子用0表示已經用過這個格子
return;
}
/*8個方向遞歸顯示所有的空白格子*/
if (i != 0 && Mine[i - 1][j].num != 1)
ShowWhite(i - 1, j);
if (i != 0 && j != 9 && Mine[i - 1][j + 1].num != 1)
ShowWhite(i - 1, j + 1);
if (j != 9 && Mine[i][j + 1].num != 1)
ShowWhite(i, j + 1);
if (j != 9 && i != 9 && Mine[i + 1][j + 1].num != 1)
ShowWhite(i + 1, j + 1);
if (i != 9 && Mine[i + 1][j].num != 1)
ShowWhite(i + 1, j);
if (i != 9 && j != 0 && Mine[i + 1][j - 1].num != 1)
ShowWhite(i + 1, j - 1);
if (j != 0 && Mine[i][j - 1].num != 1)
ShowWhite(i, j - 1);
if (i != 0 && j != 0 && Mine[i - 1][j - 1].num != 1)
ShowWhite(i - 1, j - 1);
}
主函數main.cpp
#include<stdio.h>
#include"graph.h"
#include"auxiliary.h"
#include<stdlib.h> //rand(),srand()
#include<time.h> //srand((unsigned)time(NULL))
void Game(void);//游戲主程序
void GameBegin(void);//游戲開始
void GamePlay(void);//游戲執行過程
void GameOver(void);//游戲結束
void GameWin(void);//游戲勝利
int PLAY = 0;//是否第一次玩游戲的標志
int FLAG = 1;//游戲失敗后是否重新開始的標志
int AGAIN = 0;//游戲中途重新開始的標志
int main(void)
{
initgraph(200, 230, SHOWCONSOLE);//初始化游戲界面和大小
Game();//運行游戲
closegraph();//關閉圖形界面
}
void Game(void)
{
while (1)
{
if (FLAG == 1)
{
GameBegin();//繪制出游戲界面並判斷是否玩過和重新開始
GamePlay();//游戲過程的函數
if (AGAIN == 1)
{
AGAIN = 0;
continue;
}
}
FLAG = 0;
if (m.uMsg == WM_LBUTTONDOWN)//鼠標左鍵按下事件
{
MouseGetXY();
if (MouseX > 90 && MouseX<110 && MouseY>5 && MouseY < 25)
{
FLAG = 1;
continue;
}
}
if (_kbhit())//判斷有按鍵退出
{
break;
}
}
}
void GameBegin(void)
{
int i, j;
cleardevice();
PLAY = 1;
mineNUM = 0;
setfillstyle(BS_SOLID);//此處用法和TC不同
setfillcolor(WHITE);
bar(0, 0, 200, 230); //設置背景區域
for (i = 0; i < 10; i++) //繪制每個雷區(小格)
{
for (j = 0; j < 10; j++)
{
DrawEmpty(i, j, 0, LIGHTGRAY);
}
}
DrawSmile();//畫出中間的笑臉
srand((unsigned)time(NULL));//根據時間給隨機數不同的種子數
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{
Mine[i][j].num = rand() % 8;//隨機數產生范圍0-7
if (Mine[i][j].num == 1)
{
mineNUM++;
}
else
{
Mine[i][j].num = 2;
}
printf("%3d", Mine[i][j].num);
Mine[i][j].flag = 0;
}
printf("\n");
_stprintf_s(randmineNUM, _T("%d"), mineNUM);//將minrNUM轉換成字符串類型
setbkcolor(WHITE);
setcolor(RED);
settextstyle(16, 0, _T("0"));
outtextxy(2, 2, randmineNUM);
} mineNUM = 100 - mineNUM;
}
void GamePlay(void)/*游戲過程*/
{
int i, j, Num = 0;/*Num用來接收統計函數返回一個格子周圍有多少地雷*/
for (i = 0; i < 10; i++)
for (j = 0; j<10; j++)
Mine[i][j].roundnum = MineStatistics(i, j);/*統計每個格子周圍有多少地雷*/
while (!_kbhit())
{
m = GetMouseMsg();
switch (m.uMsg)
{
case WM_LBUTTONDOWN:
{
MouseGetXY();
if (MouseX>90 && MouseX<110 && MouseY>5 && MouseY<25)/*重新來*/
{
MessageBox(NULL, TEXT("重新開始成功"), TEXT("YES"), MB_OK);
AGAIN = 1;
return;
}
if (MouseX>0 && MouseX<200 && MouseY>30 && MouseY < 230)/*當前鼠標位置在格子范圍內*/
{
j = (MouseX) / 20;/*x坐標*/
i = (MouseY - 30) / 20;/*y坐標*/
if (Mine[i][j].flag == 1)/*如果格子有紅旗則左鍵無效*/
continue;
if (Mine[i][j].num != 0)/*如果格子沒有處理過*/
{
if (Mine[i][j].num == 1)/*鼠標按下的格子是地雷*/
{
GameOver();/*游戲失敗*/
break;
}
else/*鼠標按下的格子不是地雷*/
{
Num = MineStatistics(i, j);
if (Num == 0)/*周圍沒地雷就用遞歸算法來顯示空白格子*/
ShowWhite(i, j);
else/*按下格子周圍有地雷*/
{
_stprintf_s(randmineNUM, _T("%d"), Num);/*輸出當前格子周圍的雷數*/
DrawEmpty(i, j, 1, WHITE);
setcolor(RED);
outtextxy(6 + j * 20, 32 + i * 20, randmineNUM);
mineNUM--;
}
Mine[i][j].num = 0;/*點過的格子周圍雷數的數字變為0表示這個格子已經用過*/
if (mineNUM < 1)/*勝利了*/
{
GameWin();
break;
}
}
}
}
}
case WM_RBUTTONDOWN:
{
MouseGetXY();
if (MouseX > 0 && MouseX<200 && MouseY>30 && MouseY < 230)/*當前鼠標位置在格子范圍內*/
{
j = (MouseX) / 20;/*x坐標*/
i = (MouseY - 30) / 20;/*y坐標*/
//MessageBox(NULL, TEXT("右鍵測試"), TEXT("YES"), MB_OK);
if (Mine[i][j].flag == 0 && Mine[i][j].num != 0)/*本來沒紅旗現在顯示紅旗*/
{
DrawRedFlag(i, j);
Mine[i][j].flag = 1;
}
else
if (Mine[i][j].flag == 1)/*有紅旗標志再按右鍵就紅旗消失*/
{
DrawEmpty(i, j, 0, LIGHTGRAY);
Mine[i][j].flag = 0;
}
}
}
}
}
}
void GameOver(void)
{
int i, j;
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{
if (Mine[i][j].num == 1)//顯示所有地雷
{
DrawEmpty(i, j, 0, WHITE);
setfillstyle(BS_SOLID);
setfillcolor(RED);
fillellipse(3 + j * 20, 33 + i * 20, 17 + j * 20, 47 + i * 20);
setbkcolor(WHITE);
setcolor(RED);
settextstyle(16, 0, _T("宋體"));
outtextxy(2, 2, _T("輸了請重來"));
}
}
}
}
void GameWin(void)
{
setbkcolor(WHITE);
setcolor(RED);
settextstyle(16, 0, _T("宋體"));
outtextxy(2, 2, _T("你贏了"));
}
更多功能正在完善,To be continued!!
