0% found this document useful (0 votes)
35 views10 pages

Snake Game C++

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
35 views10 pages

Snake Game C++

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

#include <iostream>

#include <vector>

#include <cstdlib>

#include <ctime>

#include <unistd.h>

#include <termios.h>

#include <fcntl.h>

#include <sys/select.h>

using namespace std;

#define HEIGHT 20

#define WIDTH 60

enum Direction { UP, DOWN, LEFT, RIGHT, STOP };

enum Difficulty { EASY, MEDIUM, HARD, EXTREME };

class SnakeGame {

private:

struct termios old_props;

Direction dir;

int score;

int fruit_x, fruit_y;

int head_x, head_y;

vector<int> tail_x;

vector<int> tail_y;

int base_speed;

int min_speed;

int current_speed;

Difficulty difficulty;
void setTerminalAttributes() {

tcgetattr(STDIN_FILENO, &old_props);

termios new_props = old_props;

new_props.c_lflag &= ~(ICANON | ECHO);

tcsetattr(STDIN_FILENO, TCSANOW, &new_props);

fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);

void resetTerminalAttributes() {

tcsetattr(STDIN_FILENO, TCSANOW, &old_props);

bool inputAvailable() {

fd_set set;

struct timeval timeout;

FD_ZERO(&set);

FD_SET(STDIN_FILENO, &set);

timeout.tv_sec = 0;

timeout.tv_usec = 0;

return select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout) > 0;

void clearScreen() {

cout << "\033[H\033[J";

bool isPositionFree(int x, int y) {

if (x == head_x && y == head_y) return false;

for (size_t i = 0; i < tail_x.size(); i++)

if (tail_x[i] == x && tail_y[i] == y)

return false;
return true;

void showMenu() {

clearScreen();

cout << "\n\t\tWelcome to The Snake Game!\n\n";

cout << "\tChoose difficulty:\n";

cout << "\t1. Easy (Slow speed)\n";

cout << "\t2. Medium (Balanced speed)\n";

cout << "\t3. Hard (Fast speed)\n";

cout << "\t4. Extreme (Very fast)\n\n";

cout << "\tPress Q to quit\n";

while (true) {

if (inputAvailable()) {

char choice = getchar();

switch (choice) {

case '1': initDifficulty(EASY); return;

case '2': initDifficulty(MEDIUM); return;

case '3': initDifficulty(HARD); return;

case '4': initDifficulty(EXTREME); return;

case 'q': case 'Q':

resetTerminalAttributes();

exit(0);

void initDifficulty(Difficulty diff) {

difficulty = diff;
switch (diff) {

case EASY: base_speed = 250000; min_speed = 100000; break;

case MEDIUM: base_speed = 180000; min_speed = 60000; break;

case HARD: base_speed = 120000; min_speed = 40000; break;

case EXTREME: base_speed = 100000; min_speed = 30000; break;

current_speed = base_speed;

void draw() {

clearScreen();

cout << "\t\tSnake Game - ";

switch (difficulty) {

case EASY: cout << "Easy"; break;

case MEDIUM: cout << "Medium"; break;

case HARD: cout << "Hard"; break;

case EXTREME: cout << "Extreme"; break;

cout << endl;

if (dir == STOP)

cout << "\t\tPAUSED (Press SPACE to resume)\n";

for (int i = 0; i < WIDTH + 2; i++) cout << "#";

cout << endl;

for (int i = 0; i < HEIGHT; i++) {

cout << "#";

for (int j = 0; j < WIDTH; j++) {

if (i == head_y && j == head_x)

cout << "O";


else if (i == fruit_y && j == fruit_x)

cout << "F";

else {

bool printed = false;

for (size_t k = 0; k < tail_x.size(); k++) {

if (tail_x[k] == j && tail_y[k] == i) {

cout << "o";

printed = true;

break;

if (!printed)

cout << " ";

cout << "#" << endl;

for (int i = 0; i < WIDTH + 2; i++) cout << "#";

cout << "\nScore: " << score << " | Speed: " << current_speed / 1000 << "ms\n";

cout << "Controls: WASD = Move | SPACE = Pause | M = Menu | X = Exit\n";

void input() {

static Direction last_dir = RIGHT;

if (inputAvailable()) {

char ch = getchar();

switch (ch) {

case 'a': case 'A':

if (dir != RIGHT) dir = LEFT;


break;

case 's': case 'S':

if (dir != UP) dir = DOWN;

break;

case 'd': case 'D':

if (dir != LEFT) dir = RIGHT;

break;

case 'w': case 'W':

if (dir != DOWN) dir = UP;

break;

case 'x': case 'X':

resetTerminalAttributes();

exit(0);

case ' ':

if (dir == STOP) dir = last_dir;

else { last_dir = dir; dir = STOP; }

break;

case 'm': case 'M':

showMenu();

setup();

break;

void gamePlay() {

if (dir == STOP) return;

for (int i = tail_x.size() - 1; i > 0; i--) {

tail_x[i] = tail_x[i - 1];

tail_y[i] = tail_y[i - 1];


}

if (!tail_x.empty()) {

tail_x[0] = head_x;

tail_y[0] = head_y;

switch (dir) {

case UP: head_y--; break;

case DOWN: head_y++; break;

case LEFT: head_x--; break;

case RIGHT: head_x++; break;

default: break;

if (head_x < 0) head_x = WIDTH - 1;

if (head_x >= WIDTH) head_x = 0;

if (head_y < 0) head_y = HEIGHT - 1;

if (head_y >= HEIGHT) head_y = 0;

for (size_t i = 0; i < tail_x.size(); i++) {

if (tail_x[i] == head_x && tail_y[i] == head_y) {

cout << "\nGame Over! Final score: " << score << endl;

resetTerminalAttributes();

exit(0);

if (head_x == fruit_x && head_y == fruit_y) {

score += 10;

tail_x.push_back(head_x);

tail_y.push_back(head_y);
do {

fruit_x = rand() % WIDTH;

fruit_y = rand() % HEIGHT;

} while (!isPositionFree(fruit_x, fruit_y));

public:

SnakeGame() {

srand(time(NULL));

setTerminalAttributes();

dir = STOP;

score = 0;

fruit_x = fruit_y = 0;

head_x = WIDTH / 2;

head_y = HEIGHT / 2;

~SnakeGame() {

resetTerminalAttributes();

void setup() {

head_x = WIDTH / 2;

head_y = HEIGHT / 2;

dir = STOP;

score = 0;

tail_x.clear();

tail_y.clear();
do {

fruit_x = rand() % WIDTH;

fruit_y = rand() % HEIGHT;

} while (!isPositionFree(fruit_x, fruit_y));

current_speed = base_speed;

void run() {

showMenu();

setup();

while (true) {

draw();

input();

gamePlay();

int target_speed = base_speed - (score * 3000);

if (target_speed < min_speed) target_speed = min_speed;

current_speed = target_speed;

usleep(current_speed);

};

int main() {

SnakeGame game;

[Link]();

return 0;
}

You might also like