#include "game.h"
#include <time.h>
#include <ctype.h>
#define ROWS 20
#define COLS 30
unsigned score;
#define MAX_LEN ROWS * COLS
struct {
unsigned head;
unsigned tail;
struct {
unsigned y[MAX_LEN+1];
unsigned x[MAX_LEN+1];
} body;
} snake;
struct {
unsigned y;
unsigned x;
bool exist;
} food;
bool is_wall(unsigned y, unsigned x)
{
return y <= 0 || y >= ROWS-1 || x <= 0 || x >= COLS-1;
}
bool is_food(unsigned y, unsigned x)
{
return food.exist && y == food.y && x == food.x;
}
bool is_body(unsigned y, unsigned x)
{
unsigned i;
for (i = snake.head; i != snake.tail; i = (i+1) % (MAX_LEN+1))
if (y == snake.body.y[i] && x == snake.body.x[i])
break;
return i != snake.tail;
}
void food_create()
{
if (!food.exist) {
do {
food.y = rand() % (ROWS-2) + 1;
food.x = rand() % (COLS-2) + 1;
} while (is_body(food.y, food.x));
food.exist = true;
}
}
void map_print()
{
unsigned y, x;
for (y = 0; y != ROWS; ++y) {
for (x = 0; x != COLS; ++x) {
if (is_wall(y, x))
printf(SYM_SQUARE);
else if (is_body(y, x))
printf(SYM_SQUARE);
else if (is_food(y, x))
printf(SYM_DIAMOND);
else
printf(SYM_BLANK);
}
putchar('\n');
}
printf("\nScores: 0\nUse wasd to play.\n");
}
void init()
{
screen_clear();
srand(time(NULL));
score = 0;
snake.head = 0;
snake.tail = 2;
snake.body.y[0] = 9;
snake.body.x[0] = 9;
snake.body.y[1] = 9;
snake.body.x[1] = 8;
food.y = 0;
food.x = 0;
food.exist = false;
food_create();
map_print();
}
void play()
{
char key;
char last_key = 'd';
key = tolower(getch());
while (true) {
bool valid = ( (key == 'w' && last_key != 's')
|| (key == 's' && last_key != 'w')
|| (key == 'a' && last_key != 'd')
|| (key == 'd' && last_key != 'a') );
if (valid)
last_key = key;
else
key = last_key;
unsigned new_y = snake.body.y[snake.head];
unsigned new_x = snake.body.x[snake.head];
switch (key) {
case 'w': --new_y; break;
case 's': ++new_y; break;
case 'a': --new_x; break;
case 'd': ++new_x; break;
}
if (is_wall(new_y, new_x)) {
break;
} else if (is_food(new_y, new_x)) {
score += 10 + rand() % 11;
mvprint(ROWS+1, 8, "%d", score);
food.exist = false;
food_create();
mvprint(food.y, 2*food.x, SYM_DIAMOND);
} else {
snake.tail = (snake.tail == 0 ? MAX_LEN : snake.tail-1);
mvprint(snake.body.y[snake.tail], 2*snake.body.x[snake.tail], SYM_BLANK);
if (is_body(new_y, new_x))
break;
}
mvprint(new_y, 2*new_x, SYM_SQUARE);
snake.head = (snake.head == 0 ? MAX_LEN : snake.head-1);
snake.body.y[snake.head] = new_y;
snake.body.x[snake.head] = new_x;
Sleep(32765/(score+200)+40);
if (kbhit())
key = tolower(getch());
}
}
bool new_game()
{
mvprint(ROWS+2, 0, "Game over! <ESC> to quit, any other key to restart\n");
return getch() != 27;
}
int main()
{
game_init();
screen_size(ROWS+4, COLS*2+1);
do {
init();
play();
} while (new_game());
game_over();
return 0;
}