择善教育公开课
//{{NO_DEPENDENCIES}} // Microsoft Visual C++ 生成的包含文件。 // 供 BrainMaster.rc 使用 // #define IDD_DIALOG_MAIN 101 #define IDC_BTN_START 1001 #define IDC_BUTTON_CHANGE_COLOR 1002 #define IDC_SLIDER_DIF 1003 #define IDC_STATIC_DIF 1004 #define IDC_COLORNOW 1005 #define IDC_GAME_AREA 1006 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1007 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif
#include <stdio.h> #include <windows.h> #include <CommCtrl.h> #include <list> using namespace std; #include "resource.h" typedef struct _gameRect{ RECT rect; //保存一个色块的位置信息 COLORREF rgb;// 保存一个色块的颜色信息 bool Win;// 保存这个色块是否唯一的颜色,即正确色块 }GameRect; typedef list<GameRect> GameList; //游戏色块链表数据类型 GameList g_GameList; // 链表 HINSTANCE g_hInstance; COLORREF g_ColorNow; // 全局变量保存当前颜色 unsigned int g_GameDiff;//当前游戏难度 unsigned int g_Stage; // 当前第几关? // 生成随机数 ...0~base DWORD GetRandrom(DWORD base) { DWORD result; __asm{ rdtsc mov result,eax } return result%base; } // 生成本次游戏的数据 void OnInitStageData(HWND hWnd) { g_GameList.clear(); // 清空原来的链表信息 DWORD nItemNum = g_Stage + 3; // 当前关卡需要显示多少个色块? if (nItemNum>8) { nItemNum = 8; } HWND GameWnd = GetDlgItem(hWnd, IDC_GAME_AREA); // 获取游戏区域的句柄 RECT WndRect; GetWindowRect(GameWnd, &WndRect); //获取游戏区域的大小 DWORD nWidth = WndRect.right - WndRect.left; DWORD nHeight = WndRect.bottom - WndRect.top; DWORD WinItemIndex = GetRandrom(nItemNum); // 生成一个随机数,指示哪一个色块是正确滴 DWORD nItemCntRow = 3; DWORD nItemCntColumn = (nItemNum % 3) ? nItemNum / 3 + 1 : nItemNum / 3;//计算需要多少行色块 DWORD nItemWidth = (nWidth - 10) / nItemCntRow; // 每个色块的宽度 DWORD nItemHeight = (nHeight - 10) / nItemCntColumn;// 每个色块的高度 for (DWORD i = 0; i <= nItemNum;i++) { GameRect gRect; gRect.rect.left = 10 + (i % 3)*nItemWidth; gRect.rect.right = gRect.rect.left + nItemWidth - 10; gRect.rect.top = 10 + (i / 3)*nItemHeight; gRect.rect.bottom = gRect.rect.top + nItemHeight - 10; gRect.rgb = g_ColorNow; // 正常的颜色 gRect.Win = false; //大部分的色块不是正确答案 if (i == WinItemIndex) { byte r = GetRValue(g_ColorNow) > 125 ? GetRValue(g_ColorNow) - g_GameDiff : GetRValue(g_ColorNow) + g_GameDiff; byte g = GetGValue(g_ColorNow) > 125 ? GetGValue(g_ColorNow) - g_GameDiff : GetGValue(g_ColorNow) + g_GameDiff; byte b = GetBValue(g_ColorNow) > 125 ? GetBValue(g_ColorNow) - g_GameDiff : GetBValue(g_ColorNow) + g_GameDiff; gRect.rgb = RGB(r, g, b); gRect.Win = TRUE; } g_GameList.push_back(gRect); } return; } void OnShowStage(HWND hWnd) { HWND GameWnd = GetDlgItem(hWnd, IDC_GAME_AREA); HDC hdc = GetDC(GameWnd); GameList::iterator iter = g_GameList.begin(); // 遍历链表,取出每个色块的信息,并按信息去进行绘图 for (; iter != g_GameList.end();iter++) { GameRect gameRect = *iter; HBRUSH hBrush = CreateSolidBrush(gameRect.rgb); HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); Rectangle(hdc, gameRect.rect.left, gameRect.rect.top, gameRect.rect.right, gameRect.rect.bottom); SelectObject(hdc, hOldBrush); } ReleaseDC(GameWnd, hdc); return; } // 功能:更新当前颜色 bool OnChangeColor(HWND hWnd) { HWND hColorWnd = GetDlgItem(hWnd, IDC_COLORNOW);//获取当前颜色指示器控件的句柄 // 初始化一个结构体... CHOOSECOLOR chs; memset(&chs, 0, sizeof(CHOOSECOLOR)); chs.lStructSize = sizeof(CHOOSECOLOR); chs.hwndOwner = hColorWnd; chs.rgbResult = g_ColorNow; chs.lpCustColors = &g_ColorNow; chs.Flags = CC_ANYCOLOR | CC_RGBINIT; ChooseColor(&chs); g_ColorNow = chs.rgbResult; //获取到选择的颜色 HDC hdc = GetDC(hColorWnd); RECT rect; GetWindowRect(hColorWnd, &rect);//获取的是指示器控件的大小 // 创建一个笔刷 HBRUSH hBrush = CreateSolidBrush(g_ColorNow); SelectObject(hdc, hBrush); Rectangle(hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top); ReleaseDC(hColorWnd, hdc); return true; } bool OnStartGame(HWND hWnd) { if (g_ColorNow == 0) // 如果点击开始游戏的时候,没有选择颜色,先要求选择一次 { OnChangeColor(hWnd); } OnInitStageData(hWnd); OnShowStage(hWnd); return false; } // 初始化的函数 bool OnInitDialog(HWND hWnd) { g_Stage = 1; return false; } // 检查一个点是否在规定矩形内 bool PointInRect(HWND hWnd,POINT pt, RECT rect) { return pt.x < (rect.right - rect.left) && pt.y < (rect.bottom - rect.top); } // 检查一个点是否是全局链表中的正确色块信息 bool PointIsRight(HWND hWnd, POINT pt) { //遍历链表,对比每个色块的位置信息与鼠标点 HWND gameWnd = GetDlgItem(hWnd, IDC_GAME_AREA); RECT WndRect; GetWindowRect(gameWnd, &WndRect); // 将屏幕坐标转换成客户区坐标并减去 POINT lefttop; lefttop.x = WndRect.left; lefttop.y = WndRect.top; ScreenToClient(hWnd, &lefttop); //570427370 // pt.x -= lefttop.x; pt.y -= lefttop.y; bool bIsRight = false; GameList::iterator iter = g_GameList.begin(); for (; iter != g_GameList.end();iter++) { GameRect gameRect = *iter; // 如果鼠标点在矩形区域内,且矩形区域是不同颜色滴...找到了正确答案 if (PointInRect(hWnd,pt,gameRect.rect) && gameRect.Win) { bIsRight = true; break; } } return bIsRight; } // Windows通过消息来驱动, INT_PTR CALLBACK GameProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { RECT gameArea; switch (uMsg) { case WM_INITDIALOG://首次创建窗口时产生 OnInitDialog(hWnd); break; case WM_LBUTTONUP: POINT pt; GetCursorPos(&pt);//获取当前鼠标的位置 ScreenToClient(hWnd, &pt);//鼠标点也转成客户区坐标系 GetWindowRect(GetDlgItem(hWnd, IDC_GAME_AREA), &gameArea); if (PointInRect(hWnd,pt,gameArea)) // 检查鼠标点是否在游戏区域内 { if (PointIsRight(hWnd, pt)) { g_Stage++; // 当前关卡加1 SendMessage(hWnd, WM_COMMAND, IDC_BTN_START, 0);//模拟鼠标点击窗口中开始游戏按钮 } else MessageBox(hWnd, L"选择错误", L"Wrong", MB_OK | MB_ICONINFORMATION); } break; case WM_NOTIFY://获取通知消息 if (wParam == IDC_SLIDER_DIF) { g_GameDiff = (unsigned int)SendMessage(GetDlgItem(hWnd, IDC_SLIDER_DIF), TBM_GETPOS, 0, 0); if (g_GameDiff <1) { g_GameDiff = 1; } char szTmp[MAX_PATH]; sprintf_s(szTmp, MAX_PATH, "当前游戏难度:%d", 100-g_GameDiff); SetDlgItemTextA(hWnd, IDC_STATIC_DIF, szTmp); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_BUTTON_CHANGE_COLOR: OnChangeColor(hWnd); break; case IDC_BTN_START: OnStartGame(hWnd); break; default: break; } break; case WM_CLOSE: case WM_DESTROY: PostQuitMessage(0); return TRUE; default: break; } return FALSE; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { g_hInstance = hInstance; HWND hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG_MAIN), NULL, GameProc); if (hWnd == 0) { MessageBox(0, L"创建窗口失败", 0, 0); return -1; } // 获取窗口大小,将窗口设置到整个屏幕的中心 RECT rect; GetWindowRect(hWnd, &rect); int nScreenX = GetSystemMetrics(SM_CXSCREEN); //获取屏幕的宽度 int nScreenY = GetSystemMetrics(SM_CYSCREEN); //获取屏幕的高度 SetWindowPos(hWnd, HWND_TOP, nScreenX / 2 - (rect.right - rect.left) / 2, nScreenY / 2 - (rect.bottom - rect.top) / 2, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);//不改变窗口大小,只将窗口置顶显示,并移动到屏幕中心 MSG msg; while (GetMessage(&msg,0,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }
鼠标点击色块区域的算法,还需进一步的修改。