diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
new file mode 100644
index 0000000000000000000000000000000000000000..c2098a2d0c4b96621c02cb4e33bc58231ccffc1d
--- /dev/null
+++ b/.vscode/c_cpp_properties.json
@@ -0,0 +1,18 @@
+{
+  "configurations": [
+    {
+      "name": "linux-gcc-x64",
+      "includePath": [
+        "${workspaceFolder}/**"
+      ],
+      "compilerPath": "/usr/bin/gcc",
+      "cStandard": "${default}",
+      "cppStandard": "${default}",
+      "intelliSenseMode": "linux-gcc-x64",
+      "compilerArgs": [
+        ""
+      ]
+    }
+  ],
+  "version": 4
+}
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000000000000000000000000000000000000..d8762db45dd0f3846188984e7b67a3952e002687
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,24 @@
+{
+  "version": "0.2.0",
+  "configurations": [
+    {
+      "name": "C/C++ Runner: Debug Session",
+      "type": "cppdbg",
+      "request": "launch",
+      "args": [],
+      "stopAtEntry": false,
+      "externalConsole": false,
+      "cwd": "/home/fredrick2.enoime/2048-clone",
+      "program": "/home/fredrick2.enoime/2048-clone/build/Debug/outDebug",
+      "MIMode": "gdb",
+      "miDebuggerPath": "gdb",
+      "setupCommands": [
+        {
+          "description": "Enable pretty-printing for gdb",
+          "text": "-enable-pretty-printing",
+          "ignoreFailures": true
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000000000000000000000000000000000..3e5eb956e1aac2b053a4d09e761fcc26bb2b106e
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,59 @@
+{
+  "C_Cpp_Runner.cCompilerPath": "gcc",
+  "C_Cpp_Runner.cppCompilerPath": "g++",
+  "C_Cpp_Runner.debuggerPath": "gdb",
+  "C_Cpp_Runner.cStandard": "",
+  "C_Cpp_Runner.cppStandard": "",
+  "C_Cpp_Runner.msvcBatchPath": "",
+  "C_Cpp_Runner.useMsvc": false,
+  "C_Cpp_Runner.warnings": [
+    "-Wall",
+    "-Wextra",
+    "-Wpedantic",
+    "-Wshadow",
+    "-Wformat=2",
+    "-Wcast-align",
+    "-Wconversion",
+    "-Wsign-conversion",
+    "-Wnull-dereference"
+  ],
+  "C_Cpp_Runner.msvcWarnings": [
+    "/W4",
+    "/permissive-",
+    "/w14242",
+    "/w14287",
+    "/w14296",
+    "/w14311",
+    "/w14826",
+    "/w44062",
+    "/w44242",
+    "/w14905",
+    "/w14906",
+    "/w14263",
+    "/w44265",
+    "/w14928"
+  ],
+  "C_Cpp_Runner.enableWarnings": true,
+  "C_Cpp_Runner.warningsAsError": false,
+  "C_Cpp_Runner.compilerArgs": [],
+  "C_Cpp_Runner.linkerArgs": [],
+  "C_Cpp_Runner.includePaths": [],
+  "C_Cpp_Runner.includeSearch": [
+    "*",
+    "**/*"
+  ],
+  "C_Cpp_Runner.excludeSearch": [
+    "**/build",
+    "**/build/**",
+    "**/.*",
+    "**/.*/**",
+    "**/.vscode",
+    "**/.vscode/**"
+  ],
+  "C_Cpp_Runner.useAddressSanitizer": false,
+  "C_Cpp_Runner.useUndefinedSanitizer": false,
+  "C_Cpp_Runner.useLeakSanitizer": false,
+  "C_Cpp_Runner.showCompilationTime": false,
+  "C_Cpp_Runner.useLinkTimeOptimization": false,
+  "C_Cpp_Runner.msvcSecureNoWarnings": false
+}
\ No newline at end of file
diff --git a/2048 b/2048
index 2822740d6a916791aeea15318772db1a1da7d0d7..012dd31c904f6c63d21b5e01db62b883bef602db 100755
Binary files a/2048 and b/2048 differ
diff --git a/2048.cpp b/2048.cpp
deleted file mode 100644
index 9d035450819c05c38184320b515cff9ad8b8a2d0..0000000000000000000000000000000000000000
--- a/2048.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#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/Extra.cpp b/Extra.cpp
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/Extra.hpp b/Extra.hpp
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..30620e687d1412a80c9f4ef2aa656d574bc48c9c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,28 @@
+# Compiler and flags
+CXX = g++
+CXXFLAGS = -std=c++11 -Wall -Wextra -Iinclude
+LDFLAGS = -lncurses  # Add this for linking ncurses
+
+# Source files
+SRC = src/2048.cpp src/UI.cpp src/Extra.cpp src/Tile.cpp src/main.cpp
+
+# Object files
+OBJ = $(SRC:.cpp=.o)
+
+# Target executable
+TARGET = 2048
+
+# Default target
+all: $(TARGET)
+
+# Link object files to create the executable
+$(TARGET): $(OBJ)
+	$(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJ) $(LDFLAGS)  # <-- Add $(LDFLAGS) here
+
+# Compile source files into object files
+%.o: %.cpp
+	$(CXX) $(CXXFLAGS) -c $< -o $@  # <-- TAB indentation
+
+# Clean up build artifacts
+clean:
+	rm -f $(OBJ) $(TARGET)  # <-- TAB indentation
\ No newline at end of file
diff --git a/Tile.cpp b/Tile.cpp
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/Tile.hpp b/Tile.hpp
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/UI.cpp b/UI.cpp
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/UI.hpp b/UI.hpp
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/2048.hpp b/include/2048.hpp
similarity index 60%
rename from 2048.hpp
rename to include/2048.hpp
index d4aeab906d82299df7729c395f3a77408275c556..47f983ccfacefadf2d2ee2f216bcb6e3c0f2e97c 100644
--- a/2048.hpp
+++ b/include/2048.hpp
@@ -1,25 +1,27 @@
-#ifndef GAME_2048_HPP
-#define GAME_2048_HPP
+#ifndef GAME2048_HPP
+#define GAME2048_HPP
 
 #include <vector>
-#include <ncurses.h>
+#define SIZE 4
 
 class Game2048 {
 private:
-    static const int SIZE = 4;
     int board[SIZE][SIZE];
     bool moved;
 
+    void spawnTile();
+    void resetBoard();
+
 public:
     Game2048();
-    void resetBoard();
-    void spawnTile();
     void drawBoard();
     void moveLeft();
     void moveRight();
     void moveUp();
     void moveDown();
-    bool isGameOver();
+    bool canMove();
+    int getScore();
+    const int (*getBoard() const)[SIZE]; // Mark this method as const
 };
 
-#endif // GAME_2048_HPP
+#endif
\ No newline at end of file
diff --git a/include/Extra.hpp b/include/Extra.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..539aa832bc5f6faf54ea2f358b6a17e0f363adba
--- /dev/null
+++ b/include/Extra.hpp
@@ -0,0 +1,9 @@
+#ifndef EXTRA_HPP
+#define EXTRA_HPP
+
+#include <ncurses.h>
+
+void initializeGame();
+void cleanupGame();
+
+#endif
\ No newline at end of file
diff --git a/include/Tile.hpp b/include/Tile.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ecf494ea72511c76903b0e04b2231c4ce84e48b3
--- /dev/null
+++ b/include/Tile.hpp
@@ -0,0 +1,14 @@
+#ifndef TILE_HPP
+#define TILE_HPP
+
+class Tile {
+private:
+    int value;
+
+public:
+    Tile();
+    void setValue(int val);
+    int getValue() const;
+};
+
+#endif
\ No newline at end of file
diff --git a/include/UI.hpp b/include/UI.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..b6d642470a7f57ce66f86b29b34665862dd53e0b
--- /dev/null
+++ b/include/UI.hpp
@@ -0,0 +1,13 @@
+#ifndef UI_HPP
+#define UI_HPP
+
+#include "2048.hpp"
+
+class UI {
+public:
+    void drawBoard(const Game2048& game);
+    void handleInput(Game2048& game);
+    void showGameOver();
+};
+
+#endif
\ No newline at end of file
diff --git a/main.cpp b/main.cpp
deleted file mode 100644
index bc0a5c8941d4d9e38acae60996c84587dce62cc5..0000000000000000000000000000000000000000
--- a/main.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#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;
-}
diff --git a/src/2048.cpp b/src/2048.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..331e64deb8e4aea861212af585d73f2788bdc6dd
--- /dev/null
+++ b/src/2048.cpp
@@ -0,0 +1,152 @@
+#include "2048.hpp"
+#include <ncurses.h>
+#include <cstdlib>
+#include <ctime>
+#include <vector>
+
+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();
+}
+
+void Game2048::moveRight() {
+    moved = false;
+    for (int i = 0; i < SIZE; ++i) {
+        int temp[SIZE] = {0}, index = SIZE - 1;
+        for (int j = SIZE - 1; j >= 0; --j) {
+            if (board[i][j] != 0) {
+                if (index < SIZE - 1 && 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();
+}
+
+void Game2048::moveUp() {
+    moved = false;
+    for (int j = 0; j < SIZE; ++j) {
+        int temp[SIZE] = {0}, index = 0;
+        for (int i = 0; i < SIZE; ++i) {
+            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 i = 0; i < SIZE; ++i) {
+            if (board[i][j] != temp[i]) moved = true;
+            board[i][j] = temp[i];
+        }
+    }
+    if (moved) spawnTile();
+}
+
+void Game2048::moveDown() {
+    moved = false;
+    for (int j = 0; j < SIZE; ++j) {
+        int temp[SIZE] = {0}, index = SIZE - 1;
+        for (int i = SIZE - 1; i >= 0; --i) {
+            if (board[i][j] != 0) {
+                if (index < SIZE - 1 && temp[index + 1] == board[i][j]) {
+                    temp[index + 1] *= 2;
+                    moved = true;
+                } else {
+                    temp[index--] = board[i][j];
+                }
+            }
+        }
+        for (int i = 0; i < SIZE; ++i) {
+            if (board[i][j] != temp[i]) moved = true;
+            board[i][j] = temp[i];
+        }
+    }
+    if (moved) spawnTile();
+}
+
+bool Game2048::canMove() {
+    for (int i = 0; i < SIZE; ++i) {
+        for (int j = 0; j < SIZE; ++j) {
+            if (board[i][j] == 0) return true;
+            if (j < SIZE - 1 && board[i][j] == board[i][j + 1]) return true;
+            if (i < SIZE - 1 && board[i][j] == board[i + 1][j]) return true;
+        }
+    }
+    return false;
+}
+
+int Game2048::getScore() {
+    int score = 0;
+    for (int i = 0; i < SIZE; ++i)
+        for (int j = 0; j < SIZE; ++j)
+            score += board[i][j];
+    return score;
+}
+
+const int (*Game2048::getBoard() const)[SIZE] {
+    return board;
+}
\ No newline at end of file
diff --git a/src/2048.o b/src/2048.o
new file mode 100644
index 0000000000000000000000000000000000000000..c199e0a7f2d9e698883681c10d56548e2bc2d52c
Binary files /dev/null and b/src/2048.o differ
diff --git a/src/Extra.cpp b/src/Extra.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..66f1cbad7cb73214f50a154c7e1e9a898adbaf50
--- /dev/null
+++ b/src/Extra.cpp
@@ -0,0 +1,13 @@
+#include "Extra.hpp"
+#include <ncurses.h>
+
+void initializeGame() {
+    initscr();
+    noecho();
+    keypad(stdscr, TRUE);
+    curs_set(0);
+}
+
+void cleanupGame() {
+    endwin();
+}
\ No newline at end of file
diff --git a/src/Extra.o b/src/Extra.o
new file mode 100644
index 0000000000000000000000000000000000000000..c65d8bce46bd620e67c5c97fa4d9dd37416bd3a8
Binary files /dev/null and b/src/Extra.o differ
diff --git a/src/Tile.cpp b/src/Tile.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..47e1f436f99e4786e83bfffe87d028909aa3ca59
--- /dev/null
+++ b/src/Tile.cpp
@@ -0,0 +1,11 @@
+#include "Tile.hpp"
+
+Tile::Tile() : value(0) {}
+
+void Tile::setValue(int val) {
+    value = val;
+}
+
+int Tile::getValue() const {
+    return value;
+}
\ No newline at end of file
diff --git a/src/Tile.o b/src/Tile.o
new file mode 100644
index 0000000000000000000000000000000000000000..2a327ba1ea273fc432998dbffe86016cddae3aa5
Binary files /dev/null and b/src/Tile.o differ
diff --git a/src/UI.cpp b/src/UI.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b27a33cdf484ea155cc488be65fcb6de3fe95698
--- /dev/null
+++ b/src/UI.cpp
@@ -0,0 +1,28 @@
+#include "UI.hpp"
+#include "2048.hpp"
+#include <ncurses.h>
+
+void UI::drawBoard(const Game2048& game) {
+    clear();
+    for (int i = 0; i < SIZE; ++i) {
+        for (int j = 0; j < SIZE; ++j) {
+            mvprintw(i * 2, j * 5, "%4d", game.getBoard()[i][j]); // Now this works
+        }
+    }
+    refresh();
+}
+
+void UI::handleInput(Game2048& game) {
+    int ch = getch();
+    switch (ch) {
+        case KEY_LEFT: game.moveLeft(); break;
+        case KEY_RIGHT: game.moveRight(); break;
+        case KEY_UP: game.moveUp(); break;
+        case KEY_DOWN: game.moveDown(); break;
+    }
+}
+
+void UI::showGameOver() {
+    mvprintw(SIZE * 2, 0, "Game Over! Press any key to exit.");
+    getch();
+}
\ No newline at end of file
diff --git a/src/UI.o b/src/UI.o
new file mode 100644
index 0000000000000000000000000000000000000000..7f1f66b496bcb640693deb1bacbfcd0cab9b099b
Binary files /dev/null and b/src/UI.o differ
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2ad697ab6c0dab29229113e1775bc6093e3458db
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,26 @@
+#include "2048.hpp"
+#include "UI.hpp"
+#include "Extra.hpp"
+#include <ncurses.h>
+
+int main() {
+    initializeGame();
+
+    Game2048 game;
+    UI ui;
+
+    ui.drawBoard(game);
+
+    while (true) {
+        ui.handleInput(game);
+        ui.drawBoard(game);
+
+        if (!game.canMove()) {
+            ui.showGameOver();
+            break;
+        }
+    }
+
+    cleanupGame();
+    return 0;
+}
\ No newline at end of file
diff --git a/src/main.o b/src/main.o
new file mode 100644
index 0000000000000000000000000000000000000000..81e031e499cf37f1c37af6a7495a82b1b505cd12
Binary files /dev/null and b/src/main.o differ