diff options
| author | Charles <sircharlesaze@gmail.com> | 2020-03-20 10:29:56 +0100 |
|---|---|---|
| committer | Charles <sircharlesaze@gmail.com> | 2020-03-20 10:29:56 +0100 |
| commit | 64f6f1eaa2ecc188292cfe4a7223606b8bcb3bf2 (patch) | |
| tree | 01717af5c690c66fa3b3a467d98a691de37763f0 /src | |
| parent | 19ae4e74aedbbfde9aaed9241f616decc3ec9059 (diff) | |
| download | 2048-64f6f1eaa2ecc188292cfe4a7223606b8bcb3bf2.tar.gz 2048-64f6f1eaa2ecc188292cfe4a7223606b8bcb3bf2.tar.bz2 2048-64f6f1eaa2ecc188292cfe4a7223606b8bcb3bf2.zip | |
refactoring to more cplusplusy version of classes
Diffstat (limited to 'src')
| -rw-r--r-- | src/expectimax.cpp | 12 | ||||
| -rw-r--r-- | src/game.cpp | 166 | ||||
| -rw-r--r-- | src/graphics.cpp | 161 | ||||
| -rw-r--r-- | src/main.cpp | 6 |
4 files changed, 192 insertions, 153 deletions
diff --git a/src/expectimax.cpp b/src/expectimax.cpp new file mode 100644 index 0000000..3d8bf54 --- /dev/null +++ b/src/expectimax.cpp @@ -0,0 +1,12 @@ +#include "expectimax.hpp" + +Expectimax::Expectimax(Game *g) +{ + game = g; +} + +Direction Expectimax::move() +{ + // algo(game->clone()); + return DIRECTION_UP; +} diff --git a/src/game.cpp b/src/game.cpp index b505f9f..7b9ee23 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1,96 +1,109 @@ #include "game.hpp" -Game::Game(int s) +Game::Game(int m_size): m_size(m_size), m_score(0) { - size = s; - grid = new int*[size]; - for (int i = 0; i < size; i++) + m_grid = new int*[m_size]; + for (int i = 0; i < m_size; i++) { - grid[i] = new int[size]; - for (int j = 0; j < size; j++) - grid[i][j] = 0; + m_grid[i] = new int[m_size]; + for (int j = 0; j < m_size; j++) + m_grid[i][j] = 0; } spawn(); spawn(); - score = 0; +} + +Game::Game(Game const &other): m_size(other.m_size), m_score(other.m_score) +{ + m_grid = new int*[m_size]; + for (int i = 0; i < m_size; i++) + { + m_grid[i] = new int[m_size]; + for (int j = 0; j < m_size; j++) + m_grid[i][j] = other.get(i, j); + } } Game::~Game() { - gridDestroy(grid); + for (int i = 0; i < m_size; i++) + delete []m_grid[i]; + delete []m_grid; } -int Game::getSize() +int Game::getSize() const { - return size; + return m_size; } -int Game::getScore() +int Game::getScore() const { - return score; + return m_score; } -int Game::at(int x, int y) +int Game::get(int y, int x) const { - return grid[y][x]; + return m_grid[y][x]; } -void Game::move(Direction direction) +bool Game::move(Direction direction) { std::vector<int> row; - int **saved = gridCopy(); + Game saved(*this); switch (direction) { case DIRECTION_LEFT: - for (int i = 0; i < size; i++) + for (int i = 0; i < m_size; i++) { row.clear(); - for (int j = 0; j < size; j++) - row.push_back(grid[i][j]); + for (int j = 0; j < m_size; j++) + row.push_back(m_grid[i][j]); mergeRow(row); - for (int j = 0; j < size; j++) - grid[i][j] = row[j]; + for (int j = 0; j < m_size; j++) + m_grid[i][j] = row[j]; } break; case DIRECTION_RIGHT: - for (int i = 0; i < size; i++) + for (int i = 0; i < m_size; i++) { row.clear(); - for (int j = size - 1; j >= 0; j--) - row.push_back(grid[i][j]); + for (int j = m_size - 1; j >= 0; j--) + row.push_back(m_grid[i][j]); mergeRow(row); - for (int j = size - 1; j >= 0; j--) - grid[i][j] = row[size - j - 1]; + for (int j = m_size - 1; j >= 0; j--) + m_grid[i][j] = row[m_size - j - 1]; } break; case DIRECTION_DOWN: - for (int j = 0; j < size; j++) + for (int j = 0; j < m_size; j++) { row.clear(); - for (int i = size - 1; i >= 0; i--) - row.push_back(grid[i][j]); + for (int i = m_size - 1; i >= 0; i--) + row.push_back(m_grid[i][j]); mergeRow(row); - for (int i = size - 1; i >= 0; i--) - grid[i][j] = row[size - i - 1]; + for (int i = m_size - 1; i >= 0; i--) + m_grid[i][j] = row[m_size - i - 1]; } break; case DIRECTION_UP: - for (int j = 0; j < size; j++) + for (int j = 0; j < m_size; j++) { row.clear(); - for (int i = 0; i < size; i++) - row.push_back(grid[i][j]); + for (int i = 0; i < m_size; i++) + row.push_back(m_grid[i][j]); mergeRow(row); - for (int i = 0; i < size; i++) - grid[i][j] = row[i]; + for (int i = 0; i < m_size; i++) + m_grid[i][j] = row[i]; } break; } - if (!gridEqual(saved)) + if (*this != saved) spawn(); - gridDestroy(saved); + else + return false; + return true; } void Game::spawn() @@ -99,32 +112,32 @@ void Game::spawn() if (lost()) return; - for (int i = 0; i < size; i++) - for (int j = 0; j < size; j++) + for (int i = 0; i < m_size; i++) + for (int j = 0; j < m_size; j++) { - if (grid[i][j] == 0) + if (m_grid[i][j] == 0) possible.push_back(std::make_pair(i, j)); } if (possible.size() < 1) return; std::pair<int, int> pos = possible[rand() % possible.size()]; - grid[pos.first][pos.second] = rand() % 2 == 0 ? 2 : 4; + m_grid[pos.first][pos.second] = rand() % 10 == 0 ? 4 : 2; } -bool Game::lost() +bool Game::lost() const { - for (int i = 0; i < size; i++) - for (int j = 0; j < size; j++) + for (int i = 0; i < m_size; i++) + for (int j = 0; j < m_size; j++) { - if (grid[i][j] == 0) + if (m_grid[i][j] == 0) return false; - if (i - 1 >= 0 && grid[i - 1][j] == grid[i][j]) + if (i - 1 >= 0 && m_grid[i - 1][j] == m_grid[i][j]) return false; - if (i + 1 < size && grid[i + 1][j] == grid[i][j]) + if (i + 1 < m_size && m_grid[i + 1][j] == m_grid[i][j]) return false; - if (j - 1 >= 0 && grid[i][j - 1] == grid[i][j]) + if (j - 1 >= 0 && m_grid[i][j - 1] == m_grid[i][j]) return false; - if (j + 1 < size && grid[i][j + 1] == grid[i][j]) + if (j + 1 < m_size && m_grid[i][j + 1] == m_grid[i][j]) return false; } return true; @@ -155,7 +168,7 @@ void Game::mergeRow(std::vector<int> &row) if (row[curr + 1] == row[curr]) { row[curr] *= 2; - score += row[curr]; + m_score += row[curr]; row[curr + 1] = 0; for (size_t i = curr + 1; i < row.size() - 1; i++) row[i] = row[i + 1]; @@ -163,30 +176,49 @@ void Game::mergeRow(std::vector<int> &row) } } -int **Game::gridCopy() +Game &Game::operator=(Game const &other) { - int **copy = new int*[size]; - for (int i = 0; i < size; i++) + if (this == &other) + return *this; + for (int i = 0; i < m_size; i++) + delete []m_grid[i]; + delete []m_grid; + m_size = other.m_size; + m_score = other.m_score; + m_grid = new int*[m_size]; + for (int i = 0; i < m_size; i++) { - copy[i] = new int[size]; - for (int j = 0; j < size; j++) - copy[i][j] = grid[i][j]; + m_grid[i] = new int[m_size]; + for (int j = 0; j < m_size; j++) + m_grid[i][j] = other.m_grid[i][j]; } - return copy; + return *this; } -bool Game::gridEqual(int **other) +bool operator==(Game const &a, Game const &b) { - for (int i = 0; i < size; i++) - for (int j = 0; j < size; j++) - if (grid[i][j] != other[i][j]) + if (a.getSize() != b.getSize()) + return false; + for (int i = 0; i < a.getSize(); i++) + for (int j = 0; j < a.getSize(); j++) + if (a.get(i, j) != b.get(i, j)) return false; return true; } -void Game::gridDestroy(int **g) +bool operator!=(Game const &a, Game const &b) { - for (int i = 0; i < size; i++) - delete []g[i]; - delete []g; + return !(a == b); +} + +std::ostream &operator<<(std::ostream &out, Game const &game) +{ + out << "score: " << game.getScore() << std::endl; + for (int i = 0; i < game.getSize(); i++) + { + for (int j = 0; j < game.getSize(); j++) + out << std::setw(5) << game.get(i, j) << " "; + out << std::endl; + } + return out; } diff --git a/src/graphics.cpp b/src/graphics.cpp index 7732bd2..0d9a054 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -2,81 +2,76 @@ #define CELL_GAP 5 #define GRID_BORDER 10 +#define UPDATE_DELAY 3 #define AI_TIME_STEP 100 -Graphics::Graphics(Game *g, std::string t, int w, int h, AI *a) +Graphics::Graphics(Game &game, std::string title, int width, int height, AI *ai): + m_running(true), m_game(game), m_title(title), m_width(width), m_height(height), m_ai(ai), m_aiTimeStep(AI_TIME_STEP) { - running = true; - game = g; - title = t; - width = w; - height = h; - gridSize = std::min(width, height); - ai = a; - aiTimeStep = AI_TIME_STEP; - aiNextTime = SDL_GetTicks(); + m_gridSize = std::min(m_width, m_height); + m_aiNextTime = SDL_GetTicks(); if (SDL_Init(SDL_INIT_VIDEO) < 0) error(); - if ((window = SDL_CreateWindow(title.c_str(), 0, 0, width, height, 0)) == NULL) + if ((m_window = SDL_CreateWindow(m_title.c_str(), 0, 0, m_width, m_height, 0)) == NULL) error(); - if ((renderer = SDL_CreateRenderer(window, -1, 0)) == NULL) + if ((m_renderer = SDL_CreateRenderer(m_window, -1, 0)) == NULL) error(); if (TTF_Init() < 0) error(); - if ((font = TTF_OpenFont("./font/noto_mono_regular.ttf", 16)) == NULL) + if ((m_font = TTF_OpenFont("./font/noto_mono_regular.ttf", 16)) == NULL) error(); - scoreText = newTextTex("score", {255, 255, 255, 255}); - palette[0] = {10, 10, 10, 255}; - palette[2] = {100, 100, 100, 255}; - palette[4] = {65, 65, 65, 255}; - palette[8] = {40, 40, 40, 255}; - palette[16] = {150, 50, 20, 255}; - palette[32] = {160, 70, 20, 255}; - palette[64] = {190, 80, 30, 255}; - palette[128] = {200, 100, 40, 255}; - palette[256] = {220, 120, 40, 255}; - palette[512] = {230, 180, 30, 255}; - palette[1024] = {230, 190, 20, 255}; - palette[2048] = {230, 200, 10, 255}; + m_scoreText = newTextTex("score", {255, 255, 255, 255}); + m_palette[0] = {10, 10, 10, 255}; + m_palette[2] = {100, 100, 100, 255}; + m_palette[4] = {65, 65, 65, 255}; + m_palette[8] = {40, 40, 40, 255}; + m_palette[16] = {150, 50, 20, 255}; + m_palette[32] = {160, 70, 20, 255}; + m_palette[64] = {190, 80, 30, 255}; + m_palette[128] = {200, 100, 40, 255}; + m_palette[256] = {220, 120, 40, 255}; + m_palette[512] = {230, 180, 30, 255}; + m_palette[1024] = {230, 190, 20, 255}; + m_palette[2048] = {230, 200, 10, 255}; } Graphics::~Graphics() { - for (size_t i = 0; i < numberTexBuf.size(); i++) - SDL_DestroyTexture(numberTexBuf[i].second); - TTF_CloseFont(font); + for (size_t i = 0; i < m_numberTexBuf.size(); i++) + SDL_DestroyTexture(m_numberTexBuf[i].second); + TTF_CloseFont(m_font); TTF_Quit(); - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); + SDL_DestroyRenderer(m_renderer); + SDL_DestroyWindow(m_window); SDL_Quit(); } void Graphics::update() { - if (game->lost()) - running = false; - SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); - SDL_RenderClear(renderer); + if (m_game.lost()) + m_running = false; + SDL_SetRenderDrawColor(m_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); + SDL_RenderClear(m_renderer); handleEvent(); drawGame(); drawScore(); - SDL_RenderPresent(renderer); - if (ai != NULL) + SDL_RenderPresent(m_renderer); + if (m_ai != NULL) { - if (SDL_TICKS_PASSED(SDL_GetTicks(), aiNextTime)) + if (SDL_TICKS_PASSED(SDL_GetTicks(), m_aiNextTime)) { - aiNextTime = SDL_GetTicks() + aiTimeStep; - game->move(ai->move()); + m_aiNextTime = SDL_GetTicks() + m_aiTimeStep; + m_game.move(m_ai->move()); } } - SDL_Delay(3); + SDL_Delay(UPDATE_DELAY); } void Graphics::drawGame() { - for (int i = 0; i < game->getSize(); i++) - for (int j = 0; j < game->getSize(); j++) + for (int i = 0; i < m_game.getSize(); i++) + for (int j = 0; j < m_game.getSize(); j++) drawCell(i, j); } @@ -86,60 +81,60 @@ void Graphics::drawCell(int x, int y) SDL_Texture *tex; SDL_Color c; - if ((tex = getNumberTex(game->at(x, y))) == NULL) - tex = addNumberTex(game->at(x, y)); - if (palette.find(game->at(x, y)) == palette.end()) + if ((tex = getNumberTex(m_game.get(y, x))) == NULL) + tex = addNumberTex(m_game.get(y, x)); + if (m_palette.find(m_game.get(y, x)) == m_palette.end()) c = {30, 30, 30, 255}; else - c = palette[game->at(x, y)]; - r.x = 2 + x * (gridSize / game->getSize()); - r.y = 2 + y * (gridSize / game->getSize()); - r.w = gridSize / game->getSize() - 5; - r.h = gridSize / game->getSize() - 5; - SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, SDL_ALPHA_OPAQUE); - SDL_RenderFillRect(renderer, &r); - if (game->at(x, y) != 0) + c = m_palette[m_game.get(y, x)]; + r.x = 2 + x * (m_gridSize / m_game.getSize()); + r.y = 2 + y * (m_gridSize / m_game.getSize()); + r.w = m_gridSize / m_game.getSize() - 5; + r.h = m_gridSize / m_game.getSize() - 5; + SDL_SetRenderDrawColor(m_renderer, c.r, c.g, c.b, SDL_ALPHA_OPAQUE); + SDL_RenderFillRect(m_renderer, &r); + if (m_game.get(y, x) != 0) { SDL_QueryTexture(tex, NULL, NULL, &r.w, &r.h); - r.x += gridSize / game->getSize() / 2 - r.w / 2; - r.y += gridSize / game->getSize() / 2 - r.h / 2; - SDL_RenderCopy(renderer, tex, NULL, &r); + r.x += m_gridSize / m_game.getSize() / 2 - r.w / 2; + r.y += m_gridSize / m_game.getSize() / 2 - r.h / 2; + SDL_RenderCopy(m_renderer, tex, NULL, &r); } } void Graphics::drawScore() { SDL_Rect r; - int dist = std::abs(width - height); + int dist = std::abs(m_width - m_height); if (dist < 50) return; - SDL_QueryTexture(scoreText, NULL, NULL, &r.w, &r.h); - if (width > height) + SDL_QueryTexture(m_scoreText, NULL, NULL, &r.w, &r.h); + if (m_width > m_height) { - r.x = width - dist / 2 - r.w / 2; - r.y = height / 2; + r.x = m_width - dist / 2 - r.w / 2; + r.y = m_height / 2; } else { - r.x = width / 2; - r.y = height - dist / 2 - r.h / 2; + r.x = m_width / 2; + r.y = m_height - dist / 2 - r.h / 2; } - SDL_RenderCopy(renderer, scoreText, NULL, &r); + SDL_RenderCopy(m_renderer, m_scoreText, NULL, &r); - SDL_Texture *scoreNumTex = newTextTex(std::to_string(game->getScore()), {255, 255, 255, 255}); + SDL_Texture *scoreNumTex = newTextTex(std::to_string(m_game.getScore()), {255, 255, 255, 255}); SDL_QueryTexture(scoreNumTex, NULL, NULL, &r.w, &r.h); - if (width > height) + if (m_width > m_height) r.y += 20; else r.x += 20; - SDL_RenderCopy(renderer, scoreNumTex, NULL, &r); + SDL_RenderCopy(m_renderer, scoreNumTex, NULL, &r); SDL_DestroyTexture(scoreNumTex); } -bool Graphics::isRunning() +bool Graphics::isRunning() const { - return running; + return m_running; } void Graphics::handleEvent() @@ -151,22 +146,22 @@ void Graphics::handleEvent() switch (e.type) { case SDL_QUIT: - running = false; + m_running = false; break; case SDL_KEYDOWN: switch (e.key.keysym.sym) { case SDLK_LEFT: - game->move(DIRECTION_LEFT); + m_game.move(DIRECTION_LEFT); break; case SDLK_RIGHT: - game->move(DIRECTION_RIGHT); + m_game.move(DIRECTION_RIGHT); break; case SDLK_DOWN: - game->move(DIRECTION_DOWN); + m_game.move(DIRECTION_DOWN); break; case SDLK_UP: - game->move(DIRECTION_UP); + m_game.move(DIRECTION_UP); break; } } @@ -178,15 +173,15 @@ SDL_Texture *Graphics::addNumberTex(int n) SDL_Texture *tex; SDL_Color c = {255, 255, 255, 255}; tex = newTextTex(std::to_string(n), c); - numberTexBuf.push_back(std::make_pair(n, tex)); + m_numberTexBuf.push_back(std::make_pair(n, tex)); return tex; } -SDL_Texture *Graphics::getNumberTex(int n) +SDL_Texture *Graphics::getNumberTex(int n) const { - for (size_t i = 0; i < numberTexBuf.size(); i++) - if (numberTexBuf[i].first == n) - return numberTexBuf[i].second; + for (size_t i = 0; i < m_numberTexBuf.size(); i++) + if (m_numberTexBuf[i].first == n) + return m_numberTexBuf[i].second; return NULL; } @@ -195,15 +190,15 @@ SDL_Texture *Graphics::newTextTex(std::string s, SDL_Color c) SDL_Surface *surface; SDL_Texture *tex; - if ((surface = TTF_RenderText_Solid(font, s.c_str(), c)) == NULL) + if ((surface = TTF_RenderText_Solid(m_font, s.c_str(), c)) == NULL) error(); - if ((tex = SDL_CreateTextureFromSurface(renderer, surface)) == NULL) + if ((tex = SDL_CreateTextureFromSurface(m_renderer, surface)) == NULL) error(); SDL_FreeSurface(surface); return (tex); } -void Graphics::error() +void Graphics::error() const { std::cout << SDL_GetError() << std::endl; exit(1); diff --git a/src/main.cpp b/src/main.cpp index a6da033..22fbc34 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,7 +8,7 @@ #define WINDOW_TITLE "2048" #define WINDOW_WIDTH 640 #define WINDOW_HEIGHT 480 -#define GAME_GRID_SIZE 6 +#define GAME_GRID_SIZE 4 int main(int argc, char **argv) { @@ -19,10 +19,10 @@ int main(int argc, char **argv) if (argc == 2 && strcmp(argv[1], "--ai") == 0) { RandAI ai = RandAI(&game); - graphics = new Graphics(&game, WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT, &ai); + graphics = new Graphics(game, WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT, &ai); } else - graphics = new Graphics(&game, WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT); + graphics = new Graphics(game, WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT); while (graphics->isRunning()) graphics->update(); delete graphics; |
