环境:Visual Studio 2022
语言:C++
数据结构:顺序表
完整代码:
#include <iostream>
#include <Windows.h>
#include <conio.h>
using namespace std;
#define H 27
#define W 60
const int dir[4][2] = {
{-1, 0}, // 上
{0, 1}, // 右
{1, 0}, // 下
{0, -1} // 左
};
enum BlockType {
EMPTY = 0,
FOOD = 1,
};
struct Map {
BlockType data[H][W];
bool hasFood;
};
struct Pos {
int x;
int y;
};
struct Snack {
Pos snack[H * W];
int snackDir;
int snackLength;
int lastMoveTime;
int moveFreqency;
};
void initSnack(Snack* snk) {
snk->snackDir = 1;
snk->snackLength = 3;
snk->snack[0] = { W / 2, H / 2 };
snk->snack[1] = { W / 2 - 1, H / 2 };
snk->snack[0] = { W / 2 - 2, H / 2 };
snk->lastMoveTime = 0;
snk->moveFreqency = 500;
}
void hideCursor() {
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO curInfo = { 1, FALSE };
SetConsoleCursorInfo(hOutput, &curInfo);
}
void initMap(Map* map) {
for (int y = 0; y < H; ++y) {
for (int x = 0; x < W; ++x) {
map->data[y][x] = BlockType::EMPTY;
}
}
map->hasFood = false;
}
void drawUnit(Pos p, const char unit[]) {
COORD coord;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
coord.X = p.x + 1;
coord.Y = p.y + 1;
SetConsoleCursorPosition(hOutput, coord);
cout << unit;
}
void drawMap(Map* map) {
system("cls");
cout << "┏";
for (int i = 0; i < W; ++i) {
cout << "━";
}
cout << "┓" << endl;
for (int y = 0; y < H; ++y) {
cout << "┃";
for (int x = 0; x < W; ++x) {
if (map->data[y][x] == BlockType::EMPTY)
cout << " ";
}
cout << "┃" << endl;
}
cout << "┗";
for (int i = 0; i < W; ++i) {
cout << "━";
}
cout << "┛" << endl;
}
void drawSnack(Snack* snk) {
for (int i = 0; i < snk->snackLength; ++i) {
drawUnit(snk->snack[i], "■");
}
}
void moveSnack(Snack* snk) {
for (int i = snk->snackLength - 1; i >= 1; --i) {
snk->snack[i] = snk->snack[i - 1];
}
snk->snack[0].y += dir[snk->snackDir][0];
snk->snack[0].x += dir[snk->snackDir][1];
}
bool checkOutOfBound(Pos p) {
if (p.x <= 0 || p.x >= W) {
return true;
}
if (p.y <= 0 || p.y >= H) {
return true;
}
return false;
}
void checkEatFood(Snack* snk, Pos tail, Map* map) {
Pos head = snk->snack[0];
if (map->data[head.y][head.x] == BlockType::FOOD) {
snk->snack[snk->snackLength++] = tail;
map->data[head.y][head.x] = BlockType::EMPTY;
map->hasFood = false;
drawUnit(tail, "■");
}
}
bool doMove(Snack* snk, Map* map) {
Pos tail = snk->snack[snk->snackLength - 1];
drawUnit(snk->snack[snk->snackLength - 1], " ");
moveSnack(snk);
if (checkOutOfBound(snk->snack[0])) {
return false;
}
checkEatFood(snk, tail, map);
drawUnit(snk->snack[0], "■");
return true;
}
bool checkSnackMove(Snack* snk, Map* map) {
int curTime = GetTickCount();
if (curTime - snk->lastMoveTime > snk->moveFreqency) {
if (false == doMove(snk, map))
return false;
snk->lastMoveTime = curTime;
}
return true;
}
void checkChangeDir(Snack* snk) {
if (_kbhit()) {
switch (_getch()) {
case 'w':
if (snk->snackDir != 2)
snk->snackDir = 0;
break;
case 'd':
if (snk->snackDir != 3)
snk->snackDir = 1;
break;
case 's':
if (snk->snackDir != 0)
snk->snackDir = 2;
break;
case 'a':
if (snk->snackDir != 1)
snk->snackDir = 3;
break;
default:
break;
}
}
}
void checkFoodGenerate(Snack* snk, Map* map) {
if (map->hasFood == false) {
while (1) {
int x = rand() % W;
int y = rand() % H;
int i = 0;
while (i < snk->snackLength) {
if (x == snk->snack[i].x && y == snk->snack[i].y) {
break;
}
i++;
}
if (i == snk->snackLength) {
map->data[y][x] = BlockType::FOOD;
map->hasFood = true;
drawUnit({ x, y }, "●");
return;
}
}
}
}
void innitGame(Snack* snk, Map* map) {
hideCursor();
initMap(map);
initSnack(snk);
drawMap(map);
drawSnack(snk);
}
int main() {
Map map;
Snack snk;
innitGame(&snk, &map);
while (1) {
checkChangeDir(&snk);
if (false == checkSnackMove(&snk, &map)) {
break;
}
checkFoodGenerate(&snk, &map);
}
drawUnit({ W / 2 - 4, H / 2 }, "Game Over!");
while(1) {}
return 0;
}
运行截图: