C++实现贪吃蛇

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值