2008-08-19

Змейка на Си

Змейка на ncurses =) Для компиляции нужна библиотека ncursess, скорей всего есть по-умолчанию: gcc -lcurses snake.c -o snake
Есть глюк, если во время движения, поверуть в противоположную сторону - змейка сама в себя врежеться. Например, если при движении вверх, нажать вниз - то врежеться змейка в себя. Надо бы как-нибудь поправть. Кстати, мой рекорд - 64 =)

#include <curses.h>
#include <stdlib.h>

#define WH 25
#define WW 25

#define MAX_SNAKE 255

typedef struct{
int y;
int x;
} head_struct;

typedef struct snk_St{
int y;
int x;
struct snk_St *next;
} snk_s;

snk_s *snk;
head_struct set_food(){
head_struct food;
food.y=1+(int)(23.0 * (rand()/(RAND_MAX+1.0)));
food.x=1+(int)(23.0 * (rand()/(RAND_MAX+1.0)));
return food;
}

int main(){
head_struct body[MAX_SNAKE], food;
int lose=0;
char *space=" ";
WINDOW *my_win, *stats_win, *lose_win;
char *str="GAME OVER press F1 to quit";
initscr();
nonl();
noecho();
timeout(60);
curs_set(0);
start_color();
if(has_colors()){
init_pair(1,COLOR_GREEN,COLOR_BLACK);
init_pair(2,COLOR_CYAN,COLOR_BLACK);
}
stats_win=newwin(3,WW+10,1,2);
wbkgd(stats_win,COLOR_PAIR(1));

my_win=newwin(WH,WW,4,7);
wbkgd(my_win,COLOR_PAIR(1)|A_BOLD);

lose_win=newwin(3,(strlen(str)+4),14,4);
wbkgd(lose_win,COLOR_PAIR(2)|A_BOLD|A_BLINK);
box(lose_win,0,0);
body[0].y=2;
body[0].x=2;
box(my_win,0,0);
int old_c=66,c,food_c=0,score=1,b=0;
for(;;)
{
if(!food_c){
food=set_food();
food_c=1;
}


if (body[0].x==food.x && body[0].y==food.y){
score+=1;
if(score == 254) lose=1;
food_c=0;
}

c=getch();
if (old_c==65 && c==66) c=65;
if (old_c==66 && c==65) c=66;
if (old_c==67 && c==68) c=67;
if (old_c==68 && c==67) c=67;
(c==ERR)?(c=old_c):(old_c=c);
for(b=score+1;b!=0;b--){
body[b].y=body[b-1].y;
body[b].x=body[b-1].x;
}


switch(c){
case 65:
body[0].y-=1;
if(body[0].y==0) body[0].y=23;
break;

case 66:
body[0].y+=1;
if(body[0].y==24) body[0].y=1;
break;
case 67:
body[0].x+=1;
if(body[0].x==24) body[0].x=1;
break;
case 68:
body[0].x-=1;
if(body[0].x==0) body[0].x=23;
break;
}
for(b=score-1;b>3;b--){
if(body[0].y==body[b].y && body[0].x==body[b].x){
lose=1;
}

}
if(lose==1){
break;
}
mvwaddch(my_win,food.y,food.x,'F');
mvwaddch(my_win,body[0].y,body[0].x,'@');
mvwaddch(my_win,body[1].y,body[1].x,'*');
mvwaddstr(my_win,body[score].y,body[score].x,space);

mvwprintw(stats_win,1,1,"Score: %d; Food: Y=%.02d X=%.02d",score,food.y,food.x);
wnoutrefresh(stats_win);
mvwaddch(my_win,body[score].y,body[score].x,32);
wnoutrefresh(stats_win);

wnoutrefresh(my_win);
doupdate();
}
wclear(my_win);
wclear(stats_win);

mvwaddstr(lose_win,1,2,str);
wnoutrefresh(lose_win);
doupdate();
c=0;
for(;;){
c=getch();
if(c==80) break;
c=0;
}
endwin();
return 0;
}

Архив