#include <cstdlib>
#include <conio.h>
#include <deque>
#include <iostream>
#include <time.h>
#include <windows.h>
typedef struct {
bool virticle = false;
int offset = 0;
}Step;
enum GiftType {
GIFT_GIFT = FOREGROUND_GREEN,
GIFT_TRAP = FOREGROUND_GREEN | FOREGROUND_BLUE,
GIFT_SWORD = FOREGROUND_RED
};
#define FACTORY_WIDTH 64
#define FACTORY_HEIGHT 36
#define SNAKE_BODY_COLOR (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
using namespace std;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
deque<COORD> snakeBody;
bool dead = false;
COORD gift, trap, sword;
bool inSnake(COORD point) {
if (snakeBody.size() == 0)
return false;
deque<COORD>::iterator iter = snakeBody.begin();
while (iter != snakeBody.end()) {
if (point.X == (*iter).X && point.Y == (*iter).Y)
return true;
++iter;
}
return false;
}
COORD createGift(GiftType color) {
static int count = 0;
++count;
COORD point;
srand(rand());
point.X = rand() % FACTORY_WIDTH * 2;
srand(rand());
point.Y = rand() % FACTORY_HEIGHT;
if (inSnake(point)) {
return createGift(color);
}
else {
SetConsoleCursorPosition(hOutput, point);
SetConsoleTextAttribute(hOutput, color);
cout << "█";
SetConsoleTextAttribute(hOutput, SNAKE_BODY_COLOR);
dead = count > 12 ? true : false;
count = 0;
return point;
}
}
void init() {
system("cls");
snakeBody.clear();
srand(time(NULL));
snakeBody.push_front({ 0, 0 });
snakeBody.push_front({ 2, 0 });
snakeBody.push_front({ 4, 0 });
deque<COORD>::iterator iter = snakeBody.begin();
while (iter != snakeBody.end()) {
SetConsoleCursorPosition(hOutput, *iter);
cout << "█";
++iter;
}
sword = createGift(GIFT_SWORD);
trap = createGift(GIFT_TRAP);
gift = createGift(GIFT_GIFT);
}
void stepOnece(Step step) {
COORD head = snakeBody.front();
(step.virticle ? head.Y : head.X) += step.offset;
if (inSnake(head)
|| snakeBody.size() == 0
|| (head.X == sword.X && head.Y == sword.Y)
|| head.X < 0 || head.X >= FACTORY_WIDTH * 2
|| head.Y < 0 || head.Y >= FACTORY_HEIGHT) {
dead = true;
return;
}
snakeBody.push_front(head);
SetConsoleCursorPosition(hOutput, head);
cout << "█";
int count;
if (head.X == trap.X && head.Y == trap.Y) {
count = 2;
trap = createGift(GIFT_TRAP);
}
else if (head.X == gift.X && head.Y == gift.Y) {
count = 0;
gift = createGift(GIFT_GIFT);
}
else
count = 1;
for (int i = 0; i < count; i++) {
COORD back = snakeBody.back();
SetConsoleCursorPosition(hOutput, back);
printf(" ");
snakeBody.pop_back();
if (snakeBody.size() == 0) {
dead = true;
break;
}
}
}
void gameLoop() {
Step curStep = { false, 2 };
Step step = curStep;
while (!dead) {
for (int i = 0; i < 200; i++) {
Sleep(1);
if (!_kbhit())
continue;
char cmd;
bool breakdown = true;
cmd = _getch();
switch (cmd) {
case 'w':
step.virticle = true;
step.offset = -1;
break;
case 's':
step.virticle = true;
step.offset = 1;
break;
case 'a':
step.virticle = false;
step.offset = -2;
break;
case 'd':
step.virticle = false;
step.offset = 2;
break;
default:
breakdown = false;
break;
}
if (step.virticle == curStep.virticle && step.offset * curStep.offset < 0)
continue;
else
curStep = step;
if (breakdown)
break;
}
stepOnece(curStep);
}
}
int main() {
SMALL_RECT rect = { 0, 0, 10, 10 };
SetConsoleWindowInfo(hOutput, true, &rect);
SetConsoleScreenBufferSize(hOutput, { FACTORY_WIDTH * 2, FACTORY_HEIGHT });
rect = { 0, 0, FACTORY_WIDTH * 2 - 1, FACTORY_HEIGHT - 1 };
SetConsoleWindowInfo(hOutput, true, &rect);
SetConsoleTextAttribute(hOutput, SNAKE_BODY_COLOR);
CONSOLE_CURSOR_INFO cursorInfo = { 1, false };
SetConsoleCursorInfo(hOutput, &cursorInfo);
cout << "使用W、S、A、D控制方向,吃到绿色礼包长度增加,吃到黄色礼包时长度减短,"\
"吃到红色礼包直接死亡。您也可以按CTRL + C退出游戏。按任意键开始游戏。" << endl;
system("pause");
while (true) {
init();
gameLoop();
system("cls");
SetConsoleCursorPosition(hOutput, { 0, 0 });
printf("You has dead! Retry? (y/n)");
char cmd;
cin >> cmd;
if (cmd != 'y')
break;
else
dead = false;
}
}