summaryrefslogtreecommitdiff
path: root/src/Model/Grid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Model/Grid.cpp')
-rw-r--r--src/Model/Grid.cpp355
1 files changed, 222 insertions, 133 deletions
diff --git a/src/Model/Grid.cpp b/src/Model/Grid.cpp
index 3a8a075..cc0fe60 100644
--- a/src/Model/Grid.cpp
+++ b/src/Model/Grid.cpp
@@ -1,5 +1,7 @@
#include "Grid.hpp"
+//==================== Constructor and Destructor ====================
+
//Constructor
Grid::Grid(): m_size(4), m_grid(4){
@@ -9,7 +11,6 @@ Grid::Grid(): m_size(4), m_grid(4){
m_grid.at(i).push_back(0);
}
}
-
}
//Destructor
@@ -17,109 +18,10 @@ Grid::~Grid(){
}
-std::string Grid::description(){
-
- //Init stringstream description
- std::stringstream description;
-
- //Get max str len of the grid
- int maxStrLen=this->maxStrLenInGrid();
-
- //Start to write description
- std::stringstream gridBorder;
- for(int i=0;i<(maxStrLen+2)*4+1;i++){
- gridBorder<<"-";
- }
- description << std::endl << gridBorder.str() << std::endl;
- for(int i=0;i<m_size;i++){
- for(int j=0;j<m_size;j++){
- std::stringstream spaceCol;
- for(int k=0;k<maxStrLen-std::to_string(m_grid.at(i).at(j)).size();k++){
- spaceCol << " ";
- }
- if(m_grid.at(i).at(j) == 0)
- description << "| " << " " << spaceCol.str();
- else
- description << "| " << m_grid.at(i).at(j) << spaceCol.str();
- }
- description << "|";
- description << std::endl;
- }
- description << gridBorder.str() << std::endl << std::endl;
-
- //Return description
- return description.str();
-}
-
-
-int Grid::maxStrLenInGrid(){
- int max=0;
- for(int i=0;i<m_size;i++){
- for(int j=0;j<m_size;j++){
- std::string number=std::to_string(m_grid.at(i).at(j));
- if(number.size() > max)
- max=number.size();
- }
- }
- return max;
-}
-
-bool Grid::isEmpty(int i, int j){
- if(m_grid.at(i).at(j) == 0)
- return true;
- return false;
-}
-
-std::tuple<int, int> Grid::getRandomEmptyCellCoord(){
-
- //Init list of candidate
- std::vector<std::tuple<int, int> > candidates;
-
- //Construct list of candidates
- for(int i=0;i<m_size;i++){
- for(int j=0;j<m_size;j++){
- if(this->isEmpty(i,j)){
- std::tuple<int, int> currentCandidate(i,j);
- candidates.push_back(currentCandidate);
- }
- }
- }
-
- //If no candidate available
- if(candidates.size() == 0)
- return std::tuple<int, int>(-1, -1);
-
- //Select the candidates
- int winnerIs(rand() % candidates.size());
-
- //Return the candidate
- return candidates.at(winnerIs);
-
-}
-
-
-
-//Change value of cell
-bool Grid::setCell(std::tuple<int, int> coord, int value){
- int i=std::get<0>(coord);
- int j=std::get<1>(coord);
+//==================== Merge and defragment methods ====================
- if(i>=0 && i<m_size && j>=0 && j<m_size){
- m_grid.at(i).at(j)=value;
- return true;
- }
-
- return false;
-}
-
-//Another setCell method
-bool Grid::setCell(int i, int j, int value){
- std::tuple<int, int> coord(i,j);
- return this->setCell(coord, value);
-}
-
-
-std::vector<int> Grid::defragmentLine(std::vector<int> line){
+//Defragment the line to the right
+std::vector<int> Grid::rightDefragment(std::vector<int> line){
for(int j=0; j<m_size-1;j++){
for(int i=0; i<m_size-1;i++){
int val1=line.at(i);
@@ -134,7 +36,16 @@ std::vector<int> Grid::defragmentLine(std::vector<int> line){
return line;
}
-std::vector<int> Grid::mergeLine(std::vector<int> line){
+//Defragment the line to the left using right defragmentation
+std::vector<int> Grid::leftDefragment(std::vector<int> line){
+
+ std::vector<int> reversedLine= this->reverseLine(line);
+
+ return this->reverseLine(this->rightDefragment(reversedLine));
+}
+
+//Merge line to the right
+std::vector<int> Grid::rightMerge(std::vector<int> line){
for(int i=0; i< m_size-1;i++){
int val1=line.at(i);
int val2=line.at(i+1);
@@ -142,72 +53,153 @@ std::vector<int> Grid::mergeLine(std::vector<int> line){
if(val1==val2){
line.at(i)=0;
line.at(i+1)=val1*2;
+ m_lastMoveScore+=val1*2;
i++;
}
}
return line;
}
-std::vector<int> Grid::swipeLine(std::vector<int> line){
-
- //Swipe line is :
- //- A defragmentation
- //- A merging
- //- Another defragmentation
- line=this->defragmentLine(line);
- line=this->mergeLine(line);
- line=this->defragmentLine(line);
+//Merge line to the left
+std::vector<int> Grid::leftMerge(std::vector<int> line){
+ for(int i=m_size-1; i>0;i--){
+ int val1=line.at(i);
+ int val2=line.at(i-1);
- //Return swiped line
+ if(val1==val2){
+ line.at(i)=0;
+ line.at(i-1)=val1*2;
+ m_lastMoveScore+=val1*2;
+ i--;
+ }
+ }
return line;
}
-//Swipe to right
-void Grid::swipeRight(){
+//==================== Swipe methods ====================
+
+
+//Swipe to the right
+bool Grid::swipeRight(){
+
+ m_lastMoveScore=0;
+ bool moveDone=false;
for(int i=0; i<m_size;i++){
- m_grid.at(i)=this->swipeLine(m_grid.at(i));
+ std::vector<int> swipedLine(this->rightDefragment(this->leftMerge(this->rightDefragment(m_grid.at(i)))));
+
+ if(!this->compareLines(m_grid.at(i), swipedLine)){
+ moveDone=true;
+ m_grid.at(i)=swipedLine;
+ }
}
+ return moveDone;
}
-//Swipe to right
-void Grid::swipeLeft(){
+//Swipe to the left
+bool Grid::swipeLeft(){
+ m_lastMoveScore=0;
+ bool moveDone=false;
for(int i=0; i<m_size;i++){
- m_grid.at(i)=this->reverseLine(this->swipeLine(this->reverseLine(m_grid.at(i))));
+ std::vector<int> swipedLine(this->leftDefragment(this->rightMerge(this->leftDefragment(m_grid.at(i)))));
+ if(!this->compareLines(m_grid.at(i), swipedLine)){
+ moveDone=true;
+ m_grid.at(i)=swipedLine;
+ }
}
+ return moveDone;
}
-void Grid::swipeUp(){
+//Swipe to the top
+bool Grid::swipeUp(){
+ m_lastMoveScore=0;
+ bool moveDone=false;
for(int i=0; i<m_size;i++){
std::vector<int> colVect=this->getCol(i);
- this->setCol(i,this->reverseLine(this->swipeLine(this->reverseLine(colVect))));
+
+ std::vector<int> swipedLine(this->leftDefragment(this->rightMerge(this->leftDefragment(colVect))));
+ if(!this->compareLines(colVect, swipedLine)){
+ moveDone=true;
+ this->setCol(i,swipedLine);
+ }
}
+ return moveDone;
}
-void Grid::swipeDown(){
+//Swipe to the bottom
+bool Grid::swipeDown(){
+ m_lastMoveScore=0;
+ bool moveDone=false;
for(int i=0; i<m_size;i++){
std::vector<int> colVect=this->getCol(i);
- this->setCol(i,this->swipeLine(colVect));
+
+ std::vector<int> swipedLine(this->rightDefragment(this->leftMerge(this->rightDefragment(colVect))));
+
+ if(!this->compareLines(colVect, swipedLine)){
+ moveDone=true;
+ this->setCol(i,swipedLine);
+ }
}
+ return moveDone;
}
-void Grid::setCol(int col, std::vector<int> colVect){
+//==================== Helpers ====================
+
+//Get the max len of a string of the numbers in the grid :
+// Exemple:
+// - 1 return 1
+// - 22 return 2
+// - 120 return 3
+// - 1000 return 4
+//This method help to calculate the columns size
+int Grid::maxStrLenInGrid(){
+ int max=0;
for(int i=0;i<m_size;i++){
- m_grid.at(i).at(col)=colVect.at(i);
+ for(int j=0;j<m_size;j++){
+ std::string number=std::to_string(m_grid.at(i).at(j));
+ if(number.size() > max)
+ max=number.size();
+ }
}
+ return max;
}
-std::vector<int> Grid::getCol(int col){
+//Test if the cell at (i,j) is empty
+bool Grid::isEmpty(int i, int j){
+ if(m_grid.at(i).at(j) == 0)
+ return true;
+ return false;
+}
- std::vector<int> colVect;
+//Return a tuple that contain a random empty cell
+std::tuple<int, int> Grid::getRandomEmptyCellCoord(){
+
+ //Init list of candidate
+ std::vector<std::tuple<int, int> > candidates;
+ //Construct list of candidates
for(int i=0;i<m_size;i++){
- colVect.push_back(m_grid.at(i).at(col));
+ for(int j=0;j<m_size;j++){
+ if(this->isEmpty(i,j)){
+ std::tuple<int, int> currentCandidate(i,j);
+ candidates.push_back(currentCandidate);
+ }
+ }
}
- return colVect;
+ //If no candidate available
+ if(candidates.size() == 0)
+ return std::tuple<int, int>(-1, -1);
+
+ //Select the candidates
+ int winnerIs(rand() % candidates.size());
+
+ //Return the candidate
+ return candidates.at(winnerIs);
+
}
+//Reverse a line
std::vector<int> Grid::reverseLine(std::vector<int> line){
std::vector<int> reversedLine;
@@ -218,7 +210,7 @@ std::vector<int> Grid::reverseLine(std::vector<int> line){
return reversedLine;
}
-
+//Return true if the grid is full. False else.
bool Grid::isFull(){
for(int i=0;i<m_size;i++){
@@ -227,10 +219,11 @@ bool Grid::isFull(){
return false;
}
}
-
+
return true;
}
+//Return true if the grid is full and no move can be performed. False else.
bool Grid::isOver(){
if(!this->isFull())
@@ -242,7 +235,7 @@ bool Grid::isOver(){
return false;
}
}
-
+
for(int i=0;i<m_size;i++){
std::vector<int> colVect(this->getCol(i));
@@ -256,3 +249,99 @@ bool Grid::isOver(){
}
+
+//Return true if line1 is equals to line2. False else.
+bool Grid::compareLines(std::vector<int> line1, std::vector<int> line2){
+
+ for(int i=0;i<m_size;i++){
+
+ if(line1.at(i) != line2.at(i))
+ return false;
+ }
+ return true;
+}
+
+//Return the description of the grid in a string.
+//In other terms, the grid in ASCII
+std::string Grid::description(){
+
+ //Init stringstream description
+ std::stringstream description;
+
+ //Get max str len of the grid
+ int maxStrLen=this->maxStrLenInGrid();
+
+ //Start to write description
+ std::stringstream gridBorder;
+ for(int i=0;i<(maxStrLen+1)*4+1;i++){
+ gridBorder<<"-";
+ }
+ description << std::endl << gridBorder.str() << std::endl;
+ for(int i=0;i<m_size;i++){
+ for(int j=0;j<m_size;j++){
+ std::stringstream spaceCol;
+ //Get number of space needed in cell
+ int nbSpace=maxStrLen-std::to_string(m_grid.at(i).at(j)).size();
+
+ for(int k=0;k<nbSpace;k++){
+ spaceCol << " ";
+ }
+ if(m_grid.at(i).at(j) == 0)
+ description << "|" << spaceCol.str() << " ";
+ else
+ description << "|"<< spaceCol.str() << m_grid.at(i).at(j) ;
+ }
+ description << "|";
+ description << std::endl;
+ }
+ description << gridBorder.str() << std::endl << std::endl;
+
+ //Return description
+ return description.str();
+}
+
+//==================== Getters and Setters ====================
+
+//Getter for m_lastMoveScore
+int Grid::getLastMoveScore(){
+ return m_lastMoveScore;
+}
+
+
+//Change value of cell with a tuple
+bool Grid::setCell(std::tuple<int, int> coord, int value){
+ int i=std::get<0>(coord);
+ int j=std::get<1>(coord);
+
+ if(i>=0 && i<m_size && j>=0 && j<m_size){
+ m_grid.at(i).at(j)=value;
+ return true;
+ }
+
+ return false;
+}
+
+//Change value of cell with int
+bool Grid::setCell(int i, int j, int value){
+ std::tuple<int, int> coord(i,j);
+ return this->setCell(coord, value);
+}
+
+//Assign a vector to a column.
+void Grid::setCol(int col, std::vector<int> colVect){
+ for(int i=0;i<m_size;i++){
+ m_grid.at(i).at(col)=colVect.at(i);
+ }
+}
+
+//Retrieve a specific column.
+std::vector<int> Grid::getCol(int col){
+
+ std::vector<int> colVect;
+
+ for(int i=0;i<m_size;i++){
+ colVect.push_back(m_grid.at(i).at(col));
+ }
+
+ return colVect;
+}