学习C语言也差不多学完了想做一个游戏,而贪吃蛇和俄罗斯方块都是非常经典的游戏,在网上也找到了许多相关的参考资料,便动手做了,这个游戏室控制台版的
游戏流程图
函数模块
函数名 | 函数功能 |
CursorPosition | 光标定位函数 |
CreateSnake | 蛇初始化函数 |
ShowWall | 显示墙体 |
UpdateSnake | 更新界面上的蛇体、分数、等级、食物 |
CollisionDetection | 判断蛇是否咬到自己 |
RandFood | 随机产生食物 |
Move | 控制方向 |
程序代码
#include <stdio.h>
#include<windows.h>
#include<conio.h>
#include<time.h>
#define CWALL printf("■")//代替墙体符号
#define CSNAKE1 printf("●")//代替蛇头符号
#define CSNAKE printf("○")//代替蛇身符号
#define CFOOD printf("◇")//代替食物符号
//蛇结构
struct Snake
{
int x,y;//坐标
Snake *next;//蛇身体(结点)
};
//全局变量
int Food;
int Food_x;//食物坐标X
int Food_y;//食物坐标Y
int Direction;//方向变量(1:上 2:左 3:下 4:右)
int Grade;//等级(速度)
int Score;//得分
//蛇头节点
Snake* snake1 =(Snake*)malloc(sizeof(Snake));
//光标坐标定位函数
void CursorPosition(int x,int y)
{
COORD pos;//坐标结构
pos.X = x-1;//x坐标
pos.Y = y-1;//y坐标
//得到控制台的输出句柄
HANDLE Out = GetStdHandle(STD_OUTPUT_HANDLE);
//将坐标设置成光标的坐标
SetConsoleCursorPosition(Out,pos);
}
//蛇初始化创建函数
void CreatSnake()
{
//蛇身体结点
Snake* snake2= (Snake*)malloc(sizeof(Snake));
//蛇头的坐标
snake1->x=13;
snake1->y=5;
//蛇身体的坐标
snake2->x=11;
snake2->y=5;
//将蛇身体接到蛇头后
snake1->next=snake2;
//清空蛇身体的指针域
snake2->next=NULL;
}
//显示墙体
void ShowWall()
{
int i;
//列墙体
for(i=2;i<=24;++i)
{
CursorPosition(1,i);
CWALL;
CursorPosition(61,i);
CWALL;
CursorPosition(79,i);
CWALL;
}
//行墙体
for(i=1;i<=80;i+=2)
{
CursorPosition(i,1);
CWALL;
CursorPosition(i,24);
CWALL;
}
}
//更新界面上的蛇体、分数、等级、食物
void UpdateSneak()
{
Snake *p;
p=snake1;
CursorPosition(p->x,p->y);//将光标移到蛇头上
CSNAKE1;//打印蛇头
p=p->next;
while(p!=NULL)
{
CursorPosition(p->x,p->y);//将光标移到蛇身体的位置上
CSNAKE;//显示蛇身体
p=p->next;
}
CursorPosition(Food_x,Food_y);//将光标移到食物的位置上
CFOOD;//显示食物
CursorPosition(67,16);//将光标移到显示分数的位置上
printf("得分: %d\n",Score);//显示分数
CursorPosition(67,19);//将光标移到显示游戏等级的位置上
printf("等级: %d\n",Grade);//显示游戏等级
}
//判断蛇是否碰到墙或者咬到自己
int CollisionDetection()
{
Snake *p;
p=snake1->next;
//通过蛇头的横坐标和纵坐标判断蛇是否碰到墙
if(snake1->x==1||snake1->x==61||snake1->y==1 || snake1->y==24)
{
return 1;
}
//通过蛇头的坐标和蛇身体的坐标判断蛇是否咬到自己
while(!(p->x == snake1->x && p->y == snake1->y))
{
if(p->next==NULL)
{
return 0;
}
p=p->next;
}
return 1;
}
//随即产生食物
void RandFood()
{
if(Food==0)
{
//随机种子(用于生成变化的随机数)
srand((int)time(0));
//通过食物的横坐标使得食物在游戏区域内
Food_y = rand() % 20 + 3;
//通过食物的纵坐标使得食物在游戏区域内
int temp = rand() % 56 + 3;
if(temp % 2 == 0)//当食物的纵坐标为0时
{
Food_x = temp + 1;//纵坐标加1
}
else
{
Food_x = temp;
}
Food=1;
}
}
//移动控制
void Move();
//游戏流程
void Game()
{
while(1)
{
//当蛇咬到自己或者撞到墙
if(1 == CollisionDetection())
{
return;//退出循环
}
//当按键盘上的上时
if(GetAsyncKeyState(VK_UP) && Direction!=3)
{
Direction=1;
goto start;
}
//当按键盘上的左时
if(GetAsyncKeyState(VK_LEFT) && Direction!=4)
{
Direction=2;
goto start;
}
//当按键盘上的下时
if(GetAsyncKeyState(VK_DOWN) && Direction!=1)
{
Direction=3;
goto start;
}
//当按键盘上的右时
if(GetAsyncKeyState(VK_RIGHT) && Direction!=2)
{
Direction=4;
goto start;
}
start:
RandFood();//随机生成食物
Move();//移动贪吃蛇
UpdateSneak();//更新游戏中的数据
Sleep(330-Grade*30);//控制贪吃蛇移到的速度
}
}
//----------------------------------------------------------------------------
void main()
{
while(1)
{
Score=0;
Grade=0;
Direction=4;
system("cls");
CursorPosition(30,12);
printf("输入游戏等级:[1-10]\n");
CursorPosition(38,14);
printf("__\b\b");
scanf("%d",&Grade);
while(Grade<1 || Grade>10)
{
system("cls");
CursorPosition(30,12);
printf("输入游戏等级:[1-10]\n");
CursorPosition(38,14);
printf("__\b\b");
scanf("%d",&Grade);
}
system("cls");
ShowWall();//显示墙体
CreatSnake();//创建一条贪吃蛇
UpdateSneak();//更新游戏中的数据
Game();
system("cls");
CursorPosition(29,12);
printf("你输了! 得 %d 分\n",Score);
CursorPosition(29,14);
printf("按任意键继续/退出(q)\n");
if(getch()=='q')
{
exit(1);
}
else
{
continue;
}
}
}
//-----------------------------------------------------------------------------
void Move()
{
Snake* q;
//定义一个临时结点
Snake* temp = (Snake*)malloc(sizeof(Snake));
if(1 == Direction)//向上移动
{
//当蛇头碰倒食物时
if((snake1->x == Food_x) && (snake1->y ==Food_y+1))
{
//将临时结点的坐标变为食物坐标
temp->x=Food_x;
temp->y=Food_y;
//将蛇头挂到临时结点的后面
temp->next=snake1;
//临时结点变成头结点(临时结点变成蛇头)
snake1=temp;
Food=0;//标志位,标志食物被蛇吃了
//计算分数,分数分数的增加数为游戏的等级数
Score+=(1*Grade);
}
else
{
//要移动的方向向上(Windows中的坐标左上角为坐标原点,没有负数)
temp->x = snake1->x;
temp->y = snake1->y-1;
//将蛇头接到新蛇头后面
temp->next=snake1;
//body1表示蛇头
snake1=temp;
//遍历结点到蛇尾
q=snake1;
while((q->next)->next !=NULL)
{
q=q->next;
}
//将光标移到蛇尾
CursorPosition((q->next)->x,(q->next)->y);
printf(" ");
//去掉蛇尾,并且释放蛇尾结点的内存
free(q->next);
q->next=NULL;
}
}
if(Direction==2)//向左移动
{
//当蛇头碰倒食物时
if((snake1->x == Food_x+2) && (snake1->y == Food_y))
{
//将临时结点的坐标变为食物坐标
temp->x=Food_x;
temp->y=Food_y;
//将蛇头挂到临时结点的后面
temp->next=snake1;
//临时结点变成头结点(临时结点变成蛇头)
snake1=temp;
Food=0;//标志位,标志食物被蛇吃了
//计算分数,分数分数的增加数为游戏的等级数
Score+=(1*Grade);
}
else
{
temp->x=snake1->x-2;
temp->y=snake1->y;
temp->next=snake1;
snake1=temp;
//遍历结点到尾结点
q=snake1;
while((q->next)->next!=NULL)
{
q=q->next;
}
//将光标移到蛇尾
CursorPosition((q->next)->x,(q->next)->y);
printf(" ");
//去掉蛇尾,并且释放蛇尾结点的内存
free(q->next);
q->next=NULL;
}
}
if(Direction==3)//向下移动
{
//当蛇头碰倒食物时
if((snake1->x == Food_x) && (snake1->y == Food_y-1))
{
//将临时结点的坐标变为食物坐标
temp->x=Food_x;
temp->y=Food_y;
//将蛇头挂到临时结点的后面
temp->next=snake1;
//临时结点变成头结点(临时结点变成蛇头)
snake1=temp;
Food=0;//标志位,标志食物被蛇吃了
//计算分数,分数分数的增加数为游戏的等级数
Score+=(1*Grade);
}
else
{
//要移动的方向向下(Windows中的坐标左上角为坐标原点,没有负数)
temp->x=snake1->x;
temp->y=snake1->y+1;
//将蛇头接到新蛇头后面
temp->next=snake1;
//body1表示蛇头
snake1=temp;
//遍历结点到尾结点
q=snake1;
while((q->next)->next!=NULL)
{
q=q->next;
}
//将光标移到蛇尾
CursorPosition((q->next)->x,(q->next)->y);
printf(" ");
//去掉蛇尾,并且释放蛇尾结点的内存
free(q->next);
q->next=NULL;
}
}
if(Direction==4)//向右移动
{
//当蛇头碰倒食物时
if((snake1->x == Food_x-2) && (snake1->y == Food_y))
{
//将临时结点的坐标变为食物坐标
temp->x=Food_x;
temp->y=Food_y;
//将蛇头挂到临时结点的后面
temp->next=snake1;
//临时结点变成头结点(临时结点变成蛇头)
snake1=temp;
Food=0;//标志位,标志食物被蛇吃了
//计算分数,分数分数的增加数为游戏的等级数
Score+=(1*Grade);
}
else
{
temp->x=snake1->x+2;
temp->y=snake1->y;
temp->next=snake1;
snake1=temp;
//遍历结点到蛇尾
q=snake1;
while((q->next)->next!=NULL)
{
q=q->next;
}
//将光标移到蛇尾
CursorPosition((q->next)->x,(q->next)->y);
printf(" ");
//去掉蛇尾,并且释放蛇尾结点的内存
free(q->next);
q->next=NULL;
}
}
}
执行结果: