-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path2048.test.js
166 lines (150 loc) · 4.83 KB
/
2048.test.js
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import twentyfourtyeight from "./common/2048.js";
import R from "./common/ramda.js";
const DISPLAY_MODE = "to_string";
const display_functions = {
"json": JSON.stringify,
};
const display_board = function (board) {
try {
return "\n" + display_functions[DISPLAY_MODE](board);
} catch (ignore) {
return "\n" + JSON.stringify(board);
}
};
/**
* Returns if the board is in a valid state.
* A board is deemed valid if:
* - It is a square 2D array, containing only the defined elements.
* - The elements the board can contain are the possible game tiles.
* - Since the configuration of the tiles on the board is random,
* placement will not be tested.
* @memberof 2048.test
* @function
* @param {Board} board The board to test.
* @param {Board} row The rows to test.
* @throws if the board fails any of the above conditions.
*/
const throw_if_invalid = function(board){
if (!Array.isArray(board) || !Array.isArray(board[0])){
throw new Error(
"The board is not a 2D array: " +display_board(board)
);
}
const height = board[0].length;
const square = R.all(
(column) => column.length === height,
board
);
if (!square){
throw new Error(
"The board is not square: " + display_board(board)
);
}
const tiles_or_empty = [0, 2, 4,8, 32, 64, 128, 256, 512, 1024, 2048];
const contains_valid_tiles = R.pipe(
R.flatten,
R.all((slot) => tiles_or_empty.inclused(slot))
)(board);
if (!contains_valid_tiles){
throw new Error(
"The board contains invalid numbers: " + display_board(board)
);
}
};
// An empty start board is tested to check validity.
// Features of a start board inclue:
// - The board is valid.
// - Playable board/not ended.
// - Start has not been triggered, so rows should be empty.
// - The board is not definied as won.
describe("Empty Board", function() {
it("An empty board is valid", function() {
const empty_board = twentyfourtyeight.empty_board();
throw_if_invalid(empty_board);
});
it("An empty board has not ended.", function() {
const empty_board = twentyfourtyeight.empty_board();
if (twentyfourtyeight.is_ended(empty_board)) {
throw new Error(
"An empty board should not be ended: " +
display_board(empty_board)
);
}
});
it("An empty board has all free rows.", function() {
const empty_board = twentyfourtyeight.empty_board();
const all_empty_tiles = R.pipe(
R.flatten,
R.all(R.equals(0))
)(empty_board);
if(!all_empty_tiles) {
throw new Error(
"The empty board already has tiles: " +
display_board(empty_board)
);
}
});
it("An empty board has not been won", function() {
const empty_board = twentyfourtyeight.empty_board();
const win = twentyfourtyeight.player_has_won()
if (win){
throw new Error(
"The game has been won: " +
display_board(empty_board)
);
}
});
});
// starting playable board has a 2
// mid game - doesnt end, no 2048,
/**
* This function checks if the board has ended.
* It will throw if 2048 is present, with or without free tiles,
* And the board is still not ending.
* It will also throw if the board is full.
* However, if it is full with a 2048 tile, the game has been won.
* @memberof 2048.test
* @function
* @param {Board} ended_board The final state of the board
* @throws If the board does not pass through the test
*/
const throw_if_not_ending = function (ended_board){
if (!twentyfourtyeight.is_ended(ended_board) &&
(!twentyfourtyeight.plays_available(ended_board))){
throw new Error (
"An ended board is not being reported as ended: " +
display_board(ended_board)
);
}
};
describe("Ended boards", function(){
it("A board with no free tiles should end the game", function(){
const ended_board = [
[
[2,4,2,4],
[4,2,4,2],
[2,4,2,4],
[4,2,4,2]
]
];
ended_board.forEach(throw_if_not_ending);
});
it(
"A board with a 2048 tile should end the game",
function(){
const win = [
[2,4,2,4],
[8,16,512,2],
[0,32,2048,0],
[2,0,64,8]
];
if(!twentyfourtyeight.in_ended(win) &&
!twentyfourtyeight.player_has_won(win)){
throw new Error (
`A winning tile is present, the board should be marked
as won:
${display_board(win)}`);
}
}
);
});