Skip to content

Commit

Permalink
Merge pull request #72 from cawvyoct/fix/refactor_gameboard_files
Browse files Browse the repository at this point in the history
Fix: Refactor and move Gameboard{} and others to own source files
  • Loading branch information
cawvyoct committed Nov 5, 2018
2 parents 725f96d + 56588d5 commit db69fa1
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 220 deletions.
164 changes: 11 additions & 153 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,103 +117,12 @@ void Game::initialiseContinueBoardArray() {
}
}

bool Game::addTile() {
constexpr auto CHANCE_OF_VALUE_FOUR_OVER_TWO = 89; // Percentage
const auto freeTiles = collectFreeTiles();

if (!freeTiles.size()) {
boardFull = true;
}

const auto randomFreeTile = freeTiles.at(randInt() % freeTiles.size());
const auto value_four_or_two =
randInt() % 100 > CHANCE_OF_VALUE_FOUR_OVER_TWO ? 4 : 2;
gamePlayBoard.setTileValue(randomFreeTile, value_four_or_two);

moveCount++;
moved = true;

if (rexit) {
return !rexit;
}

return canMove();
}

std::vector<point2D_t> Game::collectFreeTiles() {
std::vector<point2D_t> freeTiles;
for (int y = 0; y < gamePlayBoard.getPlaySize(); y++) {
for (int x = 0; x < gamePlayBoard.getPlaySize(); x++) {
const auto current_point = point2D_t{x, y};
if (!gamePlayBoard.getTileValue(current_point)) {
freeTiles.push_back(current_point);
}
}
}
return freeTiles;
}

void Game::drawBoard() {

clearScreen();
drawAscii();
drawScoreBoard(std::cout);

for (int y = 0; y < gamePlayBoard.getPlaySize(); y++) {

std::cout << " ";

if (y == 0) {
std::cout << "";
} else {
std::cout << "";
}
for (int i = 0; i < gamePlayBoard.getPlaySize(); i++) {
std::cout << "──────";
if (i < gamePlayBoard.getPlaySize() - 1) {
if (y == 0) {
std::cout << "";
} else {
std::cout << "";
}
} else {
if (y == 0) {
std::cout << "";
} else {
std::cout << "";
}
}
}
newline();
std::cout << " ";

for (int x = 0; x < gamePlayBoard.getPlaySize(); x++) {

Tile currentTile = gamePlayBoard.getTile(point2D_t{x, y});

std::cout << "";
if (!currentTile.value) {
std::cout << " ";
} else {
std::cout << currentTile.tileColor(currentTile.value) << bold_on
<< std::setw(4) << currentTile.value << bold_off << def;
}
}

std::cout << "";
newline();
}

std::cout << "";
for (int i = 0; i < gamePlayBoard.getPlaySize(); i++) {
std::cout << "──────";
if (i < gamePlayBoard.getPlaySize() - 1) {
std::cout << "";
} else {
std::cout << "";
}
}
newline(3);
std::cout << gamePlayBoard;
}

void Game::drawScoreBoard(std::ostream &out_stream) {
Expand Down Expand Up @@ -310,16 +219,16 @@ void Game::input(KeyInputErrorStatus err) {
switch (c) {
case CODE_ANSI_UP:
decideMove(UP);
goto next;
return;
case CODE_ANSI_DOWN:
decideMove(DOWN);
goto next;
return;
case CODE_ANSI_RIGHT:
decideMove(RIGHT);
goto next;
return;
case CODE_ANSI_LEFT:
decideMove(LEFT);
goto next;
return;
}
} else {
newline(4);
Expand Down Expand Up @@ -356,61 +265,6 @@ void Game::input(KeyInputErrorStatus err) {
input(KeyInputErrorStatus::STATUS_INPUT_ERROR);
break;
}

next:
unblockTiles();
}

bool Game::canMove() {

for (int y = 0; y < gamePlayBoard.getPlaySize(); y++) {
for (int x = 0; x < gamePlayBoard.getPlaySize(); x++) {
if (!gamePlayBoard.getTileValue(point2D_t{x, y})) {
return true;
}
}
}

for (int y = 0; y < gamePlayBoard.getPlaySize(); y++) {
for (int x = 0; x < gamePlayBoard.getPlaySize(); x++) {
const auto current_point_value =
gamePlayBoard.getTileValue(point2D_t{x, y});
if (testAdd(point2D_t{x, y + 1}, current_point_value)) {
return true;
}
if (testAdd(point2D_t{x, y - 1}, current_point_value)) {
return true;
}
if (testAdd(point2D_t{x + 1, y}, current_point_value)) {
return true;
}
if (testAdd(point2D_t{x - 1, y}, current_point_value)) {
return true;
}
}
}

return false;
}

bool Game::testAdd(point2D_t pt, ull value) {
int x, y;
std::tie(x, y) = pt.get();
if (y < 0 || y > gamePlayBoard.getPlaySize() - 1 || x < 0 ||
x > gamePlayBoard.getPlaySize() - 1) {
return false;
}

return gamePlayBoard.getTileValue(pt) == value;
}

void Game::unblockTiles() {

for (int y = 0; y < gamePlayBoard.getPlaySize(); y++) {
for (int x = 0; x < gamePlayBoard.getPlaySize(); x++) {
gamePlayBoard.setTileBlocked(point2D_t{x, y}, false);
}
}
}

void Game::decideMove(Directions d) {
Expand Down Expand Up @@ -610,7 +464,10 @@ void Game::playGame(ContinueStatus cont) {
while (true) {

if (moved) {
if (!addTile()) {
boardFull = gamePlayBoard.addTile();
moveCount++;
moved = true;
if (!gamePlayBoard.canMove()) {
drawBoard();
break;
}
Expand All @@ -625,6 +482,7 @@ void Game::playGame(ContinueStatus cont) {
stateSaved = false;
}
input();
gamePlayBoard.unblockTiles();
}

auto finishTime = std::chrono::high_resolution_clock::now();
Expand Down Expand Up @@ -695,7 +553,7 @@ void Game::startGame() {
ull userInput_PlaySize = setBoardSize();

gamePlayBoard = GameBoard(userInput_PlaySize);
addTile();
gamePlayBoard.addTile();

playGame(ContinueStatus::STATUS_END_GAME);
}
Expand Down
1 change: 1 addition & 0 deletions src/gameboard.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include <gameboard.hpp>
71 changes: 4 additions & 67 deletions src/headers/game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
#define GAME_H

#include "color.hpp"
#include "gameboard.hpp"
#include "global.hpp"
#include "point2d.hpp"
#include "scores.hpp"
#include "statistics.hpp"
#include <algorithm>
#include <chrono>
#include <cmath>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
Expand All @@ -20,67 +23,6 @@

enum Directions { UP, DOWN, RIGHT, LEFT };

class Tile {

public:
Tile() : value(0), blocked(false) {}
ull value;
bool blocked;
Color::Modifier tileColor(ull);
};

class RandInt {
public:
using clock = std::chrono::system_clock;
RandInt() : dist{0, std::numeric_limits<int>::max()} {
seed(clock::now().time_since_epoch().count());
}
RandInt(const int low, const int high) : dist{low, high} {
seed(clock::now().time_since_epoch().count());
}
int operator()() { return dist(re); }
void seed(const unsigned int s) { re.seed(s); }

private:
std::minstd_rand re;
std::uniform_int_distribution<> dist;
};

class GameBoard {
std::vector<Tile> board;
ull playsize{0};
int point2D_to_1D_index(point2D_t pt) const {
int x, y;
std::tie(x, y) = pt.get();
return x + playsize * y;
}

public:
GameBoard() = default;
explicit GameBoard(ull playsize)
: playsize{playsize}, board{std::vector<Tile>(playsize * playsize)} {}

Tile getTile(point2D_t pt) const { return board[point2D_to_1D_index(pt)]; }
void setTile(point2D_t pt, Tile tile) {
board[point2D_to_1D_index(pt)] = tile;
}
ull getTileValue(point2D_t pt) const {
return board[point2D_to_1D_index(pt)].value;
}
void setTileValue(point2D_t pt, ull value) {
board[point2D_to_1D_index(pt)].value = value;
}
bool getTileBlocked(point2D_t pt) const {
return board[point2D_to_1D_index(pt)].blocked;
}
void setTileBlocked(point2D_t pt, bool blocked) {
board[point2D_to_1D_index(pt)].blocked = blocked;
}
void clearGameBoard() { board = std::vector<Tile>(playsize * playsize); }
int getPlaySize() const { return playsize; }
void setPlaySize(ull newSize) { playsize = newSize; }
};

class Game {

private:
Expand All @@ -103,14 +45,9 @@ class Game {
enum { COMPETITION_GAME_BOARD_PLAY_SIZE = 4 };

void initialiseContinueBoardArray();
bool addTile();
std::vector<point2D_t> collectFreeTiles();
void drawBoard();
void drawScoreBoard(std::ostream &out_stream);
void input(KeyInputErrorStatus err = STATUS_INPUT_VALID);
bool canMove();
bool testAdd(point2D_t pt, ull);
void unblockTiles();
void decideMove(Directions);
void move(point2D_t pt, point2D_t pt_offset);
void statistics();
Expand All @@ -123,7 +60,7 @@ class Game {
public:
Game()
: win(false), moved(true), boardFull(false), rexit(false), score(0),
bestScore(0), moveCount(-2), duration(0.0), largestTile(2),
bestScore(0), moveCount(-1), duration(0.0), largestTile(2),
stateSaved(false), noSave(false) {}
void startGame();
void continueGame();
Expand Down

0 comments on commit db69fa1

Please sign in to comment.