From 9a668c78bed7197e0b349d4bd2908a67bedd295f Mon Sep 17 00:00:00 2001 From: Joursoir Date: Sat, 20 Feb 2021 13:11:12 +0000 Subject: improve AI, delete dbgprint(), fix some bugs --- GameField.hpp | 1 - ai.cpp | 24 ++++++++++--------- ai.hpp | 5 ++-- clui.cpp | 76 ++++++++++++++++++++++++++--------------------------------- 4 files changed, 49 insertions(+), 57 deletions(-) diff --git a/GameField.hpp b/GameField.hpp index 00a2764..f39c5b7 100644 --- a/GameField.hpp +++ b/GameField.hpp @@ -26,7 +26,6 @@ public: int GetState() { return state; } int GetRows() { return rows; } int GetCols() { return cols; } - int GetWhoMove() { return who_move; } bool CanMove(int y, int x); void Move(int y, int x); diff --git a/ai.cpp b/ai.cpp index bef4567..05f95af 100644 --- a/ai.cpp +++ b/ai.cpp @@ -13,23 +13,25 @@ enum scores { LOSE_SCORE = -10 }; -AI::AI(int d) : max_depth(d) +AI::AI(int p, int d) : player(p), max_depth(d), first_move(true) { srand(time(NULL)); } -void AI::GetFirstMove(int &my, int &mx, int rows, int cols) -{ - my = rand() % rows; - mx = rand() % cols; -} - void AI::GetBestMove(int &my, int &mx, GameField field) { int score = MIN_SCORE; int rows = field.GetRows(); int cols = field.GetCols(); + // give chance to user :) + if(first_move) { + my = rand() % rows; + mx = rand() % cols; + first_move = false; + return; + } + int y, x; for(y = 0; y < rows; y++) { for(x = 0; x < cols; x++) @@ -37,7 +39,7 @@ void AI::GetBestMove(int &my, int &mx, GameField field) if(!field.CanMove(y, x)) continue; field.Move(y, x); - int result = min(field, 1); // min because next move by player + int result = min(field, 1); field.UndoMove(y, x); if(result > score) { score = result; @@ -54,9 +56,9 @@ int AI::score(GameField field) if(state == G_DRAW) return DRAW_SCORE; if(state == G_XPLAYER) - return field.GetWhoMove() == G_XPLAYER ? WIN_SCORE : LOSE_SCORE; + return player == G_XPLAYER ? WIN_SCORE : LOSE_SCORE; if(state == G_OPLAYER) - return field.GetWhoMove() == G_OPLAYER ? WIN_SCORE : LOSE_SCORE; + return player == G_OPLAYER ? WIN_SCORE : LOSE_SCORE; return NONE_SCORE; } @@ -104,7 +106,7 @@ int AI::max(GameField field, int depth) if(!field.CanMove(y, x)) continue; field.Move(y, x); - int result = max(field, depth + 1); + int result = min(field, depth + 1); field.UndoMove(y, x); if(result > score) score = result; diff --git a/ai.hpp b/ai.hpp index 19420e5..0b757c9 100644 --- a/ai.hpp +++ b/ai.hpp @@ -4,11 +4,12 @@ class GameField; class AI { + int player; int max_depth; + bool first_move; public: - AI(int d); + AI(int p, int d); - void GetFirstMove(int &my, int &mx, int rows, int cols); void GetBestMove(int &my, int &mx, GameField field); private: int score(GameField field); diff --git a/clui.cpp b/clui.cpp index ecdd207..5eff6b2 100644 --- a/clui.cpp +++ b/clui.cpp @@ -42,7 +42,7 @@ int gb_lwin = MIN_RCWD; int gb_symbol = SYMBOL_PLAYERONE; int gb_depth = MIN_RCWD; -void aiMove(int y, int x); +void aiMove(); void updateCursor() { @@ -50,14 +50,6 @@ void updateCursor() refresh(); } -void dbgprint(const char *msg) -{ - move(20, 0); - clrtoeol(); // clear old - mvprintw(20, 0, msg); - updateCursor(); // return cursor back -} - void help_print(const char *msg, ...) { move(max_y + 2, 0); @@ -115,6 +107,16 @@ void drawGame(int rows, int cols) updateCursor(); } +void startGame() +{ + if(game_field) + delete game_field; + game_field = new GameField(gb_y, gb_x, gb_lwin); + drawGame(gb_y, gb_x); + if(play_with_ai && gb_symbol == SYMBOL_PLAYERTWO) + aiMove(); +} + void changePlayer() { if(print_symbol == SYMBOL_PLAYERONE) @@ -140,21 +142,17 @@ void gameMove(int y, int x) int game_y = (y - min_y) / NC_MOVE_Y; int game_x = (x - min_x) / NC_MOVE_X; - if(!game_field->CanMove(game_y, game_x)) { - dbgprint("yet 'x' or 'o'"); + if(!game_field->CanMove(game_y, game_x)) return; - } + game_field->Move(game_y, game_x); printMove(y, x, print_symbol); changePlayer(); state = game_field->GetState(); if(state == G_NONE) { - if(play_with_ai && gb_symbol != print_symbol) { - int ai_y, ai_x; - game_bot->GetBestMove(ai_y, ai_x, *game_field); - aiMove(ai_y, ai_x); - } + if(play_with_ai && gb_symbol != print_symbol) + aiMove(); } else if(state == G_DRAW) help_print("DRAW!"); @@ -164,8 +162,10 @@ void gameMove(int y, int x) help_print("WINNER: %c!", SYMBOL_PLAYERTWO); } -void aiMove(int y, int x) +void aiMove() { + int y, x; + game_bot->GetBestMove(y, x, *game_field); gameMove(min_y + NC_MOVE_Y * y, min_x + NC_MOVE_X * x); } @@ -176,31 +176,27 @@ void handleButtons() { switch(ch) { case KEY_LEFT: - if(cursor_x > min_x) cursor_x -= NC_MOVE_X; - else dbgprint("left border"); + if(cursor_x > min_x) + cursor_x -= NC_MOVE_X; break; case KEY_DOWN: - if(cursor_y < max_y) cursor_y += NC_MOVE_Y; - else dbgprint("down border"); + if(cursor_y < max_y) + cursor_y += NC_MOVE_Y; break; case KEY_UP: - if(cursor_y > min_y) cursor_y -= NC_MOVE_Y; - else dbgprint("up border"); + if(cursor_y > min_y) + cursor_y -= NC_MOVE_Y; break; case KEY_RIGHT: - if(cursor_x < max_x) cursor_x += NC_MOVE_X; - else dbgprint("right border"); + if(cursor_x < max_x) + cursor_x += NC_MOVE_X; break; - case key_enter: { + case key_enter: gameMove(cursor_y, cursor_x); break; - } - case key_restart: { - delete game_field; - drawGame(gb_y, gb_x); - game_field = new GameField(gb_y, gb_x, gb_lwin); + case key_restart: + startGame(); // no break - } default: continue; } @@ -253,7 +249,7 @@ int main(int argc, char *argv[]) }; int result; - while((result = getopt_long(argc, argv, "hr:c:w:as:", long_options, NULL)) != -1) { + while((result = getopt_long(argc, argv, "hr:c:w:as:d:", long_options, NULL)) != -1) { switch(result) { case 'h': { usage(); return 0; } case 'r': { gb_y = atoi(optarg); break; } @@ -278,18 +274,12 @@ int main(int argc, char *argv[]) SYMBOL_PLAYERONE, SYMBOL_PLAYERTWO); return 1; } - game_bot = new AI(gb_depth); + game_bot = new AI(gb_symbol == SYMBOL_PLAYERONE ? + G_OPLAYER : G_XPLAYER, gb_depth); } else gb_symbol = SYMBOL_PLAYERONE; - /* start game */ - game_field = new GameField(gb_y, gb_x, gb_lwin); - drawGame(gb_y, gb_x); - if(play_with_ai && gb_symbol == SYMBOL_PLAYERTWO) { - int ai_y, ai_x; - game_bot->GetFirstMove(ai_y, ai_x, gb_y, gb_x); - aiMove(ai_y, ai_x); - } + startGame(); handleButtons(); if(game_field) -- cgit v1.2.3-18-g5258