#include "board.h" #include #include 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(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(const std::string& path, int splitting, const sf::RenderWindow &window) { // PREPARING INITIAL BOARD STATE // if (!global_texture.loadFromFile(path) ) return false; 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(y), static_cast(x)); vec_field.push_back(new Cell({index, index, sp})); ++index; } } } } // SCALING // float scaling = 0.; if (width >= height && width > static_cast(window.getSize().x)) scaling = static_cast(window.getSize().x) / static_cast(width); if (height >= width && height > static_cast(window.getSize().y)) scaling = static_cast(window.getSize().y) / static_cast(height); if (scaling != 0.) { // Calculating new size of each tile int old_side_length = Cell::side_length; Cell::side_length = static_cast(static_cast(Cell::side_length) * scaling); int shift = Cell::side_length - old_side_length; float move_x, move_y; // Moving all scaled tiles up and left, to remove spacing for (Cells::size_type i = 0; i < vec_field.size(); ++i) { move_x = 0.f; move_y = 0.f; // The first column isn't allowed to move by x if (!(((i % cells_on_width == 0) && (i >= cells_on_width)))) move_x = static_cast(shift) * static_cast((i < cells_on_width) ? i : i % cells_on_width); // The first row isn't allowed to move by y if (i >= cells_on_width) move_y = static_cast(shift) * static_cast(i / cells_on_width); vec_field[i]->sprite->scale(scaling, scaling); vec_field[i]->sprite->move(move_x, move_y); } } // SHUFFLING // srand(static_cast(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 true; } int Board::Cell::side_length = 0;