- 转自:http://fuliang.javaeye.com/blog/69306
- #include <windows.h>
- #include <math.h>
- #include <string.h>
- #include "resource.h" // 菜单资源头文件
- #define SHADOW_WIDTH1 1 //阴影宽度
- #define SHADOW_WIDTH2 2
- #define SHADOW_WIDTH3 3
- #define BORDER 8 //边界的宽度
- #define BOX_WIDTH 20//box的宽度
- #define BOX_HEIGHT 20 //box的高度
- #define RESERVED_AREA 32 //保留区高度
- //******************************
- //自定义的函数声明
- //******************************
- LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
- void DrawBorder(HDC hdc,int x,int y,int width,int height,int BorderWidth,COLORREF &color1,COLORREF &color2,bool WTop);
- void AutoOpenBoxes(HDC &hdc,int i,int j);
- void drawRect(HDC &hdc,int x,int y);
- bool allRoundIsOpened(int row,int col);
- void InitBox();
- void UpdateTheWindow(HWND &hwnd,int rows,int cols,int mineNO);
- void ComputeRoundMineNo();
- void RandomSetMines();
- //**************************************
- //结构体Box,roundMineNO表示周围雷的个数
- //containMine表示是否里面是否有雷,
- //isOpened表示box是否已经打开
- //**************************************
- static HMENU hMenu;
- struct Box
- {
- int roundMineNO;
- bool containMine;
- bool isOpened;
- };
- static int mineNumber;
- static int ROWS; //行数
- static int COLS; //列数
- static int iSM_BorderX;
- static int iSM_BorderY;
- static int iSM_CaptionY;
- static int iSM_MenuY;
- static Box **box;
- static int i,j,numberOpened;
- static RECT mineRect;
- //********
- //main函数
- //********
- int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
- PSTR szCmdLine, int iCmdShow)
- {
- static TCHAR szAppName[] = TEXT ("SineWave") ;
- HWND hwnd ;
- MSG msg ;
- WNDCLASS wndclass ;
- mineNumber = 5;
- ROWS = 10; COLS = 10;
- mineNumber = 10;
- box = new Box* [COLS];
- for(int k=0;k<COLS;k++)
- box[k] = new Box[ROWS];
- iSM_BorderX = GetSystemMetrics(SM_CXBORDER);
- iSM_BorderY = GetSystemMetrics(SM_CYBORDER);
- iSM_CaptionY = GetSystemMetrics(SM_CYCAPTION);
- iSM_MenuY = GetSystemMetrics(SM_CYMENU);
- int cx = BOX_WIDTH * COLS + 2 * SHADOW_WIDTH3 + 2 * SHADOW_WIDTH2 + 2 * iSM_BorderX + 2 * BORDER;
- int cy = BOX_HEIGHT * ROWS + 2 * SHADOW_WIDTH3 + 4 * SHADOW_WIDTH2 + 2 * iSM_BorderY + 3 * BORDER + RESERVED_AREA+iSM_CaptionY+iSM_MenuY;
- mineRect.left = SHADOW_WIDTH3+BORDER+SHADOW_WIDTH2;
- mineRect.right =mineRect.left + BOX_WIDTH * COLS;
- mineRect.top = SHADOW_WIDTH3+2*BORDER+RESERVED_AREA+3*SHADOW_WIDTH2;
- mineRect.bottom = mineRect.top + BOX_HEIGHT * ROWS;
- wndclass.style = CS_HREDRAW | CS_VREDRAW ;
- wndclass.lpfnWndProc= WndProc ;
- wndclass.cbClsExtra = 0 ;
- wndclass.cbWndExtra = 0 ;
- wndclass.hInstance = hInstance ;
- wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
- wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
- hMenu = LoadMenu (hInstance, MAKEINTRESOURCE (IDR_MENU1)) ;
- wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
- wndclass.lpszMenuName = NULL ;
- wndclass.lpszClassName = szAppName ;
- if (!RegisterClass (&wndclass))
- {
- MessageBox ( NULL, TEXT ("Program requires Windows NT!"),
- szAppName, MB_ICONERROR) ;
- return 0 ;
- }
- hwnd = CreateWindow ( szAppName, TEXT ("扫雷-游戏"),
- WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX,
- CW_USEDEFAULT, CW_USEDEFAULT,
- cx, cy,
- NULL, hMenu, hInstance, NULL) ;
- ShowWindow (hwnd, iCmdShow) ;
- UpdateWindow (hwnd) ;
- while (GetMessage (&msg, NULL, 0, 0))
- {
- TranslateMessage (&msg) ;
- DispatchMessage (&msg) ;
- }
- return msg.wParam ;
- }
- //*************
- //消息处理函数
- //*************
- LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- HDC hdc ;
- HBRUSH hBrush ;
- PAINTSTRUCT ps ;
- static bool isLButtonDown=false;
- int xStart,yStart;
- static int m,n,cx,cy;
- static COLORREF color1=RGB(0, 0, 0),
- color2=RGB(255,255,255),
- color3=RGB(200,200,200),
- color4=RGB(120,120,200);
- static RECT grid,rect;
- static char szBuffer[2];
- POINT pt;
- switch (message)
- {
- case WM_CREATE: //初始化变量
- InitBox();
- RandomSetMines();
- ComputeRoundMineNo();
- return 0;
- case WM_PAINT:
- hdc = BeginPaint (hwnd, &ps) ;
- GetClientRect(hwnd,&rect);
- hBrush = CreateSolidBrush(RGB(200,200,200));
- SetBkColor(hdc,RGB(200,200,200));
- SelectObject(hdc,hBrush);
- SelectObject(hdc,GetStockObject(NULL_PEN));
- Rectangle(hdc,0,0,rect.right,rect.bottom);
- //绘制外边界
- DrawBorder(hdc,0,0,rect.right,rect.bottom,SHADOW_WIDTH3,color1,color2,true);
- //绘制保留区
- DrawBorder(hdc, SHADOW_WIDTH3+BORDER, SHADOW_WIDTH3+BORDER,
- BOX_WIDTH * COLS + 2 * SHADOW_WIDTH2, RESERVED_AREA + 2 * SHADOW_WIDTH2, SHADOW_WIDTH2, color1,color2,false);
- //绘制内边界
- DrawBorder(hdc, SHADOW_WIDTH3+BORDER, SHADOW_WIDTH3+2*BORDER+RESERVED_AREA+2*SHADOW_WIDTH2,
- BOX_WIDTH * COLS + 2 * SHADOW_WIDTH2, BOX_HEIGHT*ROWS + 2*SHADOW_WIDTH2, SHADOW_WIDTH2, color1,color2,false);
- //绘制雷区的box
- xStart = mineRect.left;
- yStart = mineRect.top;
- RECT rect0;
- for(i = 0; i < ROWS; i++)
- {
- for(j = 0; j < COLS; j++)
- {
- if(!box[i][j].isOpened)
- DrawBorder(hdc,xStart,yStart,BOX_WIDTH-2,BOX_HEIGHT-2,SHADOW_WIDTH2,
- color1,color2,true);
- else
- {
- DrawBorder(hdc,xStart,yStart,BOX_WIDTH-2,BOX_HEIGHT-2,SHADOW_WIDTH2,
- color3,color3,true);
- DrawBorder(hdc,xStart,yStart,BOX_WIDTH,BOX_HEIGHT,SHADOW_WIDTH1,
- color4,color4,true);
- if(box[i][j].roundMineNO != 0)
- {
- rect0.left = mineRect.left + BOX_WIDTH * j;
- rect0.right = rect0.left + BOX_WIDTH;
- rect0.top = mineRect.top + BOX_HEIGHT * i;
- rect0.bottom = rect0.top + BOX_HEIGHT;
- wsprintf(szBuffer,TEXT("%d"),box[i][j].roundMineNO);
- //输出周围雷的个数
- DrawText(hdc,szBuffer,-1,&rect0,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
- }
- }
- xStart += BOX_WIDTH;
- }
- yStart += BOX_HEIGHT;
- xStart = SHADOW_WIDTH3+BORDER+SHADOW_WIDTH2;
- }
- EndPaint(hwnd,&ps);
- return 0 ;
- case WM_LBUTTONDOWN:
- isLButtonDown = true;
- pt.x = LOWORD(lParam);
- pt.y = HIWORD(lParam);
- grid.left = mineRect.left;
- grid.right = mineRect.right;
- grid.top = mineRect.top;
- grid.bottom = mineRect.bottom;
- if(PtInRect(&grid,pt))
- {
- j = (pt.x - grid.left) / BOX_WIDTH;
- i = (pt.y - grid.top) / BOX_HEIGHT;
- grid.left += BOX_WIDTH * j;
- grid.top += BOX_HEIGHT * i;
- grid.right = grid.left + BOX_WIDTH;
- grid.bottom = grid.top + BOX_HEIGHT;
- hdc = GetDC(hwnd);
- DrawBorder(hdc,grid.left,grid.top,BOX_WIDTH-2,BOX_HEIGHT-2,SHADOW_WIDTH2,color3,color3,false);
- DrawBorder(hdc,grid.left,grid.top,BOX_WIDTH,BOX_HEIGHT,SHADOW_WIDTH1,color4,color4,false);
- }
- DeleteDC(hdc);
- return 0;
- case WM_LBUTTONUP:
- static HPEN hPen;
- static RECT rect1;
- hdc = GetDC(hwnd);
- hPen = CreatePen(PS_SOLID,2,RGB(255,255,0));
- SelectObject(hdc,hPen);
- SetBkColor(hdc,RGB(200,200,200));
- isLButtonDown = false;
- rect1.left = mineRect.left + BOX_WIDTH * j;
- rect1.right = rect1.left + BOX_WIDTH;
- rect1.top = mineRect.top + BOX_HEIGHT * i;
- rect1.bottom = rect1.top + BOX_HEIGHT;
- if(!box[i][j].isOpened)
- {
- if(!box[i][j].containMine)
- {
- if(box[i][j].roundMineNO != 0)
- {
- wsprintf(szBuffer,TEXT("%d"),box[i][j].roundMineNO);
- //输出周围雷的个数
- DrawText(hdc,szBuffer,-1,&rect1,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
- }
- box[i][j].isOpened = true;
- numberOpened ++;
- if(numberOpened == ROWS * COLS - mineNumber)
- {
- MessageBox (hwnd, TEXT ("祝贺你赢了!"),TEXT("扫雷游戏"), MB_ICONWARNING) ;
- }
- AutoOpenBoxes(hdc,i,j);
- }
- else
- {
- for(int k=0;k<ROWS;k++)
- for(int l=0;l<COLS;l++)
- {
- if(box[k][l].containMine)//点到雷后,使所有的类显现
- {
- rect.left =mineRect.left + BOX_WIDTH * l;
- rect.top = mineRect.top + BOX_HEIGHT * k;
- rect.right = rect.left + BOX_WIDTH;
- rect.bottom = rect.top + BOX_HEIGHT;
- DrawBorder(hdc,rect.left,rect.top,BOX_WIDTH-2,BOX_HEIGHT-2,SHADOW_WIDTH2,color3,color3,false);
- DrawBorder(hdc,rect.left,rect.top,BOX_WIDTH,BOX_HEIGHT,SHADOW_WIDTH1,color4,color4,false);
- DrawText(hdc,"?",-1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
- }
- }
- MessageBox (hwnd, TEXT ("游戏结束"),TEXT("扫雷游戏"), MB_ICONWARNING) ;
- }
- }
- DeleteDC(hdc);
- return 0;
- case WM_MOUSEMOVE:
- if(isLButtonDown)
- {
- pt.x = LOWORD(lParam);
- pt.y = HIWORD(lParam);
- rect.left = mineRect.left;
- rect.right = mineRect.right;
- rect.top = mineRect.top;
- rect.bottom = mineRect.bottom;
- if(PtInRect(&rect,pt))//判断是否在雷区
- {
- m = i; n = j;
- j = (pt.x - rect.left) / BOX_WIDTH;
- i = (pt.y - rect.top) / BOX_HEIGHT;
- rect.left += BOX_WIDTH * j;
- rect.top += BOX_HEIGHT * i;
- rect.right = rect.left + BOX_WIDTH;
- rect.bottom = rect.top + BOX_HEIGHT;
- if(grid.left == rect.left && grid.right==rect.right
- &&grid.bottom == rect.bottom && grid.top == rect.top)
- return 0;
- hdc = GetDC(hwnd);
- if(!box[m][n].isOpened)//鼠标移走后,恢复未按下
- {
- DrawBorder(hdc,grid.left,grid.top,BOX_WIDTH-2,BOX_HEIGHT-2,SHADOW_WIDTH2,color1,color2,true);
- DrawBorder(hdc,grid.left,grid.top,BOX_WIDTH,BOX_HEIGHT,SHADOW_WIDTH1,color3,color3,true);
- }
- //使当前的box成为按下状态
- grid.left = rect.left;
- grid.right = rect.right;
- grid.bottom = rect.bottom;
- grid.top = rect.top;
- DrawBorder(hdc,grid.left,grid.top,BOX_WIDTH-2,BOX_HEIGHT-2,SHADOW_WIDTH2,color3,color3,true);
- DrawBorder(hdc,grid.left,grid.top,BOX_WIDTH,BOX_HEIGHT,SHADOW_WIDTH1,color4,color4,true);
- }
- DeleteDC(hdc);
- }
- return 0;
- case WM_COMMAND: //响应菜单消息
- switch (LOWORD (wParam))
- {
- case IDM_PLAY:
- InitBox();
- RandomSetMines();
- ComputeRoundMineNo();
- InvalidateRect(hwnd,NULL,TRUE);
- UpdateWindow(hwnd);
- return 0;
- case IDM_BEGINER:
- UpdateTheWindow(hwnd,10,10,5);
- return 0;
- case IDM_MEDIUM:
- UpdateTheWindow(hwnd,15,15,15);
- return 0;
- case IDM_SENIOR:
- UpdateTheWindow(hwnd,20,20,30);
- return 0;
- case IDM_EXIT:
- SendMessage (hwnd, WM_CLOSE, 0, 0) ;
- return 0;
- }
- case WM_DESTROY:
- PostQuitMessage (0) ;
- return 0 ;
- }
- return DefWindowProc (hwnd, message, wParam, lParam) ;
- }
- //绘制边界
- void DrawBorder(HDC hdc,int x,int y,int width,int height,int BorderWidth,COLORREF &color1,COLORREF &color2,bool WTop)
- {
- int i;
- HPEN hpen1,hpen2;
- hpen1=CreatePen(PS_SOLID, 1, color1);
- hpen2=CreatePen(PS_SOLID, 1, color2);
- if(WTop)
- SelectObject(hdc,hpen2);
- else
- SelectObject(hdc,hpen1);
- for(i = 0; i < BorderWidth; i++)
- {
- MoveToEx(hdc,x+i,y+i,NULL);
- LineTo(hdc,x+width-i,y+i);
- MoveToEx(hdc,x+i,y+i,NULL);
- LineTo(hdc,x+i,y+height-i);
- }
- if(WTop)
- SelectObject(hdc,hpen1);
- else
- SelectObject(hdc,hpen2);
- for(i = 0; i < BorderWidth; i++)
- {
- MoveToEx(hdc,x+width-i,y+height-i,NULL);
- LineTo(hdc,x+width-i,y+i);
- MoveToEx(hdc,x+width-i,y+height-i,NULL);
- LineTo(hdc,x+i,y+height-i);
- }
- }
- //初始化box
- void InitBox()
- {
- numberOpened = 0;
- for(i=0;i<ROWS;i++)
- for(j=0;j<COLS;j++)
- {
- box[i][j].containMine = false;
- box[i][j].isOpened = false;
- box[i][j].roundMineNO = 0;
- }
- }
- //计算周围类的个数
- void ComputeRoundMineNo()
- {
- for(i=0;i<ROWS;i++)
- for(j=0;j<COLS;j++)
- {
- if(i>0&&box[i-1][j].containMine==true)
- {
- box[i][j].roundMineNO++;
- }
- if(i>0&&j<COLS-1&&box[i-1][j+1].containMine == true)
- {
- box[i][j].roundMineNO++;
- }
- if(j<COLS-1&&box[i][j+1].containMine == true)
- {
- box[i][j].roundMineNO++;
- }
- if(i<ROWS-1 && j<COLS && box[i+1][j+1].containMine == true)
- {
- box[i][j].roundMineNO++;
- }
- if(i<ROWS-1 && box[i+1][j].containMine == true)
- {
- box[i][j].roundMineNO++;
- }
- if(i<ROWS-1 && j>0 && box[i+1][j-1].containMine == true)
- {
- box[i][j].roundMineNO++;
- }
- if(j>0 && box[i][j-1].containMine == true)
- {
- box[i][j].roundMineNO++;
- }
- if(i>0 && j>0 && box[i-1][j-1].containMine == true)
- {
- box[i][j].roundMineNO++;
- }
- }
- }
- //随机布雷
- void RandomSetMines()
- {
- int row,col;
- srand((UINT)GetCurrentTime());
- for(i=0;i<mineNumber;)
- {
- row=rand()%ROWS;
- col=rand()%COLS;
- if(box[row][col].containMine != true)
- {
- box[row][col].containMine = true;
- i++;
- }
- }
- }
- //自动打开box
- void AutoOpenBoxes(HDC &hdc,int x,int y)
- {
- if(x >= 0 && y >= 0 && x < ROWS && y < COLS &&
- box[x][y].roundMineNO == 0&& !allRoundIsOpened(x,y))
- {
- drawRect(hdc,x-1,y);
- drawRect(hdc,x-1,y+1);
- drawRect(hdc,x,y+1);
- drawRect(hdc,x+1,y+1);
- drawRect(hdc,x+1,y);
- drawRect(hdc,x+1,y-1);
- drawRect(hdc,x,y-1);
- drawRect(hdc,x-1,y-1);
- AutoOpenBoxes(hdc,x-1,y);
- AutoOpenBoxes(hdc,x-1,y+1);
- AutoOpenBoxes(hdc,x,y+1);
- AutoOpenBoxes(hdc,x+1,y+1);
- AutoOpenBoxes(hdc,x+1,y);
- AutoOpenBoxes(hdc,x+1,y-1);
- AutoOpenBoxes(hdc,x,y-1);
- AutoOpenBoxes(hdc,x-1,y-1);
- }
- }
- //绘制矩形
- void UpdateTheWindow(HWND &hwnd,int rows,int cols,int mineNO)
- {
- ROWS = rows;
- COLS = cols;
- mineNumber = mineNO;
- mineRect.left = SHADOW_WIDTH3+BORDER+SHADOW_WIDTH2;
- mineRect.right =mineRect.left + BOX_WIDTH * COLS;
- mineRect.top = SHADOW_WIDTH3+2*BORDER+RESERVED_AREA+3*SHADOW_WIDTH2;
- mineRect.bottom = mineRect.top + BOX_HEIGHT * ROWS;
- box = new Box* [COLS];
- for(int k=0;k< COLS;k++)
- box[k] = new Box[ROWS];
- InitBox();
- RandomSetMines();
- ComputeRoundMineNo();
- int cx = BOX_WIDTH * COLS + 2 * SHADOW_WIDTH3 +
- 2 * SHADOW_WIDTH2 + 2 * iSM_BorderX + 2 * BORDER;
- int cy = BOX_HEIGHT * ROWS + 2 * SHADOW_WIDTH3 +
- 4 * SHADOW_WIDTH2 + 2 * iSM_BorderY + 3 * BORDER + RESERVED_AREA+iSM_CaptionY+iSM_MenuY;
- MoveWindow(hwnd,0,0,cx,cy,true);
- }
- void drawRect(HDC &hdc,int x,int y)
- {
- RECT rect1;
- COLORREF color1 = RGB(200,200,200),
- color2 = RGB(120,120,200);
- TCHAR szBuffer[2]={"0"};
- if(x<0 || y<0 || x >= ROWS || y >= COLS)
- return;
- rect1.left = mineRect.left + BOX_WIDTH * y;
- rect1.right = rect1.left + BOX_WIDTH;
- rect1.top = mineRect.top + BOX_HEIGHT * x;
- rect1.bottom = rect1.top + BOX_HEIGHT;
- if(!box[x][y].isOpened)
- {
- DrawBorder(hdc,rect1.left,rect1.top,
- BOX_WIDTH-2,BOX_HEIGHT-2,SHADOW_WIDTH2,color1,color1,true);
- DrawBorder(hdc,rect1.left,rect1.top,
- BOX_WIDTH,BOX_HEIGHT,SHADOW_WIDTH1,color2,color2,true);
- if(!box[x][y].containMine && box[x][y].roundMineNO != 0)
- {
- wsprintf(szBuffer,TEXT("%d"),box[x][y].roundMineNO);
- DrawText(hdc,szBuffer,-1,&rect1,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
- }
- box[x][y].isOpened = true;
- numberOpened ++;
- if(numberOpened == ROWS * COLS - mineNumber )
- {
- MessageBox (NULL, TEXT ("祝贺你赢了!"),TEXT("扫雷游戏"), MB_ICONWARNING) ;
- }
- }
- }
- //判断周围的所有box是否已经open
- bool allRoundIsOpened(int x,int y)
- {
- bool flag = true;
- if(x > 0 && !box[x-1][y].isOpened)
- flag = false;
- if(x > 0 && y < COLS-1 && !box[x-1][y+1].isOpened)
- flag = false;
- if(y < COLS-1 && !box[x][y+1].isOpened)
- flag = false;
- if(x < ROWS-1 && y< COLS-1 && !box[x+1][y+1].isOpened)
- flag = false;
- if(x < ROWS-1 && !box[x+1][y].isOpened)
- flag = false;
- if(x < ROWS-1 && y > 0 && !box[x+1][y-1].isOpened)
- flag = false;
- if(y > 0 && !box[x][y-1].isOpened)
- flag = false;
- if(x > 0 && y > 0 && !box[x-1][y-1].isOpened)
- flag = false;
- return flag;
- }