C++贪吃蛇
·
#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;
}
更多推荐



所有评论(0)