Skip to content

Commit

Permalink
🔄 Fix Issue #2
Browse files Browse the repository at this point in the history
 * now correctly rotating over each check,
   and even eagerly testing over
   permutations (might be overkill)
 * some redunant checks can probably be
   removed. it has been noted that:
   e = f, b = c and d = g
 * block forking and forking paths merged
   to one data structure (identical)
  • Loading branch information
avindra committed Nov 18, 2020
1 parent 4f3603b commit ea9222f
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 57 deletions.
94 changes: 39 additions & 55 deletions Src/AI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,40 @@
* Checks MUST contain at least one
* path to check.
*/
btnSquare* AI::checkMoves(QLabel* taunt, Board* board, int numChecks, int checks[][3], bool isX)
btnSquare* AI::checkMoves(Board* board, int numChecks, int checks[][3], bool isX)
{
for (int i = numChecks - 1; i >= 0; --i) {
auto row = checks[i];

do
{
btnSquare * _temp;
for (int i = numChecks - 1; i >= 0; --i)
{
auto row = checks[i];
auto A = row[0];
auto B = row[1];
auto C = row[2];

auto A = row[0];
auto B = row[1];
auto C = row[2];
do {
btnSquare* candidate;

auto spotA = board->get(A);
auto spotB = board->get(B);
auto spotC = board->get(C);

_temp = (spotA->autoCheck(isX) && spotB->autoCheck(isX) && spotC->isEnabled())
? board->get(C)
: 0;
if (_temp)
// take any available configuration
if(spotA->autoCheck(isX) && spotB->autoCheck(isX) && spotC->isEnabled()) {
candidate = spotC;
} else if(spotA->autoCheck(isX) && spotB->isEnabled() && spotC->autoCheck(isX)) {
candidate = spotB;
} else if(spotA->isEnabled() && spotB->autoCheck(isX) && spotC->autoCheck(isX)) {
candidate = spotA;
} else {
candidate = 0;
}

if (candidate)
{
taunt->setText("Move calculated! " +
QString::number(A) + " | " +
QString::number(B) + " | " +
QString::number(C)
);
board->reorient();
return _temp;
return candidate;
}
}
} while (board->rotate());
} while (board->rotate());
}

board->reorient();
return 0;
Expand Down Expand Up @@ -85,6 +86,7 @@ btnSquare* AI::pickMove(int len, int* src, Board* board) {
* @see https://en.wikipedia.org/wiki/Tic-tac-toe#Strategy
*/
btnSquare* AI::computerMove(Board* board, QLabel* taunt, bool isImpossible, bool isHard, bool isNormal) {
// similar to Game.cpp winpaths
int criticalChecks[][3] = {
{0, 1, 2},
/*
Expand All @@ -104,9 +106,6 @@ btnSquare* AI::computerMove(Board* board, QLabel* taunt, bool isImpossible, bool
_ O _
_ _ ?
*/
// I excluded 804 / 084, because later on, the
// center would be picked anyway. Similar coding
// strategy is used further down as well.
{3, 4, 5}
/*
_ _ _
Expand All @@ -124,15 +123,15 @@ btnSquare* AI::computerMove(Board* board, QLabel* taunt, bool isImpossible, bool
//win
if (isHard || isImpossible || (isNormal && (rand() % 2) >= 1))
{
if ((play = checkMoves(taunt, board, numCriticalChecks, criticalChecks, false))) {
taunt->setText("Well played! Better luck next time :)");
if ((play = checkMoves(board, numCriticalChecks, criticalChecks, false))) {
taunt->setText("Good game... better luck next time ;)");
return play;
}
}
//defend
if (isHard || isImpossible || isNormal)
{
if ((play = checkMoves(taunt, board, numCriticalChecks, criticalChecks, true))) {
if ((play = checkMoves(board, numCriticalChecks, criticalChecks, true))) {
taunt->setText("Not so fast!!");
return play;
}
Expand All @@ -158,23 +157,9 @@ btnSquare* AI::computerMove(Board* board, QLabel* taunt, bool isImpossible, bool
{0, 3, 1},
{3, 1, 0},
//<--d-->
{0, 8, 6},
{0, 6, 2},
{0, 2, 6},
{6, 2, 0},
//<--e-->
{1, 6, 7},
{1, 7, 6},
{6, 7, 1}
};
if ((play = checkMoves(taunt, board, std::size(forks), forks, false))) {
taunt->setText("Now there are two ;)");
return play;
}
//<-------------------------------------------------------------------------->
// BLOCK FORKING
//<-------------------------------------------------------------------------->
int bForks[][3] = {
//<--e-->
{1, 6, 7},
{1, 7, 6},
Expand All @@ -183,20 +168,19 @@ btnSquare* AI::computerMove(Board* board, QLabel* taunt, bool isImpossible, bool
{0, 2, 5},
{0, 5, 2},
{5, 2, 0},
//<--a-->
{0, 2, 4},
{0, 4, 2},
{2, 4, 0},
//<--b-->
{4, 6, 7},
{4, 7, 6},
{7, 6, 4},
//<--c-->
{0, 1, 3},
{0, 3, 1},
{3, 1, 0}
//<!--g-->
{0, 8, 6},
{0, 6, 8},
{6, 8, 0},
};
if ((play = checkMoves(taunt, board, std::size(bForks), bForks, true))) {

if ((play = checkMoves(board, std::size(forks), forks, false))) {
// todo: not always true
taunt->setText("Now there are two ;)");
return play;
}

if ((play = checkMoves(board, std::size(forks), forks, true))) {
taunt->setText("There can only be one");
return play;
}
Expand Down
3 changes: 1 addition & 2 deletions Src/AI.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ class AI {

private:

// todo: remove taunt
static btnSquare * checkMoves(QLabel* taunt, Board* a, int numChecks, int check[][3], bool checkX);
static btnSquare * checkMoves(Board* a, int numChecks, int check[][3], bool checkX);

/**
* Given a list of indices,
Expand Down

0 comments on commit ea9222f

Please sign in to comment.