summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoursoir <chat@joursoir.net>2021-02-20 13:11:12 +0000
committerJoursoir <chat@joursoir.net>2021-02-20 13:11:12 +0000
commit9a668c78bed7197e0b349d4bd2908a67bedd295f (patch)
tree3b94f44b7714c3c57d265be3b44ae79dad5046fe
parent34e22b1d5ea04a9bb2d8b8219f5881c90aa8cc70 (diff)
downloadlp-gomoku-9a668c78bed7197e0b349d4bd2908a67bedd295f.tar.gz
lp-gomoku-9a668c78bed7197e0b349d4bd2908a67bedd295f.tar.bz2
lp-gomoku-9a668c78bed7197e0b349d4bd2908a67bedd295f.zip
improve AI, delete dbgprint(), fix some bugs
-rw-r--r--GameField.hpp1
-rw-r--r--ai.cpp24
-rw-r--r--ai.hpp5
-rw-r--r--clui.cpp76
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)