Organize Grid cpp code
This commit is contained in:
parent
afd4ba110f
commit
af7f2fc870
1 changed files with 255 additions and 248 deletions
|
@ -1,5 +1,7 @@
|
||||||
#include "Grid.hpp"
|
#include "Grid.hpp"
|
||||||
|
|
||||||
|
//==================== Constructor and Destructor ====================
|
||||||
|
|
||||||
//Constructor
|
//Constructor
|
||||||
Grid::Grid(): m_size(4), m_grid(4){
|
Grid::Grid(): m_size(4), m_grid(4){
|
||||||
|
|
||||||
|
@ -16,6 +18,251 @@ Grid::~Grid(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==================== Merge and defragment methods ====================
|
||||||
|
|
||||||
|
//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);
|
||||||
|
int val2=line.at(i+1);
|
||||||
|
|
||||||
|
if(val1 != 0 && val2 == 0){
|
||||||
|
line.at(i)=0;
|
||||||
|
line.at(i+1)=val1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 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);
|
||||||
|
|
||||||
|
if(val1==val2){
|
||||||
|
line.at(i)=0;
|
||||||
|
line.at(i+1)=val1*2;
|
||||||
|
m_lastMoveScore+=val1*2;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 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);
|
||||||
|
|
||||||
|
if(val1==val2){
|
||||||
|
line.at(i)=0;
|
||||||
|
line.at(i-1)=val1*2;
|
||||||
|
m_lastMoveScore+=val1*2;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==================== Swipe methods ====================
|
||||||
|
|
||||||
|
|
||||||
|
//Swipe to the right
|
||||||
|
bool Grid::swipeRight(){
|
||||||
|
|
||||||
|
m_lastMoveScore=0;
|
||||||
|
bool moveDone=false;
|
||||||
|
for(int i=0; i<m_size;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 the left
|
||||||
|
bool Grid::swipeLeft(){
|
||||||
|
m_lastMoveScore=0;
|
||||||
|
bool moveDone=false;
|
||||||
|
for(int i=0; i<m_size;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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//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);
|
||||||
|
|
||||||
|
std::vector<int> swipedLine(this->leftDefragment(this->rightMerge(this->leftDefragment(colVect))));
|
||||||
|
if(!this->compareLines(colVect, swipedLine)){
|
||||||
|
moveDone=true;
|
||||||
|
this->setCol(i,swipedLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return moveDone;
|
||||||
|
}
|
||||||
|
//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);
|
||||||
|
|
||||||
|
std::vector<int> swipedLine(this->rightDefragment(this->leftMerge(this->rightDefragment(colVect))));
|
||||||
|
|
||||||
|
if(!this->compareLines(colVect, swipedLine)){
|
||||||
|
moveDone=true;
|
||||||
|
this->setCol(i,swipedLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return moveDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==================== 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++){
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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++){
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Reverse a line
|
||||||
|
std::vector<int> Grid::reverseLine(std::vector<int> line){
|
||||||
|
std::vector<int> reversedLine;
|
||||||
|
|
||||||
|
for(int j=m_size-1; j>=0;j--){
|
||||||
|
reversedLine.push_back(line.at(j));
|
||||||
|
}
|
||||||
|
|
||||||
|
return reversedLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Return true if the grid is full. False else.
|
||||||
|
bool Grid::isFull(){
|
||||||
|
|
||||||
|
for(int i=0;i<m_size;i++){
|
||||||
|
for(int j=0;j<m_size;j++){
|
||||||
|
if(m_grid.at(i).at(j) == 0)
|
||||||
|
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())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for(int i=0;i<m_size;i++){
|
||||||
|
for(int j=0;j<m_size-1;j++){
|
||||||
|
if(m_grid.at(i).at(j) == m_grid.at(i).at(j+1))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0;i<m_size;i++){
|
||||||
|
std::vector<int> colVect(this->getCol(i));
|
||||||
|
|
||||||
|
for(int j=0;j<m_size-1;j++){
|
||||||
|
if(colVect.at(j) == colVect.at(j+1))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//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(){
|
std::string Grid::description(){
|
||||||
|
|
||||||
//Init stringstream description
|
//Init stringstream description
|
||||||
|
@ -53,55 +300,15 @@ std::string Grid::description(){
|
||||||
return description.str();
|
return description.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==================== Getters and Setters ====================
|
||||||
|
|
||||||
int Grid::maxStrLenInGrid(){
|
//Getter for m_lastMoveScore
|
||||||
int max=0;
|
int Grid::getLastMoveScore(){
|
||||||
for(int i=0;i<m_size;i++){
|
return m_lastMoveScore;
|
||||||
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 with a tuple
|
||||||
//Change value of cell
|
|
||||||
bool Grid::setCell(std::tuple<int, int> coord, int value){
|
bool Grid::setCell(std::tuple<int, int> coord, int value){
|
||||||
int i=std::get<0>(coord);
|
int i=std::get<0>(coord);
|
||||||
int j=std::get<1>(coord);
|
int j=std::get<1>(coord);
|
||||||
|
@ -114,157 +321,20 @@ bool Grid::setCell(std::tuple<int, int> coord, int value){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Another setCell method
|
//Change value of cell with int
|
||||||
bool Grid::setCell(int i, int j, int value){
|
bool Grid::setCell(int i, int j, int value){
|
||||||
std::tuple<int, int> coord(i,j);
|
std::tuple<int, int> coord(i,j);
|
||||||
return this->setCell(coord, value);
|
return this->setCell(coord, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Assign a vector to a column.
|
||||||
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);
|
|
||||||
int val2=line.at(i+1);
|
|
||||||
|
|
||||||
if(val1 != 0 && val2 == 0){
|
|
||||||
line.at(i)=0;
|
|
||||||
line.at(i+1)=val1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<int> Grid::leftDefragment(std::vector<int> line){
|
|
||||||
|
|
||||||
//for(int j=0; j<m_size-1;j++){
|
|
||||||
//for(int i=m_size-1; i>0;i--){
|
|
||||||
//int val1=line.at(i);
|
|
||||||
//int val2=line.at(i-1);
|
|
||||||
|
|
||||||
//if(val1 != 0 && val2 == 0){
|
|
||||||
//line.at(i)=0;
|
|
||||||
//line.at(i-1)=val1;
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
std::vector<int> reversedLine= this->reverseLine(line);
|
|
||||||
|
|
||||||
return this->reverseLine(this->rightDefragment(reversedLine));
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
|
|
||||||
if(val1==val2){
|
|
||||||
line.at(i)=0;
|
|
||||||
line.at(i+1)=val1*2;
|
|
||||||
m_lastMoveScore+=val1*2;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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->rightDefragment(line);
|
|
||||||
line=this->rightMerge(line);
|
|
||||||
line=this->rightDefragment(line);
|
|
||||||
|
|
||||||
//Return swiped line
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Swipe to right
|
|
||||||
bool Grid::swipeRight(){
|
|
||||||
|
|
||||||
m_lastMoveScore=0;
|
|
||||||
bool moveDone=false;
|
|
||||||
for(int i=0; i<m_size;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
|
|
||||||
bool Grid::swipeLeft(){
|
|
||||||
m_lastMoveScore=0;
|
|
||||||
bool moveDone=false;
|
|
||||||
for(int i=0; i<m_size;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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Grid::swipeUp(){
|
|
||||||
m_lastMoveScore=0;
|
|
||||||
bool moveDone=false;
|
|
||||||
for(int i=0; i<m_size;i++){
|
|
||||||
std::vector<int> colVect=this->getCol(i);
|
|
||||||
|
|
||||||
std::vector<int> swipedLine(this->leftDefragment(this->rightMerge(this->leftDefragment(colVect))));
|
|
||||||
if(!this->compareLines(colVect, swipedLine)){
|
|
||||||
moveDone=true;
|
|
||||||
this->setCol(i,swipedLine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return moveDone;
|
|
||||||
}
|
|
||||||
bool Grid::swipeDown(){
|
|
||||||
m_lastMoveScore=0;
|
|
||||||
bool moveDone=false;
|
|
||||||
for(int i=0; i<m_size;i++){
|
|
||||||
std::vector<int> colVect=this->getCol(i);
|
|
||||||
|
|
||||||
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){
|
void Grid::setCol(int col, std::vector<int> colVect){
|
||||||
for(int i=0;i<m_size;i++){
|
for(int i=0;i<m_size;i++){
|
||||||
m_grid.at(i).at(col)=colVect.at(i);
|
m_grid.at(i).at(col)=colVect.at(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Retrieve a specific column.
|
||||||
std::vector<int> Grid::getCol(int col){
|
std::vector<int> Grid::getCol(int col){
|
||||||
|
|
||||||
std::vector<int> colVect;
|
std::vector<int> colVect;
|
||||||
|
@ -275,66 +345,3 @@ std::vector<int> Grid::getCol(int col){
|
||||||
|
|
||||||
return colVect;
|
return colVect;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> Grid::reverseLine(std::vector<int> line){
|
|
||||||
std::vector<int> reversedLine;
|
|
||||||
|
|
||||||
for(int j=m_size-1; j>=0;j--){
|
|
||||||
reversedLine.push_back(line.at(j));
|
|
||||||
}
|
|
||||||
|
|
||||||
return reversedLine;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Grid::isFull(){
|
|
||||||
|
|
||||||
for(int i=0;i<m_size;i++){
|
|
||||||
for(int j=0;j<m_size;j++){
|
|
||||||
if(m_grid.at(i).at(j) == 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Grid::isOver(){
|
|
||||||
|
|
||||||
if(!this->isFull())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for(int i=0;i<m_size;i++){
|
|
||||||
for(int j=0;j<m_size-1;j++){
|
|
||||||
if(m_grid.at(i).at(j) == m_grid.at(i).at(j+1))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i=0;i<m_size;i++){
|
|
||||||
std::vector<int> colVect(this->getCol(i));
|
|
||||||
|
|
||||||
for(int j=0;j<m_size-1;j++){
|
|
||||||
if(colVect.at(j) == colVect.at(j+1))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Grid::getLastMoveScore(){
|
|
||||||
return m_lastMoveScore;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue