diff --git a/Connect4.c b/Connect4.c index 9e65a5a97a471f19d0a53fb83740bc02d9f3084d..2241e3e41efd6b404cd1170f02d5ad1e1f31dcd7 100644 --- a/Connect4.c +++ b/Connect4.c @@ -1,6 +1,7 @@ #include "Connect4.h" #include <stdbool.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -52,8 +53,9 @@ void print_grid_separator(int32_t n, char *front, char *rear, char *separator1, for (int32_t i = 0; i < n; i += 1) { printf("%s", separator1); - if (i < n - 1) + if (i < n - 1) { printf("%s", separator2); + } } printf("%s", rear); @@ -73,8 +75,9 @@ void print_grid_body(Piece **grid, int32_t rows, int32_t cols, int32_t y) { printf("│"); printf("\n"); - if (y < rows - 1) + if (y < rows - 1) { print_grid_separator(cols, "├", "┤", "─", "┼"); + } } void print_grid(Piece **grid, int32_t rows, int32_t cols) { @@ -100,8 +103,9 @@ void connect4_print(Connect4 *connect4) { bool connect4_is_full(Connect4 *connect4) { for (int32_t y = 0; y < connect4->rows; y += 1) { for (int32_t x = 0; x < connect4->cols; x += 1) { - if (connect4->grid[y][x] == PieceNone) + if (connect4->grid[y][x] == PieceNone) { return false; + } } } @@ -109,8 +113,10 @@ bool connect4_is_full(Connect4 *connect4) { } int32_t count_contiguous_pieces(Connect4 *connect4, int32_t x, int32_t y, int32_t x_direction, int32_t y_direction, Piece piece) { - if (x < 0 || x >= connect4->cols || y < 0 || y >= connect4->rows || connect4->grid[y][x] != piece) + if (x < 0 || x >= connect4->cols || y < 0 || y >= connect4->rows || connect4->grid[y][x] != piece) { return 0; + } + return 1 + count_contiguous_pieces(connect4, x + x_direction, y + y_direction, x_direction, y_direction, piece); } @@ -130,10 +136,14 @@ PlacingStatus connect4_place_piece(Connect4 *connect4, Piece piece, int32_t x) { if (connect4->grid[y][x] == PieceNone) { connect4->grid[y][x] = piece; - if (connect4_check_win(connect4, x, y, piece)) + if (connect4_check_win(connect4, x, y, piece)) { return PlacingStatusPlayerWon; - if (connect4_is_full(connect4)) + } + + if (connect4_is_full(connect4)) { return PlacingStatusGridFull; + } + return PlacingStatusPiecePlaced; } } @@ -142,8 +152,10 @@ PlacingStatus connect4_place_piece(Connect4 *connect4, Piece piece, int32_t x) { } Piece change_player(Piece current_player) { - if (current_player == PiecePlayer1) + if (current_player == PiecePlayer1) { return PiecePlayer2; + } + return PiecePlayer1; } @@ -165,8 +177,11 @@ PlacingStatus connect4_play_smart(Connect4 *connect4, void (*on_piece_placed)(Co Connect4 *copied_connect4 = connect4_copy(connect4); PlacingStatus status = connect4_place_piece(copied_connect4, current_player, x); - if (status == PlacingStatusColumnFull) + if (status == PlacingStatusColumnFull) { + connect4_destroy(copied_connect4); continue; + } + int32_t y = 0; for (int32_t i = 0; i < copied_connect4->rows; i += 1) { @@ -191,21 +206,28 @@ PlacingStatus connect4_play_smart(Connect4 *connect4, void (*on_piece_placed)(Co } PlacingStatus connect4_play(Connect4 *connect4, int32_t x, void (*on_piece_placed)(Connect4 *)) { - if (x < 1 || x > connect4->cols) + if (x < 1 || x > connect4->cols) { return PlacingStatusInvalidColumn; + } + PlacingStatus status = connect4_place_piece(connect4, connect4->current_player, x - 1); - if (status != PlacingStatusInvalidColumn || status != PlacingStatusColumnFull) + if (status != PlacingStatusInvalidColumn || status != PlacingStatusColumnFull) { on_piece_placed(connect4); - if (status != PlacingStatusPiecePlaced) + } + + if (status != PlacingStatusPiecePlaced) { return status; + } + connect4->current_player = change_player(connect4->current_player); if (connect4->mode != 3 && connect4->current_player == PiecePlayer2) { - if (connect4->mode == 1) + if (connect4->mode == 1) { status = connect4_play_random(connect4, on_piece_placed); - if (connect4->mode == 2) + } else if (connect4->mode == 2) { status = connect4_play_smart(connect4, on_piece_placed); + } } return status; diff --git a/Makefile b/Makefile index 3360993f5da85a57c2bf2a38aa29565c104a6f7c..29d598cb5c269d96e5b397a15a1206a2c6986559 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,13 @@ CC = gcc CCFLAGS = -g -Wall -Wextra -pedantic -fsanitize=address -fsanitize=leak -Connect4.o: Connect4.c +Connect4.o: Connect4.c Connect4.h $(CC) $(CCFLAGS) -c $< -o $@ -random.o: random.c +random.o: random.c random.h $(CC) $(CCFLAGS) -c $< -o $@ -main.o: main.c +main.o: main.c random.h $(CC) $(CCFLAGS) -c $< -o $@ puissance4: main.o Connect4.o random.o diff --git a/main.c b/main.c index 64be9479c50181fe68b7f81e3cadeb846a7fc8f6..0660ceaca6c0183285405f1cfa4bf46194b6f9be 100644 --- a/main.c +++ b/main.c @@ -1,18 +1,22 @@ -#include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> -#include <time.h> #include "Connect4.h" char *get_game_result(int32_t mode, Piece current_player, PlacingStatus status) { - if (status == PlacingStatusGridFull) + if (status == PlacingStatusGridFull) { return "It is a draw."; - if (current_player == PiecePlayer1) + } + + if (current_player == PiecePlayer1) { return "Player one won!"; - else if (current_player == PiecePlayer2 && mode == 3) + } + + if (current_player == PiecePlayer2 && mode == 3) { return "Player two won!"; + } + return "Computer won!"; } @@ -24,18 +28,36 @@ void on_piece_placed(Connect4 *connect4) { connect4_print(connect4); } +void print_help() { + printf("Usage: puissance4 <mode> <row> <col>\n"); + printf(" mode specifies the mode: 1 = single player game (random),\n"); + printf(" 2 = single player game (AI), 3 = two players game\n"); + printf(" row specifies the number of rows (>= 4)\n"); + printf(" col specifies the number of columns (>= 4)\n"); +} + int main(int argc, char *argv[]) { srand(0); + if (argc != 4) { + print_help(); + return EXIT_FAILURE; + } + int32_t mode = atoi(argv[1]); int32_t rows = atoi(argv[2]); int32_t cols = atoi(argv[3]); + if (mode < 1 || mode > 3 || rows < 4 || cols < 4) { + print_help(); + return EXIT_FAILURE; + } + printf("Board size is %dx%d (rows x col)\n", rows, cols); Connect4 *connect4 = connect4_create(mode, rows, cols); connect4_print(connect4); - PlacingStatus status; + while (true) { do { printf("Column number? (starts at 1):"); @@ -45,11 +67,13 @@ int main(int argc, char *argv[]) { status = connect4_play(connect4, x, on_piece_placed); } while (status == PlacingStatusColumnFull || status == PlacingStatusInvalidColumn); - if (status != PlacingStatusPiecePlaced) + if (status != PlacingStatusPiecePlaced) { break; + } } print_game_result(mode, connect4->current_player, status); connect4_destroy(connect4); + return EXIT_SUCCESS; }