借鉴了这位大佬的博客及代码,键入代码后发现有很多报错,依次解决后成功运行
c++ 实现贪吃蛇(含技术难点解析和完整代码)
技术点:
C++中_kbhit()函数与_getch()函数
Windows API 坐标结构 COORD
句柄 HANDLE
获取句柄 GetStdHandle
光标的位置控 SetConsoleCursorPosition制
光标定位函数 gotoxy()与清屏函数clrscr()
(1) warning C4244: “参数”: 从“time_t”转换到“unsigned int”,可能丢失数据
原因:一个简单的C的Hello World,如果用高版本的VS来编译,会有这种提示,这个是高版的VS默认不让使用scanf,fopen等函数,说是scanf,fopen等函数不安全,而代替其函数的是scanf_s,fopen_s等函数,后边有个"_s"的形式
解决:想要使用,可以在源文件开头加个:
#define _CRT_SECURE_NO_WARNINGS
预编时处理一下,加个宏而已,让其忽略安全检测
(2) warning C4996: ‘kbhit‘: The POSIX name for this item is deprecated.
原因:暂未得知
解决:将kbhit()
改为_kbhit()
,将getch()
改为_getch()
/*********************************************************************
程序名: 贪吃蛇
*********************************************************************/
/*********************************************************************
程序名: 贪吃蛇
*********************************************************************/
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
#include
using namespace std;
#define frame_width 50
#define frame_height 25
typedef struct{
int x, y;
} Food;
typedef struct{
int x[100], y[100], len, state;
} Snake;
void gotoxy(int x, int y); //最重要的一个函数,控制光标的位置
void print_map();
void get_newfood();//生成新食物
bool check_foodinsnake();//检查新食物有没有在蛇身上
void move_snake(); // 移动食物
void check_foodeating();//是否吃到食物
bool check_snakealive();//贪吃蛇是否还存活
//需要用到的全局变量
int score;
Snake snake;
Food food;
bool check_eaten;
int main()
{
system("color 0B");
do
{
printf("1:start\t2:exit\n");
char com2;
cin >> com2;
if (com2 == '2')
break;
system("cls");
score = 0, check_eaten = 0;
print_map();
//贪吃蛇的每回合运行控制
while (1)
{
check_foodeating();//system("pause");
move_snake();
Sleep(max(50, 300 - score));//控制速度(与长度呈反比)
if (!check_snakealive())
break;
}
printf("Game Over!\n");
} while (1);
}
void gotoxy(int x, int y)
{
COORD pos;//COORD是一种自带结构体,表示一个字符在控制台屏幕上的坐标
HANDLE han = GetStdHandle(STD_OUTPUT_HANDLE); //从标准输出设备里取出一个句柄
pos.X = y, pos.Y = x;
SetConsoleCursorPosition(han, pos);//定位光标的函数
}
void print_map()
{
//打印墙壁
for (int i = 0; i<frame_height; i++)
{
gotoxy(i, 0);
printf("#");
gotoxy(i, frame_width);//因为这个标记是长度,从零开始所以最后要减1
printf("#");
}
for (int i = 0; i<frame_width; i++)
{
gotoxy(0, i);
printf("#");
gotoxy(frame_height, i);
printf("#");
}
//蛇身初始化
snake.len = 3;
snake.state = 'w';
snake.x[1] = frame_height / 2;
snake.y[1] = frame_width / 2;
gotoxy(snake.x[1], snake.y[1]);
printf("@");
for (int i = 2; i <= snake.len; i++)
{
snake.x[i] = snake.x[i - 1] + 1;
snake.y[i] = snake.y[i - 1];
gotoxy(snake.x[i], snake.y[i]);
printf("@");
}
//打印初始食物
get_newfood();
//打印右边状态栏
gotoxy(2, frame_width + 3);
printf("WELCOME TO THE GAME OF RETRO SNAKE");
gotoxy(4, frame_width + 3);
printf("UP: w");
gotoxy(6, frame_width + 3);
printf("DOWN: s");
gotoxy(8, frame_width + 3);
printf("LEFT: a");
gotoxy(10, frame_width + 3);
printf("RIGHT:d");
gotoxy(12, frame_width + 3);
printf("Your score:%d", score);
gotoxy(28, frame_width + 3);
printf("Made by majin");
}
bool check_foodinsnake()
{
for (int i = 1; i <= snake.len; i++)
if (snake.x[i] == food.x&&snake.y[i] == food.y)
return 1;
return 0;
}
void get_newfood()
{
do{
srand(time(0));
food.x = rand() % (frame_height - 1) + 1;
food.y = rand() % (frame_width - 1) + 1;
} while (check_foodinsnake());
gotoxy(food.x, food.y);
cout << "$" << endl;
}
void move_snake()
{
char com = 'n';
while (_kbhit())//键盘有输入
com = _getch();//从控制台读取一个字符,但不显示在屏幕上
//没有吃到去除蛇尾
if (!check_eaten)
{
gotoxy(snake.x[snake.len], snake.y[snake.len]);
printf(" ");
}
//将除蛇头外的其他部分向前移动
for (int i = snake.len; i>1; i--)
snake.x[i] = snake.x[i - 1],
snake.y[i] = snake.y[i - 1];
//移动蛇头
switch (com)
{
case 'w':
{
if (snake.state == 's') //如果命令与当前方向相反不起作用
snake.x[1]++;
else
snake.x[1]--, snake.state = 'w';
break;
}
case 's':
{
if (snake.state == 'w')
snake.x[1]--;
else
snake.x[1]++, snake.state = 's';
break;
}
case 'a':
{
if (snake.state == 'd')
snake.y[1]++;
else
snake.y[1]--, snake.state = 'a';
break;
}
case 'd':
{
if (snake.state == 'a')
snake.y[1]--;
else
snake.y[1]++, snake.state = 'd';
break;
}
default: //按其余键保持状态前进
{
if (snake.state == 's')
snake.x[1]++;
else if (snake.state == 'w')
snake.x[1]--;
else if (snake.state == 'd')
snake.y[1]++;
else if (snake.state == 'a')
snake.y[1]--;
break;
}
}
gotoxy(snake.x[1], snake.y[1]);
printf("@");
check_eaten = 0;
gotoxy(frame_height, 0);
}
void check_foodeating()
{
if (snake.x[1] == food.x&&snake.y[1] == food.y)
{
score += 10;
check_eaten = 1;
gotoxy(12, frame_width + 3);
printf("Your score:%d", score);
snake.len++;
get_newfood();
}
}
bool check_snakealive()
{
//检查有没有撞到墙
if (snake.x[1] == 0 || snake.x[1] == frame_height - 1 || snake.y[1] == 0 || snake.y[1] == frame_width - 1)//撞墙
return 0;
//检查有没有吃到自己
for (int i = 2; i <= snake.len; i++)
if (snake.x[i] == snake.x[1] && snake.y[i] == snake.y[1])
return 0;
return 1;
}