From 7d2550b50df132072db57e8762bf247e51834aaa Mon Sep 17 00:00:00 2001
From: Tejas Protim Neog <92169576+tpncoder@users.noreply.github.com>
Date: Sun, 19 Jul 2026 23:36:10 +0530
Subject: [PATCH] Add: Snake Game
---
Snake-Game/README.md | 19 +++++++++
Snake-Game/main.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 117 insertions(+)
create mode 100644 Snake-Game/README.md
create mode 100644 Snake-Game/main.cpp
diff --git a/Snake-Game/README.md b/Snake-Game/README.md
new file mode 100644
index 00000000..e4d862a2
--- /dev/null
+++ b/Snake-Game/README.md
@@ -0,0 +1,19 @@
+# Snake Game
+A simple snake game written in C++
+
+## Installation
+Make sure you have C++ installed on your system
+
+```clang++ -O2 -std=c++17 main.cpp -o main.exe```
+
or
+```g++ -g main.cpp -o main.exe```
+
+Execute the following to play
+```./main.exe```
+
+## Keybindings
+* ```W``` + ```Enter``` = Up
+* ```A``` + ```Enter``` = Left
+* ```S``` + ```Enter``` = Down
+* ```D``` + ```Enter``` = Down
+* ```Q``` + ```Enter``` = Quit
\ No newline at end of file
diff --git a/Snake-Game/main.cpp b/Snake-Game/main.cpp
new file mode 100644
index 00000000..0c5de48b
--- /dev/null
+++ b/Snake-Game/main.cpp
@@ -0,0 +1,98 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+constexpr int W = 20, H = 10;
+enum Direction { LEFT, RIGHT, TOP, BOTTOM };
+struct Point {
+ int x;
+ int y;
+};
+std::vector snake;
+std::atomic dir(RIGHT);
+bool game_over = false;
+
+void input_listener() {
+ while(!game_over) {
+ char c;
+ std::cin >> c;
+ c = tolower(c);
+
+ // prevent 180 deg movement -> snake eating itself lol
+ if(c == 'q') game_over = true; // exit
+ if(c == 'w' && dir != BOTTOM) dir = TOP;
+ if(c == 's' && dir != TOP) dir = BOTTOM;
+ if(c == 'a' && dir != RIGHT) dir = LEFT;
+ if(c == 'd' && dir != LEFT) dir = RIGHT;
+ }
+}
+
+Point generate_fruit() {
+ int fx, fy;
+ do {
+ fx = rand() % W;
+ fy = rand() % H;
+ } while (std::any_of(snake.begin(), snake.end(), [fx, fy](const Point& p) {
+ return p.x == fx && p.y == fy;
+ }));
+
+ Point fruit = {fx, fy};
+ return fruit;
+}
+
+int main() {
+ snake = {{W/2, H/2}, {W/2-1, H/2}, {W/2-2, H/2}};
+
+ std::thread input_thread(input_listener);
+ Point fruit = generate_fruit();
+
+ // game loop
+ while(!game_over) {
+ Point new_head = snake.front();
+ if(dir == TOP) { new_head.y--; }
+ if(dir == BOTTOM) { new_head.y++; }
+ if(dir == RIGHT) { new_head.x++; }
+ if(dir == LEFT) { new_head.x--; }
+
+ // clip through walls
+ if(new_head.x < 0) { new_head.x = W - 1; }
+ if(new_head.x >= W) { new_head.x = 0; }
+ if(new_head.y < 0) { new_head.y = H - 1; }
+ if(new_head.y >= H) { new_head.y = 0; }
+
+ // eating itself
+ for (const auto& s : snake) if (s.x == new_head.x && s.y == new_head.y) game_over = true;
+
+ // create head for moving effect
+ snake.insert(snake.begin(), new_head);
+
+ if (new_head.x == fruit.x && new_head.y == fruit.y) { fruit = generate_fruit(); }
+ else { snake.pop_back(); }
+
+ system("cls");
+ std::string frame = "";
+
+ // rendering
+ for(int i = 0; i < H; i++) {
+ for(int j = 0; j < W; j++) {
+ if(snake.front().x == j && snake.front().y == i) { frame += "O"; }
+ else if(std::any_of(snake.begin(), snake.end(), [i, j](const Point& p) { return p.x == j && p.y == i; })) { frame += "o"; }
+ else if(fruit.x == j && fruit.y == i) { frame += "X"; }
+ else { frame += "."; }
+ }
+ frame += "\n";
+ }
+ std::cout << frame << std::flush;
+
+ // 10 fps
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+
+ input_thread.join();
+ std::cout << "Game Over!\n";
+
+ return 0;
+}
\ No newline at end of file