c++实现贪吃蛇(含技术难点解析和完整代码)
⽂章⽬录
0.参考资料
1 技术难点
1.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);//定位光标的函数
}
1.2 关于蛇的移动
主要有两种实现⽅式,⼀种使⽤指针加链表,⼀种使⽤数组。笔者选择的是数组的⽅式,这种⽅法代码量略⼤,且较为丑陋,但是易于理解。每次操作后只需要清空蛇尾(如果吃到⾷物就不⽤),打印蛇头,以及将蛇⾝的坐标顺次移动。
1.2.1 从键盘上读取输⼊
⽤kbhit()和getch()函数
1.2.2 蛇的移动
需要注意的是如果此时蛇是向上移动的话,点击向下移动是⽆效的。所以需要将蛇的运动状态记录下来。⽽在写switch,case时注意要写default,即不进⾏操作时,保持原运动状态。
1.3 ⾷物的⽣成
⼀个简单的srand制造随机数就可以实现。需要注意的是,需要判断⾷物是否和当前蛇的位置重合,⽅法是暴⼒(枚举蛇的每⼀块)。可以写成⼀个函数来实现。
2.完整代码
#include<cstdio>
#include<iostream>
#include<ctime>
#include<stdlib.h>
#include<windows.h>
#include <conio.h>
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 move_snake();
void check_foodeating();
bool check_snakealive();
//需要⽤到的全局变量
int score;
Snake snake;
Food food;
bool check_eaten;
int main()
{
system("color 0B");
do
{
system("cls");
print_map();
score=0,check_eaten=0;
//贪吃蛇的每回合运⾏控制
while(1)
{
check_foodeating();//system("pause");
move_snake();
Sleep(max(50,300-score));//控制速度(与长度呈反⽐)
if(!check_snakealive())
break;
}
printf("Game Over!\n");
printf("1:Restart\t2:exit\n");
char com2;
cin>>com2;
if(com2=='2')
break;
}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);//因为这个标记是长度,从零开始所以最后要减1
printf("#");
}
for(int i=0;i<frame_width;i++)
{
gotoxy(0,i);
printf("#");
gotoxy(frame_height-1,i);
printf("#");
}
/
/蛇⾝初始化
snake.len=3;
snake.state='w';
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 jokersio");
}
bool check_foodinsnake()
{
for(int i=1;i<=snake.len;i++)
if(snake.x[i]==food.x&&snake.y[i]==food.y)
return1;
return0;
}
void get_newfood()
{
do{
srand(time(0));
food.x=rand()%(frame_height-2)+1;
food.y=rand()%(frame_width-2)+1;
}while(check_foodinsnake());
gotoxy(food.x,food.y);
cout<<"$";
}
void move_snake()
{
char com;
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.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();
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)//撞墙return0;
//检查有没有吃到⾃⼰
for(int i=2;i<=snake.len;i++)
if(snake.x[i]==snake.x[1]&&snake.y[i]==snake.y[1])
return0;
return1;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论