diff options
author | Joursoir <chat@joursoir.net> | 2021-02-19 19:00:50 +0000 |
---|---|---|
committer | Joursoir <chat@joursoir.net> | 2021-02-19 19:00:50 +0000 |
commit | 42a235befbb4fc644ec806576211999a27ef1c6e (patch) | |
tree | 774908df1c4966c86b88cfea3e67dd7ee189cd0f | |
parent | 0f2504aaa684d53bb30a6d3c152e35f9dfe6e47e (diff) | |
download | lp-gomoku-42a235befbb4fc644ec806576211999a27ef1c6e.tar.gz lp-gomoku-42a235befbb4fc644ec806576211999a27ef1c6e.tar.bz2 lp-gomoku-42a235befbb4fc644ec806576211999a27ef1c6e.zip |
add class artificial intelligence with functional
-rw-r--r-- | ai.cpp | 115 | ||||
-rw-r--r-- | ai.hpp | 19 |
2 files changed, 134 insertions, 0 deletions
@@ -0,0 +1,115 @@ +#include <stdlib.h> +#include <time.h> + +#include "ai.hpp" +#include "GameField.hpp" + +enum scores { + MIN_SCORE = -1000, + MAX_SCORE = 1000, + NONE_SCORE = 0, + DRAW_SCORE = 2, + WIN_SCORE = 10, + LOSE_SCORE = -10 +}; + +AI::AI(int d) : max_depth(d) +{ + 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(); + + int y, x; + for(y = 0; y < rows; y++) { + for(x = 0; x < cols; x++) + { + if(!field.CanMove(y, x)) + continue; + field.Move(y, x); + int result = min(field, 1); // min because next move by player + field.UndoMove(y, x); + if(result > score) { + score = result; + my = y; + mx = x; + } + } + } +} + +int AI::score(GameField field) +{ + int state = field.GetState(); + if(state == G_DRAW) + return DRAW_SCORE; + if(state == G_XPLAYER) + return field.GetWhoMove() == G_XPLAYER ? WIN_SCORE : LOSE_SCORE; + if(state == G_OPLAYER) + return field.GetWhoMove() == G_OPLAYER ? WIN_SCORE : LOSE_SCORE; + return NONE_SCORE; +} + +int AI::min(GameField field, int depth) +{ + if(field.GetState() != G_NONE || depth >= max_depth) { + return score(field); + } + + int score = MAX_SCORE; + int rows = field.GetRows(); + int cols = field.GetCols(); + + int y, x; + for(y = 0; y < rows; y++) { + for(x = 0; x < cols; x++) + { + if(!field.CanMove(y, x)) + continue; + field.Move(y, x); + int result = max(field, depth + 1); + field.UndoMove(y, x); + if(result < score) + score = result; + } + } + + return score; +} + +int AI::max(GameField field, int depth) +{ + if(field.GetState() != G_NONE || depth >= max_depth) { + return score(field); + } + + int score = MIN_SCORE; + int rows = field.GetRows(); + int cols = field.GetCols(); + + int y, x; + for(y = 0; y < rows; y++) { + for(x = 0; x < cols; x++) + { + if(!field.CanMove(y, x)) + continue; + field.Move(y, x); + int result = max(field, depth + 1); + field.UndoMove(y, x); + if(result > score) + score = result; + } + } + + return score; +} @@ -0,0 +1,19 @@ +#ifndef LPG_AI_H +#define LPG_AI_H + +class GameField; + +class AI { + int max_depth; +public: + AI(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); + int min(GameField field, int depth); + int max(GameField field, int depth); +}; + +#endif /* LPG_AI_H */ |