Compare commits

...

5 Commits

6 changed files with 80 additions and 12 deletions

View File

@@ -1,16 +1,36 @@
# Sanke # Sanke
A simple snake game in the terminal. No third party libraries needed. A simple snake game in the terminal. No third party libraries needed.
## Demo # Compiling
Click image for video Run:
```sh
compile.sh release
```
to compile an optimized build. The script creates a directory called 'target' that contains the executable.
[![Sanke demo](https://img.youtube.com/vi/_coOVAW9qa4/0.jpg)](https://www.youtube.com/watch?v=_coOVAW9qa4) See:
```sh
compile.sh help
```
for more.
## How it works # Running
Run:
```sh
sanke
```
to play with defaults settings.
See:
```sh
sanke --help
```
for setting game options.
# How it works
The program makes the terminal use non-canonical input and output by using termios. Then it updates and prints a 2D character array containing the board borders, snake, and food. Before terminating, the program restores canonical mode. The program makes the terminal use non-canonical input and output by using termios. Then it updates and prints a 2D character array containing the board borders, snake, and food. Before terminating, the program restores canonical mode.
## Info # Info
Only tested with the combination of Only tested with the combination of
- GCC - GCC
- Linux - Linux
- x86 CPU

View File

@@ -6,6 +6,18 @@ if [ -v 1 ]; then
arg=$1 arg=$1
fi fi
if [ $arg = "help" ]; then
echo "USAGE: compile.sh <option>"
echo ""
echo "Compiles debug build when called without an option."
echo "Options:"
echo " help : Show this help text."
echo " clean : Clean target directory."
echo " release: Build with optimizations."
echo " run : Build debug build and run."
exit
fi
if [ $arg = "clean" ]; then if [ $arg = "clean" ]; then
rm -rf ./target/* rm -rf ./target/*
exit exit
@@ -37,6 +49,5 @@ if [ $? -gt 0 ]; then
fi fi
if [ $arg = "run" ]; then if [ $arg = "run" ]; then
echo
./target/sanke ./target/sanke
fi fi

View File

@@ -5,6 +5,7 @@
#include "config.h" #include "config.h"
#include "Board.h" #include "Board.h"
#include "Snake.h" #include "Snake.h"
#include "utils.h"
#define MAT_INDEX(mat, w, i, j) (mat)[(j) + (w) * (i)] #define MAT_INDEX(mat, w, i, j) (mat)[(j) + (w) * (i)]
@@ -16,6 +17,9 @@ Board board_alloc(const int width, const int height) {
board.width_with_borders = board.width + 2; board.width_with_borders = board.width + 2;
board.height_with_borders = board.height + 2; board.height_with_borders = board.height + 2;
board.squares = (char*) malloc(sizeof(char) * board.width_with_borders * board.height_with_borders); board.squares = (char*) malloc(sizeof(char) * board.width_with_borders * board.height_with_borders);
if (board.squares == NULL) {
mallocError("board.squares", __FILE__, "board_alloc");
}
for (size_t i = 1; i < board.height_with_borders; i++) { for (size_t i = 1; i < board.height_with_borders; i++) {
for (size_t j = 1; j < board.width_with_borders; j++) { for (size_t j = 1; j < board.width_with_borders; j++) {

View File

@@ -3,6 +3,7 @@
#include <assert.h> #include <assert.h>
#include "Snake.h" #include "Snake.h"
#include "utils.h"
extern const char snake_vis; extern const char snake_vis;
@@ -31,6 +32,9 @@ Snake snake_alloc(
snake.length = 1; snake.length = 1;
snake.dir = init_dir; snake.dir = init_dir;
snake.parts = (BoardPiece*) malloc(sizeof(BoardPiece) * snake.max_length); snake.parts = (BoardPiece*) malloc(sizeof(BoardPiece) * snake.max_length);
if (snake.parts == NULL) {
mallocError("snake.parts", __FILE__, "snake_alloc");
}
snake.parts[0] = (BoardPiece) { .x = init_x, .y = init_y, .vis_char = '&' }; snake.parts[0] = (BoardPiece) { .x = init_x, .y = init_y, .vis_char = '&' };
return snake; return snake;

View File

@@ -4,13 +4,31 @@
#include "args.h" #include "args.h"
static void handle_version() { static void check_bounds(const char* arg_name, const int i, const int argc) {
if (i + 1 >= argc) {
printf("%s needs an argument. See: sanke --help\n", arg_name);
exit(0);
}
}
static void show_version() {
printf("Sanke version %s\n", VERSION); printf("Sanke version %s\n", VERSION);
exit(0); exit(0);
} }
static void show_help() {
printf(
"USAGE: sanke <options>\n\n"
"Options:\n"
" --width, -w: Set the width (10 - 50) of the board. Default 15.\n"
" --height, -h: Set the height (10 - 50) of the board. Default 15.\n"
" --speed, -s: Set the speed (1 - 1000) of the game in squares per second. Default 7.\n"
" --help : Display this help text.\n"
);
exit(0);
}
static void set_width(Arguments* args, char* width_str) { static void set_width(Arguments* args, char* width_str) {
printf("width_str: %s\n", width_str);
int width = atoi(width_str); int width = atoi(width_str);
if (width < 10) { if (width < 10) {
printf("Width must be between 10 and 50. Was %d.\n", width); printf("Width must be between 10 and 50. Was %d.\n", width);
@@ -23,7 +41,7 @@ static void set_width(Arguments* args, char* width_str) {
static void set_height(Arguments* args, char* height_str) { static void set_height(Arguments* args, char* height_str) {
int height = atoi(height_str); int height = atoi(height_str);
if (height < 10) { if (height < 10) {
printf("Width must be between 10 and 50. Was %d.\n", height); printf("Width must be between 10 and 50. Was %s.\n", height_str);
exit(0); exit(0);
} }
@@ -44,7 +62,7 @@ Arguments cmd_args(int argc, char** argv) {
Arguments args = { Arguments args = {
.width = 15, .width = 15,
.height = 15, .height = 15,
.sleep_ms = 150 .sleep_ms = 150,
}; };
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
@@ -53,13 +71,20 @@ Arguments cmd_args(int argc, char** argv) {
|| strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "-v") == 0
) )
{ {
handle_version(); show_version();
} else if (
strcmp(argv[i], "--help") == 0
)
{
show_help();
} else if ( } else if (
strcmp(argv[i], "--width") == 0 strcmp(argv[i], "--width") == 0
|| strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "-w") == 0
) )
{ {
check_bounds("width", i, argc);
set_width(&args, argv[i + 1]); set_width(&args, argv[i + 1]);
} else if ( } else if (
@@ -67,6 +92,7 @@ Arguments cmd_args(int argc, char** argv) {
|| strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-h") == 0
) )
{ {
check_bounds("height", i, argc);
set_height(&args, argv[i + 1]); set_height(&args, argv[i + 1]);
} else if ( } else if (
@@ -74,7 +100,9 @@ Arguments cmd_args(int argc, char** argv) {
|| strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "-s") == 0
) )
{ {
check_bounds("speed", i, argc);
set_speed(&args, argv[i + 1]); set_speed(&args, argv[i + 1]);
} }
} }

View File

@@ -18,6 +18,7 @@ int randomInt(const int start, const int end, const unsigned int seed) {
return result; return result;
} }
// TODO: Make a general error logging function and macro
void mallocError(const char* varName, const char* fileName, const char* functionName) { void mallocError(const char* varName, const char* fileName, const char* functionName) {
printf("Ran out of memory to allocate to %s in %s/%s\n", varName, fileName, functionName); printf("Ran out of memory to allocate to %s in %s/%s\n", varName, fileName, functionName);
exit(1); exit(1);