You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
6.8 KiB
C++

3 years ago
#include "board.h"
#include <cstdlib>
#include <iostream>
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<unsigned int>(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<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_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;