一个贪吃蛇的游戏,请高手帮忙修改一下
我写了一个贪吃蛇的游戏,几乎没有考虑界面的问题,只是想实现功能。但问题非常多,请各位高手帮忙修改一下。我知道的问题就有三个,但不限于这些。1、按下空格之后,即便不动他,程序在一段时间后就会异常,是不是越界了。?
2、吃下一个豆子后,键盘的输入和处理就不协调了,是不是得得用多线程编写?
3、这也是我无法理解的,每一次吃下一颗豆子之后,右上角就会出现描绘出的一块,一段时间后会消失,但我没有这么设计啊
如果能够帮我在代码中修改,更好。谢谢各位高手
程序代码:
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.' \ version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' \ language='*'\"") #include <windows.h> const int MAX = 35; const int INITIALLENGTH = 19; const int iRectSide = 20; const int IDT_TIMER1 = 1; const int IDT_TIMER2 = 2; enum SnakeDirection { UP = 0, DOWN = 1, LEFT = 2, RIGHT = 3, }; enum SnakeStatus { STOP = 0, RUN = 1, PAUSE = 2, }; struct SnakeBody { int x; int y; }; struct Snake { SnakeDirection direction; SnakeStatus status; int iBodyNum; int iHead; int iTail; SnakeBody bodys[MAX * MAX]; }; static Snake snake; static SnakeBody bean; static SnakeDirection keyboardInput = RIGHT; static HRGN hRgnSnake; static HRGN hRgnBean; static HRGN hRgnEmpty = CreateRectRgn(0, 0, 0, 0); HRGN hRgnNewBody; LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("Snake"); // 添加 HWND hwnd; MSG msg; WNDCLASSEX wndclassex = {0}; wndclassex.cbSize = sizeof(WNDCLASSEX); wndclassex.style = CS_HREDRAW | CS_VREDRAW; wndclassex.lpfnWndProc = WndProc; wndclassex.cbClsExtra = 0; wndclassex.cbWndExtra = 0; wndclassex.hInstance = hInstance; wndclassex.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclassex.hCursor = LoadCursor (NULL, IDC_ARROW); wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclassex.lpszMenuName = NULL; wndclassex.lpszClassName = szAppName; wndclassex.hIconSm = wndclassex.hIcon; if (!RegisterClassEx (&wndclassex)) { MessageBox (NULL, TEXT ("RegisterClassEx failed!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW, szAppName, TEXT ("Snake"), // 添加 WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME, CW_USEDEFAULT, CW_USEDEFAULT, (MAX + 1) * iRectSide, (MAX + 2) * iRectSide, NULL, NULL, hInstance, NULL); ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd); while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } return msg.wParam; } VOID CreateSnake(HWND hwnd, Snake & snake); VOID RunSnake(HWND hwnd, Snake & snake, SnakeBody & bean); VOID FindSnakeRgn(HWND hwnd, Snake & snake); VOID ThrowBean(HWND hwnd, SnakeBody & bean); LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; HBRUSH hBrushGray = (HBRUSH) GetStockObject(GRAY_BRUSH); HBRUSH hBrushGreen = CreateSolidBrush(RGB(0, 255, 0)); static int cxClient, cyClient; switch (message) { case WM_CREATE: hdc = GetDC (hwnd); CreateSnake(hwnd, snake); ReleaseDC (hwnd, hdc); ThrowBean(hwnd, bean); return 0; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); return 0; case WM_PAINT: hdc = BeginPaint (hwnd, &ps); for (int x = 1; x <= MAX; ++x) { MoveToEx(hdc, x * iRectSide, 0, NULL); LineTo(hdc, x * iRectSide, MAX * iRectSide); } for (int y = 1; y <= MAX; ++y) { MoveToEx(hdc, 0, y * iRectSide, NULL); LineTo(hdc, MAX * iRectSide, y * iRectSide); } FindSnakeRgn(hwnd, snake); SelectObject(hdc, hRgnSnake); FillRgn(hdc, hRgnSnake, hBrushGray); SelectObject(hdc, hRgnBean); FillRgn(hdc, hRgnBean, hBrushGreen); EndPaint (hwnd, &ps); return 0; case WM_KEYDOWN: switch (wParam) { case VK_SPACE: if (snake.status == PAUSE) { SetTimer(hwnd, IDT_TIMER2, 200, NULL); snake.status = RUN; } else { KillTimer(hwnd, IDT_TIMER2); snake.status = PAUSE; } break; case VK_UP: keyboardInput = UP; break; case VK_DOWN: keyboardInput = DOWN; break; case VK_LEFT: keyboardInput = LEFT; break; case VK_RIGHT: keyboardInput = RIGHT; break; } return 0; case WM_TIMER: if(snake.status) { RunSnake(hwnd, snake, bean); InvalidateRect(hwnd, NULL, TRUE); } return 0; case WM_CLOSE: snake.status = PAUSE; KillTimer(hwnd, IDT_TIMER2); if(IDYES == MessageBox(hwnd, TEXT("你真的不玩了吗?"), TEXT("Snake"), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2)) DestroyWindow(hwnd); return 0; case WM_DESTROY: DeleteObject(hBrushGray); DeleteObject(hBrushGreen); DeleteObject(hRgnSnake); DeleteObject(hRgnBean); DeleteObject(hRgnEmpty); DeleteObject(hRgnNewBody); PostQuitMessage (0); return 0; } return DefWindowProc (hwnd, message, wParam, lParam); } VOID CreateSnake(HWND hwnd, Snake & snake) { snake.status = PAUSE; snake.direction = RIGHT; snake.iBodyNum = INITIALLENGTH; snake.iHead = INITIALLENGTH - 1; snake.iTail = 0; hRgnSnake = hRgnEmpty; for (int i = 0; i < INITIALLENGTH; ++i) { snake.bodys[i].x = (MAX - INITIALLENGTH) / 2 - 1 + i; snake.bodys[i].y = MAX / 2; hRgnNewBody = CreateRectRgn(snake.bodys[i].x * iRectSide, snake.bodys[i].y * iRectSide, (snake.bodys[i].x + 1) * iRectSide, (snake.bodys[i].y + 1) * iRectSide); CombineRgn(hRgnSnake, hRgnNewBody, hRgnSnake, RGN_OR); } //InvalidateRect(hwnd, NULL, TRUE); } VOID RunSnake(HWND hwnd, Snake & snake, SnakeBody & bean) { SnakeBody newBody, oldBody, tempBody; switch (keyboardInput) { case UP: if(snake.direction != DOWN) { tempBody.x = snake.bodys[snake.iBodyNum - 1].x; tempBody.y = snake.bodys[snake.iBodyNum - 1].y - 1; snake.direction = keyboardInput; } else tempBody = snake.bodys[snake.iBodyNum - 1]; break; case DOWN: if(snake.direction != UP) { tempBody.x = snake.bodys[snake.iBodyNum - 1].x; tempBody.y = snake.bodys[snake.iBodyNum - 1].y + 1; snake.direction = keyboardInput; } else tempBody = snake.bodys[snake.iBodyNum - 1]; break; case LEFT: if(snake.direction != RIGHT) { tempBody.x = snake.bodys[snake.iBodyNum - 1].x - 1; tempBody.y = snake.bodys[snake.iBodyNum - 1].y; snake.direction = keyboardInput; } else tempBody = snake.bodys[snake.iBodyNum - 1]; break; case RIGHT: if(snake.direction != LEFT) { tempBody.x = snake.bodys[snake.iBodyNum - 1].x + 1; tempBody.y = snake.bodys[snake.iBodyNum - 1].y; snake.direction = keyboardInput; } else tempBody = snake.bodys[snake.iBodyNum - 1]; break; } newBody.x = (tempBody.x + MAX) % MAX; newBody.y = (tempBody.y + MAX) % MAX; oldBody = snake.bodys[snake.iTail]; if(newBody.x == bean.x && newBody.y == bean.y) { snake.iBodyNum += 1; hRgnBean = hRgnEmpty; ThrowBean(hwnd, bean); } else snake.iTail += 1; for (int i = snake.iTail; i < snake.iHead; ++i) if(newBody.x == snake.bodys[i].x && newBody.y == snake.bodys[i].y) { snake.status = STOP; if(IDYES == MessageBox(hwnd, TEXT("你太贪吃了,都咬到自己了!你是否要重新开始?"), TEXT("Snake"), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2)) { SendMessage(hwnd, WM_CREATE, 0, 0); return; } else SendMessage(hwnd, WM_CLOSE, 0, 0); } if (snake.iHead == MAX * MAX - 1) for (int i = 0, j = snake.iTail; j <= snake.iHead; ++i, ++j) snake.bodys[i] = snake.bodys[j]; snake.bodys[snake.iBodyNum] = newBody; snake.iBodyNum += 1; snake.iHead += 1; //InvalidateRect(hwnd, NULL, TRUE); } VOID FindSnakeRgn(HWND hwnd, Snake & snake) { hRgnSnake = CreateRectRgn(0, 0, 0, 0); for (int i = snake.iTail; i <= snake.iHead; ++i) { hRgnNewBody = CreateRectRgn(snake.bodys[i].x * iRectSide, snake.bodys[i].y * iRectSide, (snake.bodys[i].x + 1) * iRectSide, (snake.bodys[i].y + 1) * iRectSide); CombineRgn(hRgnSnake, hRgnNewBody, hRgnSnake, RGN_OR); } //InvalidateRect(hwnd, NULL, TRUE); } VOID ThrowBean(HWND hwnd, SnakeBody & bean) { loop: bean.x = rand() % MAX; bean.y = rand() % MAX; for (int i = snake.iTail; i <= snake.iHead; ++i) if(bean.x == snake.bodys[i].x && bean.y == snake.bodys[i].y) goto loop; hRgnBean = CreateRectRgn(bean.x * iRectSide, bean.y * iRectSide, (bean.x + 1) * iRectSide, (bean.y + 1) * iRectSide); //InvalidateRect(hwnd, NULL, TRUE); }