-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathComputer.cpp
135 lines (114 loc) · 2.85 KB
/
Computer.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <iostream>
#include <limits>
#include "Player.h"
#include "Board.h"
#include "utils.h"
#include "Computer.h"
using namespace std;
// constructor
Computer::Computer(char token, char enemyToken, int level) : Player(token) {
setEnemyToken(enemyToken);
setLevel(level);
}
// establecer ficha enemiga
void Computer::setEnemyToken(char enemyToken) {
this->enemyToken = enemyToken;
}
// obtener ficha enemiga
char Computer::getEnemyToken() const {
return enemyToken;
}
// establecer nivel
void Computer::setLevel(int level) {
if (level > 0) {
this->level = level;
}
}
// obtener nivel
int Computer::getLevel() const {
return level;
}
// algoritmo minimax
Minimax Computer::minimax(
Board board,
char maxPlayer,
char minPlayer,
int maxDepth,
int currentDepth,
bool isMaximizingPlayer
) {
// almacenar resultados del minimax (puntuacion, movida)
Minimax state;
// verificar si ha acabado la recursion
if (board.isGameOver(maxPlayer, minPlayer) || currentDepth == maxDepth) {
state.bestScore = board.evaluate(maxPlayer);
return state;
}
// almacenar mejor movida y mejor puntaje
int bestMove;
int bestScore;
// jugador actual
char currentPlayer = isMaximizingPlayer ? maxPlayer : minPlayer;
// establecer mejor puntuacion inicial
if (isMaximizingPlayer) {
bestScore = numeric_limits<int>::min();
} else {
bestScore = numeric_limits<int>::max();
}
// pasar por cada movida posible
for (int col = 0; col < board.getWidth(); col++) {
// saltar paso si la columna esta llena
if (board.isColumnFull(col)) continue;
// simular movida
Board tempBoard = board.copy();
tempBoard.addToken(col, currentPlayer);
// recursion
Minimax recursionState = minimax(
tempBoard,
maxPlayer,
minPlayer,
maxDepth,
currentDepth + 1,
!isMaximizingPlayer
);
// puntuacion actual
int currentScore = recursionState.bestScore;
// actualiza la mejor puntuacion
if (isMaximizingPlayer) {
if (currentScore > bestScore) {
bestScore = currentScore;
bestMove = col;
}
} else {
if (currentScore < bestScore) {
bestScore = currentScore;
bestMove = col;
}
}
}
// actualizar valores
state.bestScore = bestScore;
state.bestMove = bestMove;
// estado del minimax
return state;
}
// obtener la mejor movida
int Computer::getBestMove(
Board board,
char maxPlayer,
char minPlayer,
int maxDepth
) {
// obtener resultado del minimax
Minimax result = minimax(board, maxPlayer, minPlayer, maxDepth);
// devolver mejor movida
return result.bestMove;
}
// hacer movida
void Computer::makeMove(Board &board) {
int bestMove = getBestMove(board, getToken(), getEnemyToken(), getLevel());
// agregar mejor movida
board.addToken(bestMove, getToken());
// mostrar columna elegida
cout << "Columna (" << getToken() << "): " << bestMove + 1 << "\n" << endl;
}