5 bool move_possible_north(board *b);
6 bool move_possible_south(board *b);
7 bool move_possible_east(board *b);
8 bool move_possible_west(board *b);
10 void move_north(board *b);
11 void move_south(board *b);
12 void move_east(board *b);
13 void move_west(board *b);
14 void merge(board *b, const int d);
15 void merge_north(board *b);
16 void merge_south(board *b);
17 void merge_east(board *b);
18 void merge_west(board *b);
20 void place_new_piece(board *b);
21 void game_loop(board *b);
24 board *tmp = malloc(sizeof(board));
29 void init_board(board *b) {
30 for(int i = 0; i < 4; ++i) {
31 for(int j = 0; j < 4; ++j)
36 srand((uint)time(NULL));
38 // second piece will be placed in game_loop
42 printf("\e[?1049h\e[?25l]");
43 struct termios oldtio, newtio;
44 tcgetattr(STDIN_FILENO, &oldtio);
46 newtio.c_lflag &= ~(ICANON | ECHO);
47 tcsetattr(STDIN_FILENO, TCSANOW, &newtio);
48 board *b = new_board();
50 printf("\e[?1049l\e[?25h");
51 tcsetattr(STDIN_FILENO, TCSANOW, &oldtio);
56 enum direction get_input()
58 switch(fgetc(stdin)) {
74 void game_loop(board *b) {
75 while(move_possible_any(b)) {
79 enum direction d = get_input();
83 } else if(move_possible(b, d)) {
91 void place_new_piece(board *b) {
92 int prob = rand() % 100;
98 for(int i = 0; i < 4; ++i) {
99 for(int j = 0; j < 4; ++j) {
100 if(b->x[i][j] == 0) {
102 possibs[2*cnt+1] = j;
109 rx = possibs[2*pair];
110 ry = possibs[2*pair+1];
111 assert(b->x[rx][ry] == 0);
120 void free_board(board *b) {
124 void make_move(board *b, const int d) {
125 bool ok = (d == south) ||
131 * checked before already
132 * if(!move_possible(b, d))
140 bool move_possible_any(board *b) {
143 if(move_possible_south(b))
145 if(move_possible_east(b))
147 if(move_possible_north(b))
149 if(move_possible_west(b))
154 bool move_possible(board *b, const int d) {
155 bool ok = (d == south) ||
162 return move_possible_north(b);
164 return move_possible_south(b);
166 return move_possible_east(b);
168 return move_possible_west(b);
169 default: // will never execute anyway
174 void move(board *b, const int d) {
175 bool ok = (d == south) ||
193 default: // will never execute anyway
198 void merge(board *b, const int d) {
199 bool ok = (d == south) ||
217 default: // will never execute anyway
222 bool move_possible_south(board *b) {
223 for(int i = 0; i < 4; ++i) {
224 for(int j = 0; j < 3; ++j) {
225 if(b->x[i][j] != 0) {
226 if(b->x[i][j+1] == 0)
228 if(b->x[i][j] == b->x[i][j+1])
236 bool move_possible_north(board *b) {
237 for(int i = 0; i < 4; ++i) {
238 for(int j = 1; j < 4; ++j) {
239 if(b->x[i][j] != 0) {
240 if(b->x[i][j-1] == 0)
242 if(b->x[i][j] == b->x[i][j-1])
250 bool move_possible_east(board *b) {
251 for(int i = 0; i < 3; ++i) {
252 for(int j = 0; j < 4; ++j) {
253 if(b->x[i][j] != 0) {
254 if(b->x[i+1][j] == 0)
256 if(b->x[i+1][j] == b->x[i][j])
264 bool move_possible_west(board *b) {
265 for(int i = 1; i < 4; ++i) {
266 for(int j = 0; j < 4; ++j) {
267 if(b->x[i][j] != 0) {
268 if(b->x[i-1][j] == 0)
270 if(b->x[i-1][j] == b->x[i][j])
278 void move_north(board *b) {
280 for(int i = 0; i < 4; ++i) {
281 for(int j = 1; j < 4; ++j) {
282 if(b->x[i][j] != 0) {
284 while(b->x[i][k-1] == 0) {
285 b->x[i][k-1] = b->x[i][k];
296 void move_south(board *b) {
298 for(int i = 0; i < 4; ++i) {
299 for(int j = 2; j >= 0; --j) {
300 if(b->x[i][j] != 0) {
302 while(b->x[i][k+1] == 0) {
303 b->x[i][k+1] = b->x[i][k];
314 void move_east(board *b) {
316 for(int i = 2; i >= 0; --i) {
317 for(int j = 0; j < 4; ++j) {
318 if(b->x[i][j] != 0) {
320 while(b->x[k+1][j] == 0) {
321 b->x[k+1][j] = b->x[k][j];
332 void move_west(board *b) {
334 for(int i = 1; i < 4; ++i) {
335 for(int j = 0; j < 4; ++j) {
336 if(b->x[i][j] != 0) {
338 while(b->x[k-1][j] == 0) {
339 b->x[k-1][j] = b->x[k][j];
350 void merge_north(board *b) {
351 for(int i = 0; i < 4; ++i) {
352 for(int j = 1; j < 4; ++j) {
353 if(b->x[i][j] != 0 && b->x[i][j] == b->x[i][j-1]) {
357 b->points += b->x[i][j-1];
363 void merge_south(board *b) {
364 for(int i = 0; i < 4; ++i) {
365 for(int j = 2; j >= 0; --j) {
366 if(b->x[i][j] != 0 && b->x[i][j] == b->x[i][j+1]) {
370 b->points += b->x[i][j+1];
376 void merge_east(board *b) {
377 for(int i = 2; i >= 0; --i) {
378 for(int j = 0; j < 4; ++j) {
379 if(b->x[i][j] != 0 && b->x[i+1][j] == b->x[i][j]) {
381 b->points += b->x[i+1][j];
389 void merge_west(board *b) {
390 for(int i = 1; i < 4; ++i) {
391 for(int j = 0; j < 4; ++j) {
392 if(b->x[i][j] != 0 && b->x[i-1][j] == b->x[i][j]) {
394 b->points += b->x[i-1][j];
402 void print_sep(const char *left, const char *right, const char *cross, const char *line)
405 for(int i = 0; i < 4; i++) {
406 for(int j = 0; j < 6; j++)
416 void print_board_line(board *b, int l) {
419 for(int i = 0; i < 4; i++) {
434 print_sep("\u2503", "\u2503", "\u2502", " ");
437 print_sep("\u2517", "\u251B", "\u2537", "\u2501");
439 print_sep("\u2520", "\u2528", "\u253C", "\u2500");
442 void print_board(board *b) {
443 printf("\e[2J\e[0;0H");
444 printf("\e[1mScore: \e[0m%u\n", b->points);
445 print_sep("\u250F", "\u2513", "\u252F", "\u2501");
446 for(int i = 0; i < 4; ++i) {
447 print_board_line(b, i);
451 void print_score(board *b) {
452 printf("\e[1m\e[91mGame Over\e[0m\n\e[1mScore: \e[0m%u\n", b->points);
456 board *b = new_board();
460 assert(b->x[3][0] == 4);
464 board *b = new_board();
472 assert(b->x[0][0] == 4);
476 board *b = new_board();
482 assert(b->x[0][0] == 4);
486 board *b = new_board();
492 assert(b->x[0][3] == 4);
495 void move_merge_test1() {
496 board *b = new_board();
505 assert(b->x[3][3] == 4);
508 void move_north_test() {
509 board *b = new_board();
525 assert(b->x[2][0] == 8);
526 assert(b->x[0][0] == 2);
529 void move_merge_test2() {
530 board *b = new_board();
540 assert(b->x[3][1] == 4);
543 void move_merge_test3() {
544 board *b = new_board();
566 assert(b->x[3][1] == 4);