记录高级程序语言课的项目1:简单贪吃蛇小游戏(环境是Dev-C++)
第一次的小记录*~*加油
基本功能
本项目的主要功能为实现贪吃蛇小游戏,首先进行利用光标的定位来进行一系列的数据初始化,然后利用键盘上的按键来控制小蛇的移动,在此过程中,小蛇吃到食物后身体会变长,当它在移动的过程中撞到游戏边界或者咬到自己就结束游戏,并且得到一个食物就会积累相应得分。
具体模块
1、数据初始化模块
2、光标定位模块
3、移动模块
4、移动方向判定模块
具体实现代源码
/********************************************************************************
* @File name: main.c
* @Description: 此程序文件完成的是贪吃蛇小游戏,将设计出初始长度很短的小蛇,蛇头
碰到随机生成的食物就会变长,并且在此过程中,小蛇碰到游戏界面或者
碰到自己都标志着结束,吃到一个食物相应加10分,并统计最终总得分
* @ Function List: void Pos();//设置光标位置
void creatInterface();//创建游戏界面
void InitializeSnake();//初始化蛇的身体
int bite_itself(); //判断是否咬到自己
void createfood();//创建食物
void cantcrosswall();//撞墙
void snakemove();//蛇移动
void pause();//暂停游戏
void gamecircle();//游戏运行
void welcometogame();//欢迎来到游戏的显示界面
void endgame();//游戏结束
void gamestart();//游戏开始
* @Author:千阴
* @Version: 1.1
* @Date: 2019-12-07
********************************************************************************/
#include<stdio.h>
#include<time.h>
#include<windows.h>
#include<stdlib.h>
#define U 1
#define D 2
#define L 3
#define R 4 //蛇的状态,U:上 ;D:下;L:左 R:右
/* 表示蛇身上的小点* */
typedef struct SNAKE
{
int x;/*横坐标*/
int y;/*纵坐标*/
struct SNAKE *next;/*下一个蛇身子的节点指针*/
}snake;
//全局变量//
int score=0,add=10;/* 总得分与每次吃食物得分 */
int status;/* 按键数字的存放 */
int sleeptime=200;/* 每次运行的时间间隔 */
snake *head, *food;/*蛇头指针,食物指针*/
snake *q;/* 蛇的结构体指针 */
int endgamestatus=0; /*游戏结束的情况,1:撞到墙;2:咬到自己;*/
//声明全部函数//
void Pos();//设置光标位置
void creatInterface();//创建游戏界面
void InitializeSnake();//初始化蛇的身体
int bite_itself(); //判断是否咬到自己
void createfood();//创建食物
void cantcrosswall();//撞墙
void snakemove();//蛇移动
void pause();//暂停
void gamecircle();//运行
void welcometogame();//欢迎界面
void endgame();//结束游戏
void gamestart();//开始游戏
void Pos(int x,int y)
{
COORD pos;//pos是结构体类型变量
HANDLE hOutput;//新建的光标句柄
pos.X=x;
pos.Y=y;
hOutput=GetStdHandle(STD_OUTPUT_HANDLE);//句柄的实例化
SetConsoleCursorPosition(hOutput,pos);//SetConsoleCursorPosition是API中定位光标的函数
}
void creatInterface()
{
int i;
for(i=0;i<58;i+=2)//打印上下边框
{
Pos(i,0);
printf("-");//上边框
Pos(i,26);
printf("-");//下边框
}
for(i=1;i<26;i++)//打印左右边框
{
Pos(0,i);
printf("-");//左边框
Pos(56,i);
printf("-");//右边框
}
}
void InitializeSnake()
{
snake *tail;
int i;
tail=(snake*)malloc(sizeof(snake));//从蛇尾开始,头插法,用x,y设定开始的位置
tail->x=24;
tail->y=5;
tail->next=NULL;
for(i=1;i<=4;i++)
{
head=(snake*)malloc(sizeof(snake));
head->next=tail;
head->x=24+2*i;
head->y=5;
tail=head;
}
while(tail!=NULL)//从头到尾,输出蛇身
{
Pos(tail->x,tail->y);
printf("*");
tail=tail->next;
}
}
int bite_itself()
{
snake *self;
self=head->next;
while(self!=NULL)
{
if(self->x==head->x && self->y==head->y)//头的坐标和其他身子的坐标重合
{
return 1;//咬到
}
self=self->next;
}
return 0;//没有咬到
}
void createfood()//随机出现食物
{
snake *food_1;
srand((unsigned)time(NULL));
food_1=(snake*)malloc(sizeof(snake));
do //保证其为偶数,使得食物能与蛇头对齐
{
food_1->x=rand()%52+2;//随机生成食物的横坐标
}while((food_1->x%2)!=0);
food_1->y=rand()%24+1;//随机生成食物的纵坐标
q=head;
while(q->next != NULL)
{
if(q->x==food_1->x && q->y==food_1->y) //判断蛇身是否与食物重合
{
free(food_1);
food_1 = NULL;
createfood();
break;
}
q=q->next;
}
if (food_1 != NULL)//食物要是不存在,就随机生成食物
{
Pos(food_1->x,food_1->y);
food=food_1;
printf("¥");
}
}
void cantcrosswall()
{
if(head->x==0 || head->x==56 ||head->y==0 || head->y==26)//蛇头的横坐标纵坐标撞到了边界,就把endgamestatus设置为情况1
{
endgamestatus=1;//1,表示穿墙
endgame();
}
}
void snakemove()//蛇前进,上 U,下 D,左 L,右 R
{
snake *nexthead;
cantcrosswall();//首先蛇不可以撞墙
nexthead=(snake*)malloc(sizeof(snake));//动态分配内存空间
if(status==U)//向上方向键
{
nexthead->x=head->x;//横坐标不变,纵坐标减一
nexthead->y=head->y-1;
if(nexthead->x==food->x && nexthead->y==food->y)//如果下一个有食物//
{
nexthead->next=head;
head=nexthead;
q=head;
while(q!=NULL)
{
Pos(q->x,q->y);
printf("*");
q=q->next;
}
score=score+add;//计算新得分
createfood();//吃完食物后生成食物
}
else //如果下一个位置没有食物
{
nexthead->next=head;
head=nexthead;
q=head;
while(q->next->next!=NULL)
{
Pos(q->x,q->y);
printf("*");
q=q->next;
}
Pos(q->next->x,q->next->y);
printf(" ");
free(q->next);
q->next=NULL;
}
}
if(status==D)//向下移动
{
nexthead->x=head->x;//横坐标不变,纵坐标加一
nexthead->y=head->y+1;
if(nexthead->x==food->x && nexthead->y==food->y) //下一个节点有食物
{
nexthead->next=head;
head=nexthead;
q=head;
while(q!=NULL)
{
Pos(q->x,q->y);
printf("*");
q=q->next;
}
score=score+add;
createfood();
}
else //下一节点没有食物
{
nexthead->next=head;
head=nexthead;
q=head;
while(q->next->next!=NULL)
{
Pos(q->x,q->y);
printf("*");
q=q->next;
}
Pos(q->next->x,q->next->y);
printf(" ");
free(q->next);
q->next=NULL;
}
}
if(status==L)//向左移动
{
nexthead->x=head->x-2;//横坐标减2,纵坐标不变
nexthead->y=head->y;
if(nexthead->x==food->x && nexthead->y==food->y)//下一节点有食物
{
nexthead->next=head;
head=nexthead;
q=head;
while(q!=NULL)
{
Pos(q->x,q->y);
printf("*");
q=q->next;
}
score=score+add;
createfood();
}
else //下一节点没有食物
{
nexthead->next=head;
head=nexthead;
q=head;
while(q->next->next!=NULL)
{
Pos(q->x,q->y);
printf("*");
q=q->next;
}
Pos(q->next->x,q->next->y);
printf(" ");
free(q->next);
q->next=NULL;
}
}
if(status==R)//向右移动
{
nexthead->x=head->x+2;//横坐标加2,纵坐标不变
nexthead->y=head->y;
if(nexthead->x==food->x && nexthead->y==food->y)//下一节点有食物
{
nexthead->next=head;
head=nexthead;
q=head;
while(q!=NULL)
{
Pos(q->x,q->y);
printf("*");
q=q->next;
}
score=score+add;
createfood();
}
else //下一个节点没有食物
{
nexthead->next=head;
head=nexthead;
q=head;
while(q->next->next!=NULL)
{
Pos(q->x,q->y);
printf("*");
q=q->next;
}
Pos(q->next->x,q->next->y);
printf(" ");
free(q->next);
q->next=NULL;
}
}
if(bite_itself()==1) //判断是否会咬到自己
{
endgamestatus=2;
endgame();//咬到自己就会结束游戏
}
}
void pause()//游戏暂停
{
while(1)
{
Sleep(300);//延迟300ms
}
}
void gamecircle()//控制游戏
{
Pos(64,15);
printf("不能穿墙,不能咬到自己");
Pos(64,16);
printf("用上下左右键控制蛇的移动");
Pos(64,17);
printf("ESC:退出游戏。");
while(1)
{
Pos(64,10);
printf("得分:%d",score);
Pos(64,11);
printf("每个食物的得分:%d",add);
if(GetAsyncKeyState(VK_UP)&& status!=D)
{
status=U;//对应下一个按键状态
}
else if(GetAsyncKeyState(VK_DOWN)&&status!=U)
{
status=D;
}
else if(GetAsyncKeyState(VK_LEFT)&&status!=R)
{
status=L;
}
else if(GetAsyncKeyState(VK_RIGHT)&&status!=L)
{
status=R;
}
Sleep(sleeptime);//休息一段时间
snakemove();
}
}
void welcometogame()
{
Pos(20,12);
printf("欢迎来到贪吃蛇小游戏\n");
system("pause");//利用系统函数冻结屏幕
system("cls");//利用系统函数清屏,实现动态刷新
}
void endgame()//结束游戏
{
system("cls");
Pos(24,12);
if(endgamestatus==1)
{
printf("你撞到墙壁了,游戏结束!\n");
}
else if(endgamestatus==2)
{
printf("你咬到自己了,游戏结束!");
}
Pos(24,13);
printf("您的分数是%d\n",score);
// exit(0);
}
void gamestart()
{
system("mode con cols=100 lines=30"); //将界面的大小设置为100列和30行 ,要是默认的话会有溢出
welcometogame();
creatInterface();
InitializeSnake();
createfood();
}
int main()
{
gamestart();//开始
gamecircle();//运转
endgame();//结束
return 0;
}
总结及改进
(一)项目中存在的不足之处:
1、界面简单,不美观,观赏度低;
2、可操作性低,如果要改变蛇移动的速度,还需要调整相应的代码来修改,比较麻烦;
3、使用系统中的API函数来刷新界面,在Dev-C++中有时候会出现卡顿的现象,但是已经做出了相应的调整和改进,基本没有问题出现;
4、游戏的功能设计的比较少,体验感不强。
(二)进一步的改进方向:
1、为界面增添颜色,使界面更加美观。(VC++6.0中)
这里可以使用System函数(System(“color 4A”);)来实现,4是背景色,A代表前景色
其他补充的颜色代码使用:
0=黑色; 1=蓝色;2=绿色;3=湖蓝色; 4=红色; 5=紫色; 6=黄色; 7=白色;8=灰色;
9=淡蓝色;
A=浅绿色;B=淡浅绿色;C=淡红色;D=淡紫色;E=淡黄色;F=亮白色;
同时也可以在控制台设置局部的字体和颜色:SetConsoleTextAttribute(句柄,颜色)
wAttribute是用来设置颜色的参数
setbkcolor()//设置背景的颜色
setcolor()//设置前景颜色
moveto()//移动到指定坐标
PS:这里可以到EasyX的官网上下载图形库,就可以在VC++6.0的环境下绘制图形,修改颜色,这个小模块我比较感兴趣,所以可以寒假有时间再总结一下。
2、增加游戏的其他功能,例如设置其他按键功能可以使蛇的速度加快或者减慢,还可以设计按键使游戏暂停,还可以赋予小蛇生命值,来增强游戏的体验感。
(三)开发心得:
在制作这个项目中接触到了特殊的数据类型——结构体数据类型,并且在此过程中大量使用了指针,我觉得这很具有灵活性,利用指针的不同指向来增加蛇的节点,使蛇可以在设计的界面上移动,并且涉及到了动态分配内存空间的问题,以及很多的系统API的函数的使用,比如光标的定位,还有System函数的常用指令,利用它可以实现清屏操作和刷新屏幕界面,在此过程中学习到了很多以前没有接触的东西,也改变了原有的思维模式,使我受益匪浅。
来源:CSDN
作者:♚yb♥℡
链接:https://blog.csdn.net/qq_45611259/article/details/103751307