1 #include <graphics.h>
2 #include <string.h>
3 #include <time.h>
4 #define NUM_R 10 //半径
5 #define NUM_X 25 //横向个数
6 #define NUM_Y 25 //纵向个数
7 #define NUM 30 //所需节点个数
8 void exe(int x,int y,int f);
9 int GetCommand();
10 void eat(int x,int y);
11 void clear();
12 void set();
13 void flush();
14 void over(bool a);
15
16 struct pos //建立链表储存每个关节的位置
17 {
18 int x;
19 int y;
20 struct pos*next;
21 };
22 struct pos*head=(pos*)malloc(sizeof(pos)); //建立头指针
23 int n=0; //记录节点个数
24
25 void main() //初始化游戏
26 {
27 int x,y,f; //储存初始化点的位置方向
28 srand((unsigned) time(NULL)); //初始化随机库
29 do
30 {
31 x=rand()%NUM_X*NUM_R*2+NUM_R;
32 y=rand()%NUM_Y*NUM_R*2+NUM_R;
33 } while(x<4*NUM_R || y<4*NUM_R || 2*NUM_R*(NUM_X-2)<x || 2*NUM_R*(NUM_Y-2)<y); //产生不在矩形边缘的初始点
34 f=rand()%4; //随机方向
35 struct pos*a=(pos*)malloc(sizeof(pos)),*p=head; //建立链表第一个节点
36 a->x=x; //指针a储存第一个点数据
37 a->y=y;
38 head->next=a; //接链
39 a->next=NULL; //结尾
40 initgraph(2*NUM_R*NUM_X,2*NUM_R*NUM_Y+50); //初始绘图窗口
41 setcolor(WHITE);
42 line(0,2*NUM_R*NUM_Y+1,2*NUM_R*NUM_X,2*NUM_R*NUM_Y+1);
43 setcolor(getbkcolor()); //取消圆的边缘
44 setfillcolor(YELLOW); //设置填充颜色
45 fillcircle(x,y,NUM_R); //绘出初始点
46 set(); //产生食物
47 exe(x,y,f); //进入控制函数
48 }
49
50 void exe(int x,int y,int f) //操作游戏
51 {
52 int xf,yf,c,i;
53 while(1) //进入循环
54 {
55 c=0; //初始化方向
56 for(i=0;i<5;i++) //循环5次获取命令
57 {
58 Sleep(100-50*n/NUM); //等待
59 if(c==0) //若没获取到命令就进行获取
60 {
61 c=GetCommand();
62 if(c==4) //返回4时退出循环等待
63 break;
64 }
65 }
66 f=f+c; //改变方向
67 if(f>3) //溢出处理
68 f=f-4;
69 xf=yf=0; //初始化方向参数
70 switch(f)
71 {
72 case 0:xf=1;break; //方向向右时 x坐标增加
73 case 1:yf=1;break; //方向向上时 y坐标增加
74 case 2:xf=-1;break; //方向向左时 x坐标减少
75 case 3:yf=-1;break; //方向向下时 y坐标减少
76 }
77 x=x+2*NUM_R*xf; //x坐标变化
78 y=y+2*NUM_R*yf; //y坐标变化
79 if(getpixel(x,y)==RED || x<0 || y<0 || 2*NUM_X*NUM_R<x || 2*NUM_Y*NUM_R<y) //判断是否遇到自身或碰到边界
80 over(0); //结束游戏
81 else //不结束进行下步运算
82 {
83 if(getpixel(x,y)==GREEN) //判断前方是否为食物
84 set(); //产生新食物
85 else
86 clear(); //清除尾结点
87 eat(x,y); //在前方生成新结点
88 if(n>NUM-1) //判断胜利条件
89 over(1); //结束游戏
90 }
91 }
92 }
93
94 int GetCommand() //获取方向
95 {
96 int c=0; //初始化方向变量
97 if(GetAsyncKeyState(VK_RIGHT) & 0x8000) c = 1; //右转为1
98 if(GetAsyncKeyState(VK_LEFT) & 0x8000) c = 3; //左转为3
99 if(GetAsyncKeyState(VK_UP) & 0x8000) c = 4; //按上为4 快进
100 if(GetAsyncKeyState(VK_DOWN) & 0x8000) system("pause"); //按下则暂停
101 return c;
102 }
103
104 void eat(int x,int y) //增加新结点
105 {
106 struct pos*a=(pos*)malloc(sizeof(pos)),*p=head; //声明指针变量
107 while(p->next!=NULL) //寻找链表尾节点
108 p=p->next;
109 a->x=x; //把数据储存到结点
110 a->y=y;
111 p->next=a; //指针a接到尾节点后
112 a->next=NULL; //结尾
113 setcolor(getbkcolor()); //取消圆的边缘
114 setfillcolor(RED); //设置填充颜色
115 fillcircle(p->x,p->y,NUM_R); //绘制新结点
116 setfillcolor(YELLOW); //设置填充颜色
117 fillcircle(x,y,NUM_R); //绘制新结点
118 }
119
120 void clear() //清除尾结点
121 {
122 setcolor(getbkcolor()); //取消圆的边缘
123 setfillcolor(getbkcolor()); //设置填充颜色
124 fillcircle(head->next->x,head->next->y,NUM_R); //擦除结点
125 head->next=head->next->next; //删除节点数据
126 }
127
128 void set() //产生食物和胜利判断
129 {
130 flush();
131 int x,y; //声明变量
132 do
133 {
134 x=rand()%NUM_X*NUM_R*2+NUM_R;
135 y=rand()%NUM_Y*NUM_R*2+NUM_R;
136 } while (getpixel(x,y)==RED); //随机产生食物在非蛇的位置
137 setcolor(getbkcolor());
138 setfillcolor(GREEN); //设置填充颜色
139 fillcircle(x,y,NUM_R); //产生食物
140 }
141
142 void flush()
143 {
144 n++; //节点计数累加
145 char strnum[20],string[10]="进度:";
146 itoa(n,strnum,10); //转换
147 strcat(string,strnum); //链接
148 strcpy(strnum,"/"); //赋值
149 strcat(string,strnum); //连接
150 itoa(NUM,strnum,10);
151 strcat(string,strnum);
152 setcolor(WHITE);
153 settextstyle(32,0,_T("宋体")); //设置字体类型
154 outtextxy(20,2*NUM_R*NUM_Y+2," ");
155 outtextxy(20,2*NUM_R*NUM_Y+2,string);
156 }
157
158 void over(bool a) //结束游戏
159 {
160 setcolor(WHITE); //设置字体颜色
161 settextstyle(48,0,_T("宋体")); //设置字体类型
162 if(a) //判断条件
163 outtextxy(NUM_X*NUM_R-20,NUM_Y*NUM_R-20,"胜利"); //输出结果
164 else
165 outtextxy(NUM_X*NUM_R-20,NUM_Y*NUM_R-20,"失败"); //输出结果
166 Sleep(2000);
167 system("pause");
168 exit(0);
169 }