Skip to content

Instantly share code, notes, and snippets.

@naezith
Created January 4, 2016 13:09
Show Gist options
  • Select an option

  • Save naezith/14cb45d2afe7b276c62c to your computer and use it in GitHub Desktop.

Select an option

Save naezith/14cb45d2afe7b276c62c to your computer and use it in GitHub Desktop.
Snake and Mouse game and this time, you're the mouse! Full C Source Code
// Snake and Mouse game, you're the mouse. Eat cheese to get points and watch out for the snake!
// Written by naezith, you can use/change the code however you want.
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <math.h>
#include <time.h>
#define MAP_WIDTH 20
#define MAP_HEIGHT 20
#define SNAKE_SIZE 8
void init();
void input();
void draw();
void logic();
int onPlayer(int, int);
int onCheese(int, int);
int onSnake(int, int);
void spawnCheese();
void spawnSnake();
int rand_i();
int rand_j();
typedef struct S_COORD { int i, j; } MAP_COORD;
// Game variables
unsigned frameNumber = 0;
int paused = 0;
// Snake variables
float snake_pos_i, snake_pos_j, snake_speed = 0.15f;
MAP_COORD snake_body[SNAKE_SIZE];
// Player and cheese variables
int player_score, highest_score = 0;
MAP_COORD player_pos, cheese_pos;
// Returns random position on the level
int rand_i() { return rand() % MAP_HEIGHT; }
int rand_j() { return rand() % MAP_WIDTH; }
// Check if position is on player
int onPlayer(int i, int j) { return i == player_pos.i && j == player_pos.j; }
// Check if position is on cheese
int onCheese(int i, int j) { return i == cheese_pos.i && j == cheese_pos.j; }
// Check if position is on snake, if yes, return the body part number
int onSnake(int i, int j) {
int k;
for (k = 0; k < SNAKE_SIZE; ++k) if (i == snake_body[k].i && j == snake_body[k].j) return k + 1;
return 0;
}
void spawnCheese() {
// Find a proper random place for cheese: not on another cheese, not on the player and not on the snake
int i, j;
do { i = rand_i(); j = rand_j();
} while (onCheese(i, j) || onPlayer(i, j) || onSnake(i, j) == 1);
// Then place it there
cheese_pos.i = i;
cheese_pos.j = j;
}
void spawnSnake() {
// Put snake to the top left
int i;
for (i = 0; i < SNAKE_SIZE; ++i) {
snake_body[i].i = 0;
snake_body[i].j = i;
}
// Set his head position to float position holder
snake_pos_i = (float)snake_body[SNAKE_SIZE-1].i;
snake_pos_j = (float)snake_body[SNAKE_SIZE-1].j;
}
void moveSnake() {
MAP_COORD head = snake_body[SNAKE_SIZE-1], new_pos;
// Calculate the distance vector
float d_i = (float)(player_pos.i - head.i);
float d_j = (float)(player_pos.j - head.j);
// Calculate the length of the distance vector
float mag = sqrtf(d_i*d_i + d_j*d_j);
// Add the unit vector to our position
snake_pos_i += snake_speed * d_i / mag;
snake_pos_j += snake_speed * d_j / mag;
// Iterate the snake body parts when position is really changed as integer
new_pos.i = (int)snake_pos_i;
new_pos.j = (int)snake_pos_j;
if (new_pos.i != head.i || new_pos.j != head.j) {
int k;
for (k = 0; k < SNAKE_SIZE-1; ++k) snake_body[k] = snake_body[k + 1];
snake_body[k] = new_pos;
}
}
void main(void) {
int fps = 60; // 30 to 60 fps is common for rendering graphics.
int sleepTime = 1000 / fps; // To get 60 fps, we have to redraw graphics every 1000/60=17 miliseconds
srand((unsigned int)time(0));
init(); // Do your initialization before the infinite loop starts.
// This is the structure used in programming most games.
// An infinite loop is run with the game logic and graphics being updated at each iteration.
while (1) {
// Check if there is any input, update your variables accordingly.
input();
// Do not refresh graphics when paused, it causes unnecessary flicker.
if (paused == 0) {
// Refresh graphics.
draw();
// Update variables accordingly.
logic();
// At each iteration, we sleep for a predetermined amount of time.
// There are better ways of doing this (multi-threading).
Sleep(sleepTime);
}
}
}
void init() {
// Stop the game
paused = 1;
// Reset current score
player_score = 0;
// Put player in a safe field
player_pos.i = (MAP_HEIGHT + rand_i()) / 2;
player_pos.j = rand_j();
spawnSnake();
spawnCheese();
draw();
}
void input() {
char input;
// _kbhit() checks if there is a character in the buffer, i.e. if you hit any buttons during Sleep().
if (_kbhit()) {
// Since a character is already in the buffer, it is loaded to the variable instantly.
// In other words, this getch() does not stall the program and wait for your response.
input = _getch();
// Pause
if (input == 'p') paused = !paused;
// Exit
else if (input == 'x') exit(0);
// Move up
else if (input == 'w' && player_pos.i > 0) --player_pos.i;
// Move down
else if (input == 's' && player_pos.i + 1 < MAP_HEIGHT) ++player_pos.i;
// Move left
else if (input == 'a' && player_pos.j > 0) --player_pos.j;
// Move right
else if (input == 'd' && player_pos.j + 1 < MAP_WIDTH) ++player_pos.j;
// Resume the game if key is not p
if (input != 'p') paused = 0;
}
}
// This is where the magic happens. You should update game related variables here
char curr_color[1] = "F"; // Console start color
void logic() {
frameNumber++;
// Eat cheese
if (onCheese(player_pos.i, player_pos.j)) {
spawnCheese();
if (++player_score > highest_score) highest_score = player_score;
}
moveSnake();
// Snake hits player, restart.
if (onSnake(player_pos.i, player_pos.j)) init();
// Change console color for fun
if (frameNumber % 5 == 0) {
char color[9] = "color 0";
strcat_s(color, 9, curr_color);
system(color);
// Cycle colors F to A
if (curr_color[0] == 'A') curr_color[0] = 'F';
else --curr_color[0];
}
}
// Note that we have to redraw the entire image
// This is the case for all practical graphics engines.
void draw() {
int i, j;
// Clears the command line, note that this is platform specific, i.e. will not work on UNIX etc.
system("cls");
printf("\n #");
for (i = 0; i < MAP_WIDTH; ++i) printf("=");
printf("# Pause(p) Exit(x) Move(w, a, s, d)\n");
for (i = 0; i < MAP_HEIGHT; i++) {
printf(" |");
for (j = 0; j < MAP_WIDTH; j++) {
int is_snake_body_part = onSnake(i, j); // Which part of snake?
// Print player
if (onPlayer(i, j)) printf("@");
// Print Head
else if (is_snake_body_part == SNAKE_SIZE) printf("%c", 219);
// Print Body
else if (is_snake_body_part) printf("%c", is_snake_body_part % 2 == 0 ? 176 : 177);
// Print Cheese
else if (onCheese(i, j)) printf("%c", 207);
// Print Empty field
else printf(" ");
}
printf("|\n");
}
printf(" #");
for (i = 0; i < MAP_WIDTH; ++i) printf("=");
printf("# Score : %d Highest : %d", player_score, highest_score);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment