用C++实现贪吃蛇(vs2017)
初学c++,找了一个简单的游戏做一做,如果有什么地方思路复杂了,希望看到的大佬能指导一下。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <conio.h>
#include <windows.h>
#include <vector>
typedef enum DIR { up = 1, down, lef, rig };
using namespace std;
HANDLE Hout = GetStdHandle(STD_OUTPUT_HANDLE);
COORD Coord;
/************ 隐藏光标 ********************/
void hide() {
CONSOLE_CURSOR_INFO curso_info = { 1,0 };
SetConsoleCursorInfo(Hout, &curso_info);
}
/************ 定位 ************************/
void locate(int x, int y) {
Coord.X = x;
Coord.Y = y;
SetConsoleCursorPosition(Hout, Coord);
}
/************* 地图点 *******************/
typedef struct nobe {
int x, y;
char ty;
DIR nobe_dir;
};
/************ 建立n*n的地图 ****************/
void Map(COORD &c, const int x, const int y) {
for (int i = 0; i < y; i++) {
for (int j = 0; j < x; j++) {
if (i == 0 || i == (y - 1)) {
cout << '-';
}
else if (j == 0 || j == (x - 1)) {
cout << '|';
}
else {
cout << ' ';
}
}
cout << endl;
}
}
/*********** 定义蛇******************/
typedef struct Food; //预声明
class Snake {
nobe p1, p2;
public:
bool live = true;
bool got = false; //是否吃到
vector<nobe> body; //蛇的身体
Snake(int i = 25, int j = 10, DIR d = down) {
p1.x = i; p1.y = j; p1.ty = '*'; p1.nobe_dir = down; p2.x = i; p2.y = j - 1; p2.ty = '*'; p2.nobe_dir = down;
body.push_back(p1);
body.push_back(p2);
}
void go(DIR direction, Food *fd); //移动
void clean(nobe cln_buf); //清楚尾部
void eat(nobe &f); //蛇进食
void die(void);
vector<nobe>::size_type Get_Sna_Length() { return body.size(); }
};
/*********** 食物 *************/
typedef struct Food {
nobe point;
vector<nobe> granary; //粮仓
int x, y;
bool g_flag = true; //生成食物是否和蛇冲突
bool over = false; //生成完成标志
void generate(int size_x, int size_y, Snake &Sna); //生成食物
void eaten(int p);
vector<nobe>::size_type Get_grabary() { return granary.size(); }
};
/********* 蛇进食 *******************/
void Snake::eat(nobe &f) {
got = true;
body.insert(body.begin(), f);
body.begin()->ty = '*';
locate(body.begin()->x, body.begin()->y);
cout << body.begin()->ty;
}
void Snake::die(void) {
system("cls");
cout << "Game Over" << endl;
cout << "Your Length is " << Get_Sna_Length() << endl;
live = false;
}
void Snake::clean(nobe cln_buf) {
body.erase(body.begin());
locate(cln_buf.x, cln_buf.y);
cout << cln_buf.ty;
}
/********** 蛇移动 ***********************/
void Snake::go(DIR direction, Food *fd) {
nobe buffer; //身体节数缓存区
nobe clean_buff; //清除缓冲区
clean_buff.x = 0; clean_buff.y = 0; clean_buff.ty = ' ';
buffer.x = body.begin()->x;
buffer.y = body.begin()->y;
switch (direction) {
case up: {
buffer.x += 0; buffer.y -= 1; buffer.ty = '*';
for (int n = 0; n < (int)fd->Get_grabary(); n++) {
if ((buffer.x == fd->granary[n].x) && (buffer.y == fd->granary[n].y)) { eat(fd->granary[n]); fd->eaten(n); break; }
else { got = false; }
}
if (!got) {
clean_buff.x = body[(int)Get_Sna_Length() - 1].x;
clean_buff.y = body[(int)Get_Sna_Length() - 1].y;
for (int i = (int)Get_Sna_Length() - 2; i >= 0; i--) {
body[i + 1] = body[i];
if (i == 0) { clean(clean_buff); }
}
body.insert(body.begin(), buffer);
}
}break;
case down: {
buffer.x += 0; buffer.y += 1; buffer.ty = '*';
for (int n = 0; n < (int)fd->Get_grabary(); n++) {
if ((buffer.x == fd->granary[n].x) && (buffer.y == fd->granary[n].y)) { eat(fd->granary[n]); fd->eaten(n); break; }
else { got = false; }
}
if (!got) {
clean_buff.x = body[(int)Get_Sna_Length() - 1].x;
clean_buff.y = body[(int)Get_Sna_Length() - 1].y;
for (int i = (int)Get_Sna_Length() - 2; i >= 0; i--) {
body[i + 1] = body[i];
if (i == 0) {clean(clean_buff); }
}
body.insert(body.begin(), buffer);
}
}break;
case lef: {
buffer.x -= 1; buffer.y -= 0; buffer.ty = '*';
for (int n = 0; n < (int)fd->Get_grabary(); n++) {
if ((buffer.x == fd->granary[n].x) && (buffer.y == fd->granary[n].y)) { eat(fd->granary[n]); fd->eaten(n); break; }
else { got = false; }
}
if (!got) {
clean_buff.x = body[(int)Get_Sna_Length() - 1].x;
clean_buff.y = body[(int)Get_Sna_Length() - 1].y;
for (int i = (int)Get_Sna_Length() - 2; i >= 0; i--) {
body[i + 1] = body[i];
if (i == 0) { clean(clean_buff); }
}
body.insert(body.begin(), buffer);
}
}break;
case rig: {
buffer.x += 1; buffer.y -= 0; buffer.ty = '*';
for (int n = 0; n < (int)fd->Get_grabary(); n++) {
if ((buffer.x == fd->granary[n].x) && (buffer.y == fd->granary[n].y)) { eat(buffer); fd->eaten(n); break; }
else { got = false; }
}
if (!got) {
clean_buff.x = body[(int)Get_Sna_Length() - 1].x;
clean_buff.y = body[(int)Get_Sna_Length() - 1].y;
for (int i = (int)Get_Sna_Length() - 2; i >= 0; i--) {
body[i + 1] = body[i];
if (i == 0) { clean(clean_buff); }
}
body.insert(body.begin(), buffer);
}
}break;
}
for (int t = 0; t < (int)Get_Sna_Length(); t++) {
locate(body[t].x, body[t].y);
cout << body[t].ty;
}
}
/********* 食物被吃 *******/
void Food::eaten(int p) {
granary.erase(granary.begin() + p);
}
/************ 生成食物 ****************/
void Food::generate(int size_x, int size_y, Snake &Sna) {
int n = 0;
srand((unsigned)time(NULL));
over = false;
while (!over) {
x = rand() % (size_x - 2) + 1; //这里有点迷???
y = rand() % (size_y - 2) + 1;
for (int i = 0; i < (int)Sna.Get_Sna_Length(); i++) {
if (g_flag == false) { n--; g_flag = true; }
if (x == Sna.body[i].x && y == Sna.body[i].y && g_flag == true) {
g_flag = false;
break;
}
}
if (g_flag = true) {
point.x = x;
point.y = y;
point.ty = '$';
granary.push_back(point);
locate(point.x, point.y);
cout << point.ty;
n++;
if (n == 10) { over = true; }
}
}
}
/************** 获取键盘输入 *******************/
DIR scan_key(DIR &d) {
if (_kbhit()) {
switch (_getch()) {
case 119: { //按下W
if (d == down) { return d; }
else { d = up; return up; }
}
case 115: { //按下S
if (d == up) { return d; }
else { d = down; return down; }
}
case 97: { //按下A
if (d == rig) { return d; }
else { d = lef; return lef; }
}
case 100: { //按下D
if (d == lef) { return d; }
else { d = rig; return rig; }
}
default: {return d; }
}
}
else { return d; } //返回上一次按键值
}
int main() {
Food food;
Snake snake = Snake();
Coord.X = 0;
Coord.Y = 0;
Map(Coord, 50, 20);
clock_t begin, end;
DIR Last_Dir = down;
hide();
int hard = 0;
while (1) {
hard = snake.Get_Sna_Length();
if ((int)food.Get_grabary() == 0) { food.generate(50, 20, snake); }
if (!snake.live) { break; }
snake.go(scan_key(Last_Dir), &food);
begin = clock();
if (snake.body[0].x == 0 || snake.body[0].x == 49 || snake.body[0].y == 0 || snake.body[0].y == 19) { snake.die(); break; } //碰到墙壁就死
for (int t = 1; t < (int)snake.Get_Sna_Length(); t++) {
if ((snake.body[0].x == snake.body[t].x) && (snake.body[0].y == snake.body[t].y)) { snake.die(); break; }
} //自撞死亡
while (1) {
end = clock();
if (end - begin >= (200 - 5 * hard)) break;
}
locate(0, 22);
cout << "Snake's length : " << snake.Get_Sna_Length() << endl;
cout << "Granary : " << food.Get_grabary() << endl;
}
return 0;
}