Created
April 9, 2013 13:50
-
-
Save nathanharper/5345823 to your computer and use it in GitHub Desktop.
crappy C/ncurses implementation of "Snake" game
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <ncurses.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <time.h> | |
| /* Functions */ | |
| void mvdraw(int,int,int); | |
| void push(int); | |
| void game_over(int); | |
| void place_fruit(void); | |
| int shift(void); | |
| /* Variables */ | |
| int ate = 0; | |
| int stgw = 65; | |
| int stgh = 35; | |
| int dir = 1; /* 0=up, 1=right 2=down, 3=left */ | |
| int headx = 12; | |
| int heady = 12; | |
| int tailx = 9; | |
| int taily = 12; | |
| int maxy; | |
| int maxx; | |
| int sp = 3; | |
| int *trail; | |
| int main(void) | |
| { | |
| // Get the time so we have a random number. | |
| // This way, rand will not generate the same sequence each run. | |
| time_t sec; | |
| time(&sec); | |
| srand((unsigned int) sec); | |
| initscr(); | |
| noecho(); | |
| keypad(stdscr, TRUE); | |
| raw(); | |
| curs_set(0); | |
| start_color(); | |
| // init color pairs. | |
| init_pair(0,COLOR_WHITE,COLOR_BLACK); | |
| init_pair(1,COLOR_RED,COLOR_BLACK); | |
| init_pair(2,COLOR_GREEN,COLOR_BLACK); | |
| init_pair(3,COLOR_BLUE,COLOR_BLACK); | |
| init_pair(4,COLOR_YELLOW,COLOR_BLACK); | |
| char currch; | |
| int ch,i,j,nextdir; | |
| getmaxyx(stdscr,maxy,maxx); | |
| attron(COLOR_PAIR(0)); | |
| wborder(stdscr,124,124,45,45,43,43,43,43); | |
| mvprintw(2,5,"Welcome to Snake! Press any key to start."); | |
| mvprintw(3,5,"Press 'q' to quit."); | |
| mvprintw(4,5,"Press arrow keys to move."); | |
| refresh(); | |
| ch = getch(); | |
| clear(); | |
| refresh(); | |
| timeout(50); | |
| wborder(stdscr,124,124,45,45,43,43,43,43); | |
| mvdraw(12,12,64); | |
| mvdraw(12,11,64); | |
| mvdraw(12,10,64); | |
| mvdraw(12,9,64); | |
| trail = (int*) malloc(3*sizeof(int)); | |
| trail[0]=1; | |
| trail[1]=1; | |
| trail[2]=1; | |
| refresh(); | |
| int fr; | |
| for (fr=0;fr<15;fr++) { | |
| place_fruit(); | |
| } | |
| for (;;) { | |
| fflush(stdin); | |
| ch = getch(); | |
| if (ch == KEY_UP) dir = 0; | |
| else if (ch == KEY_DOWN) dir = 2; | |
| else if (ch == KEY_LEFT) dir = 3; | |
| else if (ch == KEY_RIGHT) dir = 1; | |
| else if (ch == 113 || ch == 81) break; | |
| else if (ch == 80 || ch == 112) { | |
| timeout(-1); | |
| while ((ch = getch())) { | |
| if (ch == 80 || ch == 112) break; | |
| } | |
| if (dir % 2 == 0) timeout(80); | |
| else timeout(50); | |
| } | |
| // Make sure they didn't try to go backwards | |
| if (trail[sp-1]-2 == dir || trail[sp-1] == dir-2) dir = trail[sp-1]; | |
| // set a slower timeout speed when moving vertically, | |
| // so it doesn't seem like the snake is moving faster | |
| if (dir != trail[sp-1]) { | |
| if (dir % 2 == 0) timeout(80); | |
| else timeout(50); | |
| } | |
| push(dir); | |
| if (dir == 0) heady--; | |
| else if (dir == 1) headx++; | |
| else if (dir == 2) heady++; | |
| else if (dir == 3) headx--; | |
| /* Draw the tail first so | |
| * the game doesn't get confused and think we hit | |
| * the tail when we haven't | |
| * */ | |
| if (ate == 0) { | |
| mvdraw(taily,tailx,32); | |
| nextdir = shift(); | |
| if (nextdir == 0) taily--; | |
| else if (nextdir == 1) tailx++; | |
| else if (nextdir == 2) taily++; | |
| else if (nextdir == 3) tailx--; | |
| } | |
| else { | |
| ate = 0; | |
| place_fruit(); | |
| } | |
| // Check for collisions | |
| currch = mvinch(heady,headx); | |
| if (currch == 'O') { | |
| // We got a fruit! | |
| ate = 1; | |
| } | |
| else if (currch != ' ') { | |
| // We hit something that is neither empty space nor a fruit | |
| game_over(currch); | |
| break; | |
| } | |
| mvdraw(heady,headx,64); | |
| refresh(); | |
| } | |
| endwin(); | |
| return 0; | |
| } | |
| void mvdraw(int y, int x, int code) | |
| { | |
| int pair = 0; | |
| if (code == 64) pair = 2; | |
| else if (code == 79) pair = 4; | |
| if (pair > 0) { | |
| move(y,x); | |
| addch(code|COLOR_PAIR(pair)); | |
| } | |
| else { | |
| mvprintw(y,x,"%c",code); | |
| } | |
| } | |
| void push(int n) | |
| { | |
| sp++; | |
| int *arr = (int*) malloc(sp*sizeof(int)); | |
| memmove(arr,trail,(sp-1)*sizeof(int)); | |
| free(trail); | |
| arr[sp-1] = n; | |
| trail = arr; | |
| } | |
| int shift(void) | |
| { | |
| sp--; | |
| int *arr = (int*) malloc(sp*sizeof(int)); | |
| int start = trail[0]; | |
| memmove(arr,trail+1,sp*sizeof(int)); | |
| free(trail); | |
| trail = arr; | |
| return start; | |
| } | |
| void game_over(int curr) | |
| { | |
| attron(COLOR_PAIR(1)); | |
| mvprintw(10,10,"You died! You were %d snake-units long!",++sp); | |
| mvprintw(11,10,"Way to go, stud!"); | |
| timeout(-1); | |
| refresh(); | |
| int ch = getch(); | |
| } | |
| void place_fruit(void) | |
| { | |
| char chr; | |
| int rx,ry; | |
| while (1) { | |
| rx = rand() % (maxx-1) + 1; | |
| ry = rand() % (maxy-1) + 1; | |
| chr = mvinch(ry,rx); | |
| if (chr == ' ') break; | |
| } | |
| move(ry,rx); | |
| addch('O'|COLOR_PAIR(4)); | |
| // mvprintw(ry,rx,"%c",79); | |
| refresh(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment