这个程序是以前写的,编码水平一般,规范性、命名还可以,待改进的地方有很多,大家拷下来自己玩吧。第一次把我写的代码贴出来。ok,开始,先来个截图:

当鼠标单击的时候,有一个爆炸效果将格子炸开。程序简单说明:
包含了计时,等级设置(含自定义),帮助对话框,排行榜。
技术上没有用MFC,纯SDK做的。使用了两个定时器,一个表示成绩,一个播放动画。
算法:如果单击的是空白格子,那么周围所有相连的空白格子都会打开。需要一个队列来辅助搜索,像是数据结构里的图遍历。
键盘响应:用windows的消息处理,灵敏度可以满足需要。对“同时单击左键和右键”的处理方法是,在右键的处理程序中,判断左键是否按下。
对话框:控件的编程。当对话框打开时,计时器要停表;对话框结束后,恢复计时。
排行榜:三个字符串,跟三个数字,存到文件中。文件路径源码中有。
图片:自己画的,水平还行。源码:
主程序:mine.cpp
//
mine.cpp : Defines the entry point for the application.
//
#include
"
stdafx.h
"
#include
"
resource.h
"

#include
"
stdlib.h
"
#include
"
stdio.h
"

#include
"
map.h
"
#include
"
mytimer.h
"
#include
"
mytool.h
"

#define
MAX_LOADSTRING 100

#define
BOTTOM_H 35
//
这个高度用在设置窗口大小的时候,包含标题栏的高度

//
Global Variables:
HINSTANCE hInst;
//
current instance
TCHAR szTitle[MAX_LOADSTRING];
//
The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];
//
The title bar text
GameMap gamemap;
MYTIMER mytimer;
MYTOOL mytool;

int
screenwidth
=
0
;
int
screenheight
=
0
;

int
iradio
=
0
;

//
Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE,
int
);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK DlgSet(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK DlgScore(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK DlgLevel(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK DlgInput(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);

void
GameWin(HWND hWnd);

//
game
void
InitGame(
void
);


int
APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int
nCmdShow)

...
{
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;

// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_MINE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))

...{
return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_MINE);

// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))

...{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))

...{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

return msg.wParam;
}



//
//
FUNCTION: MyRegisterClass()
//
//
PURPOSE: Registers the window class.
//
//
COMMENTS:
//
//
This function and its usage is only necessary if you want this code
//
to be compatible with Win32 systems prior to the 'RegisterClassEx'
//
function that was added to Windows 95. It is important to call this function
//
so that the application will get 'well formed' small icons associated
//
with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)

...
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_MINE);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(RGB(0,255,0));
//wcex.lpszMenuName = (LPCSTR)IDC_MINE;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

return RegisterClassEx(&wcex);
}

//
//
FUNCTION: InitInstance(HANDLE, int)
//
//
PURPOSE: Saves instance handle and creates main window
//
//
COMMENTS:
//
//
In this function, we save the instance handle in a global variable and
//
create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance,
int
nCmdShow)

...
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle,
WS_OVERLAPPED | WS_SYSMENU |WS_MINIMIZEBOX ,
CW_USEDEFAULT, 0, 400, 325, NULL, NULL, hInstance, NULL);
if (!hWnd)

...{
return FALSE;
}
screenwidth = GetSystemMetrics(SM_CXFULLSCREEN);
screenheight= GetSystemMetrics(SM_CYFULLSCREEN);

/**// game begin

gamemap.LoadScore();

gamemap.SetHINSTANCE(hInstance);
gamemap.SetHWND(hWnd);
gamemap.LoadPic();
gamemap.SetLevel(0);
MoveWindow(hWnd,(screenwidth -(32*9+150))/2,
(screenheight -(32*9+70))/2,
32*9+150,32*9+BOTTOM_H,true);
mytimer.SetHWND(hWnd);
mytimer.SetHINSTANCE(hInstance);
mytimer.LoadPic();
mytimer.Clear();
mytimer.SetPos(32*gamemap.GetWidth()+40,80);

mytool.SetHWND(hWnd);
mytool.SetHINSTANCE(hInstance);
mytool.LoadPic();
mytool.SetPos(32*gamemap.GetWidth()+30, 32*gamemap.GetHeight()-32);

SetTimer(hWnd,2,150,NULL);
InitGame();
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}

//
//
FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//
PURPOSE: Processes messages for the main window.
//
//
WM_COMMAND - process the application menu
//
WM_PAINT - Paint the main window
//
WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

...
{
int x,y;
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;

switch (message)

...{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)

...{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...

gamemap.SetDC(hdc);
gamemap.Draw();
gamemap.DrawAnimation();
gamemap.DrawButton();
mytimer.SetHDC(hdc);
mytimer.Draw();

mytool.SetHDC(hdc);
mytool.Draw();

EndPaint(hWnd, &ps);
break;

case WM_LBUTTONDOWN:
x=LOWORD(lParam);
y=HIWORD(lParam);
//按钮
if(gamemap.button_pos.x<=x && x<=gamemap.button_pos.x+32
&& gamemap.button_pos.y<=y && y<=gamemap.button_pos.y+32)

...{
gamemap.iFaceState=1;//press down
}

mytool.SetPressDown(x,y);

//雷的格子
x/=32;
y/=32;
//当游戏没有结束的时候,允许单击格子
if(gamemap.iState!=G_END)

...{
if(x>=0 && x<=gamemap.GetWidth()-1
&& y>=0 && y<=gamemap.GetHeight()-1)

...{
mytimer.StartTimer();
if(gamemap.OpenGrid(x,y))

...{
//fail
mytimer.StopTimer();
}
}
if(gamemap.CheckWin())

...{
GameWin(hWnd);
}
}
InvalidateRect(hWnd,NULL,false);
break;

case WM_LBUTTONUP:
x=LOWORD(lParam);
y=HIWORD(lParam);
//按钮
if(gamemap.button_pos.x<=x && x<=gamemap.button_pos.x+32
&& gamemap.button_pos.y<=y && y<=gamemap.button_pos.y+32)

...{
gamemap.iFaceState=0;//NORMAL
//RESET MAP
InitGame();
mytimer.Clear();
mytimer.StopTimer();
}
InvalidateRect(hWnd,NULL,false);

switch(mytool.GetButtonPress(x,y))

...{
case E_LEVEL:
mytimer.PauseTimer();
DialogBox(hInst, (LPCTSTR)IDD_DIALOG_LEVEL, hWnd, (DLGPROC)DlgLevel);

MoveWindow(hWnd,
(screenwidth -(32*gamemap.GetWidth()+150))/2,
(screenheight -(32*gamemap.GetHeight()+70))/2,
32*gamemap.GetWidth()+150,
32*gamemap.GetHeight()+BOTTOM_H,true);

mytimer.GoOnTimer();
InvalidateRect(hWnd,NULL,true);
break;

case E_HELP:
mytimer.PauseTimer();
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
mytimer.GoOnTimer();
break;

case E_SCORE:
mytimer.PauseTimer();
DialogBox(hInst, (LPCTSTR)IDD_DIALOG_SCORE, hWnd, (DLGPROC)DlgScore);
mytimer.GoOnTimer();
break;
default:
break;
}
break;

case WM_RBUTTONUP:
x=LOWORD(lParam);
y=HIWORD(lParam);

x/=32;
y/=32;
//当游戏没有结束的时候,允许右击格子
if(gamemap.iState!=G_END)

...{
if(x>=0 && x<=gamemap.GetWidth()-1
&& y>=0 && y<=gamemap.GetHeight()-1)

...{
gamemap.SetFlag(x,y);

if(gamemap.CheckWin())

...{
GameWin(hWnd);
}
}
}
InvalidateRect(hWnd,NULL,false);
break;

case WM_RBUTTONDOWN:
x=LOWORD(lParam);
y=HIWORD(lParam);

x/=32;
y/=32;
//当游戏没有结束的时候,允许右击格子
if(gamemap.iState!=G_END)

...{
if(wParam & MK_LBUTTON)

...{
gamemap.Open8around(x,y);
if(gamemap.CheckWin())

...{
GameWin(hWnd);
}
}
}
InvalidateRect(hWnd,NULL,false);
break;
case WM_TIMER:
switch(wParam)

...{
case 1:
mytimer.TimerInc();
break;
case 2:
break;
}
InvalidateRect(hWnd,NULL,false);
break;
case WM_DESTROY:
KillTimer(hWnd,2);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

//
Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

...
{
switch (message)

...{
case WM_INITDIALOG:
return TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)

...{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}

void
InitGame(
void
)

...
{
gamemap.CreateMap();
gamemap.iState=G_NULL;
gamemap.iFaceState=0;
}

LRESULT CALLBACK DlgSet(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

...
{
int minnum=0;
int w;
int h;
int num;

char temp[50]=...{0};

switch (message)

...{
case WM_INITDIALOG:
SetDlgItemInt(hDlg,IDC_EDIT_WIDTH, gamemap.GetWidth(),FALSE);
SetDlgItemInt(hDlg,IDC_EDIT_HEIGHT, gamemap.GetHeight() ,FALSE);
SetDlgItemInt(hDlg,IDC_EDIT_NUM, gamemap.GetNum(), FALSE);

return TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK)

...{
w=GetDlgItemInt(hDlg,IDC_EDIT_WIDTH,NULL,FALSE);
h=GetDlgItemInt(hDlg,IDC_EDIT_HEIGHT,NULL,FALSE);
num=GetDlgItemInt(hDlg,IDC_EDIT_NUM,NULL,FALSE);

//用户自定义的界面大小
w= (w<9)?9:w;
w= (w>20)?20:w;

h= (h<9)?9:h;
h= (h>20)?20:h;

//横向w个格子,纵向h个格子:
//限制雷的个数,最少:w和h中较小的值减一;最多,(w-1)*(h-1)
minnum=(w>h)?h:w;
num = (num< minnum-1)? minnum-1:num;
num = (num>(w-1)*(h-1))? (w-1)*(h-1):num;

gamemap.SetMap(w,h,num);
InitGame();
mytimer.Clear();

mytimer.SetPos(32*gamemap.GetWidth()+40,80);
mytool.SetPos(32*gamemap.GetWidth()+30, 32*gamemap.GetHeight()-32);
//MessageBox(hDlg,temp,"set",MB_OK);

EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
else if(LOWORD(wParam) == IDCANCEL)

...{
EndDialog(hDlg, LOWORD(wParam));
mytimer.GoOnTimer();
return TRUE;
}
break;
}
return FALSE;
}


LRESULT CALLBACK DlgScore(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

...
{

char temp[30]=...{0};
int i;
switch (message)

...{
case WM_INITDIALOG:
for(i=0;i<=2;i++)

...{
memset(temp,0,sizeof(temp));
gamemap.GetName(i, temp);
if(! strlen(temp))

...{
strcpy(temp,"匿名");
}
SetDlgItemText(hDlg, IDC_STATIC_NAME1+i, temp);

SetDlgItemInt(hDlg, IDC_STATIC_SCORE1+i,
gamemap.GetTimeValue(i) ,false);
}
return TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)

...{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
switch(LOWORD(wParam))

...{
case IDC_BUTTON_RESET1:
case IDC_BUTTON_RESET2:
case IDC_BUTTON_RESET3:
i=LOWORD(wParam)-IDC_BUTTON_RESET1;
gamemap.ResetScore(i);
SetDlgItemText(hDlg, IDC_STATIC_NAME1+i, "匿名");
SetDlgItemInt(hDlg, IDC_STATIC_SCORE1+i, 999 ,false);
break;
}
break;
return TRUE;
}
return FALSE;
}


LRESULT CALLBACK DlgLevel(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

...
{
switch (message)

...{
case WM_INITDIALOG:
iradio= gamemap.GetLevel();
CheckRadioButton(hDlg,
IDC_RADIO_LEVEL1,
IDC_RADIO_LEVEL1+2 ,
IDC_RADIO_LEVEL1+iradio);
return TRUE;

case WM_COMMAND:
switch (LOWORD(wParam) )

...{
case IDOK:
//MessageBox(hDlg,"set level ok","set dlg",MB_OK);
gamemap.SetLevel(iradio);
InitGame();
mytimer.Clear();
mytimer.SetPos(32*gamemap.GetWidth()+40,80);
mytool.SetPos(32*gamemap.GetWidth()+30, 32*gamemap.GetHeight()-32);

EndDialog(hDlg, LOWORD(wParam));
return TRUE;
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
case IDC_RADIO_LEVEL1:
iradio=0;
return TRUE;
case IDC_RADIO_LEVEL2:
iradio=1;
return TRUE;
case IDC_RADIO_LEVEL3:
iradio=2;
return TRUE;

case IDC_BUTTON_SET:
EndDialog(hDlg, LOWORD(wParam));
DialogBox(hInst, (LPCTSTR)IDD_DIALOG_SET, hDlg, (DLGPROC)DlgSet);
return TRUE;
default:
return TRUE;
}
break;
}
return FALSE;
}



LRESULT CALLBACK DlgInput(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)

...
{

char temp[30]=...{0};

switch (message)

...{
case WM_INITDIALOG:
gamemap.GetName(gamemap.GetLevel(), temp);
if(! strlen(temp))

...{
strcpy(temp,"匿名");
}
SetDlgItemText(hDlg, IDC_EDIT_INPUT ,temp);
return TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)

...{
memset(temp,sizeof(temp),0);
//处理输入的字符串,12个CHAR
GetDlgItemText(hDlg,IDC_EDIT_INPUT,temp,13);

gamemap.WriteScore(gamemap.GetLevel(), temp, mytimer.GetTimeLong());
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;

}

void
GameWin(HWND hWnd)

...
{
gamemap.iFaceState=2;//win
gamemap.iState=G_END;
mytimer.StopTimer();

//已破纪录,输入姓名
if( gamemap.IsNewScore(gamemap.GetLevel(),
mytimer.GetTimeLong()) )

...{
InvalidateRect(hWnd,NULL,false);
DialogBox(hInst, (LPCTSTR)IDD_DIALOG_INPUT, hWnd, (DLGPROC)DlgInput);
}
}
