Морской Бой. Ошибка во время режима охоты на 3 и 4 палубного корабля
Всем уже известна игра "морской бой". Так вот у меня есть логическая ошибка в случае, когда бот находит одну из палуб корабля, состоящего из 3 или 4 ячеек.
То есть, представленный бот ранил корабль по координатам (4;4), (4;5). и вместо того, чтобы продолжить по прямой, выбрав координаты (4;6) или (4;3) он перескакивает сразу на (4;8), (4;9).
Функцию выстрелов бота прикрепил ниже вместе со вспомогательными.
Подскажите в чем ошибка.
Это главная функция – бот совершает один ход на доске противника.
В зависимости от состояния он стреляет либо случайно, либо продолжает добивать уже найденный корабль.
void BotPlayer::make_turn(Board& opponent_board) {
while (true) {
int x = -1, y = -1;
if (!targeting_queue.empty()) {
auto target = targeting_queue.back();
targeting_queue.pop_back();
x = target.first;
y = target.second;
}
else {
do {
x = rand() % 10;
y = rand() % 10;
} while (!is_valid_target(x, y));
}
if (!is_valid_target(x, y)) continue;
shots_made.push_back({ x, y });
try {
cout << "? Bot shoots at (" << x << ", " << y << "): ";
CellState result = opponent_board.shoot(x, y);
if (result == CellState::Killed) {
cout << "Killed!" << endl;
hunt_state = HuntState::Searching;
targeting_queue.clear();
break;
}
else if (result == CellState::Hit) {
cout << "Hit!" << endl;
if (hunt_state == HuntState::Searching) {
first_hit = { x, y };
queue_adjacent(x, y);
hunt_state = HuntState::Hunting;
}
else if (hunt_state == HuntState::Hunting) {
second_hit = { x, y };
calculate_direction();
hunt_state = HuntState::Targeting;
int dx = direction.first;
int dy = direction.second;
for (int step = 1; step < 4; ++step) {
int tx = second_hit.first + step * dx;
int ty = second_hit.second + step * dy;
if (is_valid_target(tx, ty)) targeting_queue.push_back({ tx, ty });
else break;
}
for (int step = 1; step < 4; ++step) {
int tx = first_hit.first - step * dx;
int ty = first_hit.second - step * dy;
if (is_valid_target(tx, ty)) targeting_queue.push_back({ tx, ty });
else break;
}
}
else if (hunt_state == HuntState::Targeting) {
int dx = direction.first;
int dy = direction.second;
int tx = x + dx;
int ty = y + dy;
if (is_valid_target(tx, ty)) {
targeting_queue.push_back({ tx, ty });
}
else {
for (int step = 1; step < 4; ++step) {
int back_x = first_hit.first - step * dx;
int back_y = first_hit.second - step * dy;
if (is_valid_target(back_x, back_y)) {
targeting_queue.push_back({ back_x, back_y });
}
else break;
}
}
}
}
else if (result == CellState::Miss) {
cout << "Miss." << endl;
}
break;
}
catch (const std::exception& e) {
continue;
}
}
}
Добавляет к targeting_queue клетки, непосредственно прилегающие к заданной точке (x, y).
void BotPlayer::queue_adjacent(int x, int y) {
pair<int, int> directions[4] = {
{0, -1}, {0, 1}, {-1, 0}, {1, 0}
};
for (auto& dir : directions) {
int nx = x + dir.first;
int ny = y + dir.second;
if (is_valid_target(nx, ny)) {
targeting_queue.push_back({ nx, ny });
}
}
random_shuffle(targeting_queue.begin(), targeting_queue.end());
}
Определение направления (по горизонтали или вертикали), в котором идет корабль, на основе двух попаданий: first_hit и second_hit.
void BotPlayer::calculate_direction() {
int dx = second_hit.first - first_hit.first;
int dy = second_hit.second - first_hit.second;
if (dx != 0) { dx /= abs(dx); }
if (dy != 0) { dy /= abs(dy); }
direction = { dx, dy };
}
Проверяет, можно ли стрелять в ячейку x, y.
bool BotPlayer::is_valid_target(int x, int y) {
if (x < 0 || x >= 10 || y < 0 || y >= 10) {
return false;
}
return find(shots_made.begin(), shots_made.end(), make_pair(x, y)) == shots_made.end();
}
Ответы (1 шт):
Вам нужно отладить код (нам это придётся делать в голове).
Либо трассируйте прохождение кода - установите точку остановки (брекпойнт) на месте, после которого предполагаете ошибку в логике, и при остановке идите по шагам, пока не заметите несообразности
Либо логируйте - начало у вас уже положено: cout << "? Bot shoots at (" << x << ", " << y << "): "; и т.п., добавьте больше вывода в подозрительных местах