-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAIPlayer.cpp
111 lines (95 loc) · 2.91 KB
/
AIPlayer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include "AIPlayer.hpp"
bool PlayerAI::make_move()
{
Move best_move = find_best_move();
return game_board->make_move(best_move.row, best_move.col, is_first);
}
bool PlayerAI::make_move_graphical(sf::RenderWindow* game_window, unsigned int cell_size)
{
return make_move();
}
int PlayerAI::evaluate()
{
if (game_board->check_win(is_first))
return 100;
else if (game_board->check_win(!is_first))
return -100;
return 0;
}
int PlayerAI::minimax(int depth, bool is_maximizing)
{
int score = evaluate();
// If maximizer is winner return his score
if (score == 100)
return score - depth;
// else if minimizer won return his score
if (score == -100)
return score + depth;
// If there are no more moves we end game as tie
if (game_board->no_more_fields())
return 0;
// Stop when reaching max depth and return current evaluation
if (depth >= max_depth)
return score;
// We search for the best moves as maximizer (this is current AIPlayer move)
if (is_maximizing)
{
int best = -1000;
for (unsigned int i = 1; i <= game_board->get_size(); i++)
{
for (unsigned int j = 1; j <= game_board->get_size(); j++)
{
if (game_board->make_move(i, j, is_first))
{
best = std::max(best, minimax(depth + 1, false));
game_board->undo_move(i, j);
}
}
}
return best;
}
// We play as minimizer and try to win against maximizer (we check what chances we gave to opponent by that and we will avoid minimum path)
else
{
int best = 1000;
for (unsigned int i = 1; i <= game_board->get_size(); i++)
{
for (unsigned int j = 1; j <= game_board->get_size(); j++)
{
if (game_board->make_move(i, j, !is_first))
{
best = std::min(best, minimax(depth + 1, true));
game_board->undo_move(i, j);
}
}
}
return best;
}
}
// Check for each field that is empty how good move it is
// We select move that has the biggest value = maximizer win means our bot win
Move PlayerAI::find_best_move()
{
int best_val = -1000;
Move best_move;
best_move.row = -1;
best_move.col = -1;
for (unsigned int i = 1; i <= game_board->get_size(); i++)
{
for (unsigned int j = 1; j <= game_board->get_size(); j++)
{
if (game_board->make_move(i, j, is_first))
{
int move_val = minimax(0, false);
game_board->undo_move(i, j);
if (move_val > best_val)
{
best_move.row = i;
best_move.col = j;
best_val = move_val;
}
}
}
}
return best_move;
}