Skip to content

Instantly share code, notes, and snippets.

@nathanharper
Created April 9, 2013 13:50
Show Gist options
  • Save nathanharper/5345823 to your computer and use it in GitHub Desktop.
Save nathanharper/5345823 to your computer and use it in GitHub Desktop.
crappy C/ncurses implementation of "Snake" game
#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