#include "2048.h" #include #include #include void game_add_block(Game *game) { bool is_full = true; for (int i = 0; i < game->field_size_x; i++) { for (int j = 0; j < game->field_size_y; j++) { if (game->field[i][j] == 0) { is_full = false; break; } } } if (is_full) { game->game_over = true; return; } size_t x, y; int value; do { x = rand() % game->field_size_x; y = rand() % game->field_size_y; value = (rand() % 2) + 1; } while (game->field[x][y] != 0); game->field[x][y] = value * 2; } Game game_init(size_t field_size_x, size_t field_size_y) { Game game; game.game_over = false; game.won = false; game.field_size_x = field_size_x; game.field_size_y = field_size_y; game.score = 0; game.field = malloc(sizeof(uint16_t *) * field_size_x); for (size_t i = 0; i < field_size_x; i++) { game.field[i] = calloc(field_size_y, sizeof(uint16_t) * field_size_y); } time_t t; srand((unsigned)time(&t)); game_add_block(&game); return game; } void game_destroy(Game *game) { for (size_t i = 0; i < game->field_size_x; i++) { free(game->field[i]); } free(game->field); game->field = NULL; } void game_move(Game *game, Direction direction) { if (game->game_over || game->won) { return; } // the fuck? // I have few chained for loops that do a lot of similar stuff so I call them in a for loop for better clarity and readability for (int u = 0; u < max(game->field_size_x, game->field_size_y); u++) { for (int i = 0; i < max(game->field_size_x, game->field_size_y); i++) { uint16_t **field = game->field; // move everything on one side for (int j = 0; j < max(game->field_size_x, game->field_size_y); j++) { // the similar stuff int helper; switch (u) { case 0: case 2: default: switch (direction) { case Down: if (j >= game->field_size_y - 1) break; if (i >= game->field_size_x) break; if (field[i][j + 1] == 0) { field[i][j + 1] = field[i][j]; field[i][j] = 0; } break; case Right: if (i >= game->field_size_y) break; if (j >= game->field_size_x - 1) break; if (field[j + 1][i] == 0) { field[j + 1][i] = field[j][i]; field[j][i] = 0; } break; case Up: helper = game->field_size_y - j; if (helper >= game->field_size_y || helper <= 0) break; if (i >= game->field_size_x) break; if (field[i][helper - 1] == 0) { field[i][helper - 1] = field[i][helper]; field[i][helper] = 0; } break; case Left: helper = game->field_size_x - i; if (helper >= game->field_size_x || helper <= 0) break; if (j >= game->field_size_y) break; if (field[helper - 1][j] == 0) { field[helper - 1][j] = field[helper][j]; field[helper][j] = 0; } break; case NoDirection: // get rid of compiler warnings break; } break; case 1: switch (direction) { case Up: if (j >= game->field_size_y - 1) break; if (i >= game->field_size_x) break; if (field[i][j + 1] == field[i][j]) { field[i][j + 1] = field[i][j] * 2; game->score += field[i][j + 1]; if (field[i][j + 1] == 2048) { game->won = true; } field[i][j] = 0; j++; } break; case Left: if (j >= game->field_size_y) break; if (i >= game->field_size_x - 1) break; if (field[i + 1][j] == field[i][j]) { field[i + 1][j] = field[i][j] * 2; game->score += field[i + 1][j]; if (field[i + 1][j] == 2048) { game->won = true; } field[i][j] = 0; j++; } break; case Down: helper = game->field_size_y - j; if (helper >= game->field_size_y || helper <= 0) break; if (i >= game->field_size_x) break; if (field[i][helper - 1] == field[i][helper]) { field[i][helper - 1] = field[i][helper] * 2; game->score += field[i][helper - 1]; if (field[i][helper - 1] == 2048) { game->won = true; } field[i][helper] = 0; j++; } break; case Right: helper = game->field_size_x - i; if (helper >= game->field_size_x || helper <= 0) break; if (j >= game->field_size_y) break; if (field[helper - 1][j] == field[helper][j]) { field[helper - 1][j] = field[helper][j] * 2; game->score += field[helper - 1][j]; if (field[helper - 1][j] == 2048) { game->won = true; } field[helper][j] = 0; j++; } break; case NoDirection: break; } break; } } } } game_add_block(game); }