2048-homework/src/2048.c

197 lines
7.6 KiB
C
Raw Normal View History

2021-11-15 08:57:27 +00:00
#include "2048.h"
2021-12-14 20:26:10 +00:00
#include <stdbool.h>
2021-11-15 10:00:37 +00:00
#include <stdlib.h>
#include <time.h>
2021-12-14 18:24:51 +00:00
void game_add_block(Game *game) {
2021-12-14 17:56:37 +00:00
bool is_full = true;
for (int i = 0; i < game->field_size_x; i++) {
for (int j = 0; j < game->field_size_y; j++) {
2021-12-27 18:14:44 +00:00
if (game->field[i][j] == 0) {
2021-12-14 17:56:37 +00:00
is_full = false;
break;
}
}
}
if (is_full) {
2021-12-14 18:24:51 +00:00
game->game_over = true;
return;
2021-12-14 17:56:37 +00:00
}
2021-11-15 10:00:37 +00:00
size_t x, y;
int value;
2021-11-15 15:33:31 +00:00
do {
2021-12-14 20:26:10 +00:00
x = rand() % game->field_size_x;
2021-12-14 18:24:51 +00:00
y = rand() % game->field_size_y;
2021-11-15 15:33:31 +00:00
value = (rand() % 2) + 1;
2021-12-27 18:14:44 +00:00
} while (game->field[x][y] != 0);
game->field[x][y] = value * 2;
2021-11-15 10:00:37 +00:00
}
2021-11-15 08:57:27 +00:00
2021-11-15 21:20:16 +00:00
Game game_init(size_t field_size_x, size_t field_size_y) {
2021-11-15 08:57:27 +00:00
Game game;
2021-12-14 17:56:37 +00:00
game.game_over = false;
2021-12-14 20:06:42 +00:00
game.won = false;
2021-11-15 21:20:16 +00:00
game.field_size_x = field_size_x;
game.field_size_y = field_size_y;
2021-11-15 08:57:27 +00:00
game.score = 0;
2021-12-27 18:14:44 +00:00
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);
2021-11-15 08:57:27 +00:00
}
2021-11-15 10:00:37 +00:00
time_t t;
2021-12-14 20:26:10 +00:00
srand((unsigned)time(&t));
2021-12-14 18:24:51 +00:00
game_add_block(&game);
2021-11-15 15:33:31 +00:00
2021-11-15 08:57:27 +00:00
return game;
}
2021-12-24 13:02:00 +00:00
void game_destroy(Game *game) {
for (size_t i = 0; i < game->field_size_x; i++) {
free(game->field[i]);
2021-11-15 08:57:27 +00:00
}
2021-12-24 13:02:00 +00:00
free(game->field);
game->field = NULL;
2021-11-15 08:57:27 +00:00
}
2021-12-14 17:56:37 +00:00
void game_move(Game *game, Direction direction) {
2021-12-14 20:06:42 +00:00
if (game->game_over || game->won) {
return;
}
2021-12-27 18:14:44 +00:00
// 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
2021-12-28 20:34:06 +00:00
for (int u = 0; u < max(game->field_size_x, game->field_size_y); u++) {
2021-12-28 13:06:40 +00:00
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
2021-12-28 13:06:40 +00:00
for (int j = 0; j < max(game->field_size_x, game->field_size_y); j++) {
// the similar stuff
2021-12-28 13:06:40 +00:00
int helper;
switch (u) {
case 0:
case 2:
2021-12-28 20:34:06 +00:00
default:
2021-12-28 13:06:40 +00:00
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;
2021-12-28 20:34:06 +00:00
if (helper >= game->field_size_x || helper <= 0)
2021-12-28 13:06:40 +00:00
break;
2021-12-28 20:34:06 +00:00
if (j >= game->field_size_y)
2021-12-28 13:06:40 +00:00
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:
2021-12-28 13:06:40 +00:00
switch (direction) {
2021-12-28 20:34:06 +00:00
case Up:
2021-12-28 13:06:40 +00:00
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;
2021-12-28 20:34:06 +00:00
case Left:
2021-12-28 13:06:40 +00:00
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;
2021-12-28 20:34:06 +00:00
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;
2021-11-24 09:05:59 +00:00
}
2021-11-18 17:08:33 +00:00
}
}
}
2021-11-15 15:33:31 +00:00
2021-12-14 18:24:51 +00:00
game_add_block(game);
2021-11-15 08:57:27 +00:00
}