#include<iostream>
#include<Windows.h>
#include<conio.h>
using namespace std;

#define H 28
#define W 60

//移动
const int dir[4][2] = {
	{-1,0},//上
	{0,1},//右
	{1,0},//下
	{0,-1},//左
	
};
void hideCursor() {
	HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO curInfo = { 1,FALSE };
	SetConsoleCursorInfo(hOutput, &curInfo);
}

//需要动态的东西记录下来
//地图上每一格的类型,不是空就是食物
enum BlockType {
	EMPTY = 0,
	FOOD = 1,
};
struct Map {
	BlockType data[H][W];
	bool hasFood;//当前地图上有没有食物
};

void initMap(Map* 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;
}

//坐标位置
struct Pos {
	int x;
	int y;
};

//蛇
struct Snake {
	Pos snake[H * W];//蛇的位置
	int snakeDir;//蛇方向
	int snakeLength;//蛇的长度
	int lastMoveTime;//上一次移动的时间
	int moveFrequency;
};

//蛇初始化
void initSnake(Snake* snk) {
	snk->snakeLength = 3;
	snk->snakeDir = 1;
	snk->snake[0] = { W / 2,H / 2 };
	snk->snake[1] = { W / 2 - 1,H / 2 };
	snk->snake[2] = { W / 2 - 2,H / 2 };
	snk->lastMoveTime = 0;
	snk->moveFrequency = 200;
}


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 chekeEatFood(Snake* snk, Pos tail, Map* map) {
	Pos head = snk->snake[0];
	if (map->data[head.y][head.x] == BlockType::FOOD) {
		snk->snake[snk->snakeLength++] = tail;
		map->data[head.y][head.x] = BlockType::EMPTY;
		map->hasFood = false;
		drawUnit(tail, "+");
	}
}
//绘制地图
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 << "]";
}

void drawSnake(Snake* snk) {
	for (int i = 0; i < snk->snakeLength; i++) {
		drawUnit(snk->snake[i], "+");
	}
}
void moveSnake(Snake* snk) {
	for (int i = snk->snakeLength - 1; i >= 1; i--) {
		snk->snake[i] = snk->snake[i - 1];
	}
	snk->snake[0].y += dir[snk->snakeDir][0];
	snk->snake[0].x += dir[snk->snakeDir][1];

}


bool checkOutOfBound(Pos p) {
	if (p.x == 0 || p.x == W + 1) {
		return true;
	}
	if (p.y == 0 || p.y == H + 1) {
		return true;
	}
	return false;
}

bool doMove(Snake* snk, Map* map) {
	Pos tail = snk->snake[snk->snakeLength - 1];
	drawUnit(tail, " ");//让尾部为空
	moveSnake(snk);//让蛇王对应方向移动一格
	if (checkOutOfBound(snk->snake[0])) {
		return false;
	}
	chekeEatFood(snk, tail, map);//检查是否吃到食物
	drawUnit(snk->snake[0], "+");
	return true;
}

bool checkSnakeMove(Snake* snk, Map* map) {
	int curTime = GetTickCount();
	if (curTime - snk->lastMoveTime > snk->moveFrequency) {
		if (false == doMove(snk, map))
			return false;
		snk->lastMoveTime = curTime;
	}
	return true;
}

void checkChangeDir(Snake* snk) {
	if (_kbhit()) {
		switch (_getch()) {
		case 'w':
			if(snk->snakeDir != 2)
				snk->snakeDir = 0;
			break;
		case 'd':
			if (snk->snakeDir != 3)
				snk->snakeDir = 1;
			break;
		case 's':
			if (snk->snakeDir != 0)
				snk->snakeDir = 2;
			break;
		case 'a':
			if (snk->snakeDir != 1)
				snk->snakeDir = 3;
			break;
		default:
			break;
		}
	}
}

void checkFoodGenerate(Snake* snk, Map* map) {
	if (false == map->hasFood) {
		//没有食物就得生成一个
		while (1) {
			int x = rand() % W;
			int y = rand() % H;
			int i = 0;
			while (i < snk->snakeLength) {
				if (x == snk->snake[i].x && y == snk->snake[i].y) {
					break;
				}
				i++;
			}
			if (i == snk->snakeLength) {
				map->data[y][x] = BlockType::FOOD;
				map->hasFood = true;
				drawUnit({ x,y }, "*");
				return;
			}

		}
	}
}
int main() {
	Map map;
	Snake snk;
	hideCursor();
	initMap(&map);
	initSnake(&snk);
	drawMap(&map);
	drawSnake(&snk);

	while (1) {
		checkChangeDir(&snk);
		if (false == checkSnakeMove(&snk, &map)) {
			break;
		}
		checkFoodGenerate(&snk, &map);

	}
	while (1) {
		drawUnit({ W / 2 - 4,H / 2 }, "Game Over");
	}
	return 0;
}

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐