#include<iostream>
#include<Windows.h>
#include<conio.h>
using namespace std;
#define H 27
#define W 68
//方向
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 Snake {
pos snake[H * W];//一维数组
int SnakeDir;//蛇的方向
int SnakeLength;//蛇的长度
int lastMoveTime;
int moveFrequency;
};
//初始化蛇
void InitSnake(Snake* s) {
s->SnakeLength = 1;
s->SnakeDir = 1;
s->snake[0] = { W / 2,H / 2 };//结构体pos的初始化
s->lastMoveTime = 0;
s->moveFrequency = 200;
}
//隐藏光标
void hideCurson() {
HANDLE hOutput=GetStdHandle(STD_OUTPUT_HANDLE);//获得输出窗口的编号
CONSOLE_CURSOR_INFO curInfo = { 1,FALSE };
SetConsoleCursorInfo(hOutput, &curInfo);//隐藏光标
}
void InitMap(struct Map* M) {
//所有格子都没有食物
for (int y = 0; y < H; y++) {
for (int x = 0; x < W; x++) {
M->data[y][x] = BlockType::EMPTY;
}
}
M->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(struct Map* M) {
system("cls");//清除控制台
cout << "┏";
for (int i = 0; i < W; i++) {
cout << "━";
}
cout << "┓" << endl;
for (int j = 0; j < H; j++) {
cout << "┃";
for (int k = 0; k < W; k++) {
if (M->data[j][k] == BlockType::EMPTY)
cout << " ";
}
cout << "┃" << endl;
}
cout << "┗";
for (int x = 0; x < W; x++)
cout << "━";
cout << "┛" << endl;
}
void drawSnake(Snake* s) {
for (int i = 0; i < s->SnakeLength; i++) {
drawUnit(s->snake[i], "■");
}
}
//边界判断
bool checkOutOfBound(pos p) {
if (p.x == 0 || p.x == W + 1 || p.y == 0 || p.y == H + 1) {
return true;
}
return false;
}
void checkEatFood(Snake * s,pos tail,Map* m) {
pos head = s->snake[0];
if (m->data[head.y][head.x] == BlockType::FOOD) {
s->snake[s->SnakeLength++] = tail;
m->data[head.y][head.x] == BlockType::EMPTY;
m->hasFood = false;
drawUnit(tail, "■");
}
}
void moveSnake(Snake* s) {
for (int i = s->SnakeLength - 1; i >= 1; --i) {
s->snake[i] = s->snake[i - 1];
}
s->snake[0].y += dir[s->SnakeDir][0];
s->snake[0].x += dir[s->SnakeDir][1];
}
bool doMove(Snake* s, Map* m) {
pos tail = s->snake[s->SnakeLength - 1];
drawUnit(tail, " ");
moveSnake(s);
if (checkOutOfBound(s->snake[0])) {
return false;
}
checkEatFood(s, tail, m);
drawUnit(s->snake[0], "■");
return true;
}
bool checkSnakeMove(Snake* s, Map* m) {
int curTime=GetTickCount();
if (curTime - s->lastMoveTime > s->moveFrequency) {
if (false == doMove(s, m))
return false;
s->lastMoveTime = curTime;
}
return true;
}
void checkChangeDir(Snake* s) {
//键盘是否被按下
if (_kbhit()) {
switch(_getch()){
//按下的按键是什么
case 'w':
if(s->SnakeDir!=2)
s->SnakeDir = 0;
break;
case 'd':
if(s->SnakeDir!=3)
s->SnakeDir = 1;
break;
case 's':
if (s->SnakeDir != 0)
s->SnakeDir = 2;
break;
case 'a':
if (s->SnakeDir != 1)
s->SnakeDir = 3;
break;
default:
break;
}
}
}
void checkFoodGenerate(Snake* s,Map* m) {
if (false == m->hasFood) {
while (1) {
int x = rand() % W;
int y = rand() % H;
int i = 0;
while (i < s->SnakeLength) {
if (x == s->snake[i].x && y == s->snake[i].y)
break;
i++;
}
if (i == s->SnakeLength) {
m->data[y][x] = BlockType::FOOD;
m->hasFood = true;
drawUnit({ x,y }, "●");
return;
}
}
}
}
int main() {
Map map;
Snake s;
hideCurson();
InitMap(&map);
InitSnake(&s);
drawMap(&map);
drawSnake(&s);
while (1) {
checkChangeDir(&s);
if (false == checkSnakeMove(&s, &map))
break;
checkFoodGenerate(&s, &map);
}
drawUnit({ W / 2 - 4,H / 2 }, "Game Over");
while (1);
return 0;
}
C++实现贪吃蛇
于 2024-07-23 22:30:18 首次发布