标题:[原创]C语言写的贪吃蛇
只看楼主
271391233
Rank: 1
等 级:新手上路
帖 子:174
专家分:0
注 册:2005-2-24
 问题点数:0 回复次数:4 
[原创]C语言写的贪吃蛇

/**********************************************************/

/* 本程序在Turbo C 2.0下编译通过 */

/* */

/* 文件名: snake.c */

/**********************************************************/

/**********************************************************/

/* 程序中用到的库函数所在头文件应用 #include 命令包含进来 */

#include<graphics.h>
#include<bios.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<dos.h>
#include<conio.h>
#include<ctype.h>

/**********************************************************/
/* 定义符号常量 */

#define len sizeof(struct snake)
#define Q (*que)
#define FILENAME "c:\\person.dat" /*文件保存路径*/

/**********************************************************/

/* 定义数据结构*/


/*蛇节点*/
struct snake_base
{
int x;
int y;
};

/*队列节点 */
struct snake
{
struct snake_base data;
struct snake *next;
};

/*队列 */
struct queue
{
struct snake *front,*rear;
};

/*排行榜结构*/
struct person
{
char name[20];
int score;
};

/**********************************************************/

/* 定义全局变量 */

struct person per[5];

/**********************************************************/


/************************************************************************************/

/*自定义函数原型说明 */

void inques(struct queue *que,int x,int y); /*入队函数*/
void creatque(struct queue Q,int m); /*创建队列*/
struct snake_base delete(struct queue *que); /*出队函数,返回值为一个蛇节点*/
void *picture(int type); /*绘制方块函数*/
void draw(int x,int y,void *p); /*从图形缓存中读出数据,并显示在屏幕上*/
int search(int x,int y,struct snake *tmpHead); /*判断蛇头是否与蛇身相遇函数*/
void creat_menu(); /*产生主界面*/
void ReadFiles(); /*从文件中读取记录信息*/
void WriteFiles(struct person *); /*将记录写入文件中*/
void InitScoreFiles(); /*初始化记录文件*/
void CompareScore(struct person ); /*排行榜按分数进行排序*/
void pain_board(); /*绘制排行榜函数*/
void pain_gameover(); /*绘制游戏结束时的图形*/
void HelpMessage();
/***********************************************************************************/

/**********************************************************/

/*主函数*/
void main()
{
int gm=VGAHI,gd=VGA;
int mark,level,m,key,hi,lo,h;
int s1,m1,i,j,k,xn,yn,flag,bl;
long time;
unsigned s2;
void *p1,*p2;
char ch,string[3];
struct person CurPerson;
struct queue *que;
struct snake *q;
struct snake_base x1;
struct time t[1];
do
{
flag=1;bl=0;que=NULL; /*下面两行为初始化游戏变量*/
time=30000;mark=0;level=1;m=0;
gettime(t);/*初始化随机数*/
s1=t[0].ti_sec;
m1=t[0].ti_min;
s2=s1*m1;
srand(s2);
initgraph(&gd,&gm,"");
p1=picture(1);
p2=picture(0);
creatque(que,3);
creat_menu();
itoa(mark,string,10);
setcolor(15);
outtextxy(545,30,string);
itoa(level,string,10);
outtextxy(545,50,string);
q=Q.front->next;
for(k=0;k<=2;k++) /*遍历队列,绘制初始状态的蛇身*/
{
draw(q->data.x,q->data.y,p1);
if(k==2)
{ /*队尾节点为蛇头,取出赋值给i,j*/
i=q->data.x;j=q->data.y;
}
q=q->next;
}
do
{
xn=((unsigned long)rand())%31+1; /*随即产生两个坐标,作为新节点*/
yn=((unsigned long)rand())%29+1;
}while(xn<1||xn>31||yn<1||yn>29||search(xn,yn,que->front));/*采用条件来约束随机点的范围*/
draw(xn,yn,p1);
lo=0;hi=72;h=72;
while(flag)
{
if(kbhit())
{ /*检查键盘事件*/
key=bioskey(0);
if(kbhit())
getch();
lo=key & 0x00ff;
if(lo==0)
hi=(key & 0xff00)>>8;
}
switch(hi)
{
case 72:if(h!=80) {h=72;j--;} else {hi=80;j++;} break;
case 80:if(h!=72) {h=80;j++;} else {hi=72;j--;} break;
case 75:if(h!=77) {h=75;i--;} else {hi=77;i++;} break;
case 77:if(h!=75) {h=77;i++;} else {hi=75;i--;} break;
}

if((xn==i)&&(yn==j))
{ /*蛇头与新节点相遇,蛇身变长,同时新节点入队*/
m++;
if(m==5)/*每吃5颗子,难度增加一级*/
{
level=level+1;
if(time>6000)time=time-2000;
itoa(level,string,10);
setfillstyle(1,1);
bar(545,50,575,60);
setcolor(15);
outtextxy(545,50,string);
m=0;
}
mark=mark+1;
itoa(mark,string,10);
setfillstyle(1,1);
bar(545,30,575,40);
setcolor(15);
outtextxy(545,30,string);
inques(que,xn,yn);
do
{
xn=((unsigned long)rand())%31+1;
yn=((unsigned long)rand())%29+1;
}while(xn<1||yn>29||xn>31||yn<1||search(xn,yn,que->front));
draw(xn,yn,p1);
}
else
{
if ((i<1)||(i>31)||(j<1)||(j>29)||search(i,j,que->front)) /*判断是否到达边界*/
{
if(bl==0)
flag=0; /*游戏结束标志*/
}
else
{ /*如果没有碰到新节点,则移动蛇身,实现方法: 绘制蛇头的下一状态的,并让下一状态的坐标
入队,同时,出队一个节点(要擦除的节点坐标),用擦除图形擦除该坐标的蛇身*/
inques(que,i,j);
draw(i,j,p1);
x1=delete(que);
draw(x1.x,x1.y,p2);
}
}
delay(time); /*延时*/
bl=0;
}

ReadFiles();/*从文件中读取记录信息*/

setfillstyle(1,9);
bar(14,14,447,419);
pain_gameover();

if(mark>=per[4].score)/*比较当前玩家分数和最低记录分数,如满足条件,则将玩家分数写入记录中*/
{
outtextxy(50,250,"Congratulations! Your Score Enter the Board!");
outtextxy(50,270,"please enter your name:");
gotoxy(7,19);printf(" ");
gotoxy(7,19);scanf("%s",CurPerson.name);
CurPerson.score=mark;
CompareScore(CurPerson);
WriteFiles(per);
pain_board();
}

outtextxy(50,320,"Do you want to restart the game Now? [y/n]");/*提示信息*/
while(1)
{
ch=getch();
if(ch==’y’||ch==’Y’||ch==’n’||ch==’N’)break;
}
}while(ch==’y’||ch==’Y’);/*整个游戏的循环,用于控制重复进行游戏*/
closegraph();
}
/**********************************************************/

/*入队函数*/
void inques(struct queue *que,int x,int y)
{
struct snake *s;
s=(struct snake *)malloc(len);
s->data.x=x;s->data.y=y;s->next=NULL;
que->rear->next=s;que->rear=s;
}

/*创建队列*/
void creatque(struct queue Q,int m)
{
int i,y,x;
struct snake *h;
h=(struct snake *)malloc(len);
h->next=NULL;
Q.front=h;Q.rear=h;
for(i=0;i<m;i++) /*往队列中插入3个初始状态的节点*/
{
y=25+2-i;
inques(que,20,y);

}
}

/*出队函数,返回值为一个蛇节点*/
struct snake_base delete(struct queue *que)
{
struct snake_base x;
struct snake *p;
p=Q.front->next;Q.front->next=p->next;
x=p->data;free(p);
return(x);
}

/*绘制方块函数*/

void *picture(int type)
{
void *p;
int size;
if(type)
{
/*绘制蛇身和节点方块*/
setfillstyle(1,2);
bar(0,0,12,12);
rectangle(1,1,11,11);
rectangle(3,3,9,9);
rectangle(5,5,7,7);
}
else
{ /*绘制擦除方块*/
setfillstyle(1,9);
bar(0,0,12,12);
}
size=imagesize(0,0,12,12); /*创建图形缓存*/
p=malloc(size);
getimage(0,0,12,12,p); /*读入图片到缓存中*/
cleardevice();
return(p);
}

/*从图形缓存中读出数据,并显示在屏幕上*/
void draw(int x,int y,void *p)
{
putimage(x*14,y*14,p,0);
}

/*判断蛇头是否与蛇身相遇函数*/
int search(int x,int y,struct snake *tmpHead)
{
int k;
tmpHead=tmpHead->next; /*跳过蛇头节点*/
while(tmpHead!=NULL)
{ /*判断是否与蛇身节点有相同坐标,若有,则相碰*/
if ((tmpHead->data.x==x) && (tmpHead->data.y==y))
return(1);
else
{
tmpHead=tmpHead->next;
}
}
return(0);
}

/*绘制游戏主界面*/
void creat_menu()
{
int i;
setbkcolor(1);
setfillstyle(1,9);
bar(12,12,449,421);
setfillstyle(1,2);
setcolor(8);
rectangle(13,13,449,421);
setcolor(15);
rectangle(12,12,448,420);
setfillstyle(1,7);
bar(0,0,640,8);
setcolor(1);
setlinestyle(4,0x8888,1); /* 1000100010001000设置线*/
for(i=1;i<29;i++)/*画横线*/
line(14,13+i*14,446,13+i*14);
for(i=1;i<31;i++)/*画坚线*/
line(13+i*14,14,13+i*14,418);
setlinestyle(SOLID_LINE,1,1);
setcolor(8);
HelpMessage();
setcolor(15);
outtext(" snake--version 1.02 ");
outtextxy(480,30,"score:");
outtextxy(480,50,"level:" );
pain_board();
}

/*绘制游戏结束时的一些图形*/
void pain_gameover()
{
setfillstyle(1,6);
bar(180,130,320,190);
setfillstyle(1,15);
setcolor(15);
rectangle(181,131,319,189);
rectangle(195,145,305,175);
rectangle(193,143,307,177);
outtextxy(213,158,"GAME OVER");
}

/*绘制排行榜,可以合并到creat_menu()函数中去*/
void pain_board()
{
int i;
char string[10];
ReadFiles();
setfillstyle(1,9);
bar(482,227,599,239);
outtextxy(490,230,"Highest board");
setcolor(15);
rectangle(480,225,600,240);
setcolor(8);
rectangle(481,226,601,241);
setfillstyle(1,7);
bar(475,257,610,426);
setcolor(15);
line(475,257,610,257);line(475,257,475,426);
setcolor(8);
line(475,426,610,426);line(610,257,610,426);
setcolor(1);
outtextxy(480,265,"name score");
for(i=0;i<5;i++)
{
setcolor(4);
outtextxy(480,290+i*30,per[i].name);
itoa(per[i].score,string,10);
setcolor(14);
outtextxy(580,290+i*30,string);
setcolor(8);
line(476,280+i*30,609,280+i*30);
setcolor(15);
line(476,281+i*30,609,281+i*30);
}
}

/*读取文件操作函数*/
void ReadFiles()
{
FILE *fpread;
if((fpread=fopen(FILENAME,"ab+"))==NULL) /*如果文件不存在,则创建一个空文件,否则则打开该文件*/
{
printf("can’t open the file person.dat!");exit(0);
}
if(fgetc(fpread)==EOF)InitScoreFiles();/*如果文件内容为空,则进行记录初始化工作*/
rewind(fpread);/*重新复位文件指针*/
fread(per,sizeof(struct person),5,fpread);
fclose(fpread);
}

/*文件写入操作函数*/
void WriteFiles(struct person *tmp)
{
FILE *fpwrite;
if((fpwrite=fopen(FILENAME,"wb+"))==NULL)/*以读写方式打开文件,文件内原有的数据将被清空*/
{
printf("can’t open the file person.dat!");exit(0);
}
fwrite(tmp,sizeof(struct person),5,fpwrite);
fclose(fpwrite);
}

/*初始化记录函数,默认的分数值和名字可以自行更改*/
void InitScoreFiles()
{
int i;
struct person a[5];
for(i=0;i<5;i++)
{
a[i].score=50-i*10;
strcpy(a[i].name,"CaiHaiBo");
}
WriteFiles(a);
}

/*排序算法,如果玩家分数超过最低记录,则将玩家分数插入到合适的位置,同时删除原先的最低记录*/
void CompareScore(struct person des)
{
int i,j;
for(i=0;i<5;i++)
{
if(des.score>=per[i].score)
{
if(i<5)
{
for(j=4;j>=i+1;j--)
{
per[j]=per[j-1];
}
}
per[i]=des;
break;
}
}
}

void HelpMessage() /*显示帮助信息*/
{ char *Help[]={"Right:Move Right","Left:Move Left","Down:Move Down","Up:Move Up"};
int i;
setcolor(11);
for(i=0;i<4;i++)
outtextxy(480,100+i*20,Help[i]);
setcolor(15);
outtextxy(30,450,"CopyRight(c) Reserved By Jiaming.Hu Work Room Address:hjiaming@sina.net");
}
红色的地方有好多地方不知道
不知道有谁能帮我解释一下
搜索更多相关主题的帖子: C语言 贪吃 include gra 
2005-11-28 03:15
编写蓝图
Rank: 1
等 级:新手上路
帖 子:59
专家分:0
注 册:2005-11-28
得分:0 

是不是很难学啊?我也想学,那位哥哥帮帮忙。


2005-11-28 10:35
ctryone
Rank: 1
等 级:新手上路
帖 子:9
专家分:0
注 册:2005-11-28
得分:0 
你能将此题的每一步的功能说一下吗?以便我们能更好的学习,现在就自己看不容易看懂。谢谢
2005-11-28 11:39
君子
Rank: 1
等 级:新手上路
帖 子:16
专家分:0
注 册:2005-11-23
得分:0 
晕...
运行怎么好多错啊...

在计算机门外徘徊着.......
2005-11-28 17:09
kissyoufu
Rank: 1
等 级:新手上路
帖 子:32
专家分:0
注 册:2005-12-1
得分:0 
要是解说够多就好了
2005-12-01 11:34



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-35454-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.053496 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved