Initial upload
This commit is contained in:
parent
5032dd85d1
commit
52d34e941f
3 changed files with 322 additions and 0 deletions
18
Makefile
Normal file
18
Makefile
Normal file
|
@ -0,0 +1,18 @@
|
|||
all: serpent
|
||||
|
||||
WARNINGS = -Wall
|
||||
DEBUG = -ggdb -fno-omit-frame-pointer
|
||||
OPTIMIZE = -O2
|
||||
|
||||
serpent: Makefile serpent.c
|
||||
$(CC) -o $@ $(WARNINGS) $(DEBUG) $(OPTIMIZE) serpent.c
|
||||
|
||||
clean:
|
||||
rm -f serpent
|
||||
|
||||
install:
|
||||
echo "Installing is not supported"
|
||||
|
||||
run:
|
||||
./serpent
|
||||
|
291
serpent.c
Normal file
291
serpent.c
Normal file
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* serpent.c
|
||||
*
|
||||
* Copyright 2023 Darius Drake
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
/* Libraries */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
/* */
|
||||
|
||||
/* Program information */
|
||||
#define NAME "serpent"
|
||||
#define VERSION 0.1
|
||||
/* */
|
||||
|
||||
/* global variables/constants */
|
||||
#define REFRESH_RATE 0.08 // refresh rate (in seconds)
|
||||
#define START_SNAKE_LEN 5 // initial snake length
|
||||
#define SNAKE_BODY '*' // snake's body
|
||||
#define SNAKE_HEAD_U 'v' // head when going up
|
||||
#define SNAKE_HEAD_D '^' // head when going down
|
||||
#define SNAKE_HEAD_L '>' // head when going left
|
||||
#define SNAKE_HEAD_R '<' // head when going right
|
||||
#define FOOD '@' // normal food
|
||||
#define FOOD_SCORE 1 // score increase when snake eats food
|
||||
#define BORDER_CORNER '+' // character at corners of border
|
||||
#define BORDER_VERT '|' // character for vertical border
|
||||
#define BORDER_HORI '-' // character for horizontal border
|
||||
#define SCREEN_WIDTH 40 // the virtual screen width
|
||||
#define SCREEN_HEIGHT 30 // the virtual screen height
|
||||
/* */
|
||||
|
||||
typedef enum { UP, DOWN, LEFT, RIGHT } Direction;
|
||||
|
||||
typedef enum { RUNNING, PAUSED, STOPPED } GameState;
|
||||
|
||||
typedef struct {
|
||||
int X;
|
||||
int Y;
|
||||
} Point;
|
||||
|
||||
typedef struct {
|
||||
char borderCor;
|
||||
char borderVer;
|
||||
char borderHor;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
} Board;
|
||||
|
||||
typedef struct {
|
||||
GameState state;
|
||||
unsigned int points;
|
||||
char* player;
|
||||
} Game;
|
||||
|
||||
typedef struct {
|
||||
Point position;
|
||||
char sprite;
|
||||
SnakeNode* next;
|
||||
} SnakeNode;
|
||||
|
||||
typedef struct {
|
||||
Direction direction;
|
||||
unsigned int length;
|
||||
SnakeNode* head;
|
||||
SnakeNode* tail;
|
||||
} Snake;
|
||||
|
||||
typedef struct {
|
||||
Point position;
|
||||
unsigned int points;
|
||||
char food;
|
||||
} Food;
|
||||
|
||||
typedef struct {
|
||||
char borderCor;
|
||||
char borderVer;
|
||||
char borderHor;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
} Board;
|
||||
|
||||
// Function prototypes
|
||||
void initializeGame(Game *game, Board *board, Snake *snake, Food *food);
|
||||
void clearScreen();
|
||||
void waitForKeypress();
|
||||
void displayLogo();
|
||||
void displayMainMenu();
|
||||
void displayControls();
|
||||
void displayInfo();
|
||||
void argControls();
|
||||
void argHelp();
|
||||
void argVersion();
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
Game game;
|
||||
Board board;
|
||||
Food food;
|
||||
Snake snake;
|
||||
|
||||
int option;
|
||||
|
||||
static const char* short_options = "chv";
|
||||
static struct option long_options[] = {
|
||||
{"show-controls", no_argument, NULL, 'c'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'v'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
while ((option = getopt_long (argc, argv, short_options, long_options, NULL)) != -1) {
|
||||
switch (option) {
|
||||
case 'c':
|
||||
argControls();
|
||||
break;
|
||||
case 'h':
|
||||
argHelp();
|
||||
break;
|
||||
case 'v':
|
||||
argVersion();
|
||||
break;
|
||||
case '?':
|
||||
fprintf(stderr, "Use '-h, --help' for help.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void initializeGame(Game *game, Board *board, Snake *snake, Food *food) {
|
||||
game->state = RUNNING;
|
||||
game->points = 0;
|
||||
|
||||
// Initialize snake direction and head
|
||||
snake->direction = RIGHT;
|
||||
snake->head = (SnakeNode*)malloc(sizeof(SnakeNode));
|
||||
snake->head->sprite = SNAKE_HEAD_R;
|
||||
snake->head->position.X = SCREEN_HEIGHT / 2;
|
||||
snake->head->position.Y = SCREEN_HEIGHT / 2;
|
||||
snake->head->next = NULL;
|
||||
|
||||
// Initialize snake body
|
||||
SnakeNode *currentSegment = snake->head;
|
||||
for (int i = 1; i < START_SNAKE_LEN; ++i) {
|
||||
SnakeNode *newSegment = (SnakeNode*)malloc(sizeof(SnakeNode));
|
||||
newSegment->sprite = SNAKE_BODY;
|
||||
newSegment->position.X = snake->head->position.X - i;
|
||||
newSegment->position.Y = snake->head->position.Y;
|
||||
newSegment->next = NULL;
|
||||
|
||||
currentSegment->next = newSegment; // Link the current segment to the new one
|
||||
currentSegment = newSegment; // Move to the new segment
|
||||
}
|
||||
|
||||
// Set the tail of the snake
|
||||
snake->tail = currentSegment;
|
||||
}
|
||||
|
||||
// Function for clearing the console
|
||||
void clearScreen() {
|
||||
printf("\e[1;1H\e[2J");
|
||||
}
|
||||
|
||||
// Function for waiting for keypress
|
||||
void waitForKeypress() {
|
||||
struct termios oldt, newt;
|
||||
tcgetattr(STDIN_FILENO, &oldt);
|
||||
newt = oldt;
|
||||
newt.c_lflag &= ~(ICANON | ECHO);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
||||
while (getchar() != '\n'); // Consume any remaining characters in the input buffer
|
||||
getchar(); // Wait for a key press
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
||||
}
|
||||
|
||||
// Function for displaying the logo of the game
|
||||
void displayLogo() {
|
||||
printf(" ____ \n");
|
||||
printf(" ________________________/ O \\___/\n");
|
||||
printf("<_____________________________/ \\\n");
|
||||
printf(" __ _ \n");
|
||||
printf("/ _\\ ___ _ __ _ __ ___ _ __ | |_ \n");
|
||||
printf("\\ \\ / _ \\ '__| '_ \\ / _ \\ '_ \\| __|\n");
|
||||
printf("_\\ \\ __/ | | |_) | __/ | | | |_ \n");
|
||||
printf("\\__/\\___|_| | .__/ \\___|_| |_|\\__|\n");
|
||||
printf(" |_| \n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// Function for displaying the main menu
|
||||
void displayMainMenu() {
|
||||
displayLogo();
|
||||
printf("Welcome to serpent!\n");
|
||||
printf("\n");
|
||||
printf(" Select an option:\n");
|
||||
printf(" 1. Play\n");
|
||||
printf(" 2. Show leader board\n");
|
||||
printf(" 3. Show controls\n");
|
||||
printf(" 4. Show Info\n");
|
||||
printf(" 5. Exit\n");
|
||||
printf("\n");
|
||||
printf(" Choose [1-5]: ");
|
||||
}
|
||||
|
||||
// Function for tisplaying the game controls
|
||||
void displayControls() {
|
||||
displayLogo();
|
||||
printf("Controls.\n");
|
||||
printf("\n");
|
||||
printf(" Movement:\n");
|
||||
printf(" ↑: move up\n");
|
||||
printf(" ←: move to the left\n");
|
||||
printf(" →: move to the right\n");
|
||||
printf(" ↓: move down\n");
|
||||
printf(" Game:\n");
|
||||
printf(" q: quit\n");
|
||||
printf(" p: pause\n");
|
||||
printf(" r: restart\n");
|
||||
printf("\n");
|
||||
printf("Press any key to go back... ");
|
||||
}
|
||||
|
||||
// Function for displaying the game info
|
||||
void displayInfo() {
|
||||
displayLogo();
|
||||
printf("About this game.\n");
|
||||
printf("\n");
|
||||
printf(" Author: Darius Drake\n");
|
||||
printf(" License: GPL v3\n");
|
||||
printf(" Contribute:\n");
|
||||
printf(" The source code is available on GitHub -> https://github.com/d4r1us-drk/serpent\n");
|
||||
printf(" Feel free to contribute with ideas, issues or pull requests.\n");
|
||||
printf("\n");
|
||||
printf("Press any key to go back... ");
|
||||
}
|
||||
|
||||
// Function for displaying the game controls in the command line
|
||||
void argControls() {
|
||||
printf("%s controls.\n", NAME);
|
||||
printf("Movement:\n");
|
||||
printf("\t↑: move up\n");
|
||||
printf("\t←: move to the left\n");
|
||||
printf("\t→: move to the right\n");
|
||||
printf("\t↓: move down\n");
|
||||
printf("Game:\n");
|
||||
printf("\tq: quit\n");
|
||||
printf("\tp: pause\n");
|
||||
printf("\tr: restart\n");
|
||||
}
|
||||
|
||||
// Function to display the help message in the command line
|
||||
void argHelp() {
|
||||
printf("Usage: %s [OPTIONS]\n", NAME);
|
||||
printf("Play the all time classic snake game in the console.\n\n");
|
||||
printf("Options:\n");
|
||||
printf("\t-c, --show-controls Show the controls for the game.\n");
|
||||
printf("\t-h, --help Display this help message and exit.\n");
|
||||
printf("\t-v, --version Display version and exit.\n");
|
||||
}
|
||||
|
||||
// Function to display the version in the command line
|
||||
void argVersion() {
|
||||
printf("%s. version: %.1lf\n", NAME, VERSION);
|
||||
printf("Author: Darius Drake\n");
|
||||
printf("License: GPL v3\n");
|
||||
printf("Contribute:\n");
|
||||
printf(" The source code is available on GitHub -> https://github.com/d4r1us-drk/serpent\n");
|
||||
printf(" Feel free to contribute with ideas, issues or pull requests.\n");
|
||||
}
|
13
serpent.md
Normal file
13
serpent.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Serpent
|
||||
## Feautures
|
||||
- **Great ASCII graphics:**
|
||||
i. The snake will have different head characters depending on which direction it's going:
|
||||
- **Up:** v
|
||||
- **Down:** ^
|
||||
- **Left:** >
|
||||
- **Right:** <
|
||||
ii. The game board has the following characters:
|
||||
- **Corners:** +
|
||||
- **Vertical borders:** |
|
||||
- **Horizontal borders:** -
|
||||
iii.
|
Loading…
Reference in a new issue