File opdracht2/search.cpp added (mode: 100644) (index 0000000..190dbe9) |
|
1 |
|
// search.cpp |
|
2 |
|
// Compile with: g++ search.cpp -o search |
|
3 |
|
|
|
4 |
|
#include "search.h" |
|
5 |
|
|
|
6 |
|
typename std::vector<Vertex>::const_iterator Graph::cbegin(Vertex v) const |
|
7 |
|
{ |
|
8 |
|
currentVertex = v; |
|
9 |
|
return adjacents[v].cbegin(); |
|
10 |
|
} |
|
11 |
|
|
|
12 |
|
typename std::vector<Vertex>::const_iterator Graph::cend() const |
|
13 |
|
{ |
|
14 |
|
return adjacents[currentVertex].cend(); |
|
15 |
|
} |
|
16 |
|
|
|
17 |
|
Graph::GraphMap Graph::adjacents = { |
|
18 |
|
{ 'S', { 'A', 'B' } }, |
|
19 |
|
{ 'A', { 'B', 'D', 'S' } }, |
|
20 |
|
{ 'B', { 'S', 'A', 'C' } }, |
|
21 |
|
{ 'C', { 'B', 'E' } }, |
|
22 |
|
{ 'D', { 'A', 'G' } }, |
|
23 |
|
{ 'E', { 'C' } }, |
|
24 |
|
{ 'G', { 'D' } } |
|
25 |
|
}; |
|
26 |
|
|
|
27 |
|
Path dfs(const Graph &graph, const Vertex &start, std::function<bool(const Vertex &vertex)> goalTest) |
|
28 |
|
{ |
|
29 |
|
std::stack<Path> queue; |
|
30 |
|
std::set<Vertex> visited; |
|
31 |
|
Path path; |
|
32 |
|
|
|
33 |
|
queue.push(path); |
|
34 |
|
while (!queue.empty()) { |
|
35 |
|
path = queue.top(); |
|
36 |
|
queue.pop(); |
|
37 |
|
|
|
38 |
|
Vertex last; |
|
39 |
|
if (path.size() == 0) { |
|
40 |
|
last = start; |
|
41 |
|
} else { |
|
42 |
|
last = path.back(); |
|
43 |
|
} |
|
44 |
|
if (goalTest(last)) |
|
45 |
|
return path; // path is a vector of Vertices |
|
46 |
|
|
|
47 |
|
if (visited.find(last) == visited.end()) { |
|
48 |
|
visited.insert(last); |
|
49 |
|
for (auto it = graph.cbegin(last); it != graph.cend(); it++) { // extend path with new Vertex |
|
50 |
|
Path n = path; |
|
51 |
|
n.push_back(*it); |
|
52 |
|
queue.push(n); |
|
53 |
|
} |
|
54 |
|
} |
|
55 |
|
} |
|
56 |
|
return Path(); // return empty path |
|
57 |
|
} |
|
58 |
|
|
|
59 |
|
Path bfs(const Graph &graph, const Vertex &start, std::function<bool(const Vertex &vertex)> goalTest) |
|
60 |
|
{ |
|
61 |
|
|
|
62 |
|
} |
|
63 |
|
|
|
64 |
|
int main() |
|
65 |
|
{ |
|
66 |
|
Graph graph; |
|
67 |
|
|
|
68 |
|
Vertex start = 'S'; |
|
69 |
|
Vertex goal = 'G'; |
|
70 |
|
|
|
71 |
|
Path path = dfs(graph, start, [&](Vertex v) { return (v == goal); }); |
|
72 |
|
// Path path = bfs(graph, start, [&](Vertex v) { return (v == goal); }); |
|
73 |
|
|
|
74 |
|
std::cout << start << std::endl; |
|
75 |
|
for (auto it = path.cbegin(); it != path.cend(); it++) |
|
76 |
|
{ |
|
77 |
|
std::cout << *it << std::endl; |
|
78 |
|
} |
|
79 |
|
|
|
80 |
|
return 0; |
|
81 |
|
} |
File opdracht2/search.h added (mode: 100644) (index 0000000..60a669f) |
|
1 |
|
// search.h |
|
2 |
|
|
|
3 |
|
#ifndef SEARCH_H |
|
4 |
|
#define SEARCH_H |
|
5 |
|
|
|
6 |
|
#include <array> |
|
7 |
|
#include <vector> |
|
8 |
|
#include <iostream> |
|
9 |
|
#include <functional> |
|
10 |
|
#include <stack> |
|
11 |
|
#include <set> |
|
12 |
|
#include <map> |
|
13 |
|
|
|
14 |
|
using Vertex = char; |
|
15 |
|
using Path = std::vector<Vertex>; |
|
16 |
|
|
|
17 |
|
class Graph |
|
18 |
|
{ |
|
19 |
|
public: |
|
20 |
|
typename std::vector<Vertex>::const_iterator cbegin(Vertex v) const; |
|
21 |
|
typename std::vector<Vertex>::const_iterator cend() const; |
|
22 |
|
private: |
|
23 |
|
mutable Vertex currentVertex; |
|
24 |
|
typedef std::map<Vertex,std::vector<Vertex>> GraphMap; |
|
25 |
|
static GraphMap adjacents; |
|
26 |
|
}; |
|
27 |
|
|
|
28 |
|
Path dfs(const Graph &graph, const Vertex &start, std::function<bool(const Vertex &vertex)> goalTest); |
|
29 |
|
Path bfs(const Graph &graph, const Vertex &start, std::function<bool(const Vertex &vertex)> goalTest); |
|
30 |
|
|
|
31 |
|
#endif // SEARCH_H |
File opdracht3/8puzzle.cpp added (mode: 100644) (index 0000000..1cc21cb) |
|
1 |
|
// 8puzzle.cpp |
|
2 |
|
// Compile with: g++ 8puzzle.cpp -o 8puzzle |
|
3 |
|
|
|
4 |
|
#include "8puzzle.h" |
|
5 |
|
|
|
6 |
|
typename std::vector<Vertex>::const_iterator Graph::cbegin(Vertex v) const |
|
7 |
|
{ |
|
8 |
|
adjacents.clear(); |
|
9 |
|
|
|
10 |
|
for (int r=0; r<3; r++) { |
|
11 |
|
for (int c=0; c<3; c++) { |
|
12 |
|
if (v[r][c] == 0) { |
|
13 |
|
if (c<2) adjacents.push_back(doMove(v,Move::l)); |
|
14 |
|
if (c>0) adjacents.push_back(doMove(v,Move::r)); |
|
15 |
|
if (r<2) adjacents.push_back(doMove(v,Move::u)); |
|
16 |
|
if (r>0) adjacents.push_back(doMove(v,Move::d)); |
|
17 |
|
} |
|
18 |
|
} |
|
19 |
|
} |
|
20 |
|
return adjacents.cbegin(); |
|
21 |
|
} |
|
22 |
|
|
|
23 |
|
typename std::vector<Vertex>::const_iterator Graph::cend() const |
|
24 |
|
{ |
|
25 |
|
return adjacents.cend(); |
|
26 |
|
} |
|
27 |
|
|
|
28 |
|
Vertex doMove(const Vertex &v, const Move &m) |
|
29 |
|
{ |
|
30 |
|
bool done=false; |
|
31 |
|
Vertex n = v; |
|
32 |
|
|
|
33 |
|
for (int r=0; r<3 && !done; r++) { |
|
34 |
|
for (int c=0; c<3 && !done; c++) { |
|
35 |
|
if (v[r][c] == 0) { |
|
36 |
|
switch(m) { |
|
37 |
|
case Move::l: std::swap(n[r][c], n[r][c+1]); done = true; break; |
|
38 |
|
case Move::r: std::swap(n[r][c], n[r][c-1]); done = true; break; |
|
39 |
|
case Move::u: std::swap(n[r+1][c], n[r][c]); done = true; break; |
|
40 |
|
case Move::d: std::swap(n[r-1][c], n[r][c]); done = true; break; |
|
41 |
|
} |
|
42 |
|
} |
|
43 |
|
} |
|
44 |
|
} |
|
45 |
|
return n; |
|
46 |
|
} |
|
47 |
|
|
|
48 |
|
std::ostream &operator<<(std::ostream &os, const Vertex &state) |
|
49 |
|
{ |
|
50 |
|
for (int r=0; r<3; r++) { |
|
51 |
|
for (int c=0; c<3; c++) { |
|
52 |
|
if (state[r][c] != 0) { |
|
53 |
|
os << state[r][c]; |
|
54 |
|
} else { |
|
55 |
|
os << " "; |
|
56 |
|
} |
|
57 |
|
} |
|
58 |
|
os << std::endl; |
|
59 |
|
} |
|
60 |
|
return os; |
|
61 |
|
} |
|
62 |
|
|
|
63 |
|
Path dfs(const Graph &graph, const Vertex &start, std::function<bool(const Vertex &vertex)> goalTest) |
|
64 |
|
{ |
|
65 |
|
std::stack<Path> queue; |
|
66 |
|
std::set<Vertex> visited; |
|
67 |
|
Path path; |
|
68 |
|
|
|
69 |
|
queue.push(path); |
|
70 |
|
while (!queue.empty()) { |
|
71 |
|
path = queue.top(); |
|
72 |
|
queue.pop(); |
|
73 |
|
|
|
74 |
|
Vertex last; |
|
75 |
|
if (path.size() == 0) { |
|
76 |
|
last = start; |
|
77 |
|
} else { |
|
78 |
|
last = path.back(); |
|
79 |
|
} |
|
80 |
|
if (goalTest(last)) |
|
81 |
|
return path; // path is a vector of Vertices |
|
82 |
|
|
|
83 |
|
if (visited.find(last) == visited.end()) { |
|
84 |
|
visited.insert(last); |
|
85 |
|
for (auto it = graph.cbegin(last); it != graph.cend(); it++) { // extend path with new Vertex |
|
86 |
|
Path n = path; |
|
87 |
|
n.push_back(*it); |
|
88 |
|
queue.push(n); |
|
89 |
|
} |
|
90 |
|
} |
|
91 |
|
} |
|
92 |
|
return Path(); |
|
93 |
|
} |
|
94 |
|
|
|
95 |
|
Path bfs(const Graph &graph, const Vertex &start, std::function<bool(const Vertex &vertex)> goalTest) |
|
96 |
|
{ |
|
97 |
|
// Here goes the solution to exercise #2 |
|
98 |
|
} |
|
99 |
|
|
|
100 |
|
int main() |
|
101 |
|
{ |
|
102 |
|
Graph graph; |
|
103 |
|
|
|
104 |
|
Vertex start = {{ |
|
105 |
|
{{1,2,3}}, |
|
106 |
|
{{7,0,4}}, |
|
107 |
|
{{8,6,5}} |
|
108 |
|
}}; |
|
109 |
|
|
|
110 |
|
Vertex goal = {{ |
|
111 |
|
{{1,2,3}}, |
|
112 |
|
{{4,5,6}}, |
|
113 |
|
{{7,8,0}} |
|
114 |
|
}}; |
|
115 |
|
|
|
116 |
|
Path path = bfs(graph, start, [&](Vertex v) { return (v == goal); }); |
|
117 |
|
|
|
118 |
|
std::cout << start << std::endl; |
|
119 |
|
for (auto it = path.cbegin(); it != path.cend(); it++) |
|
120 |
|
{ |
|
121 |
|
std::cout << *it << std::endl; |
|
122 |
|
} |
|
123 |
|
|
|
124 |
|
return 0; |
|
125 |
|
} |
|
126 |
|
|
File opdracht3/8puzzle.h added (mode: 100644) (index 0000000..85363fd) |
|
1 |
|
// 8puzzle.h |
|
2 |
|
|
|
3 |
|
#ifndef _8PUZZLE_H |
|
4 |
|
#define _8PUZZLE_H |
|
5 |
|
|
|
6 |
|
#include <array> |
|
7 |
|
#include <vector> |
|
8 |
|
#include <iostream> |
|
9 |
|
#include <functional> |
|
10 |
|
#include <stack> |
|
11 |
|
#include <set> |
|
12 |
|
|
|
13 |
|
enum class Move { l, r, u, d }; |
|
14 |
|
using State = std::array<std::array<int,3>,3>; |
|
15 |
|
|
|
16 |
|
using Vertex = State; |
|
17 |
|
using Path = std::vector<Vertex>; |
|
18 |
|
|
|
19 |
|
class Graph |
|
20 |
|
{ |
|
21 |
|
public: |
|
22 |
|
typename std::vector<Vertex>::const_iterator cbegin(Vertex v) const; |
|
23 |
|
typename std::vector<Vertex>::const_iterator cend() const; |
|
24 |
|
private: |
|
25 |
|
mutable std::vector<Vertex> adjacents; |
|
26 |
|
}; |
|
27 |
|
|
|
28 |
|
std::ostream &operator<<(std::ostream &os, const Vertex &state); |
|
29 |
|
|
|
30 |
|
Vertex doMove(const Vertex &v, const Move &m); |
|
31 |
|
Path dfs(const Graph &graph, const Vertex &start, std::function<bool(const Vertex &vertex)> goalTest); |
|
32 |
|
Path bfs(const Graph &graph, const Vertex &start, std::function<bool(const Vertex &vertex)> goalTest); |
|
33 |
|
|
|
34 |
|
#endif // _8PUZZLE_H |
|
35 |
|
|
File opdracht4/ttt.cpp added (mode: 100644) (index 0000000..5557d19) |
|
1 |
|
// ttt.cpp |
|
2 |
|
|
|
3 |
|
#include "ttt.h" |
|
4 |
|
|
|
5 |
|
std::ostream &operator<<(std::ostream &os, const Player &player) |
|
6 |
|
{ |
|
7 |
|
switch(player) |
|
8 |
|
{ |
|
9 |
|
case Player::X: os << "X"; break; |
|
10 |
|
case Player::O: os << "O"; break; |
|
11 |
|
case Player::None: os << " "; break; |
|
12 |
|
default: os.setstate(std::ios_base::failbit); |
|
13 |
|
} |
|
14 |
|
return os; |
|
15 |
|
} |
|
16 |
|
|
|
17 |
|
std::ostream &operator<<(std::ostream &os, const State &state) |
|
18 |
|
{ |
|
19 |
|
for (int r=0; r<3; r++) { |
|
20 |
|
os << "+-+-+-+" << std::endl; |
|
21 |
|
for (int c=0; c<3; c++) { |
|
22 |
|
os << "|" << state[r*3+c]; |
|
23 |
|
} |
|
24 |
|
os << "|" << std::endl; |
|
25 |
|
} |
|
26 |
|
os << "+-+-+-+" << std::endl; |
|
27 |
|
return os; |
|
28 |
|
} |
|
29 |
|
|
|
30 |
|
Player getCurrentPlayer(const State &state) |
|
31 |
|
{ |
|
32 |
|
int countX = 0; |
|
33 |
|
int countO = 0; |
|
34 |
|
for (int i=0; i<9; i++) { |
|
35 |
|
if (state[i] == Player::X) countX++; |
|
36 |
|
else if(state[i] == Player::O) countO++; |
|
37 |
|
} |
|
38 |
|
return (countX > countO ? Player::O : Player::X); |
|
39 |
|
} |
|
40 |
|
|
|
41 |
|
State doMove(const State &state, const Move &m) |
|
42 |
|
{ |
|
43 |
|
State result = state; |
|
44 |
|
int countX = 0; |
|
45 |
|
int countO = 0; |
|
46 |
|
for (int i=0; i<9; i++) { |
|
47 |
|
if (result[i] == Player::X) countX++; |
|
48 |
|
else if(result[i] == Player::O) countO++; |
|
49 |
|
} |
|
50 |
|
result[m] = (countX > countO ? Player::O : Player::X); |
|
51 |
|
return result; |
|
52 |
|
} |
|
53 |
|
|
|
54 |
|
Player getWinner(const State &state) |
|
55 |
|
{ |
|
56 |
|
for (int r=0; r<3; r++) |
|
57 |
|
if (state[r*3] == state[r*3+1] && state[r*3+1] == state[r*3+2] && state[r*3] != Player::None) |
|
58 |
|
return state[r*3]; |
|
59 |
|
for (int c=0; c<3; c++) |
|
60 |
|
if (state[0+c] == state[3+c] && state[3+c] == state[6+c] && state[0+c] != Player::None) |
|
61 |
|
return state[0+c]; |
|
62 |
|
if (state[0] == state[4] && state[4] == state[8] && state[0] != Player::None) |
|
63 |
|
return state[0]; |
|
64 |
|
if (state[2] == state[4] && state[4] == state[6] && state[2] != Player::None) |
|
65 |
|
return state[2]; |
|
66 |
|
return Player::None; |
|
67 |
|
} |
|
68 |
|
|
|
69 |
|
std::vector<Move> getMoves(const State &state) |
|
70 |
|
{ |
|
71 |
|
std::vector<Move> moves; |
|
72 |
|
if (getWinner(state) == Player::None) { |
|
73 |
|
for (int i=0; i<9; i++) { |
|
74 |
|
if (state[i] == Player::None) { |
|
75 |
|
moves.push_back(i); |
|
76 |
|
} |
|
77 |
|
} |
|
78 |
|
} |
|
79 |
|
return moves; |
|
80 |
|
} |
|
81 |
|
|
File opdracht4/ttt.h added (mode: 100644) (index 0000000..fd08e62) |
|
1 |
|
// ttt.h |
|
2 |
|
|
|
3 |
|
#ifndef TTT_H |
|
4 |
|
#define TTT_H |
|
5 |
|
|
|
6 |
|
#include <tuple> |
|
7 |
|
#include <array> |
|
8 |
|
#include <vector> |
|
9 |
|
#include <ctime> |
|
10 |
|
#include <random> |
|
11 |
|
#include <iterator> |
|
12 |
|
#include <iostream> |
|
13 |
|
|
|
14 |
|
enum class Player { X, O, None }; |
|
15 |
|
using Move = int; |
|
16 |
|
using State = std::array<Player,9>; |
|
17 |
|
|
|
18 |
|
// used to get a random element from a container |
|
19 |
|
template<typename Iter, typename RandomGenerator> |
|
20 |
|
Iter select_randomly(Iter start, Iter end, RandomGenerator& g) { |
|
21 |
|
std::uniform_int_distribution<> dis(0, std::distance(start, end) - 1); |
|
22 |
|
std::advance(start, dis(g)); |
|
23 |
|
return start; |
|
24 |
|
} |
|
25 |
|
|
|
26 |
|
template<typename Iter> |
|
27 |
|
Iter select_randomly(Iter start, Iter end) { |
|
28 |
|
static std::random_device rd; |
|
29 |
|
static std::mt19937 gen(rd()); |
|
30 |
|
return select_randomly(start, end, gen); |
|
31 |
|
} |
|
32 |
|
|
|
33 |
|
std::ostream &operator<<(std::ostream &os, const State &state); |
|
34 |
|
std::ostream &operator<<(std::ostream &os, const Player &player); |
|
35 |
|
|
|
36 |
|
Player getCurrentPlayer(const State &state); |
|
37 |
|
State doMove(const State &state, const Move &m); |
|
38 |
|
Player getWinner(const State &state); |
|
39 |
|
std::vector<Move> getMoves(const State &state); |
|
40 |
|
|
|
41 |
|
#endif // TTT_H |
File opdracht4/ttt_mc.cpp added (mode: 100644) (index 0000000..e5df5db) |
|
1 |
|
// ttt_mc.cpp |
|
2 |
|
// Compile with: g++ -std=c++11 -o ttt_mc ttt_mc.cpp ttt.cpp |
|
3 |
|
|
|
4 |
|
#include <iostream> |
|
5 |
|
#include <algorithm> |
|
6 |
|
#include <map> |
|
7 |
|
#include "ttt.h" |
|
8 |
|
|
|
9 |
|
unsigned const n_trials = 1000; |
|
10 |
|
unsigned const mc_match = 1; |
|
11 |
|
unsigned const mc_other = 1; |
|
12 |
|
|
|
13 |
|
enum class PlayerType { Human, Computer }; |
|
14 |
|
|
|
15 |
|
State mcTrial(const State &board) |
|
16 |
|
{ |
|
17 |
|
} |
|
18 |
|
|
|
19 |
|
void mcUpdateScores(std::array<int,9> &scores, const State &board, const Player &player) |
|
20 |
|
{ |
|
21 |
|
} |
|
22 |
|
|
|
23 |
|
Move getBestMove(const std::array<int, 9> &scores, const State &board) |
|
24 |
|
{ |
|
25 |
|
} |
|
26 |
|
|
|
27 |
|
Move mcMove(const State &board, const Player &player) |
|
28 |
|
{ |
|
29 |
|
} |
|
30 |
|
|
|
31 |
|
int main() |
|
32 |
|
{ |
|
33 |
|
std::srand(std::time(0)); |
|
34 |
|
|
|
35 |
|
std::map<Player,PlayerType> playerType; |
|
36 |
|
playerType[Player::X] = PlayerType::Human; |
|
37 |
|
playerType[Player::O] = PlayerType::Computer; |
|
38 |
|
|
|
39 |
|
State board = { |
|
40 |
|
Player::None, Player::None, Player::None, |
|
41 |
|
Player::None, Player::None, Player::None, |
|
42 |
|
Player::None, Player::None, Player::None }; |
|
43 |
|
std::cout << board << std::endl; |
|
44 |
|
|
|
45 |
|
std::vector<Move> moves = getMoves(board); |
|
46 |
|
while (moves.size() > 0) { |
|
47 |
|
if (playerType[getCurrentPlayer(board)] == PlayerType::Human) { |
|
48 |
|
std::cout << "+-+-+-+" << std::endl << |
|
49 |
|
"|0|1|2|" << std::endl << |
|
50 |
|
"+-+-+-+" << std::endl << |
|
51 |
|
"|3|4|5|" << std::endl << |
|
52 |
|
"+-+-+-+" << std::endl << |
|
53 |
|
"|6|7|8|" << std::endl << |
|
54 |
|
"+-+-+-+" << std::endl << std::endl; |
|
55 |
|
std::cout << "Enter a move ( "; |
|
56 |
|
for (Move m: moves) std::cout << m << " "; |
|
57 |
|
std::cout << "): "; |
|
58 |
|
Move m; |
|
59 |
|
std::cin >> m; |
|
60 |
|
board = doMove(board, m); |
|
61 |
|
} else { |
|
62 |
|
board = doMove(board, mcMove(board, getCurrentPlayer(board))); |
|
63 |
|
} |
|
64 |
|
std::cout << board << std::endl; |
|
65 |
|
moves = getMoves(board); |
|
66 |
|
} |
|
67 |
|
|
|
68 |
|
return 0; |
|
69 |
|
} |
|
70 |
|
|
File opdracht5/ttt.cpp added (mode: 100644) (index 0000000..5557d19) |
|
1 |
|
// ttt.cpp |
|
2 |
|
|
|
3 |
|
#include "ttt.h" |
|
4 |
|
|
|
5 |
|
std::ostream &operator<<(std::ostream &os, const Player &player) |
|
6 |
|
{ |
|
7 |
|
switch(player) |
|
8 |
|
{ |
|
9 |
|
case Player::X: os << "X"; break; |
|
10 |
|
case Player::O: os << "O"; break; |
|
11 |
|
case Player::None: os << " "; break; |
|
12 |
|
default: os.setstate(std::ios_base::failbit); |
|
13 |
|
} |
|
14 |
|
return os; |
|
15 |
|
} |
|
16 |
|
|
|
17 |
|
std::ostream &operator<<(std::ostream &os, const State &state) |
|
18 |
|
{ |
|
19 |
|
for (int r=0; r<3; r++) { |
|
20 |
|
os << "+-+-+-+" << std::endl; |
|
21 |
|
for (int c=0; c<3; c++) { |
|
22 |
|
os << "|" << state[r*3+c]; |
|
23 |
|
} |
|
24 |
|
os << "|" << std::endl; |
|
25 |
|
} |
|
26 |
|
os << "+-+-+-+" << std::endl; |
|
27 |
|
return os; |
|
28 |
|
} |
|
29 |
|
|
|
30 |
|
Player getCurrentPlayer(const State &state) |
|
31 |
|
{ |
|
32 |
|
int countX = 0; |
|
33 |
|
int countO = 0; |
|
34 |
|
for (int i=0; i<9; i++) { |
|
35 |
|
if (state[i] == Player::X) countX++; |
|
36 |
|
else if(state[i] == Player::O) countO++; |
|
37 |
|
} |
|
38 |
|
return (countX > countO ? Player::O : Player::X); |
|
39 |
|
} |
|
40 |
|
|
|
41 |
|
State doMove(const State &state, const Move &m) |
|
42 |
|
{ |
|
43 |
|
State result = state; |
|
44 |
|
int countX = 0; |
|
45 |
|
int countO = 0; |
|
46 |
|
for (int i=0; i<9; i++) { |
|
47 |
|
if (result[i] == Player::X) countX++; |
|
48 |
|
else if(result[i] == Player::O) countO++; |
|
49 |
|
} |
|
50 |
|
result[m] = (countX > countO ? Player::O : Player::X); |
|
51 |
|
return result; |
|
52 |
|
} |
|
53 |
|
|
|
54 |
|
Player getWinner(const State &state) |
|
55 |
|
{ |
|
56 |
|
for (int r=0; r<3; r++) |
|
57 |
|
if (state[r*3] == state[r*3+1] && state[r*3+1] == state[r*3+2] && state[r*3] != Player::None) |
|
58 |
|
return state[r*3]; |
|
59 |
|
for (int c=0; c<3; c++) |
|
60 |
|
if (state[0+c] == state[3+c] && state[3+c] == state[6+c] && state[0+c] != Player::None) |
|
61 |
|
return state[0+c]; |
|
62 |
|
if (state[0] == state[4] && state[4] == state[8] && state[0] != Player::None) |
|
63 |
|
return state[0]; |
|
64 |
|
if (state[2] == state[4] && state[4] == state[6] && state[2] != Player::None) |
|
65 |
|
return state[2]; |
|
66 |
|
return Player::None; |
|
67 |
|
} |
|
68 |
|
|
|
69 |
|
std::vector<Move> getMoves(const State &state) |
|
70 |
|
{ |
|
71 |
|
std::vector<Move> moves; |
|
72 |
|
if (getWinner(state) == Player::None) { |
|
73 |
|
for (int i=0; i<9; i++) { |
|
74 |
|
if (state[i] == Player::None) { |
|
75 |
|
moves.push_back(i); |
|
76 |
|
} |
|
77 |
|
} |
|
78 |
|
} |
|
79 |
|
return moves; |
|
80 |
|
} |
|
81 |
|
|
File opdracht5/ttt.h added (mode: 100644) (index 0000000..fd08e62) |
|
1 |
|
// ttt.h |
|
2 |
|
|
|
3 |
|
#ifndef TTT_H |
|
4 |
|
#define TTT_H |
|
5 |
|
|
|
6 |
|
#include <tuple> |
|
7 |
|
#include <array> |
|
8 |
|
#include <vector> |
|
9 |
|
#include <ctime> |
|
10 |
|
#include <random> |
|
11 |
|
#include <iterator> |
|
12 |
|
#include <iostream> |
|
13 |
|
|
|
14 |
|
enum class Player { X, O, None }; |
|
15 |
|
using Move = int; |
|
16 |
|
using State = std::array<Player,9>; |
|
17 |
|
|
|
18 |
|
// used to get a random element from a container |
|
19 |
|
template<typename Iter, typename RandomGenerator> |
|
20 |
|
Iter select_randomly(Iter start, Iter end, RandomGenerator& g) { |
|
21 |
|
std::uniform_int_distribution<> dis(0, std::distance(start, end) - 1); |
|
22 |
|
std::advance(start, dis(g)); |
|
23 |
|
return start; |
|
24 |
|
} |
|
25 |
|
|
|
26 |
|
template<typename Iter> |
|
27 |
|
Iter select_randomly(Iter start, Iter end) { |
|
28 |
|
static std::random_device rd; |
|
29 |
|
static std::mt19937 gen(rd()); |
|
30 |
|
return select_randomly(start, end, gen); |
|
31 |
|
} |
|
32 |
|
|
|
33 |
|
std::ostream &operator<<(std::ostream &os, const State &state); |
|
34 |
|
std::ostream &operator<<(std::ostream &os, const Player &player); |
|
35 |
|
|
|
36 |
|
Player getCurrentPlayer(const State &state); |
|
37 |
|
State doMove(const State &state, const Move &m); |
|
38 |
|
Player getWinner(const State &state); |
|
39 |
|
std::vector<Move> getMoves(const State &state); |
|
40 |
|
|
|
41 |
|
#endif // TTT_H |
File opdracht5/ttt_ab.cpp added (mode: 100644) (index 0000000..55b34b8) |
|
1 |
|
// ttt_ab.cpp |
|
2 |
|
// Compile with: g++ -std=c++11 -o ttt_ab ttt_ab.cpp ttt.cpp |
|
3 |
|
|
|
4 |
|
#include <iostream> |
|
5 |
|
#include <algorithm> |
|
6 |
|
#include <map> |
|
7 |
|
#include <limits> |
|
8 |
|
#include "ttt.h" |
|
9 |
|
|
|
10 |
|
enum class PlayerType { Human, Computer }; |
|
11 |
|
|
|
12 |
|
int eval(const State &board, const Player &player) |
|
13 |
|
{ |
|
14 |
|
} |
|
15 |
|
|
|
16 |
|
Move alphaBeta(const State &board, int ply) |
|
17 |
|
{ |
|
18 |
|
} |
|
19 |
|
|
|
20 |
|
int main() |
|
21 |
|
{ |
|
22 |
|
std::srand(std::time(0)); |
|
23 |
|
|
|
24 |
|
std::map<Player,PlayerType> playerType; |
|
25 |
|
playerType[Player::X] = PlayerType::Human; |
|
26 |
|
playerType[Player::O] = PlayerType::Computer; |
|
27 |
|
|
|
28 |
|
State board = { |
|
29 |
|
Player::None, Player::None, Player::None, |
|
30 |
|
Player::None, Player::None, Player::None, |
|
31 |
|
Player::None, Player::None, Player::None }; |
|
32 |
|
std::cout << board << std::endl; |
|
33 |
|
|
|
34 |
|
std::vector<Move> moves = getMoves(board); |
|
35 |
|
while (moves.size() > 0) { |
|
36 |
|
if (playerType[getCurrentPlayer(board)] == PlayerType::Human) { |
|
37 |
|
std::cout << "+-+-+-+" << std::endl << |
|
38 |
|
"|0|1|2|" << std::endl << |
|
39 |
|
"+-+-+-+" << std::endl << |
|
40 |
|
"|3|4|5|" << std::endl << |
|
41 |
|
"+-+-+-+" << std::endl << |
|
42 |
|
"|6|7|8|" << std::endl << |
|
43 |
|
"+-+-+-+" << std::endl << std::endl; |
|
44 |
|
std::cout << "Enter a move ( "; |
|
45 |
|
for (Move m: moves) std::cout << m << " "; |
|
46 |
|
std::cout << "): "; |
|
47 |
|
Move m; |
|
48 |
|
std::cin >> m; |
|
49 |
|
board = doMove(board, m); |
|
50 |
|
} else { |
|
51 |
|
board = doMove(board, alphaBeta(board, 5)); |
|
52 |
|
} |
|
53 |
|
std::cout << board << std::endl; |
|
54 |
|
moves = getMoves(board); |
|
55 |
|
} |
|
56 |
|
|
|
57 |
|
return 0; |
|
58 |
|
} |
|
59 |
|
|