diff --git a/2048 b/2048
new file mode 100755
index 0000000000000000000000000000000000000000..2822740d6a916791aeea15318772db1a1da7d0d7
Binary files /dev/null and b/2048 differ
diff --git a/2048.cpp b/2048.cpp
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9d035450819c05c38184320b515cff9ad8b8a2d0 100644
--- a/2048.cpp
+++ b/2048.cpp
@@ -0,0 +1,62 @@
+#include "2048.hpp"
+#include <iostream>
+#include <cstdlib>
+#include <ctime>
+
+Game2048::Game2048() {
+    std::srand(std::time(0));
+    resetBoard();
+}
+
+void Game2048::resetBoard() {
+    for (int i = 0; i < SIZE; ++i)
+        for (int j = 0; j < SIZE; ++j)
+            board[i][j] = 0;
+    spawnTile();
+    spawnTile();
+}
+
+void Game2048::spawnTile() {
+    std::vector<std::pair<int, int>> emptyTiles;
+    for (int i = 0; i < SIZE; ++i)
+        for (int j = 0; j < SIZE; ++j)
+            if (board[i][j] == 0)
+                emptyTiles.push_back({i, j});
+
+    if (!emptyTiles.empty()) {
+        int idx = std::rand() % emptyTiles.size();
+        board[emptyTiles[idx].first][emptyTiles[idx].second] = (std::rand() % 10 == 0) ? 4 : 2;
+    }
+}
+
+void Game2048::drawBoard() {
+    clear();
+    for (int i = 0; i < SIZE; ++i) {
+        for (int j = 0; j < SIZE; ++j) {
+            mvprintw(i * 2, j * 5, "%4d", board[i][j]);
+        }
+    }
+    refresh();
+}
+
+void Game2048::moveLeft() {
+    moved = false;
+    for (int i = 0; i < SIZE; ++i) {
+        int temp[SIZE] = {0}, index = 0;
+        for (int j = 0; j < SIZE; ++j) {
+            if (board[i][j] != 0) {
+                if (index > 0 && temp[index - 1] == board[i][j]) {
+                    temp[index - 1] *= 2;
+                    moved = true;
+                } else {
+                    temp[index++] = board[i][j];
+                }
+            }
+        }
+        for (int j = 0; j < SIZE; ++j) {
+            if (board[i][j] != temp[j]) moved = true;
+            board[i][j] = temp[j];
+        }
+    }
+    if (moved) spawnTile();
+}
diff --git a/2048.hpp b/2048.hpp
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d4aeab906d82299df7729c395f3a77408275c556 100644
--- a/2048.hpp
+++ b/2048.hpp
@@ -0,0 +1,25 @@
+#ifndef GAME_2048_HPP
+#define GAME_2048_HPP
+
+#include <vector>
+#include <ncurses.h>
+
+class Game2048 {
+private:
+    static const int SIZE = 4;
+    int board[SIZE][SIZE];
+    bool moved;
+
+public:
+    Game2048();
+    void resetBoard();
+    void spawnTile();
+    void drawBoard();
+    void moveLeft();
+    void moveRight();
+    void moveUp();
+    void moveDown();
+    bool isGameOver();
+};
+
+#endif // GAME_2048_HPP
diff --git a/main.cpp b/main.cpp
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bc0a5c8941d4d9e38acae60996c84587dce62cc5 100644
--- a/main.cpp
+++ b/main.cpp
@@ -0,0 +1,24 @@
+#include "2048.hpp"
+#include <ncurses.h>
+
+int main() {
+    initscr();
+    noecho();
+    keypad(stdscr, TRUE);
+    curs_set(0);
+
+    Game2048 game;
+    game.drawBoard();
+
+    int ch;
+    while ((ch = getch()) != 'q') {
+        switch (ch) {
+            case KEY_LEFT: game.moveLeft(); break;
+            // TODO: Add moveRight(), moveUp(), moveDown()
+        }
+        game.drawBoard();
+    }
+
+    endwin();
+    return 0;
+}