今天發布源代碼,由於寫在一個文件里非常亂,所以分三個文件寫
繪圖和鼠標函數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!!