Как избежать дублирования кода
Есть метод класса, который добавляет корабль на игровое поле. Корабль может быть повёрнут в разные стороны, быть разной длины. Для добавления имеется такой код:
bool SeaBattleCore::addShip(PlayerNumber pn, Ship *s)
{
if (s == nullptr
|| s->getX() >= m_fieldSize || s->getX() < 0
|| s->getY() >= m_fieldSize || s->getY() < 0)
{
return false;
}
switch (s->getDir())
{
default:
case Direction::right:
if (s->getX() + s->getShipSize() > m_fieldSize)
{
return false;
}
for (unsigned int x = s->getX(); x < s->getX() + s->getShipSize(); ++x)
{
if (m_gameField[pn.getNumber()][x][s->getY()].haveShipInThisSquare())
{
return false;
}
}
for (unsigned int x = s->getX(); x < s->getX() + s->getShipSize(); ++x)
{
m_gameField[pn.getNumber()][x][s->getY()].setShip(s);
}
break;
case Direction::left:
if (s->getX() >= s->getShipSize() - 1)
{
return false;
}
for (unsigned int x = s->getX() + s->getShipSize() - 1; x >= s->getX() ; --x)
{
if (m_gameField[pn.getNumber()][x][s->getY()].haveShipInThisSquare())
{
return false;
}
}
for (unsigned int x = s->getX() + s->getShipSize() - 1; x >= s->getX() ; --x)
{
m_gameField[pn.getNumber()][x][s->getY()].setShip(s);
}
break;
case Direction::up:
if (s->getY() >= s->getShipSize() - 1)
{
return false;
}
for (unsigned int y = s->getY() + s->getShipSize() - 1; y >= s->getX() ; --y)
{
if (m_gameField[pn.getNumber()][s->getX()][y].haveShipInThisSquare())
{
return false;
}
}
for (unsigned int y = s->getY() + s->getShipSize() - 1; y >= s->getX() ; --y)
{
m_gameField[pn.getNumber()][s->getX()][y].setShip(s);
}
break;
case Direction::down:
if (s->getY() + s->getShipSize() > m_fieldSize)
{
return false;
}
for (unsigned int y = s->getX(); y < s->getX() + s->getShipSize(); ++y)
{
if (m_gameField[pn.getNumber()][s->getX()][y].haveShipInThisSquare())
{
return false;
}
}
for (unsigned int y = s->getX(); y < s->getX() + s->getShipSize(); ++y)
{
m_gameField[pn.getNumber()][s->getX()][y].setShip(s);
}
break;
}
}
Есть какие-нибудь идеи как избежать дублирование кода? Просто я дурачек |:b
Ответы (1 шт):
Автор решения: Zhihar
→ Ссылка
switch (s->getDir())
{
default:
case Direction::right:
а что так можно было? а в чем тогда смысл default?
если у вас корабли имеют одинаковую структуру, то вам надо только горизонтальная и вертикальная расположение
и тогда вам нужно будет только 2 цикла-проверки
для горизонтали:
bool is_correct = true;
for (int deck = 0; deck < decks_count; deck++)
{
if (pos_x + deck >= width) || (m_field[pos_x + deck][pos_y] != 0)
is_correct = false;
}
if (is_corrent)
{
for (int deck = 0; deck < decks_count; deck++)
m_field[pos_x + deck][pos_y] = 1;
}
для вертикали такой же:
при этом если правильно выбирать начало корабля, то проверка на выход за границы поля вообще не нужна:
const int pos_x = random(0, width - decks_count); // псевдокод - просто поставил функцию random чтобы показать диапазон значений
и тогда код станет таким:
bool is_correct = true;
for (int deck = 0; deck < decks_count; deck++)
{
if (m_field[pos_x + deck][pos_y] != 0)
is_correct = false;
}
if (is_corrent)
{
for (int deck = 0; deck < decks_count; deck++)
m_field[pos_x + deck][pos_y] = 1;
}