diff --git a/puissance4.c b/puissance4.c index fb4712f5c7a07384c2ee3630af4258a33324ab5b..1fca65c0b8a8f4c9fbb0fe56dfd720f307bf8fe6 100644 --- a/puissance4.c +++ b/puissance4.c @@ -8,7 +8,7 @@ void init_board(int rows, int cols, int** board); void print_board(int rows, int cols, int** board); -struct coordinate add_token(int col, int player, int rows, int** board); +// struct coordinate add_token(int col, int player, int rows, int** board); bool does_player_win(int col, int row, int rows, int cols, int** board); void flush_input(); int** create_board(int rows, int cols); @@ -17,6 +17,8 @@ bool is_valid_game_mode(int game_mode); bool is_valid_board_size(int rows, int cols); bool is_column_full(int col, int rows, int** board); int select_random_column(int number_of_columns, int number_of_rows, int** board); +int select_smart_column(int number_of_columns, int number_of_rows, int** board); + enum STATE { @@ -38,6 +40,8 @@ enum GAME_MODE { char transform_state_to_char(enum STATE state); +void place_token(int player, struct coordinate coordinate, int** board); +struct coordinate find_empty_slot(int col, int rows, int** board); int main(int argc, char const* argv[]) { if (argc != 4 || !is_valid_game_mode(atoi(argv[1])) || !is_valid_board_size(atoi(argv[2]), atoi(argv[3]))) { @@ -72,14 +76,22 @@ int main(int argc, char const* argv[]) { printf("\nColumn number? (starts at 1):"); scanf("%d", &player_selected_column); } else { - player_selected_column = select_random_column(cols, rows, board); + if (game_mode == PLAYER_VS_RANDOM_AI) { + player_selected_column = select_random_column(cols, rows, board); + } else if (game_mode == PLAYER_VS_SMART_AI) { + player_selected_column = select_smart_column(cols, rows, board); + } } if (player_selected_column < 1 || player_selected_column > cols) { continue; } - coordinate = add_token(player_selected_column, player % 2, rows, board); + // coordinate = add_token(player_selected_column, player % 2, rows, board); + coordinate = find_empty_slot(player_selected_column, rows, board); + if (coordinate.x != -1 && coordinate.y != -1) { + place_token(player % 2, coordinate, board); + } print_board(rows, cols, board); if (does_player_win(coordinate.x, coordinate.y, rows, cols, board)) { @@ -88,7 +100,6 @@ int main(int argc, char const* argv[]) { } else { printf("\n%s won!\n", player % 2 == 0 ? "Player one" : "Computer"); } - break; } if (player + 1 == rows * cols) { @@ -123,6 +134,53 @@ int select_random_column(int number_of_columns, int number_of_rows, int** board) return robot_selected_column; } +int select_smart_column(int number_of_columns, int number_of_rows, int** board) { + int robot_selected_column = -999; + + // Check if the player can win in the next move, if so, block it + for (int col = 0; col < number_of_columns; col++) { + if (!is_column_full(col + 1, number_of_rows, board)) { + struct coordinate temp_coordinate = find_empty_slot(col + 1, number_of_rows, board); + + // Check if the player can win in the next move + board[temp_coordinate.x][temp_coordinate.y] = PLAYER1; + if (does_player_win(temp_coordinate.x, temp_coordinate.y, number_of_rows, number_of_columns, board)) { + robot_selected_column = col + 1; + board[temp_coordinate.x][temp_coordinate.y] = EMPTY; + break; + } + board[temp_coordinate.x][temp_coordinate.y] = EMPTY; + } + } + + if (robot_selected_column != -999) { + return robot_selected_column; + } + + // Check if the AI can win in the next move, if so, play it + for (int col = 0; col < number_of_columns; col++) { + if (!is_column_full(col + 1, number_of_rows, board)) { + struct coordinate temp_coordinate = find_empty_slot(col + 1, number_of_rows, board); + + board[temp_coordinate.x][temp_coordinate.y] = PLAYER2; + if (does_player_win(temp_coordinate.x, temp_coordinate.y, number_of_rows, number_of_columns, board)) { + robot_selected_column = col + 1; + board[temp_coordinate.x][temp_coordinate.y] = EMPTY; + break; + } + board[temp_coordinate.x][temp_coordinate.y] = EMPTY; + } + + } + + // If no winning move is found, select a random column + if (robot_selected_column == -999) { + robot_selected_column = select_random_column(number_of_columns, number_of_rows, board); + } + + return robot_selected_column; +} + bool is_column_full(int col, int rows, int** board) { for (int i = 0; i < rows; i++) { if (board[i][col - 1] == EMPTY) { @@ -132,11 +190,10 @@ bool is_column_full(int col, int rows, int** board) { return true; } -struct coordinate add_token(int col, int player, int rows, int** board) { - struct coordinate coordinate = { 0,0 }; +struct coordinate find_empty_slot(int col, int rows, int** board) { + struct coordinate coordinate = { -1, -1 }; for (int i = rows - 1; i >= 0; i--) { if (board[i][col - 1] == EMPTY) { - board[i][col - 1] = player == 0 ? PLAYER1 : PLAYER2; coordinate.x = i; coordinate.y = col - 1; break; @@ -145,6 +202,12 @@ struct coordinate add_token(int col, int player, int rows, int** board) { return coordinate; } +void place_token(int player, struct coordinate coordinate, int** board) { + if (coordinate.x != -1 && coordinate.y != -1) { + board[coordinate.x][coordinate.y] = player == 0 ? PLAYER1 : PLAYER2; + } +} + int** create_board(int rows, int cols) { int** board = malloc(rows * sizeof(int*)); if (board == NULL) {