1 /* http://bbs.chinaunix.net/thread-1170202-1-1.html
2 许久没来,贡献一个原创小程序,是unix下用终端控制字符实现的贪吃蛇小游戏,供大家一乐。
5 AIX下:cc -qcpluscmt -o snake snake.c
6 sco unix下:cc -o snake snake.c
8 [ 本帖最后由 forest077 于 2008-6-25 13:23 编辑 ]
14 #include <sys/types.h>
15 #include <sys/select.h>
18 #include <unistd.h> // ttyname
19 #include <stdlib.h> // rand, srand
20 #include <string.h> // strlen
24 #define SNAKE_SHAPE '*'
25 #define SNAKE_INITLEN 8
33 #define MAX_INTER 200000
37 #define OVER "Game Over!!!"
53 struct stNode
*gpstHead
,*gpstTail
;
54 struct stFood gastFood
[MAX_RICH
];
60 void settty(int iFlag
)
65 if((fd
= open(ttyname(1),O_RDWR
))==-1) return;
68 ioctl(fd
,TCGETA
,&stTerm
);
69 stTerm
.c_lflag
&= ~ICANON
;
70 stTerm
.c_lflag
&= ~ECHO
;
73 stTerm
.c_iflag
&= ~ISTRIP
;
74 stTerm
.c_cflag
|= CS8
;
75 stTerm
.c_cflag
&= ~PARENB
;
76 ioctl(fd
,TCSETA
,&stTerm
);
80 ioctl(fd
,TCGETA
,&stTerm
);
81 stTerm
.c_lflag
|= ICANON
;
82 stTerm
.c_lflag
|= ECHO
;
85 stTerm
.c_iflag
&= ~ISTRIP
;
86 stTerm
.c_cflag
|= CS8
;
87 stTerm
.c_cflag
&= ~PARENB
;
88 ioctl(fd
,TCSETA
,&stTerm
);
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
);
100 void vDrawOneFood(int x
,int y
)
102 printf("\033[1m\033[40;36m\033[%d;%d;H%c",y
,x
,'@');
106 int iGetDir(int iOriDir
)
116 hTmo
.tv_usec
=MAX_INTER
-(MAX_INTER
-MIN_INTER
)/MAX_LEVEL
*giLevel
;
118 iRet
=select(1,&rset
,NULL
,NULL
,&hTmo
);
139 return((!((cCh
-0x41)^iOriDir
^1))^(cCh
-0x41));
149 printf("\033[?25l\033[2J");
152 void vRestoreScreen()
154 printf("\033[24;1H\033[1m\033[40;34m\033[?25h");
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
++)
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,' ');
175 struct stNode
*pstNew
;
178 gpstHead
=(struct stNode
*)malloc(sizeof(struct stNode
));
179 gpstHead
->x
=SNAKE_INITX
;
180 gpstHead
->y
=SNAKE_INITY
;
181 gpstHead
->shape
=SNAKE_SHAPE
;
183 vDrawOneNode(gpstHead
,1);
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
;
192 vDrawOneNode(pstNew
,1);
193 gpstHead
->next
=pstNew
;
201 struct stNode
*pstNode
;
203 for(pstNode
=gpstTail
;gpstTail
!=NULL
;)
205 gpstTail
=pstNode
->next
;
211 void vGenFood(int iIdx
)
213 struct stNode
*pstNode
;
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
)
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
)
240 if(!iFound
) continue;
242 vDrawOneFood(gastFood
[iIdx
].x
,gastFood
[iIdx
].y
);
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
)
262 if(x
==pstNode
->x
&& y
==pstNode
->y
)
264 pstNode
=pstNode
->next
;
269 int iEat(int x
,int y
)
273 for(i
=0;i
<giRich
;i
++)
275 if(x
==gastFood
[i
].x
&& y
==gastFood
[i
].y
)
280 if(giLevel
<MAX_LEVEL
)
290 int iDir
=2,iNextX
,iNextY
;
291 struct stNode
*pstNew
;
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
);
309 pstNew
=(struct stNode
*)malloc(sizeof(struct stNode
));
312 pstNew
->shape
=SNAKE_SHAPE
;
314 gpstHead
->next
=pstNew
;
316 vDrawOneNode(gpstHead
,1);
317 if(!iEat(iNextX
,iNextY
))
319 vDrawOneNode(gpstHead
,1);
320 vDrawOneNode(gpstTail
,0);
322 gpstTail
=pstNew
->next
;
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
);