add better method
This commit is contained in:
parent
6362853abd
commit
db8e2596ef
@ -1,19 +1,13 @@
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include "strategic_player1.h"
|
||||
#include "common.h"
|
||||
|
||||
extern "C" IPlayer* PlayerFactory()
|
||||
{
|
||||
extern "C" IPlayer *PlayerFactory() {
|
||||
return new StrategicPlayer1();
|
||||
}
|
||||
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
string StrategicPlayer1::PlayerInfo() {
|
||||
return "Big MAN Smol PP";
|
||||
return "Sandipsinh Rathod (sdr5549@psu.edu), Sapan Shah (scs6041@psu.edu)";
|
||||
}
|
||||
|
||||
void StrategicPlayer1::Init(int board_rows, int board_cols, char box_type, char line_type) {
|
||||
@ -28,57 +22,73 @@ void StrategicPlayer1::Close() {
|
||||
board.FreeBoard();
|
||||
}
|
||||
|
||||
void StrategicPlayer1::EventAddLine(char bar, const Loc& loc) {
|
||||
void StrategicPlayer1::EventAddLine(char bar, const Loc &loc) {
|
||||
board(loc) = bar; // Update the board with the added line
|
||||
}
|
||||
|
||||
void StrategicPlayer1::EventAddBox(char box, const Loc& loc) {
|
||||
void StrategicPlayer1::EventAddBox(char box, const Loc &loc) {
|
||||
board(loc) = box; // Update the board with the assigned box
|
||||
}
|
||||
|
||||
Loc StrategicPlayer1::SelectLineLocation() {
|
||||
Loc box_completing_move = FindBoxCompletingMove();
|
||||
if (box_completing_move.row != -1 && box_completing_move.col != -1) {
|
||||
return box_completing_move; // Prioritize moves that complete a box
|
||||
vector<Loc> empty_lines;
|
||||
ListEmptyLines(empty_lines);
|
||||
|
||||
// Step 1: Look for a move to complete a box
|
||||
Loc move = FindBoxCompletingMove();
|
||||
if (move.row != -1) {
|
||||
return move;
|
||||
}
|
||||
|
||||
return FindOptimalMove(); // Fall back to a heuristic-based optimal move
|
||||
// Step 2: Force opponent into bad moves
|
||||
move = ForceOpponentMistake(empty_lines);
|
||||
if (move.row != -1) {
|
||||
return move;
|
||||
}
|
||||
|
||||
// Step 3: Fall back to the optimal move
|
||||
return FindOptimalMove();
|
||||
}
|
||||
|
||||
StrategicPlayer1::~StrategicPlayer1() {
|
||||
Close();
|
||||
}
|
||||
|
||||
// Private helper functions
|
||||
Loc StrategicPlayer1::FindBoxCompletingMove() {
|
||||
vector<Loc> empty_lines;
|
||||
ListEmptyLines(empty_lines);
|
||||
|
||||
for (const Loc& loc : empty_lines) {
|
||||
for (const Loc &loc: empty_lines) {
|
||||
int row = loc.row, col = loc.col;
|
||||
|
||||
// Check if adding a line at this location completes a box
|
||||
if ((row % 2 == 0 && col % 2 == 1) || (row % 2 == 1 && col % 2 == 0)) {
|
||||
if (DoesMoveCompleteBox(row, col)) {
|
||||
return loc; // Return the first box-completing move found
|
||||
}
|
||||
if (DoesMoveCompleteBox(row, col)) {
|
||||
return loc;
|
||||
}
|
||||
}
|
||||
|
||||
return Loc(-1, -1); // No box-completing move found
|
||||
return Loc(-1, -1);
|
||||
}
|
||||
|
||||
bool StrategicPlayer1::DoesMoveCompleteBox(int row, int col) {
|
||||
// Check adjacent boxes based on the move's orientation
|
||||
if (row % 2 == 0 && col % 2 == 1) { // Horizontal line
|
||||
return (CountBoxLines(row - 1, col) == 3 || CountBoxLines(row + 1, col) == 3);
|
||||
} else if (row % 2 == 1 && col % 2 == 0) { // Vertical line
|
||||
return (CountBoxLines(row, col - 1) == 3 || CountBoxLines(row, col + 1) == 3);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Loc StrategicPlayer1::ForceOpponentMistake(const vector<Loc> &empty_lines) {
|
||||
Loc best_move(-1, -1);
|
||||
|
||||
for (const Loc &loc: empty_lines) {
|
||||
if (!DoesMoveCreateChain(loc.row, loc.col)) {
|
||||
return loc; // Choose the first safe move
|
||||
}
|
||||
}
|
||||
|
||||
return best_move;
|
||||
}
|
||||
|
||||
Loc StrategicPlayer1::FindOptimalMove() {
|
||||
vector<Loc> empty_lines;
|
||||
ListEmptyLines(empty_lines);
|
||||
@ -86,7 +96,7 @@ Loc StrategicPlayer1::FindOptimalMove() {
|
||||
int min_cost = numeric_limits<int>::max();
|
||||
Loc best_move(-1, -1);
|
||||
|
||||
for (const Loc& loc : empty_lines) {
|
||||
for (const Loc &loc: empty_lines) {
|
||||
int cost = EvaluateMoveCost(loc.row, loc.col);
|
||||
if (cost < min_cost) {
|
||||
min_cost = cost;
|
||||
@ -97,10 +107,28 @@ Loc StrategicPlayer1::FindOptimalMove() {
|
||||
return best_move;
|
||||
}
|
||||
|
||||
bool StrategicPlayer1::DoesMoveCreateChain(int row, int col) {
|
||||
board(row, col) = name;
|
||||
|
||||
bool creates_chain = false;
|
||||
|
||||
if (row % 2 == 0 && col % 2 == 1) {
|
||||
if (CountBoxLines(row - 1, col) == 2 || CountBoxLines(row + 1, col) == 2) {
|
||||
creates_chain = true;
|
||||
}
|
||||
} else if (row % 2 == 1 && col % 2 == 0) {
|
||||
if (CountBoxLines(row, col - 1) == 2 || CountBoxLines(row, col + 1) == 2) {
|
||||
creates_chain = true;
|
||||
}
|
||||
}
|
||||
|
||||
board(row, col) = ' ';
|
||||
return creates_chain;
|
||||
}
|
||||
|
||||
int StrategicPlayer1::EvaluateMoveCost(int row, int col) {
|
||||
int cost = 0;
|
||||
|
||||
// Evaluate the "cost" of the move by summing the number of sides completed for adjacent boxes
|
||||
if (row % 2 == 0 && col % 2 == 1) { // Horizontal line
|
||||
cost += CountBoxLines(row - 1, col);
|
||||
cost += CountBoxLines(row + 1, col);
|
||||
@ -113,13 +141,11 @@ int StrategicPlayer1::EvaluateMoveCost(int row, int col) {
|
||||
}
|
||||
|
||||
int StrategicPlayer1::CountBoxLines(int row, int col) {
|
||||
// Ensure the location is within bounds
|
||||
if (row < 0 || row >= board.GetRows() || col < 0 || col >= board.GetCols()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
// Check all four sides of the box
|
||||
if (board(row - 1, col) != ' ') count++; // Top
|
||||
if (board(row + 1, col) != ' ') count++; // Bottom
|
||||
if (board(row, col - 1) != ' ') count++; // Left
|
||||
@ -128,12 +154,12 @@ int StrategicPlayer1::CountBoxLines(int row, int col) {
|
||||
return count;
|
||||
}
|
||||
|
||||
void StrategicPlayer1::ListEmptyLines(vector<Loc>& empty_lines) {
|
||||
void StrategicPlayer1::ListEmptyLines(vector<Loc> &empty_lines) {
|
||||
for (int r = 0; r < board.GetRows(); r++) {
|
||||
for (int c = 0; c < board.GetCols(); c++) {
|
||||
Loc loc(r, c);
|
||||
if (loc.IsLineLocation() && board(r, c) == ' ') {
|
||||
empty_lines.push_back(loc); // Add all empty line locations to the list
|
||||
empty_lines.push_back(loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "board.h"
|
||||
#include "player.h"
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
|
||||
class StrategicPlayer1 : public IPlayer {
|
||||
char name;
|
||||
@ -26,6 +27,8 @@ public:
|
||||
void ListEmptyLines(vector<Loc>& empty_lines);
|
||||
bool DoesMoveCompleteBox(int row, int col);
|
||||
Loc FindBoxCompletingMove();
|
||||
bool DoesMoveCreateChain(int row, int col);
|
||||
Loc ForceOpponentMistake(const vector<Loc>& empty_lines);
|
||||
|
||||
~StrategicPlayer1();
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user