225 lines
6.7 KiB
C++
225 lines
6.7 KiB
C++
#include "board.h"
|
|
#include <cstdlib>
|
|
#include <iostream>
|
|
|
|
Board::Board() :
|
|
selection_index(0),
|
|
on_selection(false)
|
|
{}
|
|
|
|
Board::~Board()
|
|
{
|
|
for (Cell *cell : vec_field)
|
|
{
|
|
delete cell->sprite;
|
|
delete cell;
|
|
}
|
|
}
|
|
|
|
void Board::draw(sf::RenderWindow& window)
|
|
{
|
|
for (const Cell *cell : vec_field)
|
|
window.draw(*cell->sprite);
|
|
|
|
window.draw(rect_selection);
|
|
}
|
|
|
|
bool Board::moveSelection(const DIRECTION &direction)
|
|
{
|
|
if (!on_selection)
|
|
{
|
|
switch (direction) {
|
|
case DIRECTION::UP:
|
|
if (selection_index < cells_on_width) // if upper row
|
|
return false;
|
|
selection_index -= cells_on_width;
|
|
setSelectionVertex(selection_index);
|
|
break;
|
|
|
|
case DIRECTION::DOWN:
|
|
if (selection_index > (cells_on_width * (cells_on_height - 1))) // if bottom row
|
|
return false;
|
|
selection_index += cells_on_width;
|
|
setSelectionVertex(selection_index);
|
|
break;
|
|
|
|
case DIRECTION::RIGHT:
|
|
++selection_index;
|
|
if (selection_index == vec_field.size()) // if the last cell of right bottom corner
|
|
selection_index = 0; // move to the first cell of upper left corner
|
|
setSelectionVertex(selection_index);
|
|
break;
|
|
|
|
case DIRECTION::LEFT:
|
|
if (selection_index == 0) // if the first cell of of upper left corner
|
|
selection_index = vec_field.size() - 1; // move to the last cell of right bottom corner
|
|
else
|
|
--selection_index;
|
|
setSelectionVertex(selection_index);
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
switch (direction) {
|
|
case DIRECTION::UP:
|
|
if (selection_index < cells_on_width) // if upper row
|
|
return false;
|
|
swapCells(selection_index, selection_index - cells_on_width);
|
|
selection_index -= cells_on_width;
|
|
setSelectionVertex(selection_index);
|
|
break;
|
|
|
|
case DIRECTION::DOWN:
|
|
if (selection_index > (cells_on_width * (cells_on_height - 1))) // if bottom row
|
|
return false;
|
|
swapCells(selection_index, selection_index + cells_on_width);
|
|
selection_index += cells_on_width;
|
|
setSelectionVertex(selection_index);
|
|
break;
|
|
|
|
case DIRECTION::RIGHT:
|
|
if ((selection_index + 1) % cells_on_width == 0)
|
|
return false;
|
|
swapCells(selection_index, selection_index + 1);
|
|
++selection_index;
|
|
setSelectionVertex(selection_index);
|
|
break;
|
|
|
|
case DIRECTION::LEFT:
|
|
if (((selection_index % cells_on_width == 0) && (selection_index > cells_on_width)) || selection_index == 0)
|
|
return false;
|
|
swapCells(selection_index, selection_index - 1);
|
|
--selection_index;
|
|
setSelectionVertex(selection_index);
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
on_selection = false;
|
|
return true;
|
|
}
|
|
|
|
void Board::onSelectionMode()
|
|
{
|
|
on_selection = !on_selection;
|
|
}
|
|
|
|
void Board::setSelectionVertex(Cells::size_type index)
|
|
{
|
|
const auto& cell = vec_field[index];
|
|
const auto& pos = cell->sprite->getPosition();
|
|
const auto& x = pos.x;
|
|
const auto& y = pos.y;
|
|
const float length = static_cast<float>(Cell::side_length);
|
|
|
|
rect_selection = sf::VertexArray(sf::LinesStrip, 5);
|
|
rect_selection[0].position = pos;
|
|
rect_selection[0].color = sf::Color::Red;
|
|
rect_selection[1].position = sf::Vector2f(x + length, y);
|
|
rect_selection[1].color = sf::Color::Red;
|
|
rect_selection[2].position = sf::Vector2f(x + length, y + length);
|
|
rect_selection[2].color = sf::Color::Red;
|
|
rect_selection[3].position = sf::Vector2f(x, y + length);
|
|
rect_selection[3].color = sf::Color::Red;
|
|
rect_selection[4].position = pos;
|
|
rect_selection[4].color = sf::Color::Red;
|
|
}
|
|
|
|
void Board::swapCells(Cells::size_type curr_index, Cells::size_type swap_index)
|
|
{
|
|
Cell *curr_cell = vec_field[curr_index];
|
|
Cell *swap_cell = vec_field[swap_index];
|
|
const sf::Vector2f temp_pos = curr_cell->sprite->getPosition();
|
|
const Cells::size_type temp_cell_index = curr_cell->current_index;
|
|
|
|
curr_cell->sprite->setPosition(swap_cell->sprite->getPosition());
|
|
curr_cell->current_index = swap_cell->current_index;
|
|
|
|
swap_cell->sprite->setPosition(temp_pos);
|
|
swap_cell->current_index = temp_cell_index;
|
|
|
|
Cell* temp = vec_field[curr_index];
|
|
vec_field[curr_index] = vec_field[swap_index];
|
|
vec_field[swap_index] = temp;
|
|
}
|
|
|
|
bool Board::isWinCondition() const
|
|
{
|
|
return std::all_of(vec_field.begin(), vec_field.end(), [](const Cell *cell){ return cell->current_index == cell->inital_index; });
|
|
}
|
|
|
|
bool Board::init(int splitting, const std::string& path)
|
|
{
|
|
// PREPARING INITIAL BOARD STATE //
|
|
|
|
if (!global_texture.loadFromFile(path) )
|
|
return EXIT_FAILURE;
|
|
|
|
if (splitting <= 1) // If it's 1, the game is already over
|
|
{
|
|
sf::Sprite* sp = new sf::Sprite(global_texture);
|
|
vec_field.push_back(new Cell{0, 0, sp});
|
|
return EXIT_SUCCESS; // why not
|
|
}
|
|
|
|
const int width = global_texture.getSize().x;
|
|
const int height = global_texture.getSize().y;
|
|
|
|
Cell::side_length = (width < height) ? width / splitting : height / splitting;
|
|
cells_on_height = height / Cell::side_length;
|
|
cells_on_width = width / Cell::side_length;
|
|
|
|
vec_field.reserve(cells_on_height * cells_on_width);
|
|
|
|
/* Iterating board cells' screen positions.
|
|
* The initial image after this would look exactly like the loaded picture, not shuffled yet. */
|
|
Cells::size_type index = 0;
|
|
for (int x = 0; x < height; x += Cell::side_length)
|
|
{
|
|
if ((height - x) >= Cell::side_length)
|
|
{
|
|
for (int y = 0; y < width; y += Cell::side_length)
|
|
{
|
|
if ((width - y) >= Cell::side_length)
|
|
{
|
|
sf::Sprite* sp = new sf::Sprite(global_texture, sf::IntRect(y, x, Cell::side_length, Cell::side_length));
|
|
sp->setPosition(static_cast<float>(y), static_cast<float>(x));
|
|
|
|
vec_field.push_back(new Cell({index, index, sp}));
|
|
++index;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// SHUFFLING //
|
|
|
|
srand(static_cast<unsigned int>(time(nullptr)));
|
|
for (Cells::size_type curr_i = 0; curr_i < vec_field.size(); ++curr_i)
|
|
{
|
|
Cells::size_type swap_i;
|
|
do
|
|
{ // find two different tiles
|
|
swap_i = rand() & (vec_field.size() - 1);
|
|
} while (curr_i == swap_i);
|
|
|
|
swapCells(curr_i, swap_i);
|
|
}
|
|
|
|
// Set initial position of cursor
|
|
setSelectionVertex(selection_index);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
int Board::Cell::side_length = 0;
|