#include <graphics.h>
#include <conio.h>
#include
#include
#include
#include <Windows.h>
using namespace std;
const int GAME_WIDTH = 600;
const int GAME_HEIGHT = 400;
const int CELL_SIZE = 20;
enum Direction { STOP, LEFT, RIGHT, UP, DOWN };
class SnakeGame {
private:
deque snakeBody;
POINT foodPos;
Direction currentDir;
bool isGameOver;
int gameScore;
IMAGE gameOverImage;
void GenerateFood() {
bool onSnake;
do {
onSnake = false;
foodPos.x = (rand() % (GAME_WIDTH / CELL_SIZE)) * CELL_SIZE;
foodPos.y = (rand() % (GAME_HEIGHT / CELL_SIZE)) * CELL_SIZE;
for (const auto& part : snakeBody) {
if (foodPos.x == part.x && foodPos.y == part.y) {
onSnake = true;
break;
}
}
} while (onSnake);
}
public:
SnakeGame() : currentDir(STOP), isGameOver(false), gameScore(0) {
srand(static_cast(time(nullptr)));
ResetGame();
}
void ProcessInput() {
if (GetAsyncKeyState('A') & 0x8000 && currentDir != RIGHT) currentDir = LEFT;
else if (GetAsyncKeyState('D') & 0x8000 && currentDir != LEFT) currentDir = RIGHT;
else if (GetAsyncKeyState('W') & 0x8000 && currentDir != DOWN) currentDir = UP;
else if (GetAsyncKeyState('S') & 0x8000 && currentDir != UP) currentDir = DOWN;
else if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) isGameOver = true;
}
void UpdateGame() {
if (currentDir == STOP || isGameOver) return;
POINT newHead = snakeBody.front();
switch (currentDir) {
case LEFT: newHead.x -= CELL_SIZE; break;
case RIGHT: newHead.x += CELL_SIZE; break;
case UP: newHead.y -= CELL_SIZE; break;
case DOWN: newHead.y += CELL_SIZE; break;
}
// 边界检测
if (newHead.x < 0 || newHead.x >= GAME_WIDTH ||
newHead.y < 0 || newHead.y >= GAME_HEIGHT) {
isGameOver = true;
return;
}
// 自身碰撞检测
for (auto it = snakeBody.begin() + 1; it != snakeBody.end(); ++it) {
if (newHead.x == it->x && newHead.y == it->y) {
isGameOver = true;
return;
}
}
snakeBody.push_front(newHead);
if (newHead.x == foodPos.x && newHead.y == foodPos.y) {
gameScore += 10;
GenerateFood();
}
else {
snakeBody.pop_back();
}
}
void RenderFrame() {
cleardevice();
if (!isGameOver) {
// 绘制蛇身
for (const auto& part : snakeBody) {
rectangle(part.x, part.y, part.x + CELL_SIZE, part.y + CELL_SIZE);
}
// 绘制食物
rectangle(foodPos.x, foodPos.y, foodPos.x + CELL_SIZE, foodPos.y + CELL_SIZE);
// 绘制分数
wchar_t scoreText[32];
swprintf(scoreText, 32, L"分数: %d", gameScore);
outtextxy(10, 10, scoreText);
}
else {
// 显示分数和提示
wchar_t scoreText[50];
swprintf(scoreText, 50, L"最终分数: %d", gameScore);
settextcolor(RED);
outtextxy(GAME_WIDTH / 2 - textwidth(scoreText) / 2, GAME_HEIGHT - 100, scoreText);
wchar_t restartText[] = L"按 Enter 重新开始";
wchar_t exitText[] = L"按 ESC 退出游戏";
settextcolor(BLACK);
outtextxy(GAME_WIDTH / 2 - textwidth(restartText) / 2, GAME_HEIGHT - 70, restartText);
outtextxy(GAME_WIDTH / 2 - textwidth(exitText) / 2, GAME_HEIGHT - 40, exitText);
}
}
bool GameOver() const { return isGameOver; }
void ResetGame() {
snakeBody.clear();
POINT head = { GAME_WIDTH / 2, GAME_HEIGHT / 2 };
snakeBody.push_back(head);
for (int i = 1; i < 3; i++) {
POINT body = { head.x - i * CELL_SIZE, head.y };
snakeBody.push_back(body);
}
currentDir = STOP;
isGameOver = false;
gameScore = 0;
GenerateFood();
}
};
int main() {
initgraph(GAME_WIDTH, GAME_HEIGHT);
setbkcolor(WHITE);
cleardevice();
setlinecolor(BLACK);
SnakeGame game;
while (true) {
while (!game.GameOver()) {
game.ProcessInput();
game.UpdateGame();
game.RenderFrame();
// 处理Windows消息
MSG msg;
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(100); // 控制游戏速度
}
// 游戏结束后的处理
game.RenderFrame();
// 等待用户选择
bool restart = false;
bool exitGame = false;
while (!restart && !exitGame) {
if (GetAsyncKeyState(VK_RETURN) & 0x8000) {
restart = true;
}
else if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) {
exitGame = true;
}
// 处理消息
MSG msg;
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
exitGame = true;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(100);
}
if (exitGame) break;
if (restart) game.ResetGame();
}
closegraph();
return 0;
}