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