From 514e9f397f284b8a1876eb83daa6c3fb09d2daff Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 8 Oct 2021 15:17:11 +0200 Subject: [PATCH 01/30] Fist version of play_move() --- src/model.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/model.c b/src/model.c index f7b6499..2eaf771 100644 --- a/src/model.c +++ b/src/model.c @@ -260,7 +260,7 @@ void set_tictactoe_winner(s_tictactoe *p_ttt){ if ( p_ttt->content[i] == NOBODY ) { find = true; break; - } + } } if ( find == false ) { p_ttt->winner = BOTH; @@ -271,12 +271,26 @@ void set_tictactoe_winner(s_tictactoe *p_ttt){ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { if (is_move_valid(p_uttt, p_move) == YES) { // we can process things - if ( p_uttt->inception_level == 1 ) { - p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; + p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; + list_element_s_move *value = (list_element_s_move*) + malloc(sizeof(list_element_s_move)); + value->last_move = p_move; + if ( p_uttt->history == NULL ){ + value->next = NULL; } else { - + value->next = p_uttt->history; } + p_uttt->history = value; } + else { + return NO; + } + if ( p_uttt->inception_level == 1 ) { + } + else { + set_tictactoe_winner(p_uttt->inner_tictactoes[p_move->inner_position]); + } + set_tictactoe_winner(p_uttt->outer_tictactoe); return YES; } From 10d2bca6970f9f5a3accec16bc42761fc3dea8d2 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 8 Oct 2021 15:25:52 +0200 Subject: [PATCH 02/30] Update p_uttt in play_move) --- src/model.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/model.c b/src/model.c index 2eaf771..24e1410 100644 --- a/src/model.c +++ b/src/model.c @@ -270,7 +270,7 @@ void set_tictactoe_winner(s_tictactoe *p_ttt){ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { if (is_move_valid(p_uttt, p_move) == YES) { - // we can process things + p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; list_element_s_move *value = (list_element_s_move*) malloc(sizeof(list_element_s_move)); @@ -287,8 +287,10 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { return NO; } if ( p_uttt->inception_level == 1 ) { + p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; } else { + p_uttt->inner_tictactoes[p_move->outer_position]->content[p_move->inner_position] = p_move->player; set_tictactoe_winner(p_uttt->inner_tictactoes[p_move->inner_position]); } set_tictactoe_winner(p_uttt->outer_tictactoe); From d4ce681a9d50f2bf4e4efbfc0629b8554081599a Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 8 Oct 2021 15:32:11 +0200 Subject: [PATCH 03/30] Define outer_ttt winner (if one) un play_move() --- src/model.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/model.c b/src/model.c index 24e1410..a47bb88 100644 --- a/src/model.c +++ b/src/model.c @@ -292,6 +292,10 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { else { p_uttt->inner_tictactoes[p_move->outer_position]->content[p_move->inner_position] = p_move->player; set_tictactoe_winner(p_uttt->inner_tictactoes[p_move->inner_position]); + if ( p_uttt->inner_tictactoes[p_move->outer_position]->winner != NOBODY ) { + p_uttt->outer_tictactoe->content[p_move->outer_position] = + p_uttt->inner_tictactoes[p_move->outer_position]->winner; + } } set_tictactoe_winner(p_uttt->outer_tictactoe); return YES; From 943e63ee450efdf07cd9e0c548bef625a3861649 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 8 Oct 2021 15:34:15 +0200 Subject: [PATCH 04/30] Wrong test for winner in play_move() --- src/model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/model.c b/src/model.c index a47bb88..78ad746 100644 --- a/src/model.c +++ b/src/model.c @@ -291,7 +291,7 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { } else { p_uttt->inner_tictactoes[p_move->outer_position]->content[p_move->inner_position] = p_move->player; - set_tictactoe_winner(p_uttt->inner_tictactoes[p_move->inner_position]); + set_tictactoe_winner(p_uttt->inner_tictactoes[p_move->outer_position]); if ( p_uttt->inner_tictactoes[p_move->outer_position]->winner != NOBODY ) { p_uttt->outer_tictactoe->content[p_move->outer_position] = p_uttt->inner_tictactoes[p_move->outer_position]->winner; From c1a044640226a4f51bd759de19b76fda2c09b7bc Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 8 Oct 2021 16:39:57 +0200 Subject: [PATCH 05/30] Add a test for i in set_tictactoe_winner() --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 1 - src/model.c | 57 +++++++++++++++++++++++----------------------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 79aa1eb..b1b6ce3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_C_FLAGS "-std=c99 -g -Wall") set(CMAKE_INSTALL_PREFIX ".") -#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) include_directories(include) +#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) project(utictactoe) add_executable(${PROJECT_NAME} src/utictactoe.c src/model.c) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8722958..80462b7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,5 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_C_FLAGS "-std=c99 -g -Wall") set(CMAKE_INSTALL_PREFIX ".") include_directories(../include) - project(utictactoe) add_executable(${PROJECT_NAME} utictactoe.c model.c) diff --git a/src/model.c b/src/model.c index 78ad746..af633ef 100644 --- a/src/model.c +++ b/src/model.c @@ -198,39 +198,40 @@ void set_tictactoe_winner(s_tictactoe *p_ttt){ return; } } - } + - /* - * second diagonal, from the end of line - */ - if ( i == TICTACTOE_WIDTH - 1 ) { + /* + * second diagonal, from the end of line + */ + if ( i == TICTACTOE_WIDTH - 1 ) { + find = true; + for ( int l = 1; l < TICTACTOE_WIDTH; l++){ + next = (TICTACTOE_WIDTH - 1) * l; + if ( p_ttt->content[i] == p_ttt->content[next] ) { + find = false; + break; + } + } + if ( find == true ){ + p_ttt->winner = p_ttt->content[i]; + return; + } + } + + /* + * column + */ find = true; - for ( int l = 1; l < TICTACTOE_WIDTH; l++){ - next = (TICTACTOE_WIDTH - 1) * l; - if ( p_ttt->content[i] == p_ttt->content[next] ) { + for (int c = 1; c < TICTACTOE_WIDTH; c++ ) { + next = TICTACTOE_WIDTH * c + i; + if ( p_ttt->content[i] != p_ttt->content[next]) { find = false; break; } - } - if ( find == true ){ - p_ttt->winner = p_ttt->content[i]; - return; - } - } - - /* - * column - */ - find = true; - for (int c = 1; c < TICTACTOE_WIDTH; c++ ) { - next = TICTACTOE_WIDTH * c + i; - if ( p_ttt->content[i] != p_ttt->content[next]) { - find = false; - break; - } - if ( find == true ){ - p_ttt->winner = p_ttt->content[i]; - return; + if ( find == true ){ + p_ttt->winner = p_ttt->content[i]; + return; + } } } From ed98fa9d32149ac50d599ca1f289fce4e8ae737f Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 8 Oct 2021 16:52:28 +0200 Subject: [PATCH 06/30] Rewrite set_tictactoe_winner() --- src/model.c | 130 +++++++++++++++------------------------------------- 1 file changed, 38 insertions(+), 92 deletions(-) diff --git a/src/model.c b/src/model.c index af633ef..84856d4 100644 --- a/src/model.c +++ b/src/model.c @@ -170,103 +170,49 @@ e_status is_move_valid(s_utictactoe *p_uttt, s_move *p_move) { } void set_tictactoe_winner(s_tictactoe *p_ttt){ - bool find; - int next; - if ( p_ttt->winner == NOBODY ) { - for(int i = 0; i < TICTACTOE_WIDTH; i++){ - - /* - * Test for first diagonale - */ - if ( p_ttt->content[i] != NOBODY ) { - // if case 0 we need to test diagonale - if ( i == 0 ){ - int next; - find = true; - for (int l = 1; l < TICTACTOE_WIDTH; l++) { - // Maybe it is overkill to test diagonal but... - // ... no need to rewrite if we update TICTACTOE_WIDTH - next = l * TICTACTOE_WIDTH + l; - if ( p_ttt->content[i] != p_ttt ->content[next]) { - find = false; - break; - } - } - if (find == true) { - p_ttt->winner = p_ttt->content[i]; - return; - } - } - - - /* - * second diagonal, from the end of line - */ - if ( i == TICTACTOE_WIDTH - 1 ) { - find = true; - for ( int l = 1; l < TICTACTOE_WIDTH; l++){ - next = (TICTACTOE_WIDTH - 1) * l; - if ( p_ttt->content[i] == p_ttt->content[next] ) { - find = false; - break; - } - } - if ( find == true ){ - p_ttt->winner = p_ttt->content[i]; - return; - } - } - - /* - * column - */ - find = true; - for (int c = 1; c < TICTACTOE_WIDTH; c++ ) { - next = TICTACTOE_WIDTH * c + i; - if ( p_ttt->content[i] != p_ttt->content[next]) { - find = false; - break; - } - if ( find == true ){ - p_ttt->winner = p_ttt->content[i]; - return; - } - } - } - - /* - * line - */ - int line = i * TICTACTOE_WIDTH; - if (p_ttt->content[line] != NOBODY){ - find = true; - for ( int l = 1; l < TICTACTOE_WIDTH; l++ ) { - next = line + l; - if ( p_ttt->content[line] != p_ttt->content[next] ) { - find = false; - break; - } - } - if ( find == true ) { - p_ttt->winner = p_ttt->content[line]; - return; - } - } + // columns + for ( int i=0; i < TICTACTOE_WIDTH; i++ ) { + if (p_ttt->content[i] != NOBODY + &&p_ttt->content[i] == p_ttt->content[i+1] + && p_ttt->content[i] == p_ttt->content[i+6]) { + p_ttt->winner = p_ttt->content[i]; + return; } + } - // check if a move could be done, if not retuen BOTH (no winner) - find = false; - for (int i = 0; i < TICTACTOE_SIZE; i++){ - if ( p_ttt->content[i] == NOBODY ) { - find = true; - break; - } + //lines + for ( int i=0; i < TICTACTOE_SIZE; i=i+3 ) { + if (p_ttt->content[i] != NOBODY + &&p_ttt->content[i] == p_ttt->content[i+1] + && p_ttt->content[i] == p_ttt->content[i+2]) { + p_ttt->winner = p_ttt->content[i]; + return; } - if ( find == false ) { - p_ttt->winner = BOTH; + } + + //diagonale + if ( p_ttt->content[0] != NOBODY + && p_ttt->content[0] == p_ttt->content[4] + && p_ttt->content[0] == p_ttt->content[8] ) { + p_ttt->winner = p_ttt->content[0]; + return; + } + //diagonale + if ( p_ttt->content[2] != NOBODY + && p_ttt->content[2] == p_ttt->content[4] + && p_ttt->content[2] == p_ttt->content[6] ) { + p_ttt->winner = p_ttt->content[0]; + return; + } + + // check if a move could be done, if not retuen BOTH (no winner) + for (int i = 0; i < TICTACTOE_SIZE; i++){ + if ( p_ttt->content[i] == NOBODY ) { + return; } - } + } + p_ttt->winner = BOTH; } e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { From dd55f8fa055eaf10bcb29fa9f1d5c5e9bcd7f2c5 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 8 Oct 2021 17:00:14 +0200 Subject: [PATCH 07/30] Little moficitations in play_move() --- src/model.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/model.c b/src/model.c index 84856d4..3eee693 100644 --- a/src/model.c +++ b/src/model.c @@ -239,9 +239,10 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { else { p_uttt->inner_tictactoes[p_move->outer_position]->content[p_move->inner_position] = p_move->player; set_tictactoe_winner(p_uttt->inner_tictactoes[p_move->outer_position]); + + //check if we have a winner in inner_ttt then set player to outer if ( p_uttt->inner_tictactoes[p_move->outer_position]->winner != NOBODY ) { - p_uttt->outer_tictactoe->content[p_move->outer_position] = - p_uttt->inner_tictactoes[p_move->outer_position]->winner; + p_uttt->outer_tictactoe->content[p_move->outer_position] = p_uttt->inner_tictactoes[p_move->outer_position]->winner; } } set_tictactoe_winner(p_uttt->outer_tictactoe); From 777480000dbb598d4dcd5736726436d9b6d70c4a Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 8 Oct 2021 17:02:46 +0200 Subject: [PATCH 08/30] Bad winner when check second diagonale --- src/model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/model.c b/src/model.c index 3eee693..eb1c02f 100644 --- a/src/model.c +++ b/src/model.c @@ -202,7 +202,7 @@ void set_tictactoe_winner(s_tictactoe *p_ttt){ if ( p_ttt->content[2] != NOBODY && p_ttt->content[2] == p_ttt->content[4] && p_ttt->content[2] == p_ttt->content[6] ) { - p_ttt->winner = p_ttt->content[0]; + p_ttt->winner = p_ttt->content[2]; return; } From bc3b831d42f712e0c30afd2722f0d83c75f7a4ff Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 8 Oct 2021 17:05:17 +0200 Subject: [PATCH 09/30] Set correct player for outer_ttt in play(move) --- src/model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/model.c b/src/model.c index eb1c02f..cc3e64c 100644 --- a/src/model.c +++ b/src/model.c @@ -242,7 +242,7 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { //check if we have a winner in inner_ttt then set player to outer if ( p_uttt->inner_tictactoes[p_move->outer_position]->winner != NOBODY ) { - p_uttt->outer_tictactoe->content[p_move->outer_position] = p_uttt->inner_tictactoes[p_move->outer_position]->winner; + p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; } } set_tictactoe_winner(p_uttt->outer_tictactoe); From dc5b803e03219f56b870bfa71a67bf0359a8841b Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 8 Oct 2021 17:09:00 +0200 Subject: [PATCH 10/30] Bad test in set_ttt_winner() --- src/model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/model.c b/src/model.c index cc3e64c..cd642ee 100644 --- a/src/model.c +++ b/src/model.c @@ -174,7 +174,7 @@ void set_tictactoe_winner(s_tictactoe *p_ttt){ // columns for ( int i=0; i < TICTACTOE_WIDTH; i++ ) { if (p_ttt->content[i] != NOBODY - &&p_ttt->content[i] == p_ttt->content[i+1] + &&p_ttt->content[i] == p_ttt->content[i+3] && p_ttt->content[i] == p_ttt->content[i+6]) { p_ttt->winner = p_ttt->content[i]; return; From f4fb6f51375f302b122abd6483b5552a6156ce62 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 15 Oct 2021 14:46:38 +0200 Subject: [PATCH 11/30] Some corrections in play_move --- src/model.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/model.c b/src/model.c index cd642ee..5dc12f5 100644 --- a/src/model.c +++ b/src/model.c @@ -216,25 +216,21 @@ void set_tictactoe_winner(s_tictactoe *p_ttt){ } e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { - if (is_move_valid(p_uttt, p_move) == YES) { - - p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; - list_element_s_move *value = (list_element_s_move*) - malloc(sizeof(list_element_s_move)); - value->last_move = p_move; - if ( p_uttt->history == NULL ){ - value->next = NULL; - } - else { - value->next = p_uttt->history; - } - p_uttt->history = value; - } - else { + if (is_move_valid(p_uttt, p_move) == NO) { return NO; } - if ( p_uttt->inception_level == 1 ) { - p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; + p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; + list_element_s_move *value = (list_element_s_move*) + malloc(sizeof(list_element_s_move)); + + // we need to create a s_move in memory... + // and affect p_move + value->last_move = create_empty_move(); + value->last_move = p_move; + value->next = ( p_uttt->history == NULL ) ? NULL : p_uttt->history; + p_uttt->history = value; + + if ( p_uttt->inception_level != 1 ) { } else { p_uttt->inner_tictactoes[p_move->outer_position]->content[p_move->inner_position] = p_move->player; @@ -245,6 +241,8 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; } } + p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; set_tictactoe_winner(p_uttt->outer_tictactoe); return YES; } + From 3a020073f9372b67b0c7f552596155f217634c44 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 15 Oct 2021 14:52:25 +0200 Subject: [PATCH 12/30] Set inner_ttt winner correctly in play_move() --- src/model.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/model.c b/src/model.c index 5dc12f5..a13bd2b 100644 --- a/src/model.c +++ b/src/model.c @@ -231,15 +231,12 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { p_uttt->history = value; if ( p_uttt->inception_level != 1 ) { - } - else { p_uttt->inner_tictactoes[p_move->outer_position]->content[p_move->inner_position] = p_move->player; set_tictactoe_winner(p_uttt->inner_tictactoes[p_move->outer_position]); - //check if we have a winner in inner_ttt then set player to outer - if ( p_uttt->inner_tictactoes[p_move->outer_position]->winner != NOBODY ) { - p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; - } + //check if we have a winner in inner_ttt then set player to outer + p_uttt->outer_tictactoe->content[p_move->outer_position] = p_uttt->inner_tictactoes[p_move->outer_position]->winner; + } p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; set_tictactoe_winner(p_uttt->outer_tictactoe); From e9dca0371f0f65c21ef515fc512d19f969e0009c Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 15 Oct 2021 15:44:46 +0200 Subject: [PATCH 13/30] Add savefile function --- include/model.h | 3 ++- src/model.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 3 deletions(-) diff --git a/include/model.h b/include/model.h index 21be7e1..8b465a6 100644 --- a/include/model.h +++ b/include/model.h @@ -192,4 +192,5 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move); /*Given usefull functions*/ void draw_utictactoe(s_utictactoe *p_uttt); void draw_utictactoe_history(s_utictactoe *p_uttt); -#endif /* MODEL_H */ \ No newline at end of file +void save_a_utictactoe_to_file(FILE *p_f, s_utictactoe *p_uttt); +#endif /* MODEL_H */ diff --git a/src/model.c b/src/model.c index a13bd2b..a46daa4 100644 --- a/src/model.c +++ b/src/model.c @@ -1,5 +1,51 @@ #include "model.h" +// Define shorts positions +char * get_short_position(e_location pos){ + switch(pos) { + case TOPLEFT: + return "TO"; + case TOPCENTER: + return "TC"; + case TOPRIGHT: + return "TR"; + case MIDLEFT: + return "ML"; + case MIDCENTER: + return "MC"; + case MIDRIGHT: + return "MR"; + case BOTTOMLEFT: + return "BL"; + case BOTTOMCENTER: + return "BC"; + case BOTTOMRIGHT: + return "BR"; + case FREE: + return "FR"; + case NONE: + return "NO"; + default: + return "NO"; + } +} + +char get_short_player(e_player player){ + switch(player){ + case PLAYER_O: + return 'O'; + case PLAYER_X: + return 'X'; + case NOBODY: + return '.'; + case BOTH: + return '#'; + default: + return NO; + } +} + +#define SHORT_VERSION(code) SHORT_##code /* * Create empty move @@ -236,10 +282,28 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { //check if we have a winner in inner_ttt then set player to outer p_uttt->outer_tictactoe->content[p_move->outer_position] = p_uttt->inner_tictactoes[p_move->outer_position]->winner; - } - p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; + else { + p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; + } set_tictactoe_winner(p_uttt->outer_tictactoe); return YES; } +void save_a_utictactoe_to_file(FILE *p_f, s_utictactoe *p_uttt){ + assert(p_f); + assert(p_uttt); + fprintf(p_f, "%d\n", p_uttt->inception_level); + if(p_uttt->history){ + list_element_s_move * c_hist = p_uttt->history; + while (c_hist != NULL){ + if(c_hist->last_move){ + fprintf(p_f, "%s %s %c\n", + get_short_position(c_hist->last_move->inner_position), + get_short_position(c_hist->last_move->outer_position), + get_short_player(c_hist->last_move->player)); + } + c_hist = c_hist->next; + } + } +} From 8db53c2eaf589cc94d2e5695a0bb2d3e4dfce258 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 15 Oct 2021 16:39:52 +0200 Subject: [PATCH 14/30] Corrections in play_move() --- src/model.c | 2 -- src/utictactoe.c | 31 ++++++++++++++++++++----------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/model.c b/src/model.c index a46daa4..6d7a052 100644 --- a/src/model.c +++ b/src/model.c @@ -45,7 +45,6 @@ char get_short_player(e_player player){ } } -#define SHORT_VERSION(code) SHORT_##code /* * Create empty move @@ -265,7 +264,6 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { if (is_move_valid(p_uttt, p_move) == NO) { return NO; } - p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; list_element_s_move *value = (list_element_s_move*) malloc(sizeof(list_element_s_move)); diff --git a/src/utictactoe.c b/src/utictactoe.c index b23d427..e1c65be 100644 --- a/src/utictactoe.c +++ b/src/utictactoe.c @@ -140,15 +140,24 @@ int main(int argc, char* argv[]) { exit (EXIT_FAILURE); } } - s_move *test_move = create_empty_move(); - free_move(test_move); - s_tictactoe *test_ttt = create_empty_tictactoe(); - free_tictactoe(test_ttt); - s_utictactoe *test_uttt = create_empty_utictactoe(1); - free_utictactoe(test_uttt); - test_uttt = create_empty_utictactoe(2); - free_utictactoe(test_uttt); - test_uttt = create_empty_utictactoe(3); - free_utictactoe(test_uttt); + FILE *f = fopen("save.txt", "w+"); + s_utictactoe *s = create_empty_utictactoe(2); //replace by 2 for uttt play + s_move *m = create_empty_move(); + m->outer_position = TOPLEFT + rand() % TICTACTOE_SIZE; + while (s->outer_tictactoe->winner == NOBODY) { + draw_utictactoe(s); + m->player = get_next_player_to_play(s); + m->inner_position = TOPLEFT + rand() % TICTACTOE_SIZE; + play_move(s, m); + m->outer_position = m->inner_position; + } + draw_utictactoe(s); + draw_utictactoe_history(s); + save_a_utictactoe_to_file(f, s); + printf("The winner is : %c\n", s->outer_tictactoe->winner); + free_move(m); + free_utictactoe(s); + fclose(f); return EXIT_SUCCESS; -} + + } From 1fb60df60eed9a339d2fa387696215a76b2cbbd8 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 15 Oct 2021 16:47:06 +0200 Subject: [PATCH 15/30] Replace ternary operator with if..else.. --- src/model.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/model.c b/src/model.c index 6d7a052..26dfa0c 100644 --- a/src/model.c +++ b/src/model.c @@ -271,7 +271,12 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { // and affect p_move value->last_move = create_empty_move(); value->last_move = p_move; - value->next = ( p_uttt->history == NULL ) ? NULL : p_uttt->history; + if ( p_uttt->history == NULL ) { + value->next = NULL; + } + else { + value->next = p_uttt->history; + } p_uttt->history = value; if ( p_uttt->inception_level != 1 ) { From 517bcfdc429f64a9056ea56726f375452c42ed01 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 15 Oct 2021 16:49:10 +0200 Subject: [PATCH 16/30] Comment some element --- src/model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/model.c b/src/model.c index 26dfa0c..4490ef5 100644 --- a/src/model.c +++ b/src/model.c @@ -287,7 +287,7 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { p_uttt->outer_tictactoe->content[p_move->outer_position] = p_uttt->inner_tictactoes[p_move->outer_position]->winner; } else { - p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; + //p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; } set_tictactoe_winner(p_uttt->outer_tictactoe); return YES; From e1f15eacc683d73c2d8362f4dc70cc6729538e85 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 15 Oct 2021 16:50:33 +0200 Subject: [PATCH 17/30] Comment some elements --- src/model.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/model.c b/src/model.c index 4490ef5..4102b3c 100644 --- a/src/model.c +++ b/src/model.c @@ -286,9 +286,9 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { //check if we have a winner in inner_ttt then set player to outer p_uttt->outer_tictactoe->content[p_move->outer_position] = p_uttt->inner_tictactoes[p_move->outer_position]->winner; } - else { - //p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; - } + //else { + // p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; + //} set_tictactoe_winner(p_uttt->outer_tictactoe); return YES; } From 4f8ced6d0ec39478e08ad6c54b37df2e058ddac0 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 15 Oct 2021 16:51:44 +0200 Subject: [PATCH 18/30] Comment some elements --- src/model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/model.c b/src/model.c index 4102b3c..267444f 100644 --- a/src/model.c +++ b/src/model.c @@ -270,7 +270,7 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { // we need to create a s_move in memory... // and affect p_move value->last_move = create_empty_move(); - value->last_move = p_move; + //value->last_move = p_move; if ( p_uttt->history == NULL ) { value->next = NULL; } From 97ecb4d93a16cd2f25b2a29ee4252f5ada1d5335 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 15 Oct 2021 16:54:00 +0200 Subject: [PATCH 19/30] value get all p_move value separately un play_move() --- src/model.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/model.c b/src/model.c index 267444f..374c9bf 100644 --- a/src/model.c +++ b/src/model.c @@ -270,7 +270,10 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { // we need to create a s_move in memory... // and affect p_move value->last_move = create_empty_move(); - //value->last_move = p_move; + + value->last_move->inner_position = p_move->inner_position; + value->last_move->outer_position = p_move->outer_position; + value->last_move->player = p_move->player; if ( p_uttt->history == NULL ) { value->next = NULL; } From f2bc1a2c1239ca459d6b7d98a5702f94c032f361 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 15 Oct 2021 16:59:22 +0200 Subject: [PATCH 20/30] Bad shot name of TOPLEFT --- src/model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/model.c b/src/model.c index 374c9bf..d7e5f1e 100644 --- a/src/model.c +++ b/src/model.c @@ -4,7 +4,7 @@ char * get_short_position(e_location pos){ switch(pos) { case TOPLEFT: - return "TO"; + return "TL"; case TOPCENTER: return "TC"; case TOPRIGHT: From 64c85567d9996ec3007b325e714704dfdca0d0a7 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 15 Oct 2021 17:01:32 +0200 Subject: [PATCH 21/30] Add draw function in model.c --- src/model.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/model.c b/src/model.c index d7e5f1e..4650d36 100644 --- a/src/model.c +++ b/src/model.c @@ -313,3 +313,56 @@ void save_a_utictactoe_to_file(FILE *p_f, s_utictactoe *p_uttt){ } } } +void draw_ith_line_of_ttt(s_tictactoe *p_ttt, uint line) { + assert(p_ttt); + printf("%c%c%c", p_ttt->content[line * TICTACTOE_WIDTH], + p_ttt->content[line * TICTACTOE_WIDTH + 1], + p_ttt->content[line * TICTACTOE_WIDTH + 2]); +} + +void draw_tictactoe(s_tictactoe *p_ttt) { + assert(p_ttt); + for (uint line = 0; line < TICTACTOE_WIDTH; line++) { + draw_ith_line_of_ttt(p_ttt, line); + printf("\n"); + } +} + +void draw_utictactoe_history(s_utictactoe *p_uttt) { + assert(p_uttt); + char *e_location_name[] = {"TL", "TC", "TR", "ML", "MC", "MR", + "BL", "BC", "BR", "FREE", "NONE"}; + list_element_s_move *tmp = p_uttt->history; + while (tmp != NULL) { + if (tmp->last_move) { + printf(" - %s %s %c \n", e_location_name[tmp->last_move->inner_position], + e_location_name[tmp->last_move->outer_position], + tmp->last_move->player); + } + tmp = tmp->next; + } +} + +void draw_utictactoe(s_utictactoe *p_uttt) { + assert(p_uttt); + if (p_uttt->inception_level == 1) { + draw_tictactoe(p_uttt->outer_tictactoe); + } else { + for (uint id_ttt = 0; id_ttt < TICTACTOE_SIZE; + id_ttt = id_ttt + TICTACTOE_WIDTH) { + for (uint line = 0; line < TICTACTOE_WIDTH; line++) { + draw_ith_line_of_ttt(p_uttt->inner_tictactoes[id_ttt], line); + printf("|"); + draw_ith_line_of_ttt(p_uttt->inner_tictactoes[id_ttt + 1], line); + printf("|"); + draw_ith_line_of_ttt(p_uttt->inner_tictactoes[id_ttt + 2], line); + printf("\n"); + } + if (id_ttt + TICTACTOE_WIDTH < TICTACTOE_SIZE) { + printf("-----------"); + printf("\n"); + } + } + } + printf("\n####\n"); +} From 8656f37eabbf0598c603dd017d7df9147c5fa869 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 15 Oct 2021 17:26:48 +0200 Subject: [PATCH 22/30] First commit with view --- CMakeLists.txt | 4 ++-- src/CMakeLists.txt | 4 ++-- src/utictactoe.c | 32 ++++++++++++++++++++++---------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b1b6ce3..2c7ce5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.5) -set(CMAKE_C_FLAGS "-std=c99 -g -Wall") +set(CMAKE_C_FLAGS "-std=c99 -lncurses -g -Wall") set(CMAKE_INSTALL_PREFIX ".") include_directories(include) #set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) project(utictactoe) -add_executable(${PROJECT_NAME} src/utictactoe.c src/model.c) +add_executable(${PROJECT_NAME} src/utictactoe.c src/model.c src/view.c) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 80462b7..4812c33 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.5) -set(CMAKE_C_FLAGS "-std=c99 -g -Wall") +set(CMAKE_C_FLAGS "-std=c99 -lncurses -g -Wall") set(CMAKE_INSTALL_PREFIX ".") include_directories(../include) project(utictactoe) -add_executable(${PROJECT_NAME} utictactoe.c model.c) +add_executable(${PROJECT_NAME} utictactoe.c model.c view.c) diff --git a/src/utictactoe.c b/src/utictactoe.c index e1c65be..74ee33a 100644 --- a/src/utictactoe.c +++ b/src/utictactoe.c @@ -8,6 +8,7 @@ #include "utictactoe.h" #include "common.h" #include "model.h" +#include "view.h" #define OPTIONAL_ARGUMENT_IS_PRESENT \ ((optarg == NULL && optind < argc && argv[optind][0] != '-') \ @@ -140,24 +141,35 @@ int main(int argc, char* argv[]) { exit (EXIT_FAILURE); } } - FILE *f = fopen("save.txt", "w+"); - s_utictactoe *s = create_empty_utictactoe(2); //replace by 2 for uttt play + s_utictactoe *s = create_empty_utictactoe(1); s_move *m = create_empty_move(); - m->outer_position = TOPLEFT + rand() % TICTACTOE_SIZE; + p_view v = create_view(s); while (s->outer_tictactoe->winner == NOBODY) { - draw_utictactoe(s); m->player = get_next_player_to_play(s); - m->inner_position = TOPLEFT + rand() % TICTACTOE_SIZE; + m->outer_position=get_next_outer_position(s); + set_next_player_move(m,v); play_move(s, m); - m->outer_position = m->inner_position; } + free_view(v); draw_utictactoe(s); draw_utictactoe_history(s); - save_a_utictactoe_to_file(f, s); printf("The winner is : %c\n", s->outer_tictactoe->winner); free_move(m); free_utictactoe(s); - fclose(f); - return EXIT_SUCCESS; - } + s = create_empty_utictactoe(2); + m = create_empty_move(); + v = create_view(s); + while (s->outer_tictactoe->winner == NOBODY) { + m->player = get_next_player_to_play(s); + m->outer_position=get_next_outer_position(s); + set_next_player_move(m,v); + play_move(s, m); + m->outer_position = m->inner_position; + } + free_view(v); + draw_utictactoe_history(s); + printf("The winner is : %c\n", s->outer_tictactoe->winner); + free_move(m); + free_utictactoe(s); +} From dafe6f73ee6935f64383ec77c3097979a0ad5f16 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Mon, 18 Oct 2021 21:39:00 +0200 Subject: [PATCH 23/30] Ncurse interface seems to work... --- include/view.h | 36 ++++++++++++ src/model.c | 6 +- src/utictactoe.c | 30 +++++----- src/view.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 199 insertions(+), 18 deletions(-) create mode 100644 include/view.h create mode 100644 src/view.c diff --git a/include/view.h b/include/view.h new file mode 100644 index 0000000..6c7f91c --- /dev/null +++ b/include/view.h @@ -0,0 +1,36 @@ +#ifndef VIEW_H +#define VIEW_H +#include +#include "common.h" +#include "model.h" + +typedef struct view * p_view; + +/*! + * This function allocates dynamically a struct view in order to handle the corresponding u_tictactoe. + * + * \param p_uttt a pointer on a s_utictactoe. + * \return a reference to the s_utictactoe memory space allocated, NULL in case + * of allocation problem. + */ +p_view create_view(s_utictactoe * p_uttt); + +void draw_ttt(WINDOW * w, s_tictactoe * t); +e_location get_ttt_position( int x, int y); +/*! + * This function retrieves a valid move proposal from the user using the corresponding view. + * + * \param p_move a pointer on a s_move to be modified. + * \param v a pointer on the view to use. + */ +void set_next_player_move(s_move * p_move, p_view v); + +/*! + * This function free all the memory used by a given view which + * reference is given. + * + * \param v a pointer on a view to be freed. + */ +void free_view(p_view v); + +#endif /* VIEW_H */ diff --git a/src/model.c b/src/model.c index 4650d36..14d5d93 100644 --- a/src/model.c +++ b/src/model.c @@ -289,9 +289,9 @@ e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { //check if we have a winner in inner_ttt then set player to outer p_uttt->outer_tictactoe->content[p_move->outer_position] = p_uttt->inner_tictactoes[p_move->outer_position]->winner; } - //else { - // p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; - //} + else { + p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; + } set_tictactoe_winner(p_uttt->outer_tictactoe); return YES; } diff --git a/src/utictactoe.c b/src/utictactoe.c index 74ee33a..eda2eef 100644 --- a/src/utictactoe.c +++ b/src/utictactoe.c @@ -157,19 +157,19 @@ int main(int argc, char* argv[]) { free_move(m); free_utictactoe(s); - s = create_empty_utictactoe(2); - m = create_empty_move(); - v = create_view(s); - while (s->outer_tictactoe->winner == NOBODY) { - m->player = get_next_player_to_play(s); - m->outer_position=get_next_outer_position(s); - set_next_player_move(m,v); - play_move(s, m); - m->outer_position = m->inner_position; - } - free_view(v); - draw_utictactoe_history(s); - printf("The winner is : %c\n", s->outer_tictactoe->winner); - free_move(m); - free_utictactoe(s); + // s = create_empty_utictactoe(2); + // m = create_empty_move(); + // v = create_view(s); + // while (s->outer_tictactoe->winner == NOBODY) { + // m->player = get_next_player_to_play(s); + // m->outer_position=get_next_outer_position(s); + // set_next_player_move(m,v); + // play_move(s, m); + // m->outer_position = m->inner_position; + // } + // free_view(v); + // draw_utictactoe_history(s); + // printf("The winner is : %c\n", s->outer_tictactoe->winner); + // free_move(m); + // free_utictactoe(s); } diff --git a/src/view.c b/src/view.c new file mode 100644 index 0000000..c0c6f2f --- /dev/null +++ b/src/view.c @@ -0,0 +1,145 @@ +#include "common.h" +#include "model.h" +#include "view.h" + +struct view{ + s_utictactoe * p_uttt; + WINDOW* w_uttt; + WINDOW* w_ttt; +}; + + +p_view create_view(s_utictactoe * u) +{ + p_view v = (p_view) malloc(sizeof(p_view)); + v->p_uttt = u; + + int p_left = 4; + int p_top = 2; + + initscr(); + raw(); + noecho(); + start_color(); + keypad(stdscr, TRUE); + init_pair(1, COLOR_BLACK,COLOR_WHITE); + init_pair(2, COLOR_BLACK,COLOR_RED); + curs_set( 0 ); + + // Create the outer win + WINDOW * w_outer = subwin(stdscr, 9, 11, p_left, p_top); + box(w_outer, ACS_VLINE, ACS_HLINE); + draw_ttt(w_outer, u->outer_tictactoe); + v->w_uttt = w_outer; + + // If needed, create the inner ttt + if ( u->inception_level == 2 ){ + int r,c; + getmaxyx(w_outer, c, r); + WINDOW * w_inner = subwin(stdscr, 9, 11, c + p_left, p_top); + box(w_inner, ACS_VLINE, ACS_HLINE); + //draw_ttt(w_innera); + //wrefresh(w_inner); + v->w_ttt = w_inner; + } + wrefresh(w_outer); + wrefresh(stdscr); + + return v; +} + + +void draw_ttt(WINDOW * w, s_tictactoe * u){ + int x,y; + int i = 0; + for( y = 2; y < 7; y++){ + if ( y % 2 == 0){ + for(x = 3; x < 8 ;x++){ + if (x % 2 != 0) { + mvwprintw(w,y,x,"%c", (u->content[i] == NOBODY)?'.':u->content[i]); + i++; + } + else { mvwprintw(w,y,x,"|"); } + } + } + else { mvwprintw(w,y,3,"-----"); } + } +} + +void set_next_player_move(s_move * m,p_view v) +{ + int ch=-1; + char * s="Player to play:%c"; + int pos_x=3; + int pos_y=2; + while(ch!=' '){ + draw_ttt(v->w_uttt, v->p_uttt->outer_tictactoe); + mvwprintw(stdscr,1,0,s, m->player); + wattron(v->w_uttt, COLOR_PAIR(2)); + mvwaddch(v->w_uttt,pos_y, pos_x, + v->p_uttt->outer_tictactoe->content[get_ttt_position(pos_y, pos_x)] + ); + wattroff(v->w_uttt, COLOR_PAIR(2)); + wrefresh(v->w_uttt); + wrefresh(stdscr); + ch = wgetch(stdscr); + switch(ch) + { + case KEY_BACKSPACE: + case 127: + case '\b': + exit(1); + break; + case KEY_RIGHT: + if(pos_x+1<8){ + pos_x=pos_x+2; + } + break; + case KEY_LEFT: + if(pos_x>3){ + pos_x=pos_x-2; + } + break; + case KEY_UP: + if(pos_y>2){ + pos_y=pos_y-2; + } + break; + case KEY_DOWN: + if(pos_y<6){ + pos_y=pos_y+2; + } + break; + } + + } + // m->inner_position=(e_location)(TOPLEFT + rand() % TICTACTOE_SIZE); + // m->outer_position=(e_location)(TOPLEFT + rand() % TICTACTOE_SIZE); + m->outer_position = get_ttt_position( pos_y, pos_x); + +} + +e_location get_ttt_position( int y, int x) { + if ( y == 2 && x == 3 ){ return TOPLEFT; } + if ( y == 2 && x == 5 ){ return TOPCENTER; } + if ( y == 2 && x == 7 ){ return TOPRIGHT; } + if ( y == 4 && x == 3 ){ return MIDLEFT; } + if ( y == 4 && x == 5 ){ return MIDCENTER; } + if ( y == 4 && x == 7 ){ return MIDRIGHT; } + if ( y == 6 && x == 3 ){ return BOTTOMLEFT; } + if ( y == 6 && x == 5 ){ return BOTTOMCENTER; } + if ( y == 6 && x == 7 ){ return BOTTOMRIGHT; } + return NONE; +} + + +void free_view(p_view v){ + if(v->p_uttt->inception_level == 2){ + delwin(v->w_uttt); + v->w_uttt = NULL; + } + delwin(v->w_ttt); + v->w_ttt = NULL; + v->w_uttt = NULL; + endwin(); +} From 46a55f31d1f6445c4761e159cf153465d4af468a Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Thu, 21 Oct 2021 02:10:16 +0200 Subject: [PATCH 24/30] First working version with ncurse an inception = 2 --- include/view.h | 4 +- src/utictactoe.c | 34 +++++----- src/view.c | 158 ++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 149 insertions(+), 47 deletions(-) diff --git a/include/view.h b/include/view.h index 6c7f91c..9dee319 100644 --- a/include/view.h +++ b/include/view.h @@ -16,7 +16,9 @@ typedef struct view * p_view; p_view create_view(s_utictactoe * p_uttt); void draw_ttt(WINDOW * w, s_tictactoe * t); -e_location get_ttt_position( int x, int y); +//e_location display_ttt( WINDOW * w, s_tictactoe * ttt); +e_location coord_to_elocation( int x, int y); +int elocation_to_coord(e_location l); /*! * This function retrieves a valid move proposal from the user using the corresponding view. * diff --git a/src/utictactoe.c b/src/utictactoe.c index eda2eef..67f2f02 100644 --- a/src/utictactoe.c +++ b/src/utictactoe.c @@ -144,32 +144,32 @@ int main(int argc, char* argv[]) { s_utictactoe *s = create_empty_utictactoe(1); s_move *m = create_empty_move(); p_view v = create_view(s); + while (s->outer_tictactoe->winner == NOBODY) { + m->player = get_next_player_to_play(s); + m->outer_position=get_next_outer_position(s); + set_next_player_move(m,v); + play_move(s, m); + } + free_view(v); + draw_utictactoe(s); + draw_utictactoe_history(s); + printf("The winner is : %c\n", s->outer_tictactoe->winner); + free_move(m); + free_utictactoe(s); + + s = create_empty_utictactoe(2); + m = create_empty_move(); + v = create_view(s); while (s->outer_tictactoe->winner == NOBODY) { m->player = get_next_player_to_play(s); m->outer_position=get_next_outer_position(s); set_next_player_move(m,v); play_move(s, m); + m->outer_position = m->inner_position; } free_view(v); - draw_utictactoe(s); draw_utictactoe_history(s); printf("The winner is : %c\n", s->outer_tictactoe->winner); free_move(m); free_utictactoe(s); - - // s = create_empty_utictactoe(2); - // m = create_empty_move(); - // v = create_view(s); - // while (s->outer_tictactoe->winner == NOBODY) { - // m->player = get_next_player_to_play(s); - // m->outer_position=get_next_outer_position(s); - // set_next_player_move(m,v); - // play_move(s, m); - // m->outer_position = m->inner_position; - // } - // free_view(v); - // draw_utictactoe_history(s); - // printf("The winner is : %c\n", s->outer_tictactoe->winner); - // free_move(m); - // free_utictactoe(s); } diff --git a/src/view.c b/src/view.c index c0c6f2f..025af9a 100644 --- a/src/view.c +++ b/src/view.c @@ -26,8 +26,9 @@ p_view create_view(s_utictactoe * u) init_pair(2, COLOR_BLACK,COLOR_RED); curs_set( 0 ); + mvwprintw(stdscr,0,0,"Inception level %d", u->inception_level); // Create the outer win - WINDOW * w_outer = subwin(stdscr, 9, 11, p_left, p_top); + WINDOW * w_outer = subwin(stdscr, 9, 11, p_top, p_left); box(w_outer, ACS_VLINE, ACS_HLINE); draw_ttt(w_outer, u->outer_tictactoe); v->w_uttt = w_outer; @@ -35,8 +36,8 @@ p_view create_view(s_utictactoe * u) // If needed, create the inner ttt if ( u->inception_level == 2 ){ int r,c; - getmaxyx(w_outer, c, r); - WINDOW * w_inner = subwin(stdscr, 9, 11, c + p_left, p_top); + getmaxyx(w_outer, r, c); + WINDOW * w_inner = subwin(stdscr, 9, 11, p_top, p_left + c); box(w_inner, ACS_VLINE, ACS_HLINE); //draw_ttt(w_innera); //wrefresh(w_inner); @@ -48,7 +49,6 @@ p_view create_view(s_utictactoe * u) return v; } - void draw_ttt(WINDOW * w, s_tictactoe * u){ int x,y; int i = 0; @@ -68,21 +68,61 @@ void draw_ttt(WINDOW * w, s_tictactoe * u){ void set_next_player_move(s_move * m,p_view v) { - int ch=-1; char * s="Player to play:%c"; - int pos_x=3; - int pos_y=2; - while(ch!=' '){ + int in_x = 3, out_x = 3; + int out_y = 2, in_y = 2; + bool outer_selected, played = false; + int ch=-1; + int p_x, p_y, p_yx = 0; + if ( v->p_uttt->inception_level == 2 && m->outer_position != FREE ) { + p_yx = elocation_to_coord(m->outer_position); + p_y = p_yx/10; + p_x = p_yx - ( p_y * 10); + } + while(played == false){ + // debug print + mvwprintw(stdscr, 20,0, " position out: y:%d x:%d, in: y:%d x:%d\n", out_y, out_x, in_y, in_x); + + mvwprintw(stdscr,1,0,s, m->player); draw_ttt(v->w_uttt, v->p_uttt->outer_tictactoe); - mvwprintw(stdscr,1,0,s, m->player); - wattron(v->w_uttt, COLOR_PAIR(2)); - mvwaddch(v->w_uttt,pos_y, pos_x, - v->p_uttt->outer_tictactoe->content[get_ttt_position(pos_y, pos_x)] + + // Need to draw the second tictac toe if we have an inecption level + if ( v->p_uttt->inception_level == 2 ) { + draw_ttt(v->w_ttt, v->p_uttt->inner_tictactoes[coord_to_elocation(out_y, out_x)]); + + // and mark the current active inner ttt with red cursor + if ( m->outer_position != FREE && v->p_uttt->inception_level == 2) { + wattron(v->w_uttt, COLOR_PAIR(2)); + mvwaddch(v->w_uttt ,p_y, p_x, + v->p_uttt->outer_tictactoe->content[m->outer_position] + ); + wattroff(v->w_uttt, COLOR_PAIR(2)); + } + } + + // inner_cursor cursor + if ( outer_selected == true ) { + wattron(v->w_ttt, COLOR_PAIR(1)); + mvwaddch(v->w_ttt ,in_y, in_x, + v->p_uttt->inner_tictactoes[coord_to_elocation(out_y, out_x)]->content[coord_to_elocation(in_y, in_x)] ); - wattroff(v->w_uttt, COLOR_PAIR(2)); + wattroff(v->w_ttt, COLOR_PAIR(1)); + } + + // outer_cursor cursor + wattron(v->w_uttt, COLOR_PAIR(1)); + mvwaddch(v->w_uttt ,out_y, out_x, + v->p_uttt->outer_tictactoe->content[coord_to_elocation(out_y, out_x)] + ); + wattroff(v->w_uttt, COLOR_PAIR(1)); + + // refresh screen wrefresh(v->w_uttt); + if (v->p_uttt->inception_level == 2) wrefresh(v->w_ttt); wrefresh(stdscr); + ch = wgetch(stdscr); + switch(ch) { case KEY_BACKSPACE: @@ -90,36 +130,62 @@ void set_next_player_move(s_move * m,p_view v) case '\b': exit(1); break; - case KEY_RIGHT: - if(pos_x+1<8){ - pos_x=pos_x+2; + case KEY_RIGHT: + if ( outer_selected ) { + if(in_x < 7) { in_x+=2; } + } + else { + if(out_x < 7) { out_x+=2; } } break; - case KEY_LEFT: - if(pos_x>3){ - pos_x=pos_x-2; + case KEY_LEFT: + if ( outer_selected ) { + if( in_x > 3 ) { in_x-=2; } + } + else { + if ( out_x > 3 ) { out_x-=2; } } break; - case KEY_UP: - if(pos_y>2){ - pos_y=pos_y-2; + case KEY_UP: + if ( outer_selected ) { + if ( in_y > 2 ) { in_y-=2; } + } + else { + if ( out_y > 2 ) { out_y-=2; } } break; case KEY_DOWN: - if(pos_y<6){ - pos_y=pos_y+2; + if ( outer_selected ) { + if ( in_y < 6 ) { in_y+=2; } + } + else { + if ( out_y < 6 ) { out_y+=2; } + } + break; + case ' ': + if ( v->p_uttt->inception_level == 1 ) { + m->outer_position = coord_to_elocation( out_y, out_x); + return; + } + else { + if ( outer_selected == true ) { + m->outer_position = coord_to_elocation( out_y, out_x); + m->inner_position = coord_to_elocation( in_y, in_x); + return; + } + else { + if ( coord_to_elocation( out_y, out_x ) == m->outer_position || m->outer_position == FREE){ + outer_selected = true; + } + } } break; } - } - // m->inner_position=(e_location)(TOPLEFT + rand() % TICTACTOE_SIZE); - // m->outer_position=(e_location)(TOPLEFT + rand() % TICTACTOE_SIZE); - m->outer_position = get_ttt_position( pos_y, pos_x); } -e_location get_ttt_position( int y, int x) { +e_location coord_to_elocation( int y, int x) { if ( y == 2 && x == 3 ){ return TOPLEFT; } if ( y == 2 && x == 5 ){ return TOPCENTER; } if ( y == 2 && x == 7 ){ return TOPRIGHT; } @@ -132,6 +198,39 @@ e_location get_ttt_position( int y, int x) { return NONE; } +int elocation_to_coord(e_location l){ + switch(l){ + case TOPLEFT: + return 23; + break; + case TOPCENTER: + return 25; + break; + case TOPRIGHT: + return 27; + break; + case MIDLEFT: + return 43; + break; + case MIDCENTER: + return 45; + break; + case MIDRIGHT: + return 47; + break; + case BOTTOMLEFT: + return 63; + break; + case BOTTOMCENTER: + return 65; + break; + case BOTTOMRIGHT: + return 67; + break; + default: + return NONE; + } +} void free_view(p_view v){ if(v->p_uttt->inception_level == 2){ @@ -143,3 +242,4 @@ void free_view(p_view v){ v->w_uttt = NULL; endwin(); } + From 9c47a74bc8cbf2f5bdabf05067f1246f43eca384 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Thu, 21 Oct 2021 23:47:04 +0200 Subject: [PATCH 25/30] remove debug output (jut comment it) --- src/view.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/view.c b/src/view.c index 025af9a..b2dd8f7 100644 --- a/src/view.c +++ b/src/view.c @@ -81,7 +81,7 @@ void set_next_player_move(s_move * m,p_view v) } while(played == false){ // debug print - mvwprintw(stdscr, 20,0, " position out: y:%d x:%d, in: y:%d x:%d\n", out_y, out_x, in_y, in_x); + // mvwprintw(stdscr, 20,0, " position out: y:%d x:%d, in: y:%d x:%d\n", out_y, out_x, in_y, in_x); mvwprintw(stdscr,1,0,s, m->player); draw_ttt(v->w_uttt, v->p_uttt->outer_tictactoe); From 83df11530c3d079965a2d1f8d916d1ed14a9c9d1 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 22 Oct 2021 00:37:38 +0200 Subject: [PATCH 26/30] Validate with enter (not space) --- src/view.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/view.c b/src/view.c index b2dd8f7..b43319a 100644 --- a/src/view.c +++ b/src/view.c @@ -66,7 +66,7 @@ void draw_ttt(WINDOW * w, s_tictactoe * u){ } } -void set_next_player_move(s_move * m,p_view v) +void set_next_player_move(s_move * m, p_view v) { char * s="Player to play:%c"; int in_x = 3, out_x = 3; @@ -162,7 +162,7 @@ void set_next_player_move(s_move * m,p_view v) if ( out_y < 6 ) { out_y+=2; } } break; - case ' ': + case '\n': if ( v->p_uttt->inception_level == 1 ) { m->outer_position = coord_to_elocation( out_y, out_x); return; From 283bd63877d85178d11dcdc3fe8e8a85b721e45f Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 22 Oct 2021 08:41:42 +0200 Subject: [PATCH 27/30] Backspace can now go back in outer_ttt when in inner --- src/view.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/view.c b/src/view.c index b43319a..97c46c6 100644 --- a/src/view.c +++ b/src/view.c @@ -128,7 +128,12 @@ void set_next_player_move(s_move * m, p_view v) case KEY_BACKSPACE: case 127: case '\b': - exit(1); + if ( outer_selected == true && v->p_uttt->inception_level == 2 ) { + outer_selected = false; + } + else { + exit(1); + } break; case KEY_RIGHT: if ( outer_selected ) { From 96499a06cbac2aa33e19ffcf653d94e0aa24f12a Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Fri, 22 Oct 2021 08:49:10 +0200 Subject: [PATCH 28/30] delete all windows on free_view() Avoid terminal corruption on exit --- src/view.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/view.c b/src/view.c index 97c46c6..6341937 100644 --- a/src/view.c +++ b/src/view.c @@ -238,10 +238,8 @@ int elocation_to_coord(e_location l){ } void free_view(p_view v){ - if(v->p_uttt->inception_level == 2){ - delwin(v->w_uttt); - v->w_uttt = NULL; - } + delwin(v->w_uttt); + v->w_uttt = NULL; delwin(v->w_ttt); v->w_ttt = NULL; v->w_uttt = NULL; From 033a436be2401ca077b103a0706939e87da9028b Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Sun, 24 Oct 2021 17:27:27 +0200 Subject: [PATCH 29/30] Exit programm properly when exit with KEY_DELETE --- src/view.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/view.c b/src/view.c index 6341937..28b3c29 100644 --- a/src/view.c +++ b/src/view.c @@ -128,10 +128,15 @@ void set_next_player_move(s_move * m, p_view v) case KEY_BACKSPACE: case 127: case '\b': + // if we are in inner TTT window, go back to outer if ( outer_selected == true && v->p_uttt->inception_level == 2 ) { outer_selected = false; } else { + // If not Exit programm, but we need to do it properly. + free_utictactoe(v->p_uttt); + free_move(m); + free_view(v); exit(1); } break; From 87e7ff5829a8c0f012c4ed052a3d9568d4b8a548 Mon Sep 17 00:00:00 2001 From: Yorick Barbanneau Date: Sun, 24 Oct 2021 23:22:43 +0200 Subject: [PATCH 30/30] Dumb but not dumber IA --- include/common.h | 5 +++ include/ia.h | 17 +++++++++++ include/view.h | 3 +- src/CMakeLists.txt | 2 +- src/ia.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++ src/utictactoe.c | 49 ++++++++++++------------------ src/view.c | 27 ++++++++++++++-- 7 files changed, 145 insertions(+), 34 deletions(-) create mode 100644 include/ia.h create mode 100644 src/ia.c diff --git a/include/common.h b/include/common.h index 371b0f6..97101b6 100644 --- a/include/common.h +++ b/include/common.h @@ -24,4 +24,9 @@ typedef enum { ALMOST, } e_status; +typedef enum { + HUMAN, + RANDOM, + CLEVER, +} e_tactic; #endif /*COMMON*/ diff --git a/include/ia.h b/include/ia.h new file mode 100644 index 0000000..f61ce40 --- /dev/null +++ b/include/ia.h @@ -0,0 +1,17 @@ +#ifndef IA_H +#define IA_H +#include "common.h" +#include "model.h" +/*! + * This function modify the move in parameter in order to get a valid move (1) randomly if tactic is 0 or + * (2) in a clever way if tactic is 1 in the corresponding utictactoe u. + * + * \param p_uttt a pointer on a s_utictactoe. + * \param p_move a pointer on a s_move to be modified. + * \param tactic an e_tactic set to 0 for random strategy and 1 for clever one. + */ +void best_move(s_utictactoe* p_uttt, s_move* p_move, e_tactic tactic); + +s_tictactoe * clone_ttt( s_tictactoe * p_ttt ); +e_location get_best_random_position( s_tictactoe * p_uttt, e_player player); +#endif diff --git a/include/view.h b/include/view.h index 9dee319..a5d5e5d 100644 --- a/include/view.h +++ b/include/view.h @@ -25,8 +25,9 @@ int elocation_to_coord(e_location l); * \param p_move a pointer on a s_move to be modified. * \param v a pointer on the view to use. */ -void set_next_player_move(s_move * p_move, p_view v); +void set_next_player_move(s_move * p_move, p_view v, e_tactic tactic); +void display_winner(p_view v); /*! * This function free all the memory used by a given view which * reference is given. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4812c33..996dcc8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,4 +3,4 @@ set(CMAKE_C_FLAGS "-std=c99 -lncurses -g -Wall") set(CMAKE_INSTALL_PREFIX ".") include_directories(../include) project(utictactoe) -add_executable(${PROJECT_NAME} utictactoe.c model.c view.c) +add_executable(${PROJECT_NAME} utictactoe.c model.c view.c ia.c) diff --git a/src/ia.c b/src/ia.c new file mode 100644 index 0000000..64a73ff --- /dev/null +++ b/src/ia.c @@ -0,0 +1,76 @@ +#include "common.h" +#include "model.h" +#include "view.h" +#include "ia.h" + +void best_move (s_utictactoe * p_uttt, s_move * m ,e_tactic tactic) +{ + //do{ + if ( p_uttt->inception_level == 1 ) { + m->outer_position = get_best_random_position( + p_uttt->outer_tictactoe, + m->player + ); + } + else { + m->outer_position = get_next_outer_position(p_uttt); + if ( m->outer_position == FREE ) { + do { + m->outer_position = (e_location)(TOPLEFT + rand() % TICTACTOE_SIZE); + } while(p_uttt->inner_tictactoes[m->outer_position]->winner != NOBODY); + } + + m->inner_position = get_best_random_position( + p_uttt->inner_tictactoes[m->outer_position], + m->player + ); + } + //} while (is_move_valid(p_uttt,m) != YES); + return; +} + +s_tictactoe * clone_ttt( s_tictactoe * p_ttt ) { + s_tictactoe * t = create_empty_tictactoe(); + for (int i=0; icontent[i] = p_ttt->content[i]; + } + return t; +} + +e_location get_best_random_position (s_tictactoe * p_ttt, e_player player) { + mvwprintw(stdscr, 13, 0, " "); + s_tictactoe * c_ttt = clone_ttt(p_ttt); + e_player opponent = ( player == PLAYER_O )?PLAYER_X:PLAYER_O; + + // Check if IA player can win + for(int i=0; icontent[i] == NOBODY) { + c_ttt->content[i] = player; + set_tictactoe_winner(c_ttt); + if ( c_ttt->winner != NOBODY ) { + free_tictactoe(c_ttt); + mvwprintw(stdscr, 13, 0, "Je vais gagner "); + return i; + } + c_ttt->content[i] = NOBODY; + } + } + + // avoid loosing + for(int i=0; icontent[i] == NOBODY) { + c_ttt->content[i] = opponent; + set_tictactoe_winner(c_ttt); + if ( c_ttt->winner != NOBODY ) { + free_tictactoe(c_ttt); + mvwprintw(stdscr, 13, 0, "Je ne peux pas te laisser gagner!"); + return i; + } + c_ttt->content[i] = NOBODY; + } + } + + // We have not a winnner move... + free_tictactoe(c_ttt); + return (e_location)(rand() % TICTACTOE_SIZE); +} diff --git a/src/utictactoe.c b/src/utictactoe.c index 67f2f02..e3d957b 100644 --- a/src/utictactoe.c +++ b/src/utictactoe.c @@ -9,6 +9,7 @@ #include "common.h" #include "model.h" #include "view.h" +#include "ia.h" #define OPTIONAL_ARGUMENT_IS_PRESENT \ ((optarg == NULL && optind < argc && argv[optind][0] != '-') \ @@ -46,15 +47,15 @@ int check_int_value ( char *value, int min, int max){ int main(int argc, char* argv[]) { int optc; - int cross_ai, round_ai = 0; - int inception_level = 0; + e_tactic tactic_cross = HUMAN, tactic_round = HUMAN; + int inception_level = 2; bool verbose, contest_mode = false; char * contest_file; static struct option long_opts[] = { {"inception-level", optional_argument, 0, 'i'}, - {"cross-ai", required_argument, 0, 'x'}, - {"round-ai", required_argument, 0, 'o'}, + {"tactic_cross", required_argument, 0, 'x'}, + {"tactic_round", required_argument, 0, 'o'}, {"contest", required_argument, 0, 'c'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, @@ -80,8 +81,8 @@ int main(int argc, char* argv[]) { case 'x': printf ("cross ai\n"); if ( optarg ) { - cross_ai = check_int_value(optarg, 0, 1); - if ( cross_ai == -1 ) { + tactic_cross = check_int_value(optarg, 0, 2); + if ( tactic_cross == -1 ) { fprintf(stderr, "Error: incorrect cross ai value\n"); exit (EXIT_FAILURE); } @@ -96,8 +97,8 @@ int main(int argc, char* argv[]) { case 'o': printf ("round ai\n"); if ( optarg ) { - round_ai = check_int_value(optarg, 0, 1); - if ( round_ai == -1 ) { + tactic_round = check_int_value(optarg, 0, 2); + if ( tactic_round == -1 ) { fprintf(stderr, "Error: incorrect round ai value\n"); exit (EXIT_FAILURE); } @@ -141,35 +142,23 @@ int main(int argc, char* argv[]) { exit (EXIT_FAILURE); } } - s_utictactoe *s = create_empty_utictactoe(1); + srand(time(NULL)); + s_utictactoe *s = create_empty_utictactoe(inception_level); s_move *m = create_empty_move(); p_view v = create_view(s); - while (s->outer_tictactoe->winner == NOBODY) { - m->player = get_next_player_to_play(s); - m->outer_position=get_next_outer_position(s); - set_next_player_move(m,v); - play_move(s, m); - } - free_view(v); - draw_utictactoe(s); - draw_utictactoe_history(s); - printf("The winner is : %c\n", s->outer_tictactoe->winner); - free_move(m); - free_utictactoe(s); - - s = create_empty_utictactoe(2); - m = create_empty_move(); - v = create_view(s); while (s->outer_tictactoe->winner == NOBODY) { m->player = get_next_player_to_play(s); - m->outer_position=get_next_outer_position(s); - set_next_player_move(m,v); + m->outer_position = get_next_outer_position(s); + if (m->player == PLAYER_X) { + set_next_player_move(m, v, tactic_cross); + } else { + set_next_player_move(m, v, tactic_round); + } play_move(s, m); - m->outer_position = m->inner_position; } + display_winner(v); + getchar();//just to pause before quitting the program free_view(v); - draw_utictactoe_history(s); - printf("The winner is : %c\n", s->outer_tictactoe->winner); free_move(m); free_utictactoe(s); } diff --git a/src/view.c b/src/view.c index 28b3c29..45a1ea6 100644 --- a/src/view.c +++ b/src/view.c @@ -1,6 +1,7 @@ #include "common.h" #include "model.h" #include "view.h" +#include "ia.h" struct view{ s_utictactoe * p_uttt; @@ -66,8 +67,15 @@ void draw_ttt(WINDOW * w, s_tictactoe * u){ } } -void set_next_player_move(s_move * m, p_view v) +void set_next_player_move(s_move * m, p_view v, e_tactic tactic ) { + + // computer player + if(tactic != HUMAN) { + best_move(v->p_uttt, m, tactic); + return ; + } + char * s="Player to play:%c"; int in_x = 3, out_x = 3; int out_y = 2, in_y = 2; @@ -120,7 +128,7 @@ void set_next_player_move(s_move * m, p_view v) wrefresh(v->w_uttt); if (v->p_uttt->inception_level == 2) wrefresh(v->w_ttt); wrefresh(stdscr); - + ch = wgetch(stdscr); switch(ch) @@ -242,6 +250,21 @@ int elocation_to_coord(e_location l){ } } +void display_winner(p_view v){ + int ch = ' '; + draw_ttt(v->w_uttt, v->p_uttt->outer_tictactoe); + wrefresh(v->w_uttt); + if (v->p_uttt->inception_level == 2){ + draw_ttt(v->w_ttt, v->p_uttt->inner_tictactoes[TOPLEFT]); + } + wrefresh(stdscr); + do { + mvwprintw(stdscr, 1, 0, "le gagnant est : %c, apputez sur 'entree' pour quitter", + v->p_uttt->outer_tictactoe->winner); + ch = wgetch(stdscr); + } while (ch != '\n'); + +} void free_view(p_view v){ delwin(v->w_uttt); v->w_uttt = NULL;