2024-11-19 23:54:26 +00:00
|
|
|
#include "strategic_player.h"
|
|
|
|
|
2024-11-20 00:11:06 +00:00
|
|
|
StrategicPlayer::StrategicPlayer(char name) {
|
|
|
|
this->name = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StrategicPlayer::selectLineLocation(Board &board, int &row, int &col) {
|
2024-11-19 23:54:26 +00:00
|
|
|
int rows = board.getRows();
|
|
|
|
int cols = board.getCols();
|
|
|
|
|
|
|
|
// Step 1: Try to complete a box
|
2024-11-20 00:11:06 +00:00
|
|
|
for (int r = 1; r < 2 * rows - 2; r += 2) {
|
|
|
|
// Iterate over box centers (odd rows)
|
|
|
|
for (int c = 1; c < 2 * cols - 2; c += 2) {
|
|
|
|
// Iterate over box centers (odd cols)
|
2024-11-19 23:54:26 +00:00
|
|
|
// Check adjacent lines for an opportunity to complete a box
|
|
|
|
if (board.isLineValid(r - 1, c) && // Top line
|
|
|
|
board.get(r + 1, c) != ' ' && // Bottom line
|
|
|
|
board.get(r, c - 1) != ' ' && // Left line
|
2024-11-20 00:11:06 +00:00
|
|
|
board.get(r, c + 1) != ' ') {
|
|
|
|
// Right line
|
2024-11-19 23:54:26 +00:00
|
|
|
row = r - 1;
|
|
|
|
col = c;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (board.isLineValid(r + 1, c) && // Bottom line
|
|
|
|
board.get(r - 1, c) != ' ' && // Top line
|
|
|
|
board.get(r, c - 1) != ' ' && // Left line
|
2024-11-20 00:11:06 +00:00
|
|
|
board.get(r, c + 1) != ' ') {
|
|
|
|
// Right line
|
2024-11-19 23:54:26 +00:00
|
|
|
row = r + 1;
|
|
|
|
col = c;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (board.isLineValid(r, c - 1) && // Left line
|
|
|
|
board.get(r - 1, c) != ' ' && // Top line
|
|
|
|
board.get(r + 1, c) != ' ' && // Bottom line
|
2024-11-20 00:11:06 +00:00
|
|
|
board.get(r, c + 1) != ' ') {
|
|
|
|
// Right line
|
2024-11-19 23:54:26 +00:00
|
|
|
row = r;
|
|
|
|
col = c - 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (board.isLineValid(r, c + 1) && // Right line
|
|
|
|
board.get(r - 1, c) != ' ' && // Top line
|
|
|
|
board.get(r + 1, c) != ' ' && // Bottom line
|
2024-11-20 00:11:06 +00:00
|
|
|
board.get(r, c - 1) != ' ') {
|
|
|
|
// Left line
|
2024-11-19 23:54:26 +00:00
|
|
|
row = r;
|
|
|
|
col = c + 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-20 00:11:06 +00:00
|
|
|
// Step 2: Avoid moves that leave a box with one line remaining
|
|
|
|
for (int r = 0; r < 2 * rows - 1; ++r) {
|
|
|
|
// Iterate over all valid rows
|
|
|
|
for (int c = 0; c < 2 * cols - 1; ++c) {
|
|
|
|
// Iterate over all valid cols
|
2024-11-19 23:54:26 +00:00
|
|
|
if (board.isLineValid(r, c)) {
|
|
|
|
// Simulate placing the line
|
|
|
|
board.placeLine(r, c, name);
|
|
|
|
|
|
|
|
// Check if this move leaves a box with only one line remaining
|
|
|
|
bool createsOpportunity = false;
|
2024-11-20 00:11:06 +00:00
|
|
|
for (int nr = 1; nr < 2 * rows - 2; nr += 2) {
|
|
|
|
// Iterate over box centers
|
2024-11-19 23:54:26 +00:00
|
|
|
for (int nc = 1; nc < 2 * cols - 2; nc += 2) {
|
|
|
|
if (board.get(nr, nc) == ' ') {
|
|
|
|
int adjacentLines = 0;
|
|
|
|
if (nr > 0 && board.get(nr - 1, nc) != ' ') adjacentLines++; // Top line
|
|
|
|
if (nr < 2 * rows - 2 && board.get(nr + 1, nc) != ' ') adjacentLines++; // Bottom line
|
|
|
|
if (nc > 0 && board.get(nr, nc - 1) != ' ') adjacentLines++; // Left line
|
|
|
|
if (nc < 2 * cols - 2 && board.get(nr, nc + 1) != ' ') adjacentLines++; // Right line
|
|
|
|
|
2024-11-20 00:11:06 +00:00
|
|
|
if (adjacentLines == 3) {
|
|
|
|
// Opponent can complete this box
|
2024-11-19 23:54:26 +00:00
|
|
|
createsOpportunity = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (createsOpportunity) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
board.set(r, c, ' '); // Undo the simulated move
|
|
|
|
|
|
|
|
if (!createsOpportunity) {
|
|
|
|
row = r;
|
|
|
|
col = c;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Step 3: Fallback to the first valid move
|
|
|
|
for (int r = 0; r < 2 * rows - 1; ++r) {
|
|
|
|
for (int c = 0; c < 2 * cols - 1; ++c) {
|
|
|
|
if (board.isLineValid(r, c)) {
|
|
|
|
row = r;
|
|
|
|
col = c;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-11-20 00:11:06 +00:00
|
|
|
|
|
|
|
char StrategicPlayer::getName() const {
|
|
|
|
return this->name;
|
|
|
|
}
|