Skip to content
Snippets Groups Projects
Commit 19f2b7a7 authored by anthony.bouillan's avatar anthony.bouillan
Browse files

Create game file

parent 0733e87a
Branches
No related tags found
No related merge requests found
Pipeline #39534 failed
...@@ -3,11 +3,12 @@ CFLAGS = -g -Wall -Wextra -Wpedantic ...@@ -3,11 +3,12 @@ CFLAGS = -g -Wall -Wextra -Wpedantic
LDLIBS = -lm LDLIBS = -lm
LDFLAGS = -fsanitize=address -fsanitize=leak LDFLAGS = -fsanitize=address -fsanitize=leak
puissance4: puissance4.c src/board.o src/game.o puissance4: puissance4.o src/board.o src/game.o
$(CC) $(CFLAGS) $^ -o $@ $(LDLIBS) $(LDFLAGS) $(CC) $(CFLAGS) $^ -o $@ $(LDLIBS) $(LDFLAGS)
board.o: src/board.h board.o: src/board.h
game.o: src/game.h game.o: src/game.h
puissance4.o: puissance4.h
clean: clean:
@echo "this rule must clean everything up (including candidate files in testbed)" @echo "this rule must clean everything up (including candidate files in testbed)"
...@@ -29,8 +30,13 @@ tests_rand_ai: puissance4 ...@@ -29,8 +30,13 @@ tests_rand_ai: puissance4
tests_smart_ai: puissance4 tests_smart_ai: puissance4
$(MAKE) -C testbed/smart_ai $(MAKE) -C testbed/smart_ai
generate_board_test: src/test_board.o src/board.o tests_game: src/test_game.o src/game.o src/board.o
$(CC) $(CFLAGS) $^ -o src/test_board $(LDLIBS) $(LDFLAGS) $(CC) $(CFLAGS) $^ -o tests_game $(LDLIBS) $(LDFLAGS)
./tests_game
tests_board: generate_board_test tests_board: src/test_board.o src/board.o
./src/test_board $(CC) $(CFLAGS) $^ -o tests_board $(LDLIBS) $(LDFLAGS)
\ No newline at end of file ./tests_board
run_tests: tests_game tests_board
@echo "All tests executed successfully."
\ No newline at end of file
#include <stdio.h> #include "puissance4.h"
#include <stdlib.h>
#include <stdbool.h> // #define AI_SEED 0
#include "src/game.h" // #define MIN_COLUMN 4
#include "src/board.h" // #define MIN_ROW 4
#define AI_SEED 0 // void flush_input();
#define MIN_COLUMN 4 // bool is_valid_game_mode(int game_mode);
#define MIN_ROW 4 // bool is_valid_board_size(int rows, int cols);
// bool is_column_full(int col, int rows, int** board);
void flush_input(); // int select_random_column(int number_of_columns, int number_of_rows, int** board);
bool is_valid_game_mode(int game_mode); // int select_smart_column(int number_of_columns, int number_of_rows, int** board);
bool is_valid_board_size(int rows, int cols); // void announce_winner(enum GAME_MODE game_mode, int current_turn);
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);
int main(int argc, char const* argv[]) { 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]))) { if (argc != 4 || !is_valid_game_mode(atoi(argv[1])) || !is_valid_board_size(atoi(argv[2]), atoi(argv[3]))) {
...@@ -26,10 +23,63 @@ int main(int argc, char const* argv[]) { ...@@ -26,10 +23,63 @@ int main(int argc, char const* argv[]) {
} }
enum GAME_MODE game_mode = atoi(argv[1]); enum GAME_MODE game_mode = atoi(argv[1]);
int rows = atoi(argv[2]); int row_count = atoi(argv[2]);
int cols = atoi(argv[3]); int col_count = atoi(argv[3]);
srand(AI_SEED); srand(AI_SEED);
return play_game(game_mode, rows, cols);
int** board = create_board(row_count, col_count);
if (board == NULL) {
fprintf(stderr, "Error: Unable to allocate memory for the board.\n");
return EXIT_FAILURE;
}
fill_board(row_count, col_count, board);
printf("Board size is %dx%d (rows x col)", row_count, col_count);
print_board(row_count, col_count, board);
int current_turn = 0;
struct coordinate empty_slot;
while (true) {
int selected_column = get_selected_column(game_mode, current_turn, col_count, row_count, board);
if (!is_valid_column(selected_column, col_count)) {
continue;
}
empty_slot = find_empty_slot(selected_column - 1, row_count, board);
place_token(current_turn % 2, empty_slot, board);
print_board(row_count, col_count, board);
if (does_player_win(empty_slot, row_count, col_count, board)) {
announce_winner(game_mode, current_turn);
break;
}
if (is_board_full(current_turn, row_count, col_count)) {
printf("\nIt is a draw.\n");
break;
}
current_turn++;
}
if (destroy_board(row_count, board) == EXIT_FAILURE) {
fprintf(stderr, "Error: Unable to free memory for the board.\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
void announce_winner(enum GAME_MODE game_mode, int current_turn) {
const char* winner = (current_turn % 2 == 0) ? "Player one" : "Computer";
if (game_mode == PLAYER_VS_PLAYER) {
winner = (current_turn % 2 == 0) ? "one" : "two";
printf("\nPlayer %s won!\n", winner);
} else {
printf("\n%s won!\n", winner);
}
} }
bool is_valid_game_mode(int game_mode) { bool is_valid_game_mode(int game_mode) {
......
#ifndef _PUSSIANCE4_h_
#define _PUSSIANCE4_h_
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "src/game.h"
#include "src/board.h"
#define AI_SEED 0
#define MIN_COLUMN 4
#define MIN_ROW 4
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "src/game.h"
#include "src/board.h"
void announce_winner(enum GAME_MODE game_mode, int current_turn);
bool is_valid_game_mode(int game_mode);
bool is_valid_board_size(int rows, int cols);
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);
bool is_column_full(int col, int rows, int** board);
void flush_input();
#endif
┌─┬─┬─┬─┬─┬─┬─┐
│ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │
├─┼─┼─┼─┼─┼─┼─┤
│ │ │ │ │ │ │ │
└─┴─┴─┴─┴─┴─┴─┘
1 2 3 4 5 6 7
\ No newline at end of file
...@@ -23,60 +23,41 @@ struct coordinate find_empty_slot(int x, int rows, int** board) { ...@@ -23,60 +23,41 @@ struct coordinate find_empty_slot(int x, int rows, int** board) {
return coordinate; return coordinate;
} }
int play_game(enum GAME_MODE game_mode, int rows, int cols) { bool is_valid_column(int column, int col_count) {
int** board = create_board(rows, cols); return column >= 1 && column <= col_count;
if (board == NULL) { }
fprintf(stderr, "Error: Unable to allocate memory for the board.\n");
return EXIT_FAILURE;
}
fill_board(rows, cols, board);
printf("Board size is %dx%d (rows x col)", rows, cols);
print_board(rows, cols, board);
int player_selected_column, player = 0;
struct coordinate coordinate;
while (true) { int get_player_input() {
if (game_mode == PLAYER_VS_PLAYER || player % 2 == 0) { int column;
printf("\nColumn number? (starts at 1):"); printf("\nColumn number? (starts at 1):");
scanf("%d", &player_selected_column); scanf("%d", &column);
} else { return column;
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) { bool is_board_full(int current_turn, int row_count, int col_count) {
continue; return current_turn + 1 == row_count * col_count;
} }
coordinate = find_empty_slot(player_selected_column - 1, rows, board); int get_selected_column(enum GAME_MODE game_mode, int current_turn, int col_count, int row_count, int** board) {
place_token(player % 2, coordinate, board); if (is_human_turn(game_mode, current_turn)) {
return get_player_input();
}
return get_ai_move(game_mode, col_count, row_count, board);
}
print_board(rows, cols, board); bool is_human_turn(enum GAME_MODE game_mode, int current_turn) {
if (does_player_win(coordinate, rows, cols, board)) { return game_mode == PLAYER_VS_PLAYER || current_turn % 2 == 0;
if (game_mode == PLAYER_VS_PLAYER) { }
printf("\nPlayer %s won!\n", player % 2 == 0 ? "one" : "two");
} else {
printf("\n%s won!\n", player % 2 == 0 ? "Player one" : "Computer");
}
break;
}
if (player + 1 == rows * cols) {
printf("\nIt is a draw.\n");
break;
}
player++; int get_ai_move(enum GAME_MODE game_mode, int col_count, int row_count, int** board) {
} switch (game_mode) {
if (destroy_board(rows, board) == EXIT_FAILURE) { case PLAYER_VS_RANDOM_AI:
fprintf(stderr, "Error: Unable to free memory for the board.\n"); return select_random_column(col_count, row_count, board);
return EXIT_FAILURE; case PLAYER_VS_SMART_AI:
return select_smart_column(col_count, row_count, board);
default:
return -1;
} }
return EXIT_SUCCESS;
} }
bool does_player_win(struct coordinate coordinate, int rows, int cols, int** board) { bool does_player_win(struct coordinate coordinate, int rows, int cols, int** board) {
......
#ifndef GAME_H #ifndef _GAME_H
#define GAME_H #define _GAME_H
#include <stdbool.h> #include <stdbool.h>
#include "board.h" #include "board.h"
...@@ -15,9 +15,14 @@ struct coordinate { ...@@ -15,9 +15,14 @@ struct coordinate {
int y; int y;
}; };
int play_game(enum GAME_MODE game_mode, int rows, int cols);
struct coordinate find_empty_slot(int x, int rows, int** board); struct coordinate find_empty_slot(int x, int rows, int** board);
bool does_player_win(struct coordinate coordinate, int rows, int cols, int** board); bool does_player_win(struct coordinate coordinate, int rows, int cols, int** board);
void place_token(int player, struct coordinate coordinate, int** board); void place_token(int player, struct coordinate coordinate, int** board);
bool is_valid_column(int column, int col_count);
bool is_board_full(int current_turn, int row_count, int col_count);
int get_selected_column(enum GAME_MODE game_mode, int current_turn, int col_count, int row_count, int** board);
bool is_human_turn(enum GAME_MODE game_mode, int current_turn);
int get_ai_move(enum GAME_MODE game_mode, int col_count, int row_count, int** board);
int get_player_input();
#endif #endif
...@@ -4,23 +4,18 @@ ...@@ -4,23 +4,18 @@
#include <string.h> #include <string.h>
#include "../src/board.h" #include "../src/board.h"
#define EXPECTED_OUTPUT "src/expected_output.txt"
#define ACTUAL_OUTPUT "src/actual_output.txt"
#define GREEN "\033[1;32m" #define GREEN "\033[1;32m"
#define RED "\033[1;31m" #define RED "\033[1;31m"
#define RESET "\033[0m" #define RESET "\033[0m"
void test_destroy_board(); void test_destroy_board();
void test_fill_board(); void test_fill_board();
// void test_print_board();
void test_create_board(); void test_create_board();
int main() { int main() {
test_create_board(); test_create_board();
test_fill_board(); test_fill_board();
test_destroy_board(); test_destroy_board();
// test_print_board();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
...@@ -38,43 +33,6 @@ void test_destroy_board() { ...@@ -38,43 +33,6 @@ void test_destroy_board() {
printf(GREEN "test_destroy_board: PASSED\n" RESET); printf(GREEN "test_destroy_board: PASSED\n" RESET);
} }
// void test_print_board() {
// int rows = 6;
// int cols = 7;
// int** board = create_board(rows, cols);
// assert(board != NULL && "Board creation failed");
// fill_board(rows, cols, board);
// FILE* expected_output_file = fopen(EXPECTED_OUTPUT, "w");
// assert(expected_output_file != NULL && "Failed to open expected output file");
// freopen(EXPECTED_OUTPUT, "w", stdout);
// print_board(rows, cols, board);
// fclose(expected_output_file);
// freopen("/dev/tty", "w", stdout);
// FILE* actual_output_file = fopen(EXPECTED_OUTPUT, "r");
// assert(actual_output_file != NULL && "Failed to open actual output file");
// char actual_output[1024] = { 0 };
// fread(actual_output, sizeof(char), 1024, actual_output_file);
// fclose(actual_output_file);
// FILE* expected_output_file_read = fopen(EXPECTED_OUTPUT, "r");
// assert(expected_output_file_read != NULL && "Failed to open expected output file for reading");
// char expected_output[1024] = { 0 };
// fread(expected_output, sizeof(char), 1024, expected_output_file_read);
// fclose(expected_output_file_read);
// assert(strncmp(actual_output, expected_output, strlen(expected_output)) == 0
// && "Output does not match expected output");
// printf(GREEN "test_print_board: PASSED\n" RESET);
// destroy_board(rows, board);
// }
void test_create_board() { void test_create_board() {
int rows = 6; int rows = 6;
int cols = 7; int cols = 7;
......
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "game.h"
int** setup_board(int rows, int cols, int default_value) {
int** board = create_board(rows, cols);
if (board == NULL) {
fprintf(stderr, "Error: Unable to allocate memory for the board.\n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
board[i][j] = default_value;
}
}
return board;
}
void test_place_token() {
int rows = 6, cols = 7;
int** board = setup_board(rows, cols, EMPTY);
// Player1
struct coordinate coord = { 2, 3 };
place_token(0, coord, board);
assert(board[2][3] == PLAYER1);
// Player2
coord.x = 4;
coord.y = 5;
place_token(1, coord, board);
assert(board[4][5] == PLAYER2);
destroy_board(rows, board);
}
void test_find_empty_slot() {
int rows = 6, cols = 7;
int** board = setup_board(rows, cols, EMPTY);
// Search for an empty slot in a column
board[5][2] = PLAYER1;
struct coordinate coord = find_empty_slot(2, rows, board);
assert(coord.x == 4 && coord.y == 2);
// Search for an empty slot in a column with multiple tokens
board[4][2] = PLAYER2;
coord = find_empty_slot(2, rows, board);
assert(coord.x == 3 && coord.y == 2);
destroy_board(rows, board);
}
void test_is_valid_column() {
int cols = 7;
assert(is_valid_column(1, cols) == true);
assert(is_valid_column(7, cols) == true);
assert(is_valid_column(0, cols) == false);
assert(is_valid_column(8, cols) == false);
}
void test_is_board_full() {
int rows = 6, cols = 7;
assert(is_board_full(41, rows, cols) == true); // Full board
assert(is_board_full(40, rows, cols) == false); // Not full board
}
void test_does_player_win() {
int rows = 6, cols = 7;
int** board = setup_board(rows, cols, EMPTY);
// Test horizontal win
board[5][0] = PLAYER1;
board[5][1] = PLAYER1;
board[5][2] = PLAYER1;
board[5][3] = PLAYER1;
struct coordinate coord = { 5, 3 };
assert(does_player_win(coord, rows, cols, board) == true);
// Test vertical win
fill_board(rows, cols, board);
board[5][2] = PLAYER2;
board[4][2] = PLAYER2;
board[3][2] = PLAYER2;
board[2][2] = PLAYER2;
coord.x = 2;
coord.y = 2;
assert(does_player_win(coord, rows, cols, board) == true);
// Test diagonal win (left to right)
fill_board(rows, cols, board);
board[5][0] = PLAYER1;
board[4][1] = PLAYER1;
board[3][2] = PLAYER1;
board[2][3] = PLAYER1;
coord.x = 2;
coord.y = 3;
assert(does_player_win(coord, rows, cols, board) == true);
// Test diagonal win (right to left)
fill_board(rows, cols, board);
board[5][3] = PLAYER2;
board[4][2] = PLAYER2;
board[3][1] = PLAYER2;
board[2][0] = PLAYER2;
coord.x = 2;
coord.y = 0;
assert(does_player_win(coord, rows, cols, board) == true);
destroy_board(rows, board);
}
int main() {
test_place_token();
test_find_empty_slot();
test_is_valid_column();
test_is_board_full();
test_does_player_win();
printf("All tests passed successfully.\n");
return EXIT_SUCCESS;
}
\ No newline at end of file
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment