Add Horizontal and Vertical win checking

Adds horizontal and vertical win checking, as well as tests for such
features.

Adds valgrind to the flake.nix

Adds test_connect4 option to Makefile
This commit is contained in:
Julia Lange 2024-07-15 18:57:53 -07:00
parent 28a3188ea3
commit b3b369a076
Signed by: Julia
SSH key fingerprint: SHA256:5DJcfxa5/fKCYn57dcabJa2vN2e6eT0pBerYi5SUbto
7 changed files with 142 additions and 20 deletions

View file

@ -14,7 +14,7 @@ struct Board *make_board(size_t height, size_t width)
new_board->tile_heights = calloc(width, sizeof(*(new_board->tile_heights)));
if (!new_board->tile_heights)
goto out_tile_heights;
new_board->height = height;
new_board->width = width;
new_board->next_player = RED;
@ -28,26 +28,81 @@ out_tilemap:
return NULL;
}
int drop_tile(struct Board *board, size_t drop_pos) {
void free_board(struct Board *board)
{
free(board->tile_heights);
free(board->tilemap);
free(board);
}
int check_for_win_horizontal(struct Board *board, size_t pos_i, size_t pos_j)
{
enum Tile current_player = board->next_player * -1;
char in_a_row = 1;
// Right
size_t npos_i = pos_i + 1;
while (npos_i < board->width && IDX(npos_i, pos_j, board) == current_player) {
in_a_row++;
npos_i++;
if (in_a_row >= 4)
return 1;
}
// Left
npos_i = pos_i - 1;
while (npos_i < board->width && IDX(npos_i, pos_j, board) == current_player) {
in_a_row++;
npos_i--;
if (in_a_row >= 4)
return 1;
}
return 0;
}
int check_for_win_vertical(struct Board *board, size_t pos_i, size_t pos_j)
{
enum Tile current_player = board->next_player * -1;
char in_a_row = 1;
// Down
size_t npos_j = pos_j + 1;
while (npos_j < board->height && \
IDX(pos_i, npos_j, board) == current_player) {
in_a_row++;
npos_j++;
if (in_a_row >= 4)
return 1;
}
return 0;
}
int check_for_win(struct Board *board, size_t pos_i, size_t pos_j)
{
if (check_for_win_horizontal(board, pos_i, pos_j))
return 1;
if (check_for_win_vertical(board, pos_i, pos_j))
return 1;
return 0;
}
int drop_tile(struct Board *board, size_t drop_pos)
{
if (drop_pos >= board->width)
return -1;
size_t tower_height = board->height-board->tile_heights[drop_pos]-1;
if (tower_height < 0)
if (tower_height > board->height)
return -1;
IDX(drop_pos, tower_height, board) = board->next_player;
board->tile_heights[drop_pos]++;
board->next_player *= -1;
// Check if player won in separate function
return 0;
return check_for_win(board, drop_pos, tower_height);
}
void print_board(struct Board *board) {
void print_board(struct Board *board)
{
for (int j = 0; j < board->height; j++) {
printf("|");
for (int i = 0; i < board->width; i++) {