#include "board.h" #include #include const std::string picture_dest = "art.png"; Board::Board(int splitting) : selection_index(0), on_selection(false) { // PREPARING INITIAL BOARD STATE // if (!global_texture.loadFromFile(picture_dest) ) return; const float width = global_texture.getSize().x; const float 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); vec_ref.reserve(vec_field.size()); /* 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(y, x); vec_field.push_back({index, index, sp}); vec_ref.push_back(index); ++index; } } } } // SHUFFLING // srand(static_cast(time(nullptr))); for (Cells::iterator curr_it = vec_field.begin(); curr_it != vec_field.end(); ++curr_it) { bool success = false; while (!success) { Cells::iterator swap_it = cellByCurrentIndex(rand() & (vec_field.size() - 1)); if (curr_it->current_index == swap_it->current_index) continue; swapCells(curr_it, swap_it); success = true; } } setSelectionVertex(selection_index); } Board::~Board() { for (Cell& cell : vec_field) delete cell.sprite; } 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(cellByCurrentIndex(selection_index), cellByCurrentIndex(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(cellByCurrentIndex(selection_index), cellByCurrentIndex(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(cellByCurrentIndex(selection_index), cellByCurrentIndex(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(cellByCurrentIndex(selection_index), cellByCurrentIndex(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 = cellByCurrentIndex(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_cell_ind, Cells::size_type swap_cell_ind) { auto& curr_cell = vec_field[curr_cell_ind]; auto& swap_cell = vec_field[swap_cell_ind]; const sf::Vector2f temp_pos = curr_cell.sprite->getPosition(); const Cells::size_type temp_cell_index = curr_cell.current_index; curr_cell.sprite->setPosition(vec_field[swap_cell_ind].sprite->getPosition()); curr_cell.current_index = vec_field[swap_cell_ind].current_index; swap_cell.sprite->setPosition(temp_pos); swap_cell.current_index = temp_cell_index; } Board::Cells::iterator Board::cellByCurrentIndex(Cells::size_type index) { return std::find_if(vec_field.begin(), vec_field.end(), [&](const Cell& cell) { return cell.current_index == index; }); } bool Board::isWinCondition() const { return std::all_of(vec_field.begin(), vec_field.end(), [](const Cell& cell){ return cell.current_index == cell.inital_index; }); } int Board::Cell::side_length = 0;