curssses

Snake game for the linux terminal.
git clone git://git.amin.space/curssses.git
Log | Files | Refs | LICENSE

commit e491eef5214078afe13da6a4e745659ddf7c88a0
parent def33a23cd09f8e2e2da44e8c20869fcff626289
Author: amin <dev@aminmesbah.com>
Date:   Fri,  2 Dec 2016 07:48:08 +0000

Implement snake as linked list.

FossilOrigin-Name: 379593fc4149e519dada1797698b7daa3ee741acff1efe623afeedec1f0694fb
Diffstat:
Mcurssses.c | 175++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 124 insertions(+), 51 deletions(-)

diff --git a/curssses.c b/curssses.c @@ -15,13 +15,103 @@ typedef enum DOWN, } direction; -typedef struct +typedef struct segment segment; +struct segment { - char symbol; int x; int y; + segment *prev; + segment *next; +}; + +typedef struct snake snake; +struct snake +{ + char symbol; direction d; -} snake; + int length; + segment *head; + segment *tail; +}; + +snake* snake_init() +{ + segment *first = malloc(sizeof(segment)); + first->x = COLS / 2; + first->y = LINES / 2; + first->prev = 0; + first->next = 0; + + snake *s = malloc(sizeof(snake)); + s->symbol = 'o'; + s->d = RIGHT; + s->length = 1; + s->head = first; + s->tail = first; + + return s; +} + +void snake_add_segment(snake *s) +{ + segment *new = malloc(sizeof(segment)); + new->x = s->tail->x; + new->y = s->tail->y; + new->prev = s->tail; + new->next = 0; + + s->tail->next = new; + s->tail = new; + s->length++; +} + +void snake_move(snake *s) +{ + segment *current = s->tail; + while (current != s->head) + { + current->x = current->prev->x; + current->y = current->prev->y; + current = current->prev; + } + + switch (s->d) + { + case LEFT: + { + --s->head->x; + } break; + case RIGHT: + { + ++s->head->x; + } break; + case UP: + { + --s->head->y; + } break; + case DOWN: + { + ++s->head->y; + } break; + } + + if (s->head->y >= LINES) + { + s->head->y = 0; + } + else if (s->head->y < 0) + { + s->head->y = LINES - 1; + } + if (s->head->x >= COLS) + { + s->head->x = 0; + } + else if (s->head->x < 0) + { + s->head->x = COLS - 1; + } +} int main(void) { @@ -35,87 +125,70 @@ int main(void) keypad(stdscr, TRUE); curs_set(0); - snake s; - s.symbol = 'o'; - s.x = COLS / 2; - s.y = LINES / 2; + snake *s = snake_init(); + for (int i = 0; i < 4; ++i) + { + snake_add_segment(s); + } int input = 0; while (1) { - input = getch(); - erase(); - - printw("Position: (%d, %d) Total: [%d, %d]", s.x, s.y, COLS, LINES); switch (input) { case KEY_LEFT: case 'h': { - s.d = LEFT; + s->d = LEFT; } break; case KEY_RIGHT: case 'l': { - s.d = RIGHT; + s->d = RIGHT; } break; case KEY_UP: case 'k': { - s.d = UP; + s->d = UP; } break; case KEY_DOWN: case 'j': { - s.d = DOWN; - } break; - } - - switch (s.d) - { - case LEFT: - { - --s.x; - } break; - case RIGHT: - { - ++s.x; + s->d = DOWN; } break; - case UP: + case 'p': { - --s.y; - } break; - case DOWN: - { - ++s.y; - } break; + // pause until keypress + nodelay(stdscr, FALSE); + getch(); + nodelay(stdscr, TRUE); + } } - if (s.y == LINES) - { - s.y = 0; - } - else if (s.y < 0) - { - s.y = LINES - 1; - } - if (s.x == COLS) - { - s.x = 0; - } - else if (s.x < 0) + erase(); + + snake_move(s); + + mvprintw( + 0, 0, + "Screen: [%d, %d]\nSnake Length: %d\nHead: (%d, %d)\nTail: (%d, %d)", + COLS, LINES, s->length, s->head->x, s->head->y, s->tail->x, s->tail->y); + + segment *current = s->head; + int i = 0; + while (current != 0) { - s.x = COLS - 1; + mvaddch(current->y, current->x, s->symbol); + mvprintw(i+4, 0, "Segment %d (%d, %d)", i+1, current->x, current->y); + current = current->next; + i++; } - mvaddch(s.y, s.x, s.symbol); - refresh(); usleep(SECOND / FPS); } - clear(); endwin(); exit(0);