前言
实现代码
<snake.h>文件
#define _CRT_SECURE_NO_WARNINGS
#include <locale.h>
#include <stdio.h>
#include <windows.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1) ? 1 : 0)
#define POS_X 24
#define POS_Y 5
typedef struct SnakeNode
{
int x;
int y;
struct SnakeNode* next;
}SnakeNode;
typedef struct SnakeNode* pSnakeNode;
typedef struct Snake
{
pSnakeNode _pSnake;
pSnakeNode _pFood;
enum Direction _dir;
enum Game_Statues _status;
int _food_weight;
int _score;
int _sleep_time;
}Snake;
typedef struct Snake* pSnake;
enum Direction
{
UP,
DOWN,
LEFT,
RIGHT
};
enum Game_Status
{
OK,
KILL_BY_WALL,
KILL_BY_SELF,
END_NORMAL
};
void GameStart(pSnake ps);
void WelcomeToGame();
void SetPos(int x, int y);
void CreateMap();
void InitSnake(pSnake ps);
void CreateFood(pSnake ps);
void GameRun(pSnake ps);
void PrintHelpInfo();
void Pause();
void SnakeMove(pSnake ps);
int NextIsFood(pSnakeNode pn, pSnake ps);
void EatFood(pSnakeNode pn, pSnake ps);
void NoFood(pSnakeNode pn, pSnake ps);
void KillByWall(pSnake ps);
void KillBySelf(pSnake ps);
void GameEnd(pSnake ps);
<snake.c>文件
#include "snake.h"
void GameStart(pSnake ps)
{
system("mode con cols=100 lines=30");
system("title 贪吃蛇");
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
if (houtput == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "Failed to get standard output handle.\n");
return;
}
CONSOLE_CURSOR_INFO CursorInfo;
if (!GetConsoleCursorInfo(houtput, &CursorInfo))
{
fprintf(stderr, "Failed to get console cursor info.\n");
return;
}
CursorInfo.bVisible = false;
if (!SetConsoleCursorInfo(houtput, &CursorInfo))
{
fprintf(stderr, "Failed to set console cursor info.\n");
return;
}
WelcomeToGame();
CreateMap();
InitSnake(ps);
CreateFood(ps);
}
void WelcomeToGame()
{
SetPos(32, 13);
printf("Welcome to the Classic Snake Game!");
SetPos(39, 22);
system("pause");
system("cls");
SetPos(30, 13);
wprintf(L"Navigate the Snake using ↑ ↓ ← →.");
SetPos(33, 15);
wprintf(L"Accelerate to earn more points.");
SetPos(38, 23);
system("pause");
system("cls");
}
void SetPos(int x, int y)
{
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = { x,y };
SetConsoleCursorPosition(houtput, pos);
}
void CreateMap()
{
int i = 0;
for (i = 0; i < 29; i++)
{
wprintf(L"□");
}
SetPos(0, 26);
for (i=0; i < 29; i++)
{
wprintf(L"□");
}
for (i = 1; i <= 25; i++)
{
SetPos(0, i);
wprintf(L"□");
}
for (i = 1; i <= 25; i++)
{
SetPos(56, i);
wprintf(L"□");
}
}
void InitSnake(pSnake ps)
{
int i = 0;
for (i = 0; i < 5; i++)
{
pSnakeNode cur = (pSnakeNode)malloc(sizeof(SnakeNode));
if (cur == NULL)
{
perror("InitSnake error");
exit(1);
}
cur->next = NULL;
cur->x = POS_X + 2 * i;
cur->y = POS_Y;
if (ps->_pSnake == NULL)
{
ps->_pSnake = cur;
}
else
{
cur->next = ps->_pSnake;
ps->_pSnake = cur;
}
}
pSnakeNode cur = ps->_pSnake;
while (cur != NULL)
{
SetPos(cur->x, cur->y);
wprintf(L"●");
cur = cur->next;
}
ps->_dir = RIGHT;
ps->_score = 0;
ps->_food_weight = 10;
ps->_sleep_time = 200;
ps->_status = OK;
}
void CreateFood(pSnake ps)
{
int x;
int y;
again:
do
{
x = (rand()) % 53 + 2;
y = (rand()) % 25 + 1;
} while (x % 2 != 0);
pSnakeNode cur = ps->_pSnake;
while (cur != NULL)
{
if ((x == cur->x) = cur->y))
{
goto again;
}
cur = cur->next;
}
pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));
if (pFood == NULL)
{
perror("CreateFood error");
exit(1);
}
pFood->x = x;
pFood->y = y;
pFood->next = NULL;
SetPos(x, y);
wprintf(L"★");
ps->_pFood = pFood;
}
void GameRun(pSnake ps)
{
PrintHelpInfo();
do
{
SetPos(64, 7);
printf("Current score: %d", ps->_score);
SetPos(64, 8);
printf("Current food score: %2d", ps->_food_weight);
if (KEY_PRESS(VK_UP) && (ps->_dir != UP))
{
ps->_dir = UP;
}
else if (KEY_PRESS(VK_DOWN) && (ps->_dir != DOWN))
{
ps->_dir = DOWN;
}
else if (KEY_PRESS(VK_LEFT) && (ps->_dir != LEFT))
{
ps->_dir = LEFT;
}
else if (KEY_PRESS(VK_RIGHT) && (ps->_dir != RIGHT))
{
ps->_dir = RIGHT;
}
else if (KEY_PRESS(VK_SPACE))
{
Pause();
}
else if (KEY_PRESS(VK_ESCAPE))
{
ps->_status = END_NORMAL;
}
else if (KEY_PRESS(VK_F3))
{
if (ps->_sleep_time > 80)
{
ps->_sleep_time -= 30;
ps->_food_weight += 2;
}
}
else if (KEY_PRESS(VK_F4))
{
if (ps->_food_weight > 2)
{
ps->_sleep_time += 30;
ps->_food_weight -= 2;
}
}
SnakeMove(ps);
Sleep(ps->_sleep_time);
} while (ps->_status == OK);
}
void PrintHelpInfo()
{
SetPos(64, 10);
wprintf(L"No wall passing. No self-biting.");
SetPos(64, 12);
wprintf(L"F3 to speed up. F4 to slow down.");
SetPos(64, 14);
wprintf(L"ESC to exit. Space to pause.");
SetPos(74, 21);
wprintf(L"Made by HSY,");
SetPos(66, 22);
wprintf(L"a uniquely independent pig.");
}
void Pause()
{
while (1)
{
Sleep(200);
if (KEY_PRESS(VK_SPACE))
{
break;
}
}
}
void SnakeMove(pSnake ps)
{
pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));
if (pNextNode == NULL)
{
perror("SnakeMove error");
exit(1);
}
switch (ps->_dir)
{
case UP:
pNextNode->x = ps->_pSnake->x;
pNextNode->y = ps->_pSnake->y - 1;
break;
case DOWN:
pNextNode->x = ps->_pSnake->x;
pNextNode->y = ps->_pSnake->y + 1;
break;
case LEFT:
pNextNode->x = ps->_pSnake->x - 2;
pNextNode->y = ps->_pSnake->y;
break;
case RIGHT:
pNextNode->x = ps->_pSnake->x + 2;
pNextNode->y = ps->_pSnake->y;
break;
}
if (NextIsFood(pNextNode,ps))
{
EatFood(pNextNode, ps);
}
else
{
NoFood(pNextNode, ps);
}
KillByWall(ps);
KillBySelf(ps);
}
int NextIsFood(pSnakeNode pn, pSnake ps)
{
return (ps->_pFood->x == pn->x && ps->_pFood->y == pn->y);
}
void EatFood(pSnakeNode pn, pSnake ps)
{
ps->_pFood->next = ps->_pSnake;
ps->_pSnake = ps->_pFood;
free(pn);
pn = NULL;
pSnakeNode cur = ps->_pSnake;
while (cur!=NULL)
{
SetPos(cur->x, cur->y);
wprintf(L"●");
cur = cur->next;
}
ps->_score += ps->_food_weight;
CreateFood(ps);
}
void NoFood(pSnakeNode pn, pSnake ps)
{
pn->next = ps->_pSnake;
ps->_pSnake = pn;
pSnakeNode cur = ps->_pSnake;
while (cur->next->next != NULL)
{
SetPos(cur->x, cur->y);
wprintf(L"●");
cur = cur->next;
}
SetPos(cur->next->x, cur->next->y);
printf(" ");
free(cur->next);
cur->next = NULL;
}
void KillByWall(pSnake ps)
{
if (ps->_pSnake->x == 0 || ps->_pSnake->x == 56 || ps->_pSnake->y == 0 || ps->_pSnake->y == 26)
{
ps->_status = KILL_BY_WALL;
}
}
void KillBySelf(pSnake ps)
{
pSnakeNode cur = ps->_pSnake->next;
while (cur)
{
if (cur->x == ps->_pSnake->x && cur->y == ps->_pSnake->y)
{
ps->_status = KILL_BY_SELF;
break;
}
cur = cur->next;
}
}
void GameEnd(pSnake ps)
{
switch (ps->_status)
{
case END_NORMAL:
SetPos(17, 12);
printf("You have ended the game.");
break;
case KILL_BY_WALL:
SetPos(10, 12);
printf("You ended the game by hitting a wall.");
break;
case KILL_BY_SELF:
SetPos(10, 12);
printf("You ended the game by self-collision.");
break;
}
pSnakeNode cur = ps->_pSnake;
pSnakeNode prev = NULL;
while (cur)
{
prev = cur;
cur = cur->next;
free(prev);
}
}
<test.c>文件
#include "snake.h"
void test()
{
char ch;
do
{
system("cls");
Snake snake = { 0 };
GameStart(
GameRun(
GameEnd(
SetPos(20, 15);
printf("Play again? (Y/N)");
ch = getchar();
getchar();
} while (ch == 'Y'|| ch == 'y');
SetPos(0, 28);
}
int main()
{
setlocale(LC_ALL, "");
srand((unsigned int)time(NULL));
test();
return 0;
}
致谢