Win32项目-贪吃蛇

 请先把项目属性改为多字节!!!

 

#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);
}

效果展示: 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值