modified: SpatialOmicsCoord.py
[GalaxyCodeBases.git] / c_cpp / etc / tiny / snake.c
blob9ec3ea268812ea6a8ca6f78c91d93f0a48600386
1 /* http://bbs.chinaunix.net/thread-1170202-1-1.html
2 许久没来,贡献一个原创小程序,是unix下用终端控制字符实现的贪吃蛇小游戏,供大家一乐。
4 编译方法:
5 AIX下:cc -qcpluscmt -o snake snake.c
6 sco unix下:cc -o snake snake.c
8 [ 本帖最后由 forest077 于 2008-6-25 13:23 编辑 ]
9 */
10 /***snake.c***/
11 #include <stdio.h>
12 #include <malloc.h>
13 #include <sys/time.h>
14 #include <sys/types.h>
15 #include <sys/select.h>
16 #include <termio.h>
17 #include <fcntl.h>
18 #include <unistd.h> // ttyname
19 #include <stdlib.h> // rand, srand
20 #include <string.h> // strlen
22 #define SNAKE_INITX 5
23 #define SNAKE_INITY 5
24 #define SNAKE_SHAPE '*'
25 #define SNAKE_INITLEN 8
27 #define WIN_X1 1
28 #define WIN_X2 80
29 #define WIN_Y1 1
30 #define WIN_Y2 24
32 #define MAX_LEVEL 20
33 #define MAX_INTER 200000
34 #define MIN_INTER 0
35 #define MAX_RICH 10
36 #define DEVRATE 5
37 #define OVER "Game Over!!!"
39 struct stNode
41 int x;
42 int y;
43 char shape;
44 struct stNode *next;
47 struct stFood
49 int x;
50 int y;
53 struct stNode *gpstHead,*gpstTail;
54 struct stFood gastFood[MAX_RICH];
55 int giLevel=1;
56 int giRich=1;
57 int giScore=0;
58 int giLen=0;
60 void settty(int iFlag)
62 int fd;
63 struct termio stTerm;
65 if((fd = open(ttyname(1),O_RDWR))==-1) return;
66 if(iFlag == 1)
68 ioctl(fd,TCGETA,&stTerm);
69 stTerm.c_lflag &= ~ICANON;
70 stTerm.c_lflag &= ~ECHO;
71 stTerm.c_cc[4] = 1;
72 stTerm.c_cc[5] = 0;
73 stTerm.c_iflag &= ~ISTRIP;
74 stTerm.c_cflag |= CS8;
75 stTerm.c_cflag &= ~PARENB;
76 ioctl(fd,TCSETA,&stTerm);
78 else
80 ioctl(fd,TCGETA,&stTerm);
81 stTerm.c_lflag |= ICANON;
82 stTerm.c_lflag |= ECHO;
83 stTerm.c_cc[4] = 4;
84 stTerm.c_cc[5] = 5;
85 stTerm.c_iflag &= ~ISTRIP;
86 stTerm.c_cflag |= CS8;
87 stTerm.c_cflag &= ~PARENB;
88 ioctl(fd,TCSETA,&stTerm);
90 close(fd);
93 void vDrawOneNode(struct stNode *pstNode,int iFlag)
95 printf("\033[%dm\033[40;%dm\033[%d;%d;H%c",
96 iFlag,iFlag*3+30,pstNode->y,pstNode->x,pstNode->shape);
97 fflush(stdout);
100 void vDrawOneFood(int x,int y)
102 printf("\033[1m\033[40;36m\033[%d;%d;H%c",y,x,'@');
103 fflush(stdout);
106 int iGetDir(int iOriDir)
108 fd_set rset;
109 struct timeval hTmo;
110 int iRet,iFlag=0;
111 char cCh;
113 FD_ZERO(&rset);
114 FD_SET(0,&rset);
115 hTmo.tv_sec=0;
116 hTmo.tv_usec=MAX_INTER-(MAX_INTER-MIN_INTER)/MAX_LEVEL*giLevel;
118 iRet=select(1,&rset,NULL,NULL,&hTmo);
119 if(iRet<=0)
121 return(iOriDir);
123 for(;;)
125 cCh=getchar();
126 if(cCh != -1)
128 switch(cCh)
130 case 27 :
131 case 91 :
132 iFlag++;
133 break;
134 case 65 ://UP
135 case 66 ://DOWN
136 case 67 ://RIGHT
137 case 68 ://LEFT
138 if(iFlag==2)
139 return((!((cCh-0x41)^iOriDir^1))^(cCh-0x41));
140 default :
141 return(iOriDir);
146 void vInitScreen()
148 settty(1);
149 printf("\033[?25l\033[2J");
152 void vRestoreScreen()
154 printf("\033[24;1H\033[1m\033[40;34m\033[?25h");
155 settty(0);
158 void vDrawScope()
160 int i,j;
162 for(j=WIN_Y1;j<=WIN_Y2;j+=WIN_Y2-WIN_Y1)
164 printf("\033[%d;%dH+",j,WIN_X1);
165 for(i=WIN_X1+1;i<WIN_X2;i++)
166 printf("-");
167 printf("+");
169 for(i=WIN_Y1+1;i<WIN_Y2;i++)
170 printf("\033[%d;%dH|%*c|\n",i,WIN_X1,WIN_X2-WIN_X1-1,' ');
173 void vCreateSnake()
175 struct stNode *pstNew;
176 int i;
178 gpstHead=(struct stNode*)malloc(sizeof(struct stNode));
179 gpstHead->x=SNAKE_INITX;
180 gpstHead->y=SNAKE_INITY;
181 gpstHead->shape=SNAKE_SHAPE;
182 gpstHead->next=NULL;
183 vDrawOneNode(gpstHead,1);
184 gpstTail=gpstHead;
185 for(i=1;i<SNAKE_INITLEN;i++)
187 pstNew=(struct stNode*)malloc(sizeof(struct stNode));
188 pstNew->x=gpstHead->x+1;
189 pstNew->y=gpstHead->y;
190 pstNew->shape=SNAKE_SHAPE;
191 pstNew->next=NULL;
192 vDrawOneNode(pstNew,1);
193 gpstHead->next=pstNew;
194 gpstHead=pstNew;
196 return;
199 void vKillSnake()
201 struct stNode *pstNode;
203 for(pstNode=gpstTail;gpstTail!=NULL;)
205 gpstTail=pstNode->next;
206 free(pstNode);
207 pstNode=gpstTail;
211 void vGenFood(int iIdx)
213 struct stNode *pstNode;
214 int i,iFound=0;
216 for(;!iFound;)
218 iFound=1;
219 gastFood[iIdx].x=rand()%(WIN_X2-WIN_X1-1)+WIN_X1+1;
220 gastFood[iIdx].y=rand()%(WIN_Y2-WIN_Y1-1)+WIN_Y1+1;
221 for(i=0;i<giRich;i++)
223 if(i!=iIdx && gastFood[iIdx].x==gastFood[i].x &&
224 gastFood[iIdx].y==gastFood[i].y)
226 iFound=0;
227 break;
230 if(!iFound) continue;
231 for(pstNode=gpstTail;pstNode!=NULL;pstNode=pstNode->next)
233 if(gastFood[iIdx].x==pstNode->x &&
234 gastFood[iIdx].y==pstNode->y)
236 iFound=0;
237 break;
240 if(!iFound) continue;
242 vDrawOneFood(gastFood[iIdx].x,gastFood[iIdx].y);
245 void vInitFood()
247 int i;
249 srand(getpid());
250 for(i=0;i<giRich;i++) vGenFood(i);
253 int iIsValid(int x,int y)
255 struct stNode *pstNode;
257 if(x<=WIN_X1 || x>=WIN_X2 || y<=WIN_Y1 || y>=WIN_Y2)
258 return(0);
259 pstNode=gpstTail;
260 for(;pstNode!=NULL;)
262 if(x==pstNode->x && y==pstNode->y)
263 return(0);
264 pstNode=pstNode->next;
266 return(1);
269 int iEat(int x,int y)
271 int i;
273 for(i=0;i<giRich;i++)
275 if(x==gastFood[i].x && y==gastFood[i].y)
277 vGenFood(i);
278 giScore+=giLevel*10;
279 giLen++;
280 if(giLevel<MAX_LEVEL)
281 if(giLen%DEVRATE==0)
282 giLevel++;
283 return(1);
286 return(0);
288 int main()
290 int iDir=2,iNextX,iNextY;
291 struct stNode *pstNew;
292 char sPrompt[80];
294 vInitScreen();
295 vDrawScope();
296 vCreateSnake();
297 vInitFood();
298 for(;;)
300 iDir=iGetDir(iDir);
301 iNextX=gpstHead->x+(iDir>>1)*(5-(iDir<<1));
302 iNextY=gpstHead->y-(!(iDir>>1))*(1-(iDir<<1));
303 if(!iIsValid(iNextX,iNextY))
305 printf("\033[%d;%zdH\033[1m\033[40;34m%s\033[0m",
306 WIN_Y2-1,(WIN_X1+WIN_X2)/2-strlen(OVER)/2,OVER);
307 break;
309 pstNew=(struct stNode*)malloc(sizeof(struct stNode));
310 pstNew->x=iNextX;
311 pstNew->y=iNextY;
312 pstNew->shape=SNAKE_SHAPE;
313 pstNew->next=NULL;
314 gpstHead->next=pstNew;
315 gpstHead=pstNew;
316 vDrawOneNode(gpstHead,1);
317 if(!iEat(iNextX,iNextY))
319 vDrawOneNode(gpstHead,1);
320 vDrawOneNode(gpstTail,0);
321 pstNew=gpstTail;
322 gpstTail=pstNew->next;
323 free(pstNew);
325 sprintf(sPrompt,"Score:%7d Level:%2d",giScore,giLevel);
326 printf("\033[%d;%zdH\033[1m\033[40;34m%s\033[0m",
327 WIN_Y2,(WIN_X1+WIN_X2)/2-strlen(sPrompt)/2,sPrompt);
329 vKillSnake();
330 vRestoreScreen();