From 74e2b93b658575fa792ada51c3bf1cdc3cfde247 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Thu, 27 Apr 2017 00:18:16 +0200 Subject: [PATCH] Add the basic code to make othello playable without any rule checks MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- lib/constants.c | 22 ++++++++++--- lib/constants.h | 16 ++++++--- lib/othello.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++ lib/othello.h | 15 +++++++-- lib/ui.c | 88 ++++++++++++++++++++++++++++++++++++++++--------- lib/ui.h | 8 ++++- src/main.c | 69 ++++++++++++++++++++++++++++++++------ 7 files changed, 262 insertions(+), 39 deletions(-) diff --git a/lib/constants.c b/lib/constants.c index 7559432..66728da 100644 --- a/lib/constants.c +++ b/lib/constants.c @@ -1,9 +1,9 @@ /* * ===================================================================================== * - * Filename: constants.h + * Filename: constants.c * - * Description: Header for constant values + * Description: Constant values definition * * Version: 1.0 * Created: 24/04/2017 21:06:32 @@ -17,6 +17,18 @@ */ /* exported const definitions */ -const int empty = 0; -const int white = 1; -const int black = 2; + +#include "constants.h" + +//const unsigned int board_size = 8; + +const unsigned int empty = 0; +const unsigned int white = 1; +const unsigned int black = 2; + +/* FIXME: reuse the two above variables would be better */ +const unsigned int player_one = 2; /* first player is black */ +const unsigned int player_two = 1; + +const unsigned int hint_allowed = 3; +const unsigned int hint_forbidden = 4; diff --git a/lib/constants.h b/lib/constants.h index 902489d..aa6bc51 100644 --- a/lib/constants.h +++ b/lib/constants.h @@ -3,7 +3,7 @@ * * Filename: constants.h * - * Description: Header for constant values + * Description: Header for constant values export * * Version: 1.0 * Created: 24/04/2017 21:06:32 @@ -20,10 +20,18 @@ #define CONSTANTS_H #define board_size 8 +//extern const unsigned int board_size; /* 8 */ -extern const int empty; -extern const int white; -extern const int black; +extern const unsigned int empty; /* 0 */ +extern const unsigned int white; /* 1 */ +extern const unsigned int black; /* 2 */ + +extern const unsigned int player_one; /* black */ +extern const unsigned int player_two; /* white */ + + +extern const unsigned int hint_allowed; /* legal place for a pawn */ +extern const unsigned int hint_forbidden; /* illegal place for a pawn */ #endif /* CONSTANTS_H */ diff --git a/lib/othello.c b/lib/othello.c index 0cd65a4..02eac9d 100644 --- a/lib/othello.c +++ b/lib/othello.c @@ -16,4 +16,87 @@ * ===================================================================================== */ +#include +#include +#include "othello.h" + +unsigned int current_player(unsigned int round_count) { + + if (round_count % 2 != 0) { + return player_two; + } else { + return player_one; + } +} + +/* for consitency with ncurses, the board coordinates are in the following order: + * --x--> + * | + * y + * | + * v */ + +unsigned int get_box_value(int y, int x, unsigned int pawn_array[board_size][board_size]) { + + return pawn_array[y][x]; +} + +bool is_box_type(int y, int x, unsigned int pawn_array[board_size][board_size], unsigned int type) { + + if (type > 2) { + return NULL; + } + if (get_box_value(y, x, pawn_array) == type) { + return true; + } else { + return false; + } +} + +/* helper function to set a value != empty at the (y, x) in the pawns array */ +int** set_pawn(int y, int x, unsigned int type, unsigned int pawn_array[board_size][board_size]) { + + if (is_box_type(y, x, pawn_array, empty)) { + pawn_array[y][x] = type; + return pawn_array; + } else { + return NULL; + } +} + +static int** zero_pawns(unsigned int pawn_array[board_size][board_size]) { + for (unsigned int i = 0; i < board_size; i++) { + for (unsigned int j = 0; j < board_size; j++) { + pawn_array = set_pawn(i, j, empty, pawn_array); + } + } + return pawn_array; +} + +/* set the pawns in the start position */ +int** init_pawns(unsigned int pawn_array[board_size][board_size]) { + + pawn_array = zero_pawns(pawn_array); + pawn_array = set_pawn(5, 4, black, pawn_array); + pawn_array = set_pawn(4, 5, black, pawn_array); + pawn_array = set_pawn(4, 4, white, pawn_array); + pawn_array = set_pawn(5, 5, white, pawn_array); + return pawn_array; +} + +unsigned int count_pawn_type(unsigned int pawn_array[board_size][board_size], unsigned int type) { + unsigned int count = 0; + + if (type > 2) { + return -1; + } + for (unsigned int i = 0; i < board_size; i++) { + for (unsigned int j = 0; j < board_size; j++) { + if (pawn_array[i][j] == type) { + count++; + } + } + } + return count; +} diff --git a/lib/othello.h b/lib/othello.h index 7123697..628f8e1 100644 --- a/lib/othello.h +++ b/lib/othello.h @@ -21,8 +21,17 @@ #include "constants.h" -int pawn[board_size][board_size] = { - {0, 0} -}; +/* FIXME: declare and initialize the array here */ +//unsigned int pawns[board_size][board_size]; + +unsigned int current_player(unsigned int round_count); + +int** init_pawns(unsigned int pawn_array[board_size][board_size]); + +bool is_box_type(int y, int x, unsigned int pawn_array[board_size][board_size], unsigned int type); +unsigned int get_box_value(int y, int x, unsigned int pawn_array[board_size][board_size]); +int** set_pawn(int y, int x, unsigned int type, unsigned int pawn_array[board_size][board_size]); + +unsigned int count_pawn_type(unsigned int pawn_array[board_size][board_size], unsigned int type); #endif /* OTHELLO_H */ diff --git a/lib/ui.c b/lib/ui.c index c786772..2673dc9 100644 --- a/lib/ui.c +++ b/lib/ui.c @@ -16,7 +16,7 @@ * ===================================================================================== */ -#include +#include #include "ui.h" @@ -43,51 +43,107 @@ void print_board(int y, int x) { mvprintw(y+14, x, "5| | | | | | | | |"); mvprintw(y+15, x, " | | | | | | | | |"); mvprintw(y+16, x, " +----+----+----+----+----+----+----+----+"); - mvprintw(y+17, x, "7| | | | | | | | |"); + mvprintw(y+17, x, "6| | | | | | | | |"); mvprintw(y+18, x, " | | | | | | | | |"); mvprintw(y+19, x, " +----+----+----+----+----+----+----+----+"); - mvprintw(y+20, x, "8| | | | | | | | |"); + mvprintw(y+20, x, "7| | | | | | | | |"); mvprintw(y+21, x, " | | | | | | | | |"); - mvprintw(y+22, x, " -----+----+----+----+----+----+----+-----"); + mvprintw(y+22, x, " +----+----+----+----+----+----+----+----+"); + mvprintw(y+23, x, "8| | | | | | | | |"); + mvprintw(y+24, x, " | | | | | | | | |"); + mvprintw(y+25, x, " -----+----+----+----+----+----+----+-----"); } -static void print_o(int y, int x, int type) { +static void print_o(int y, int x, unsigned int type) { + if (type == black) { + init_color(COLOR_CYAN, 0, 0, 0); /* redefine to a dark black color */ + init_pair(2, COLOR_WHITE, COLOR_CYAN); + attron(COLOR_PAIR(2)); + } else { + init_pair(3, COLOR_BLACK, COLOR_WHITE); + attron(COLOR_PAIR(3)); + } mvprintw(y, x, "/\\"); mvprintw(y+1, x, "\\/"); + /* reset to default */ + init_pair(1, COLOR_WHITE, COLOR_BLACK); + attron(COLOR_PAIR(1)); } /* will be used for pawn placement hints */ -static void print_x(int y, int x, int type) { +static void print_x(int y, int x, unsigned int type) { + if (type == hint_allowed) { + init_pair(4, COLOR_GREEN, COLOR_BLACK); + attron(COLOR_PAIR(4)); + } else { + init_pair(5, COLOR_RED, COLOR_BLACK); + attron(COLOR_PAIR(5)); + } mvprintw(y, x, "\\/"); mvprintw(y+1, x,"/\\"); + /* reset to default */ + init_pair(1, COLOR_WHITE, COLOR_BLACK); + attron(COLOR_PAIR(1)); } /* y = 1: y -> 0 x = 1: 1 -> 1 * y > 1: y -> y + 3 x > 1: x -> x + 5 */ static int remap_y(int y) { - + if (y == 1) { - return 0; - } else if (y > 1) { - return (remap_y(y -1) + 3); + return 2; + } else if (y > 1 && y < board_size + 1) { + return (remap_y(y - 1) + 3); } + return -1; } static int remap_x(int x) { if (x == 1) { - return x; - } else if (x > 1) { + return 3; + } else if (x > 1 && x < board_size + 1) { return (remap_x(x - 1) + 5); } + return -1; } -void print_pawns(int pawn_array[board_size][board_size]) { - for (int i = 0; i < board_size; i++) { - for (int j = 0; j < board_size; j++) { - //mvprintw(i, j, "pawn[%d][%d] = %d\n", i, j, pawn_array[i][j]); +void print_pawns(int base_y, int base_x, unsigned int pawn_array[board_size][board_size]) { + for (unsigned int i = 0; i < board_size; i++) { + for (unsigned int j = 0; j < board_size; j++) { + if (pawn_array[i][j] != empty) { + print_o(base_y + remap_y(i), base_x + remap_x(j), pawn_array[i][j]); + } } } } + +int map_col_letter_to_int(char c) { + + if (c == 'a' || c == 'A') { + return 1; + } else if (c == 'b' || c == 'B') { + return 2; + } else if (c == 'c' || c == 'C') { + return 3; + } else if (c == 'd' || c == 'D') { + return 4; + } else if (c == 'e' || c == 'E') { + return 5; + } else if (c == 'f' || c == 'F') { + return 6; + } else if (c == 'g' || c == 'G') { + return 7; + } else if (c == 'h' || c == 'H') { + return 8; + } + return -1; +} + +int prompt_values(WINDOW* windows, int base_y, int base_x, const char* msg, int* y, char* x) { + mvwprintw(windows, base_y, base_x, "%s\n", msg); + int retVal = mvwscanw(windows, base_y + 1, base_x, "%d%c", y, x); + return (retVal == 1) ? 0 : 1; +} diff --git a/lib/ui.h b/lib/ui.h index ad32628..b24b674 100644 --- a/lib/ui.h +++ b/lib/ui.h @@ -19,11 +19,17 @@ #ifndef UI_H #define UI_H +#include + #include "constants.h" +int prompt_values(WINDOW* windows, int base_y, int base_x, const char* msg, int* y, char* x); + +int map_col_letter_to_int(char c); + /* ncurses printing */ void print_board(int y, int x); -void print_pawns(int pawn_array[board_size][board_size]); +void print_pawns(int base_y, int base_x, unsigned int pawn_array[board_size][board_size]); /* non ncurses printing */ diff --git a/src/main.c b/src/main.c index 7a327be..195bdbe 100644 --- a/src/main.c +++ b/src/main.c @@ -8,8 +8,15 @@ int main() { int row = 0, col = 0; - int key_pressed = 0; + unsigned int round = 0; + unsigned int player = player_one; /* first player is black */ bool exit_condition = false; + unsigned int nb_white = 0, nb_black = 0; + + char* player_msg; + + unsigned int pawns[board_size][board_size] = {{}}; + pawns[board_size][board_size] = init_pawns(pawns); initscr(); if (has_colors() == false) { @@ -19,22 +26,64 @@ int main() { } start_color(); getmaxyx(stdscr, row, col); - noecho(); + //noecho(); + echo(); curs_set(0); - /* center the board */ - int center_board_y = row/2 - 23/2; - int center_board_x = col/2 - 41/2; + /* center */ + int center_y = row/2; + int center_x = col/2; + /* base coordinates to center the board */ + int board_center_y = center_y - 26/2; + int board_center_x = center_x - 42/2; do { - print_board(center_board_y, center_board_x); + print_board(board_center_y, board_center_x); + print_pawns(board_center_y, board_center_x, pawns); + + char* title_msg = "Jeu othello"; + mvprintw(center_y - 26/2 - 4, (center_x - strlen(title_msg)/2), title_msg); - key_pressed = getch(); - if (key_pressed == 'q') { - exit_condition = true; + nb_white = count_pawn_type(pawns, white); + nb_black = count_pawn_type(pawns, black); + + char* score_white_msg = "Pions blancs: %d"; + mvprintw(center_y, center_x - 42/2 - strlen(score_white_msg) - 2, score_white_msg, nb_white); + char* score_black_msg = "Pions noirs: %d"; + mvprintw(center_y, center_x + 42/2 + 2, score_black_msg, nb_black); + + player = current_player(round); + + if (player == player_one) { + player_msg = "Joueur un (noir) joue !"; + } else { + player_msg = "Joueur deux (blanc) joue !"; } - } while (!exit_condition); + mvprintw(center_y - 26/2 - 2, (center_x - strlen(player_msg)/2), player_msg); + int y; + char x; + bool input_ok = false; + do { + y = 0; + x = ""; + char* prompt_msg = "Prochain pion ? - ligne colonne (chiffre lettre):"; + prompt_values(stdscr, center_y + 26/2 + 1, center_x - strlen(prompt_msg)/2, prompt_msg, &y, &x); + /* FIXME: separate the tests to permit to print explicit error messages */ + if (((y > 0 && y < board_size + 1) || \ + (map_col_letter_to_int(x) > 0 && map_col_letter_to_int(x) < board_size + 1)) \ + && is_box_type(y, x, pawns, empty)) { + input_ok = true; + } + } while (!input_ok); + pawns[board_size][board_size] = set_pawn(y, map_col_letter_to_int(x), player, pawns); + + round++; /* increment the round count */ + + refresh(); + + } while (!exit_condition); + endwin(); exit(EXIT_SUCCESS); -- 2.34.1