📄 ztscards.c
字号:
#include "ztsCards.h"
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = "CardsWin";
HANDLE hAccel;
HWND hwnd;
MSG msg;
WNDCLASS wc;
hInst = hInstance;
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; //CS_DBLCLKS 风格是为了窗口能接收到 WM_LBUTTONDBLCLK 消息
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_MAIN));
wc.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wc.hbrBackground= CreateSolidBrush ( RGB(0,0x7a,0) );
wc.lpszMenuName = (LPCSTR)IDM_MAIN;
wc.lpszClassName= szAppName;
RegisterClass (&wc);
hwnd = CreateWindowEx(0,
szAppName,
"ZTS's 空当接龙 1.0",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
480,
NULL,
NULL,
hInstance,
NULL);
ShowWindow (hwnd, iCmdShow);
UpdateWindow (hwnd);
hAccel = LoadAccelerators (hInstance, MAKEINTRESOURCE(IDA_MAIN));
while (GetMessage (&msg, NULL, 0, 0))
{
if (!TranslateAccelerator (hwnd, hAccel, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
RECT* pRect;
char buf[80];
MCI_OPEN_PARMS mciOpen;
MCI_PLAY_PARMS mciPlay;
MCIERROR mciError;
switch (uMsg)
{
case WM_CREATE:
cdtInit (&nCardWidth, &nCardHeight);
OnCreate (hWnd);
if (BkgroundMusic[0] != '1')
{
mciOpen.lpstrDeviceType = "MPEGVideo";
mciOpen.lpstrElementName = BkgroundMusic;
mciError = mciSendCommand (0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT, (DWORD)&mciOpen);
if (!mciError)
{
mciSendCommand (mciOpen.wDeviceID, MCI_PLAY, MCI_DGV_PLAY_REPEAT, (DWORD)&mciPlay);
}
}
return 0;
case WM_PAINT:
BeginPaint (hWnd, &ps);
OnPaint (hWnd, ps.hdc);
EndPaint (hWnd, &ps);
return 0;
case WM_COMMAND:
switch (LOWORD (wParam))
{
case IDM_GAME_START: //开局
if (bPlaying)
{//如果正在游戏中
if (MessageBox (hWnd, "是否放弃本局?", "ZTS's 空当接龙", MB_YESNO | MB_ICONQUESTION) == IDNO)
break;
cur_losses++;
lost++;
if (stype == -1)
streak++;
else
{
stype = -1;
streak = 1;
}
if (stype == -1)
{
if (streak > losses)
losses = streak;
}
}
bPlaying = TRUE;
EnableMenuItem (GetMenu (hWnd), IDM_GAME_RESTART, MF_ENABLED);
nNum = GenerateNum ();
wsprintf (buf, "ZTS's 空当接龙 1.0 #%d", nNum);
SetWindowText (hWnd, buf);
SetCardsOrder (nNum);
InvalidateRect (hWnd, NULL, TRUE);
break;
case IDM_GAME_SELECT: //选局...
nNum = GenerateNum ();
if (bPlaying)
{//如果正在游戏中
if (MessageBox (hWnd, "是否放弃本局?", "ZTS's 空当接龙", MB_YESNO | MB_ICONQUESTION) == IDNO)
break;
cur_losses++;
lost++;
if (stype == -1)
streak++;
else
{
stype = -1;
streak = 1;
}
if (stype == -1)
{
if (streak > losses)
losses = streak;
}
}
if (DialogBoxParam (hInst, MAKEINTRESOURCE(DLG_SELECTNUM), hWnd, DlgSelectNumProc, 0))
{//如果按了“确定”按钮
bPlaying = TRUE;
EnableMenuItem (GetMenu (hWnd), IDM_GAME_RESTART, MF_ENABLED);
wsprintf (buf, "ZTS's 空当接龙 1.0 #%d", nNum);
SetWindowText (hWnd, buf);
SetCardsOrder (nNum);
InvalidateRect (hWnd, NULL, TRUE);
}
break;
case IDM_GAME_RESTART: //重玩
if (bPlaying)
{//如果正在游戏中
if (MessageBox (hWnd, "是否放弃本局?", "ZTS's 空当接龙", MB_YESNO | MB_ICONQUESTION) == IDNO)
break;
cur_losses++;
lost++;
if (stype == -1)
streak++;
else
{
stype = -1;
streak = 1;
}
if (stype == -1)
{
if (streak > losses)
losses = streak;
}
}
bPlaying = TRUE;
SetCardsOrder (nNum);
InvalidateRect (hWnd, NULL, TRUE);
break;
case IDM_GAME_SCORE: //战况...
DialogBoxParam (hInst, MAKEINTRESOURCE(DLG_SCORE), hWnd, DlgScoreProc, 0);
break;
case IDM_GAME_OPTION: //选项...
DialogBoxParam (hInst, MAKEINTRESOURCE(DLG_OPTION), hWnd, DlgOptionProc, 0);
break;
case IDM_GAME_UNDO: //撤销
break;
case IDM_GAME_EXIT: //退出
SendMessage (hWnd, WM_CLOSE, 0, 0);
break;
case IDM_HELP_ABOUT: //关于...
MessageBox (hWnd, "界面和操作方式完全模仿 Windows 自带的空当接龙\n\n编程:一块三毛钱\n信箱:crazy_soft@163.net\n主页:zhongts.yeah.net", "ZTS's 空当接龙 1.0", MB_OK);
break;
}
return 0;
case WM_MOUSEMOVE:
OnMouseMove (hWnd, LOWORD (lParam), HIWORD (lParam));
break;
case WM_LBUTTONDOWN:
OnLbuttonDown (hWnd, LOWORD (lParam), HIWORD (lParam));
break;
//要想在鼠标双击时接收到该消息需要在注册窗口类时加上 CS_DBLCLKS 风格
case WM_LBUTTONDBLCLK:
OnLbuttonDblclk (hWnd, LOWORD (lParam), HIWORD (lParam));
break;
case WM_RBUTTONDOWN:
OnRbuttonDown (hWnd, LOWORD (lParam), HIWORD (lParam));
break;
case WM_RBUTTONUP:
OnRbuttonUp (hWnd);
break;
//===================================================\ 限制窗口的宽度在 640px
case WM_SIZING:
pRect = (LPRECT)lParam;
if ((wParam == WMSZ_BOTTOMRIGHT) ||
(wParam == WMSZ_RIGHT) ||
(wParam == WMSZ_TOPRIGHT))
pRect->right = pRect->left + 640;
else
pRect->left = pRect->right - 640;
return 0;
case WM_SIZE:
if (wParam == SIZE_MAXIMIZED)
MoveWindow (hWnd, 0, 0, 640, GetSystemMetrics (SM_CYSCREEN), TRUE);
return 0;
//===================================================/
case WM_CLOSE:
if (bPlaying)
{//如果正在游戏中
if (MessageBox (hWnd, "是否放弃本局?", "ZTS's 空当接龙", MB_YESNO | MB_ICONQUESTION) == IDNO)
return 0;
cur_losses++;
lost++;
if (stype == -1)
streak++;
else
{
stype = -1;
streak = 1;
}
if (stype == -1)
{
if (streak > losses)
losses = streak;
}
}
wsprintf (buf, "%d", bErrorMessage);
WritePrivateProfileString ("Option", "ErrorMsg", buf, iniFile);
wsprintf (buf, "%d", bQuickMoveCard);
WritePrivateProfileString ("Option", "QuickMove", buf, iniFile);
wsprintf (buf, "%d", bCanMouseDblclk);
WritePrivateProfileString ("Option", "Dblclk", buf, iniFile);
wsprintf (buf, "%d", won);
WritePrivateProfileString ("Score", "won", buf, iniFile);
wsprintf (buf, "%d", lost);
WritePrivateProfileString ("Score", "lost", buf, iniFile);
wsprintf (buf, "%d", wins);
WritePrivateProfileString ("Score", "wins", buf, iniFile);
wsprintf (buf, "%d", losses);
WritePrivateProfileString ("Score", "losses", buf, iniFile);
wsprintf (buf, "%d", streak);
WritePrivateProfileString ("Score", "streak", buf, iniFile);
wsprintf (buf, "%d", stype);
WritePrivateProfileString ("Score", "stype", buf, iniFile);
DestroyWindow (hWnd);
return 0;
case WM_DESTROY:
cdtTerm();
PostQuitMessage (0);
return 0;
}
return DefWindowProc (hWnd, uMsg, wParam, lParam);
}
//处理 WM_CREATE 消息//////////////////////////////////////////////////////////
void OnCreate (HWND hWnd)
{
int i, j;
HDC hdc, hMemDC;
DWORD hPen_Old, hBrush_Old, hBmp_Old;
char buf[MAX_PATH];
GetModuleFileName (hInst, iniFile, MAX_PATH);
i = lstrlen (iniFile);
iniFile[i-3] = 'i';
iniFile[i-2] = 'n';
iniFile[i-1] = 'i'; //buf = "可执行文件所在目录\ztsCard.ini"
//读取 ini 文件中的设置参数
GetPrivateProfileString ("Option", "ErrorMsg", "1", buf, MAX_PATH, iniFile);
bErrorMessage = (buf[0] == '1') ? TRUE : FALSE;
GetPrivateProfileString ("Option", "QuickMove", "1", buf, MAX_PATH, iniFile);
bQuickMoveCard = (buf[0] == '1') ? TRUE : FALSE;
GetPrivateProfileString ("Option", "Dblclk", "1", buf, MAX_PATH, iniFile);
bCanMouseDblclk = (buf[0] == '1') ? TRUE : FALSE;
//读取 ini 文件中的战况
won = GetPrivateProfileInt ("Score", "won", 0, iniFile);
lost = GetPrivateProfileInt ("Score", "lost", 0, iniFile);
wins = GetPrivateProfileInt ("Score", "wins", 0, iniFile);
losses = GetPrivateProfileInt ("Score", "losses", 0, iniFile);
streak = GetPrivateProfileInt ("Score", "streak", 0, iniFile);
stype = GetPrivateProfileInt ("Score", "stype", 0, iniFile);
//背景音乐,算作一个彩蛋
GetPrivateProfileString ("Option", "Music", "1", BkgroundMusic, MAX_PATH, iniFile);
cur_losses = 0;
cur_wins = 0;
bPlaying = FALSE;
bRbuttonDown = FALSE;
ColumnSelected = -1;
//初始化左右空当
for (i=0; i<4; i++)
{
SpaceLeft[i] = -1;
SpaceRight[i] = -1;
}
//初始化每列牌
for (i=0;i<8;i++)
for (j=0;j<21;j++)
Cards[i][j] = -1;
EnableMenuItem (GetMenu (hWnd), IDM_GAME_RESTART, MF_GRAYED);
EnableMenuItem (GetMenu (hWnd), IDM_GAME_UNDO, MF_GRAYED);
//创建一个绿色的画笔和一个深绿色的刷子
hPen_Green = CreatePen (0, 1, RGB (0, 0xff, 0));
hBrush_Bground = CreateSolidBrush (RGB (0, 0x7a, 0));
//===================================================\ 绘制表示空当的位图
hdc = GetDC (hWnd);
hMemDC = CreateCompatibleDC (hdc);
hBmpSpace = CreateCompatibleBitmap (hdc, nCardWidth, nCardHeight);
hBmp_Old = (DWORD) SelectObject (hMemDC, hBmpSpace);
hBrush_Old = (DWORD) SelectObject (hMemDC, hBrush_Bground);
hPen_Old = (DWORD) SelectObject (hMemDC, GetStockObject (BLACK_PEN));
//绘制位图的背景和凸凹框
PatBlt (hMemDC, 0, 0, nCardWidth, nCardHeight, PATCOPY);
MoveToEx (hMemDC, 0, nCardHeight, NULL);
LineTo (hMemDC, 0, 0);
LineTo (hMemDC, nCardWidth, 0);
SelectObject (hMemDC, hPen_Green);
MoveToEx (hMemDC, nCardWidth-1, 1, NULL);
LineTo (hMemDC, nCardWidth-1, nCardHeight-1);
LineTo (hMemDC, 1, nCardHeight-1);
SelectObject (hMemDC, (HPEN)hPen_Old);
SelectObject (hMemDC, (HBRUSH)hBrush_Old);
SelectObject (hMemDC, (HBITMAP)hBmp_Old);
DeleteDC (hMemDC);
ReleaseDC (hWnd, hdc);
//===================================================/
}
//处理 WM_PAINT 消息///////////////////////////////////////////////////////////
void OnPaint (HWND hWnd, HDC hdc)
{
DWORD hPen_Old;
int i;
//画中间的头像
hPen_Old = (DWORD) SelectObject (hdc, hPen_Green);
MoveToEx (hdc, x_Logo, y_Logo+36, NULL);
LineTo (hdc, x_Logo, y_Logo);
LineTo (hdc, x_Logo+36, y_Logo);
SelectObject (hdc, GetStockObject (BLACK_PEN));
LineTo (hdc, x_Logo+36, y_Logo+36);
LineTo (hdc, x_Logo, y_Logo+36);
SelectObject (hdc, (HPEN)hPen_Old);
DrawLogo (hdc, 1);
//画空档
DrawSpaceLeft (hdc);
DrawSpaceRight (hWnd, hdc);
//画每列扑克
for (i=0; i<8; i++)
{
DrawColumn (hdc, i, FALSE);
}
}
//处理 WM_MOUSEMOVE 消息///////////////////////////////////////////////////////
void OnMouseMove (HWND hWnd, int xPos, int yPos)
{
int m, n, i, j, t, k;
//中间头像的偏左或偏右
if (yPos < nCardHeight)
{
if (xPos < 4*nCardWidth)
DrawLogo (GetDC (hWnd), 0);
else if (xPos > 348)
DrawLogo (GetDC (hWnd), 1);
}
//可以移动牌的指示光标
if (ColumnSelected != -1)
{
if (yPos < nCardHeight)
{//空当
if (xPos < 4*nCardWidth)
{//左空当
m = xPos/nCardWidth;
if (SpaceLeft[m] == -1)
SetCursor (LoadCursor (NULL, IDC_UPARROW));
}
else if (xPos > 348)
{//右空当
m = (xPos - 348) / nCardWidth;
m = 3 - m;
if (SpaceRight[m] == -1)
{
if (ColumnSelected < 8)
{
n = CalcColumnCards (ColumnSelected);
n = Cards[ColumnSelected][n];
}
else
{
n = SpaceLeft[ColumnSelected-8];
}
if ((n / 4) == 0)
SetCursor (LoadCursor (NULL, IDC_UPARROW));
}
else
{
if (ColumnSelected < 8)
{
n = CalcColumnCards (ColumnSelected);
n = Cards[ColumnSelected][n];
}
else
{
n = SpaceLeft[ColumnSelected-8];
}
if (n == SpaceRight[m] + 4)
SetCursor (LoadCursor (NULL, IDC_UPARROW));
}
}
}
else
{//列
m = xPos / (nCardWidth + dxCard);
n = xPos % (nCardWidth + dxCard);
i = CalcColumnCards (m);
if (i == -1)
{//空列
if ((n > dxCard) && (yPos > nCardHeight+10))
{
SetCursor (LoadCursor (NULL, IDC_UPARROW));
}
}
else if ((n > dxCard) && (yPos > nCardHeight+10) && (yPos < nCardHeight+10+dyCard*i+nCardHeight))
{
if (ColumnSelected < 8)
{
i = CalcColumnCards (ColumnSelected);
j = i;
for ( ; j>=0; j--)
{
if (!IsMatch (Cards[ColumnSelected][j-1], Cards[ColumnSelected][j]))
break;
}
j = i - j + 1; //现在 j 中保存着选中列下端有几张按规则排列的牌
//再计算鼠标按下列的最下面一张牌能不能和上面那几张牌
//中的任意几张牌构成一个新的规则排列
k = CalcColumnCards (m);
for (t=0; t<j; t++)
{
if (IsMatch (Cards[m][k], Cards[ColumnSelected][i-t]))
break;
}
if (t != j)
{
t++;
if (CalcSpaceAll(FALSE) >= t)
{//空当够用
SetCursor (LoadCursor (hInst, MAKEINTRESOURCE(IDC_DOWNARROW)));
}
}
}
else
{
if (IsMatch (Cards[m][i], SpaceLeft[ColumnSelected-8]))
SetCursor (LoadCursor (hInst, MAKEINTRESOURCE(IDC_DOWNARROW)));
}
}
}
}
}
//处理 WM_LBUTTONDOWN 消息/////////////////////////////////////////////////////
void OnLbuttonDown (HWND hWnd, int xPos, int yPos)
{
int m, n, i, j, k, t;
char buf[80];
m = xPos / (nCardWidth + dxCard);
n = xPos % (nCardWidth + dxCard);
if ((yPos < nCardHeight) && (xPos < 4*nCardWidth))
{//鼠标落在左边空当上
m = xPos / nCardWidth;
if (ColumnSelected == -1)
{//当前没有选中任何牌
if (SpaceLeft[m] != -1)
{//鼠标按下点的空当有牌
ColumnSelected = m + 8;
DrawSpaceLeft (GetDC (hWnd));
}
}
else
{//当前已经选中了某一列牌
if (ColumnSelected == m+8)
{//如果再次选中这一空当,则取消该列的选中状态
ColumnSelected = -1;
DrawSpaceLeft (GetDC (hWnd));
}
else
{
if (SpaceLeft[m] == -1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -