-
Notifications
You must be signed in to change notification settings - Fork 0
/
board.hpp
129 lines (126 loc) · 3.59 KB
/
board.hpp
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
#include <algorithm>
#include <array>
#include <cassert>
#include <random>
#include <string>
#include <vector>
const int height = 6;
const int width = 5;
const int init_height = 2;
const double init_two_rate = 0.4;
const double two_rate = 0.2;
const double three_rate = 0.05;
class Board {
std::array<std::array<int,width>,height> board;
std::mt19937 rnd;
int score, next, steps;
bool status;
void next_gen() {
int max_piece = 0;
for (auto &ary: board)
max_piece = std::max(max_piece, *std::max_element(begin(ary), end(ary)));
double x = std::uniform_real_distribution<>(0.0, 1.0)(rnd);
if (max_piece <= 2)
next = 1;
else if (x < three_rate)
next = std::uniform_int_distribution<>(2, max_piece - 1)(rnd);
else if (x < two_rate)
next = 2;
else
next = 1;
}
void push(std::vector<int> cand) {
int pos = cand[std::uniform_int_distribution<>(0, (int)cand.size() - 1)(rnd)];
for (int i = height - 2; i >= 0; --i)
board[i+1][pos] = board[i][pos];
board[0][pos] = next;
next_gen();
}
public:
Board() : rnd(std::random_device()()), score(0), next(0), steps(0), status(true) {
for (int i = 0; i < height; ++i)
for (int j = 0; j < width; ++j)
board[i][j] = 0;
std::uniform_real_distribution<> unif(0.0, 1.0);
for (int i = 0; i < init_height; ++i)
for (int j = 0; j < width; ++j)
board[i][j] = (unif(rnd) < init_two_rate) + 1;
next_gen();
}
std::string to_json() {
std::string res = "{\"status\":" + std::to_string((int)status) + ",[";
for (int i = 0; i < height - 1; ++i) {
res += "[";
for (int j = 0; j < width; ++j)
res += std::to_string(board[i][j]) + (j == width - 1 ? "]" : ",");
res += (i == height - 2 ? "]," : ",");
}
res += "\"score\":" + std::to_string(score) + ",";
res += "\"next\":" + std::to_string(next) + "}\n";
return res;
}
void output() {
printf("=== #%d ===\n", steps);
printf("Score : %d\n", score);
printf("Next : %d\n", next);
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
int n = board[i][j];
if (i < height - 1 || n > 0) {
#ifdef __APPLE__
printf("\033[1;3%dm%2d\033[0m ", n > 0 ? n % 7 + 1 : 0, n);
#elif __unix__
printf("\e[3%dm%2d \e[37m", n > 0 ? n % 7 : 7, n);
#else
printf("%2d ", n);
#endif
}
else printf(" ");
}
puts("");
}
puts("");
}
bool play(int detach, int attach) {
assert (status);
++steps;
int num = -1, combo = 1;
for (int i = height - 1; i >= 0; --i) {
if (board[i][detach] != 0) {
num = board[i][detach];
board[i][detach] = 0;
break;
}
}
if (num == -1) return false;
for (int i = height - 2;; --i) {
if (i < 0) { board[0][attach] = num; break; }
if (board[i][attach] == 0) continue;
if (board[i][attach] != num) {
board[i+1][attach] = num;
break;
}
board[i][attach] = 0;
score += combo * num;
++num; combo *= 2;
}
std::vector<int> cand;
for (int i = 0; i < width; ++i)
if (board[height-2][i] == 0 && i != attach) cand.push_back(i);
if (cand.empty()) {
for (int i = 0; i < width; ++i)
if (i != attach) cand.push_back(i);
}
push(cand);
for (int i = 0; i < width; ++i)
if (board[height-1][i] != 0) { status = false; return false; }
return true;
}
int final_score() {
int res = score;
for (int i = 0; i < height; ++i)
for (int j = 0; j < width; ++j)
res += board[i][j] * (6 - i);
return res;
}
};