请先把项目属性改为多字节!!!
#include <Windows.h>
#include <stdio.h>
#include <time.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void Init();
void CreateFood();
enum Key { UP, DOWN, LEFT, RIGHT };
Key KEY = RIGHT;
RECT g_rtClient = { 0, 0, 800, 500 };
BOOL UpToDate = TRUE;
BOOL isDead = FALSE;
HDC g_hdc;
HDC g_hMemDC;
HBITMAP g_hBmp;
HBITMAP g_hOldBmp;
HBRUSH g_hBrush[3];
HBRUSH g_hOldBrush;
HPEN g_hPen[2];
HPEN g_hOldPen;
short SnkLen;
struct MYPOINT
{
char x;
char y;
};
MYPOINT Direction = { 0 };
MYPOINT Snake[1000];
MYPOINT Food;
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPreInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
RECT rt = g_rtClient;
srand((unsigned int)time(NULL));
AdjustWindowRect(&rt, WS_OVERLAPPEDWINDOW, FALSE);
WNDCLASS wc = { 0 };
wc.hbrBackground = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "ClsSnake";
RegisterClass(&wc);
HWND hWnd = CreateWindow("ClsSnake", "Snake", WS_SYSMENU | WS_MINIMIZEBOX, 100, 100, rt.right - rt.left, rt.bottom - rt.top, NULL, NULL, hInstance, NULL);
Init();
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
MSG uMsg;
while (GetMessage(&uMsg, NULL, 0, 0))
{
TranslateMessage(&uMsg);
DispatchMessage(&uMsg);
}
return 0;
}
void Init()
{
SnkLen = 3;
Snake[0] = { 5, 5 };
CreateFood();
for (int i = 1; i < SnkLen; i++) {
Snake[i].x = Snake[0].x - i;
Snake[i].y = Snake[0].y;
}
}
void CreateFood()
{
char Flag = 1;
while (Flag)
{
Food.x = rand() % (g_rtClient.right - g_rtClient.left) / 20;
Food.y = rand() % (g_rtClient.bottom - g_rtClient.top) / 20;
for (int i = 0; i < SnkLen; i++) {
if (Snake[i].x == Food.x && Snake[i].y == Food.y) {
Flag = 1;
break;
}
Flag = 0;
}
}
}
void UpdateWnd()
{
FillRect(g_hMemDC, &g_rtClient, (HBRUSH)(COLOR_WINDOW + 1));
SelectObject(g_hMemDC, g_hPen[1]);
SelectObject(g_hMemDC, g_hBrush[2]);
Rectangle(g_hMemDC, 20 * Food.x, 20 * Food.y, (20 * Food.x) + 20, (20 * Food.y) + 20);
SelectObject(g_hMemDC, g_hPen[0]);
SelectObject(g_hMemDC, g_hBrush[0]);
Rectangle(g_hMemDC, 20 * Snake[0].x, 20 * Snake[0].y, (20 * Snake[0].x) + 20, (20 * Snake[0].y) + 20);
SelectObject(g_hMemDC, g_hBrush[1]);
for (int i = 1; i < SnkLen; i++) {
Rectangle(g_hMemDC, 20 * Snake[i].x, 20 * Snake[i].y, (20 * Snake[i].x) + 20, (20 * Snake[i].y) + 20);
}
BitBlt(g_hdc, 0, 0, g_rtClient.right - g_rtClient.left, g_rtClient.bottom - g_rtClient.top, g_hMemDC, 0, 0, SRCCOPY);
}
void GameOver(HWND hWnd)
{
char ScoreText[12] = { 0 };
FillRect(g_hdc, &g_rtClient, (HBRUSH)(COLOR_WINDOW + 1));
sprintf_s(ScoreText, "SCORE: %d", SnkLen - 3);
TextOut(g_hdc, 100, 100, ScoreText, strlen(ScoreText));
}
void OnTimer(HWND hWnd)
{
if (Direction.x + Direction.y == 0) return;
if (Snake[0].x == Food.x && Snake[0].y == Food.y) {
CreateFood();
SnkLen++;
}
for (int i = SnkLen - 1; i > 0; i--) {
Snake[i] = Snake[i - 1];
}
Snake[0].x += Direction.x;
Snake[0].y += Direction.y;
UpToDate = TRUE;
if (Snake[0].x < 0 || Snake[0].y < 0 || Snake[0].x >= g_rtClient.right / 20 || Snake[0].y >= g_rtClient.bottom / 20)
{
KillTimer(hWnd, 1);
isDead = TRUE;
MessageBox(hWnd, "GameOver", "Snake", MB_OK);
GameOver(hWnd);
return;
}
for (int i = 1; i < SnkLen; i++) {
if (Snake[0].x == Snake[i].x && Snake[0].y == Snake[i].y) {
KillTimer(hWnd, 1);
isDead = TRUE;
MessageBox(hWnd, "GameOver", "Snake", MB_OK);
GameOver(hWnd);
return;
}
}
UpdateWnd();
}
void OnKeyDown(HWND hWnd, WPARAM wParam)
{
if (isDead) {
return;
}
if (!UpToDate) {
OnTimer(hWnd);
}
switch (wParam)
{
case VK_LEFT:
if (KEY != RIGHT) {
Direction = { -1, 0 };
KEY = LEFT;
}
break;
case VK_RIGHT:
if (KEY != LEFT) {
Direction = { 1, 0 };
KEY = RIGHT;
}
break;
case VK_UP:
if (KEY != DOWN) {
Direction = { 0, -1 };
KEY = UP;
}
break;
case VK_DOWN:
if (KEY != UP) {
Direction = { 0, 1 };
KEY = DOWN;
}
break;
}
UpToDate = FALSE;
}
void OnCreate(HWND hWnd)
{
g_hdc = GetDC(hWnd);
g_hMemDC = CreateCompatibleDC(g_hdc);
g_hBmp = CreateCompatibleBitmap(g_hdc, g_rtClient.right - g_rtClient.left, g_rtClient.bottom - g_rtClient.top);
g_hPen[0] = CreatePen(PS_SOLID, 1, RGB(105, 105, 105));
g_hPen[1] = CreatePen(PS_NULL, 1, 0);
g_hBrush[0] = CreateSolidBrush(RGB(255, 0, 0));
g_hBrush[1] = CreateSolidBrush(RGB(0, 255, 0));
g_hBrush[2] = CreateSolidBrush(RGB(0, 255, 255));
g_hOldBmp = (HBITMAP)SelectObject(g_hMemDC, g_hBmp);
g_hOldPen = (HPEN)SelectObject(g_hMemDC, g_hPen[0]);
g_hOldBrush = (HBRUSH)SelectObject(g_hMemDC, g_hBrush[0]);
SetTimer(hWnd, 1, 200, NULL);
}
void OnDestroy(HWND hWnd)
{
SelectObject(g_hMemDC, g_hOldBrush);
SelectObject(g_hMemDC, g_hOldPen);
for (int i = 0; i < 2; i++) {
DeleteObject(g_hBrush[i]);
DeleteObject(g_hPen[i]);
}
DeleteObject(g_hBrush[2]);
SelectObject(g_hMemDC, g_hOldBmp);
DeleteObject(g_hBmp);
DeleteDC(g_hMemDC);
ReleaseDC(hWnd, g_hdc);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
OnCreate(hWnd);
break;
case WM_TIMER:
OnTimer(hWnd);
break;
case WM_KEYDOWN:
OnKeyDown(hWnd, wParam);
break;
case WM_SIZE:
if (isDead) {
GameOver(hWnd);
}
else {
UpdateWnd();
}
break;
case WM_DESTROY:
OnDestroy(hWnd);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
效果展示: