diff --git a/2048 b/2048 index 9282b48a78ef1c2e12b4549b31ee62da69605d49..c7c546fcb6a8996c9f964d9987173c168731fa75 100755 Binary files a/2048 and b/2048 differ diff --git a/include/2048.hpp b/include/2048.hpp index 7ae5bbcd9a88874c7ef0907a5858469c832e7220..a3b667aae7bc80eefbef24e52fcd3d12370375a4 100644 --- a/include/2048.hpp +++ b/include/2048.hpp @@ -10,20 +10,22 @@ class Game2048 { private: Tile board[SIZE][SIZE]; bool moved; + int score; void spawnTile(); - void resetBoard(); + void addToScore(int value); public: Game2048(); + void resetBoard(); // Made public for restart functionality void drawBoard(); void moveLeft(); void moveRight(); void moveUp(); void moveDown(); bool canMove(); - int getScore(); - const Tile (*getBoard() const)[SIZE]; // Return Tile array instead of int array + int getScore() const; + const Tile (*getBoard() const)[SIZE]; }; #endif \ No newline at end of file diff --git a/include/Extra.hpp b/include/Extra.hpp index 539aa832bc5f6faf54ea2f358b6a17e0f363adba..e380a77ad2ea5e0a928f970c463fd5944690694f 100644 --- a/include/Extra.hpp +++ b/include/Extra.hpp @@ -5,5 +5,26 @@ void initializeGame(); void cleanupGame(); +void initColors(); // New function to initialize color pairs + +// Define color pair constants +enum ColorPairs { + COLOR_PAIR_DEFAULT = 1, + COLOR_PAIR_2 = 2, + COLOR_PAIR_4 = 3, + COLOR_PAIR_8 = 4, + COLOR_PAIR_16 = 5, + COLOR_PAIR_32 = 6, + COLOR_PAIR_64 = 7, + COLOR_PAIR_128 = 8, + COLOR_PAIR_256 = 9, + COLOR_PAIR_512 = 10, + COLOR_PAIR_1024 = 11, + COLOR_PAIR_2048 = 12, + COLOR_PAIR_HIGHER = 13 +}; + +// Function to get color pair based on tile value +int getTileColorPair(int value); #endif \ No newline at end of file diff --git a/include/UI.hpp b/include/UI.hpp index 36c9d787942f3bf5191318334c3073f7d6aac0ea..1e52a83003bb997c5b3254fdd82dbf87843a44f5 100644 --- a/include/UI.hpp +++ b/include/UI.hpp @@ -8,7 +8,9 @@ class UI { public: void drawBoard(const Game2048& game); void handleInput(Game2048& game); - void showGameOver(); + void showGameOver(Game2048& game); // Modified to allow restart + void displayScore(const Game2048& game); + void displayInstructions(); // New method to show game instructions }; #endif \ No newline at end of file diff --git a/src/2048.cpp b/src/2048.cpp index 6e64e22e4d47f2e1500d28601674e19a45e5ac61..dd59286d8271c2b77d812ad18cef2eee55370d2f 100644 --- a/src/2048.cpp +++ b/src/2048.cpp @@ -4,12 +4,13 @@ #include <ctime> #include <vector> -Game2048::Game2048() { +Game2048::Game2048() : score(0) { std::srand(std::time(0)); resetBoard(); } void Game2048::resetBoard() { + score = 0; for (int i = 0; i < SIZE; ++i) for (int j = 0; j < SIZE; ++j) board[i][j].setValue(0); @@ -31,6 +32,10 @@ void Game2048::spawnTile() { } } +void Game2048::addToScore(int value) { + score += value; +} + void Game2048::drawBoard() { clear(); for (int i = 0; i < SIZE; ++i) { @@ -49,7 +54,9 @@ void Game2048::moveLeft() { for (int j = 0; j < SIZE; ++j) { if (board[i][j].getValue() != 0) { if (index > 0 && temp[index - 1] == board[i][j]) { - temp[index - 1] *= 2; + int mergedValue = board[i][j].getValue() * 2; + temp[index - 1].setValue(mergedValue); + addToScore(mergedValue); // Add to score when tiles merge moved = true; } else { temp[index++] = board[i][j]; @@ -72,7 +79,9 @@ void Game2048::moveRight() { for (int j = SIZE - 1; j >= 0; --j) { if (board[i][j].getValue() != 0) { if (index < SIZE - 1 && temp[index + 1] == board[i][j]) { - temp[index + 1] *= 2; + int mergedValue = board[i][j].getValue() * 2; + temp[index + 1].setValue(mergedValue); + addToScore(mergedValue); // Add to score when tiles merge moved = true; } else { temp[index--] = board[i][j]; @@ -95,7 +104,9 @@ void Game2048::moveUp() { for (int i = 0; i < SIZE; ++i) { if (board[i][j].getValue() != 0) { if (index > 0 && temp[index - 1] == board[i][j]) { - temp[index - 1] *= 2; + int mergedValue = board[i][j].getValue() * 2; + temp[index - 1].setValue(mergedValue); + addToScore(mergedValue); // Add to score when tiles merge moved = true; } else { temp[index++] = board[i][j]; @@ -118,7 +129,9 @@ void Game2048::moveDown() { for (int i = SIZE - 1; i >= 0; --i) { if (board[i][j].getValue() != 0) { if (index < SIZE - 1 && temp[index + 1] == board[i][j]) { - temp[index + 1] *= 2; + int mergedValue = board[i][j].getValue() * 2; + temp[index + 1].setValue(mergedValue); + addToScore(mergedValue); // Add to score when tiles merge moved = true; } else { temp[index--] = board[i][j]; @@ -144,11 +157,7 @@ bool Game2048::canMove() { 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].getValue(); +int Game2048::getScore() const { return score; } diff --git a/src/2048.o b/src/2048.o index be2aee928509ea705690354e04eb0040bf3447ae..8980af415a3af453f1c2406f739659a30b323ac5 100644 Binary files a/src/2048.o and b/src/2048.o differ diff --git a/src/Extra.cpp b/src/Extra.cpp index 66f1cbad7cb73214f50a154c7e1e9a898adbaf50..da68b9dcdb63c8c9de7ffa328edb8ba51304e37c 100644 --- a/src/Extra.cpp +++ b/src/Extra.cpp @@ -6,6 +6,47 @@ void initializeGame() { noecho(); keypad(stdscr, TRUE); curs_set(0); + + // Initialize colors + if(has_colors()) { + start_color(); + initColors(); + } +} + +void initColors() { + // Initialize color pairs + init_pair(COLOR_PAIR_DEFAULT, COLOR_BLACK, COLOR_WHITE); + init_pair(COLOR_PAIR_2, COLOR_BLACK, COLOR_GREEN); + init_pair(COLOR_PAIR_4, COLOR_BLACK, COLOR_CYAN); + init_pair(COLOR_PAIR_8, COLOR_BLACK, COLOR_BLUE); + init_pair(COLOR_PAIR_16, COLOR_BLACK, COLOR_MAGENTA); + init_pair(COLOR_PAIR_32, COLOR_BLACK, COLOR_RED); + init_pair(COLOR_PAIR_64, COLOR_WHITE, COLOR_BLUE); + init_pair(COLOR_PAIR_128, COLOR_WHITE, COLOR_MAGENTA); + init_pair(COLOR_PAIR_256, COLOR_WHITE, COLOR_RED); + init_pair(COLOR_PAIR_512, COLOR_WHITE, COLOR_YELLOW); + init_pair(COLOR_PAIR_1024, COLOR_BLACK, COLOR_YELLOW); + init_pair(COLOR_PAIR_2048, COLOR_WHITE, COLOR_GREEN); + init_pair(COLOR_PAIR_HIGHER, COLOR_WHITE, COLOR_RED); +} + +int getTileColorPair(int value) { + switch(value) { + case 0: return COLOR_PAIR_DEFAULT; + case 2: return COLOR_PAIR_2; + case 4: return COLOR_PAIR_4; + case 8: return COLOR_PAIR_8; + case 16: return COLOR_PAIR_16; + case 32: return COLOR_PAIR_32; + case 64: return COLOR_PAIR_64; + case 128: return COLOR_PAIR_128; + case 256: return COLOR_PAIR_256; + case 512: return COLOR_PAIR_512; + case 1024: return COLOR_PAIR_1024; + case 2048: return COLOR_PAIR_2048; + default: return COLOR_PAIR_HIGHER; // For values > 2048 + } } void cleanupGame() { diff --git a/src/Extra.o b/src/Extra.o index c65d8bce46bd620e67c5c97fa4d9dd37416bd3a8..432792b0a7526b491a41031367d7f06027aadfd2 100644 Binary files a/src/Extra.o and b/src/Extra.o differ diff --git a/src/UI.cpp b/src/UI.cpp index 37f775b7e32ac2e6f75f5702c63e2de40344a37b..630870ca801c9bfe897577fda39d6e8a7c25c13e 100644 --- a/src/UI.cpp +++ b/src/UI.cpp @@ -1,17 +1,59 @@ #include "UI.hpp" #include "2048.hpp" +#include "Extra.hpp" #include <ncurses.h> +#include <cstdlib> void UI::drawBoard(const Game2048& game) { clear(); + + // Display title + attron(A_BOLD); + mvprintw(0, 0, "2048 Game"); + attroff(A_BOLD); + + // Display the board for (int i = 0; i < SIZE; ++i) { for (int j = 0; j < SIZE; ++j) { - mvprintw(i * 2, j * 5, "%4d", game.getBoard()[i][j].getValue()); + int value = game.getBoard()[i][j].getValue(); + int colorPair = getTileColorPair(value); + + // Calculate position for the tile + int yPos = i * 2 + 2; + int xPos = j * 6; + + // Draw the tile with color + attron(COLOR_PAIR(colorPair) | A_BOLD); + if (value != 0) { + mvprintw(yPos, xPos, "%5d", value); + } else { + mvprintw(yPos, xPos, " "); // Empty tile + } + attroff(COLOR_PAIR(colorPair) | A_BOLD); } } + + // Display the score with highlight + displayScore(game); + + // Display instructions + displayInstructions(); + refresh(); } +void UI::displayScore(const Game2048& game) { + attron(COLOR_PAIR(COLOR_PAIR_HIGHER) | A_BOLD); + mvprintw(0, SIZE * 6 + 2, "Score: %d", game.getScore()); + attroff(COLOR_PAIR(COLOR_PAIR_HIGHER) | A_BOLD); + + mvprintw(SIZE * 2 + 3, 0, "Score: %d", game.getScore()); +} + +void UI::displayInstructions() { + mvprintw(SIZE * 2 + 4, 0, "Controls: Arrow keys to move, 'r' to restart, 'q' to quit"); +} + void UI::handleInput(Game2048& game) { int ch = getch(); switch (ch) { @@ -19,10 +61,27 @@ void UI::handleInput(Game2048& game) { case KEY_RIGHT: game.moveRight(); break; case KEY_UP: game.moveUp(); break; case KEY_DOWN: game.moveDown(); break; + case 'r': case 'R': game.resetBoard(); break; // Restart on 'r' key + case 'q': case 'Q': endwin(); exit(0); break; // Quit on 'q' key } } -void UI::showGameOver() { - mvprintw(SIZE * 2, 0, "Game Over! Press any key to exit."); - getch(); +void UI::showGameOver(Game2048& game) { + attron(COLOR_PAIR(COLOR_PAIR_HIGHER) | A_BOLD); + mvprintw(SIZE * 2 + 6, 0, "GAME OVER!"); + attroff(COLOR_PAIR(COLOR_PAIR_HIGHER) | A_BOLD); + + mvprintw(SIZE * 2 + 7, 0, "Press 'r' to restart or 'q' to quit"); + refresh(); + + while (true) { + int ch = getch(); + if (ch == 'r' || ch == 'R') { + game.resetBoard(); + break; + } else if (ch == 'q' || ch == 'Q') { + endwin(); + exit(0); + } + } } \ No newline at end of file diff --git a/src/UI.o b/src/UI.o index 6884c76d42125ee5b58f5bdb8aee7765dd1e54f6..30433495b505e870cdf9860ba7f717ff9de76884 100644 Binary files a/src/UI.o and b/src/UI.o differ diff --git a/src/main.cpp b/src/main.cpp index 2ad697ab6c0dab29229113e1775bc6093e3458db..8708fb433038bf557f1965c71437a41a2a6c18e5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include <ncurses.h> int main() { + // Initialize the game and colors initializeGame(); Game2048 game; @@ -16,8 +17,9 @@ int main() { ui.drawBoard(game); if (!game.canMove()) { - ui.showGameOver(); - break; + ui.showGameOver(game); + // After restart, redraw the board + ui.drawBoard(game); } } diff --git a/src/main.o b/src/main.o index 81e031e499cf37f1c37af6a7495a82b1b505cd12..618be4a5c4dc1eefa3ddc87ac01405fe3e818fbd 100644 Binary files a/src/main.o and b/src/main.o differ