From 2fbe4a6052180f98dfac543d9b65d56f85ac398e Mon Sep 17 00:00:00 2001 From: zulianc Date: Mon, 3 Mar 2025 22:34:46 +0100 Subject: [PATCH] meilleurs coms ig --- src/Core/Bag.cpp | 14 ++--------- src/Core/Board.cpp | 5 ++-- src/Core/Game.cpp | 9 +++---- src/Core/GameBoard.cpp | 5 +--- src/Core/GameParameters.cpp | 4 --- src/Core/Menu.cpp | 5 ++-- src/Core/Menu.h | 4 ++- src/Core/Player.cpp | 7 ------ src/Core/Player.h | 7 ++++++ src/Pieces/Generator.cpp | 4 +-- src/Pieces/PiecesFiles.cpp | 1 + src/Pieces/Polyomino.cpp | 50 ++++++++++++++++--------------------- src/TextUI/TextApp.cpp | 19 ++++++++------ 13 files changed, 56 insertions(+), 78 deletions(-) diff --git a/src/Core/Bag.cpp b/src/Core/Bag.cpp index f7edb6e..bbff269 100644 --- a/src/Core/Bag.cpp +++ b/src/Core/Bag.cpp @@ -11,23 +11,19 @@ Bag::Bag(const std::shared_ptr& piecesList) : piecesList(piecesList) { - // initialize bags this->currentBag = this->piecesList->getSelectedPieces(); this->nextBag.clear(); - // prepare first piece this->prepareNext(); } void Bag::jumpToNextBag() { - // if the bag is empty switch to the next bag - if (this->currentBag.empty()) { + if (this->currentBag.size() < this->nextBag.size()) { std::swap(this->currentBag, this->nextBag); } - // get the already used pieces back to the current bag for (const std::pair& pieceIndex : this->nextBag) { - this->currentBag.emplace_back(pieceIndex); + this->currentBag.push_back(pieceIndex); } this->nextBag.clear(); } @@ -37,27 +33,21 @@ Piece Bag::lookNext() { } Piece Bag::getNext() { - // get the piece to return std::pair nextIndex = this->next; - // prepare the piece even after the next this->prepareNext(); - // return the next piece return this->piecesList->getPiece(nextIndex); } void Bag::prepareNext() { - // if the bag is empty switch to the next bag if (this->currentBag.empty()) { std::swap(this->currentBag, this->nextBag); } - // pick a random piece from the current bag int indexIndex = std::rand() % this->currentBag.size(); this->next = this->currentBag.at(indexIndex); - // move the piece over to the next bag this->nextBag.push_back(this->next); this->currentBag.erase(this->currentBag.begin() + indexIndex); } diff --git a/src/Core/Board.cpp b/src/Core/Board.cpp index 9ac46e4..7006d51 100644 --- a/src/Core/Board.cpp +++ b/src/Core/Board.cpp @@ -20,7 +20,6 @@ Board::Board(int width, int height) : } void Board::changeBlock(const Position& position, Block block) { - // if the block is out of bounds we discard it if (position.x < 0 || position.x >= this->width || position.y < 0) return; // resize the grid if needed @@ -62,7 +61,7 @@ int Board::clearRows() { if (lineIsFull) { this->grid.erase(this->grid.begin() + j); - if(this->grid.size() < height) { + if(this->grid.size() < this->height) { this->grid.push_back(this->emptyRow); } clearedLines++; @@ -74,7 +73,7 @@ int Board::clearRows() { void Board::clearBoard() { this->grid.clear(); - for (int j = 0; j < height; j++) { + for (int j = 0; j < this->height; j++) { this->grid.push_back(this->emptyRow); } } diff --git a/src/Core/Game.cpp b/src/Core/Game.cpp index 4f6a31b..f58d057 100644 --- a/src/Core/Game.cpp +++ b/src/Core/Game.cpp @@ -230,17 +230,14 @@ void Game::nextFrame(const std::set& playerActions) { return; } } - - // update remembered actions for next frame + + this->heldActions = playerActions; + if ((!this->started) || this->leftARETime > 0) { for (Action action : playerActions) { this->initialActions.insert(action); } - } - this->heldActions = playerActions; - - if (this->leftARETime > 0) { if (playerActions.contains(MOVE_LEFT)) { this->heldDAS = std::min(-1, this->heldDAS - 1); } diff --git a/src/Core/GameBoard.cpp b/src/Core/GameBoard.cpp index f5e0526..bcbd490 100644 --- a/src/Core/GameBoard.cpp +++ b/src/Core/GameBoard.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -150,7 +151,6 @@ bool GameBoard::tryKicking(bool testingBottom, const std::set& safePos } } - // do the same on the left side if (overlapsLeft) { Position shift{-i, j}; if (!this->activePieceOverlaps(safePositions, shift)) { @@ -220,7 +220,6 @@ bool GameBoard::hold(Rotation initialRotation) { this->heldPiece->defaultRotation(); - // this piece has done nothing yet this->isLastMoveKick = false; return true; @@ -232,8 +231,6 @@ bool GameBoard::spawnNextPiece() { this->nextQueue.erase(this->nextQueue.begin()); this->goToSpawnPosition(); - - // this piece has done nothing yet this->isLastMoveKick = false; return this->activePieceInWall(); diff --git a/src/Core/GameParameters.cpp b/src/Core/GameParameters.cpp index 16df69f..bbf8206 100644 --- a/src/Core/GameParameters.cpp +++ b/src/Core/GameParameters.cpp @@ -12,7 +12,6 @@ GameParameters::GameParameters(Gamemode gamemode, const Player& controls) : } void GameParameters::reset() { - // initialize lines and level this->clearedLines = 0; switch (this->gamemode) { // lowest gravity @@ -26,17 +25,14 @@ void GameParameters::reset() { default : this->level = 1; } - // initialize stats this->updateStats(); } void GameParameters::clearLines(int lineNumber) { - // update lines and level switch (this->gamemode) { // modes where level increases case MARATHON : case MASTER : { - // update cleared lines int previousLines = this->clearedLines; this->clearedLines += lineNumber; diff --git a/src/Core/Menu.cpp b/src/Core/Menu.cpp index 2be52e6..8d2d9e1 100644 --- a/src/Core/Menu.cpp +++ b/src/Core/Menu.cpp @@ -10,9 +10,8 @@ Menu::Menu() { this->piecesList = std::make_shared(PiecesList()); - // default board size - this->boardHeight = 20; - this->boardWidth = 10; + this->boardWidth = DEFAULT_BOARD_WIDTH; + this->boardHeight = DEFAULT_BOARD_HEIGHT; } Game Menu::startGame(Gamemode gamemode) const { diff --git a/src/Core/Menu.h b/src/Core/Menu.h index 27f98ef..954be3a 100644 --- a/src/Core/Menu.h +++ b/src/Core/Menu.h @@ -4,7 +4,9 @@ #include "Player.h" #include "Game.h" -static const int FRAMES_PER_SECOND = 60; // the number of frames per second, all the values in the game were choosen with this number in mind +static const int FRAMES_PER_SECOND = 60; // the number of frames per second, all the values in the game were choosen with this number in mind +static const int DEFAULT_BOARD_WIDTH = 10; // the default width of the board when starting the menu +static const int DEFAULT_BOARD_HEIGHT = 20; // the default height of the board when starting the menu /** diff --git a/src/Core/Player.cpp b/src/Core/Player.cpp index 7b6f68a..e01bcc6 100644 --- a/src/Core/Player.cpp +++ b/src/Core/Player.cpp @@ -1,12 +1,5 @@ #include "Player.h" -static const int DAS_MIN_VALUE = 0; // 0ms -static const int DAS_MAX_VALUE = 30; // 500ms -static const int ARR_MIN_VALUE = 0; // 0ms -static const int ARR_MAX_VALUE = 30; // 500ms -static const int SDR_MIN_VALUE = 0; // 0ms -static const int SDR_MAX_VALUE = 6; // 100ms - Player::Player() { // default settings diff --git a/src/Core/Player.h b/src/Core/Player.h index 69e0033..60cae91 100644 --- a/src/Core/Player.h +++ b/src/Core/Player.h @@ -1,5 +1,12 @@ #pragma once +static const int DAS_MIN_VALUE = 0; // the minimal selectable DAS value, equals to 0ms +static const int DAS_MAX_VALUE = 30; // the maximal selectable DAS value, equals to 500ms +static const int ARR_MIN_VALUE = 0; // the minimal selectable ARR value, equals to 0ms +static const int ARR_MAX_VALUE = 30; // the maximal selectable ARR value, equals to 500ms +static const int SDR_MIN_VALUE = 0; // the minimal selectable SDR value, equals to 0ms +static const int SDR_MAX_VALUE = 6; // the maximal selectable SDR value, equals to 100ms + /** * The controls of a player diff --git a/src/Pieces/Generator.cpp b/src/Pieces/Generator.cpp index 3e1db47..8329755 100644 --- a/src/Pieces/Generator.cpp +++ b/src/Pieces/Generator.cpp @@ -18,7 +18,7 @@ std::vector Generator::generatePolyominos(int polyominoSize) { // a polyomino has at least 1 square if (polyominoSize < 1) return this->validPolyominos; - // start generating from the monomino + // always place the first cell at (0, 0) this->currentTestedShape.insert(Position{0, 0}); std::map candidatePositions; @@ -57,7 +57,7 @@ void Generator::generate(int polyominoSize, int lastAddedPositionNumber, int nex this->tryToAddCandidatePosition(Position{position.x - 1, position.y}, nextAvaibleNumber, candidatePositions); } - // generate polyominos for all positions with a higher number than the last one + // try adding a square only to positions with a higher number than the last one for (auto [key, val] : candidatePositions) { if (val > lastAddedPositionNumber) { this->currentTestedShape.insert(key); diff --git a/src/Pieces/PiecesFiles.cpp b/src/Pieces/PiecesFiles.cpp index a457b15..ee403c0 100644 --- a/src/Pieces/PiecesFiles.cpp +++ b/src/Pieces/PiecesFiles.cpp @@ -64,6 +64,7 @@ bool PiecesFiles::loadPieces(int polyominoSize, std::vector& pieces, std: holelessPieces.clear(); otherPieces.clear(); + // we shift the first color of each size so that the small polyominos (size 1-2-3) don't all have the same color Block pieceBlock = firstPieceBlockType(); for (int i = 0; i < polyominoSize; i++) { nextPieceBlockType(pieceBlock); diff --git a/src/Pieces/Polyomino.cpp b/src/Pieces/Polyomino.cpp index 7ee6118..58ed2f8 100644 --- a/src/Pieces/Polyomino.cpp +++ b/src/Pieces/Polyomino.cpp @@ -7,10 +7,10 @@ #include #include #include +#include Polyomino::Polyomino(const std::set& positions) { - // find min/max int minX = INT_MAX; int maxX = INT_MIN; int minY = INT_MAX; @@ -22,15 +22,14 @@ Polyomino::Polyomino(const std::set& positions) { if (position.y > maxY) maxY = position.y; } - // normalize + this->length = std::max(maxX - minX + 1, maxY - minY + 1); + + // we normalize here instead of calling this->normalize() to reduce the number of calculations for the generation algorithm std::set newPositions; for (Position position : positions) { newPositions.insert(Position{position.x - minX, position.y - minY}); } this->positions = std::move(newPositions); - - // set polyomino length - this->length = std::max(maxX - minX + 1, maxY - minY + 1); } Polyomino::Polyomino(const std::set& positions, int length) : @@ -39,7 +38,6 @@ Polyomino::Polyomino(const std::set& positions, int length) : } void Polyomino::normalize() { - // find min values int minX = INT_MAX; int minY = INT_MAX; for (Position position : this->positions) { @@ -47,7 +45,6 @@ void Polyomino::normalize() { if (position.y < minY) minY = position.y; } - // translate the polyomino to the lowest unsigned values std::set newPositions; for (Position position : this->positions) { newPositions.insert(Position{position.x - minX, position.y - minY}); @@ -82,6 +79,7 @@ void Polyomino::rotateCCW() { void Polyomino::goToSpawnPosition() { // initialize array std::vector> linesCompleteness; + linesCompleteness.reserve(4); std::vector empty; for (int j = 0; j < this->length; j++) { empty.push_back(0); @@ -98,15 +96,15 @@ void Polyomino::goToSpawnPosition() { linesCompleteness.at(3).at(position.x) += 1; // 3 = left to right = CCW } - // count empty lines + // count empty lines and push the non-empty lines to the start of each vector int horizontalEmptyLines = 0; int verticalEmptyLines = 0; for (int i = 0; i < 4; i++) { for (int j = this->length - 1; j >= 0; j--) { if (linesCompleteness.at(i).at(j) == 0) { - // push the non-empty lines to the start of each vector linesCompleteness.at(i).erase(linesCompleteness.at(i).begin() + j); linesCompleteness.at(i).push_back(0); + if (i == 0) horizontalEmptyLines++; if (i == 1) verticalEmptyLines++; } @@ -124,11 +122,11 @@ void Polyomino::goToSpawnPosition() { currentFlattestSides[3] = false; } - // checks for the flattest sides + // checks for the flattest side int sideToBeOn = -1; this->checkForFlattestSide(linesCompleteness, currentFlattestSides, sideToBeOn, false); - // if all sides are as flat, checks for the most left-biased side + // if ther's no winner, checks for the side which has the flattest side to its left if (sideToBeOn == -1) { this->checkForFlattestSide(linesCompleteness, currentFlattestSides, sideToBeOn, true); } @@ -148,12 +146,16 @@ void Polyomino::goToSpawnPosition() { sideToBeOn = candidateSides.at(std::distance(candidateRotations.begin(), std::min_element(candidateRotations.begin(), candidateRotations.end()))); } - // do the correct rotation - if (sideToBeOn == 1) this->rotateCW(); - if (sideToBeOn == 2) this->rotate180(); - if (sideToBeOn == 3) this->rotateCCW(); + switch (sideToBeOn) { + case 1 : {this->rotateCW(); break;} + case 2 : {this->rotate180(); break;} + case 3 : {this->rotateCCW(); break;} + default: break; + } + if (sideToBeOn % 2 == 1) { + std::swap(verticalEmptyLines, horizontalEmptyLines); + } - // find min int minX = INT_MAX; int minY = INT_MAX; for (Position position : this->positions) { @@ -161,10 +163,7 @@ void Polyomino::goToSpawnPosition() { if (position.y < minY) minY = position.y; } - // center the piece with an up bias if it is assymetric - if (sideToBeOn % 2 == 1) { - std::swap(verticalEmptyLines, horizontalEmptyLines); - } + // center the piece with an up bias std::set newPositions; for (Position position : positions) { newPositions.insert(Position{(position.x - minX) + (verticalEmptyLines / 2), (position.y - minY) + ((horizontalEmptyLines + 1) / 2)}); @@ -174,19 +173,17 @@ void Polyomino::goToSpawnPosition() { void Polyomino::checkForFlattestSide(const std::vector>& linesCompleteness, bool currentFlattestSides[4], int& sideToBeOn, bool checkLeftSide) const { for (int j = 0; j < this->length; j++) { + // we check which sides are the flattest on this line int max = 0; std::set maxOwners; for (int i = 0; i < 4; i++) { - // only the candidate sides are compared if (!currentFlattestSides[i]) continue; - // if we need to check the flatness of the side to the left int sideToCheck = i; if (checkLeftSide) { sideToCheck = (i + 3) % 4; } - // we check which sides are the flattest if (linesCompleteness.at(sideToCheck).at(j) > max) { max = linesCompleteness.at(sideToCheck).at(j); maxOwners.clear(); @@ -203,7 +200,7 @@ void Polyomino::checkForFlattestSide(const std::vector>& linesC return; } - // else we only keep the flattest from this round and ignore the others + // else we only keep the flattest on this line and ignore the others else { for (int i = 0; i < 4; i++) { currentFlattestSides[i] = currentFlattestSides[i] && maxOwners.contains(i); @@ -213,14 +210,12 @@ void Polyomino::checkForFlattestSide(const std::vector>& linesC } bool Polyomino::isConvex() const { - // for each line and column we check if every squares are adjacent to each others for (int j = 0; j < this->length; j++) { bool startedLine = false; bool completedLine = false; bool startedColumn = false; bool completedColumn = false; for (int i = 0; i < this->length; i++) { - // line check if (this->positions.contains(Position{i, j})) { if (completedLine) return false; else startedLine = true; @@ -228,7 +223,7 @@ bool Polyomino::isConvex() const { else { if (startedLine) completedLine = true; } - // column check + if (this->positions.contains(Position{j, i})) { if (completedColumn) return false; else startedColumn = true; @@ -282,7 +277,6 @@ int Polyomino::getPolyominoSize() const { bool Polyomino::operator<(const Polyomino& other) const { if (this->length != other.length) return this->length < other.length; - // we check for all positions from left to right and top to bottom, until one has a square that the other doesn't for (int y = this->length - 1; y >= 0; y--) { for (int x = 0; x < this->length; x++) { bool hasThisPosition = this->positions.contains(Position{x, y}); diff --git a/src/TextUI/TextApp.cpp b/src/TextUI/TextApp.cpp index ce3c5eb..582d663 100644 --- a/src/TextUI/TextApp.cpp +++ b/src/TextUI/TextApp.cpp @@ -10,12 +10,12 @@ #include #include -static const int FRAMES_PER_INPUT = FRAMES_PER_SECOND / 2; -static const int MAXIMUM_PIECE_SIZE = 10; -static const int DEFAULT_PIECE_SIZE = 4; -static const int MAXIMUM_BOARD_WIDTH = 30; -static const int MAXIMUM_BOARD_HEIGHT = 40; -static const Gamemode DEFAULT_GAMEMODE = SPRINT; +static const int FRAMES_PER_INPUT = FRAMES_PER_SECOND / 2; // the number of frames that will pass everytime the player gives an input +static const int MAXIMUM_PIECE_SIZE = 10; // the maximum size of pieces that will be loaded and utilizable +static const int DEFAULT_PIECE_SIZE = 4; // the default size of pieces that will be selected when first running the app +static const int MAXIMUM_BOARD_WIDTH = 30; // the maximum selectable width of the board +static const int MAXIMUM_BOARD_HEIGHT = 40; // the maximum selectable height of the board +static const Gamemode DEFAULT_GAMEMODE = SPRINT; // the gamemode that will be used when starting a new game TextApp::TextApp() { @@ -31,8 +31,6 @@ TextApp::TextApp() { void TextApp::run() { bool quit = false; - std::string answer; - int selectedAnswer = 0; while (!quit) { std::cout << "\n\n\n"; std::cout << "===| WELCOME TO JMINOS! |===" << std::endl; @@ -42,7 +40,10 @@ void TextApp::run() { std::cout << "4- Start game" << std::endl; std::cout << "5- Quit" << std::endl; std::cout << "Choice: "; + + std::string answer; std::getline(std::cin, answer); + int selectedAnswer = 0; try { selectedAnswer = std::stoi(answer); } @@ -232,6 +233,7 @@ void TextApp::printGame(const Game& game) const { for (int y = maxHeight; y >= 0; y--) { for (int x = 0; x < game.getBoard().getWidth(); x++) { + /* BOARD PRINTING */ bool isActivePieceHere = (game.getActivePiece() != nullptr) && (game.getActivePiece()->getPositions().contains(Position{x, y} - game.getActivePiecePosition())); bool isGhostPieceHere = (game.getActivePiece() != nullptr) && (game.getActivePiece()->getPositions().contains(Position{x, y} - game.ghostPiecePosition())); Block block = (isActivePieceHere || isGhostPieceHere) ? game.getActivePiece()->getBlockType() : game.getBoard().getBlock(Position{x, y}); @@ -262,6 +264,7 @@ void TextApp::printGame(const Game& game) const { } if (y < game.getBoard().getGridHeight()) { + /* SIDEBAR PRINTING */ std::cout << " "; if (!lineCountPrinted) { std::cout << getResetConsoleColorCode() << "Lines: " << game.getClearedLines();