Advertisement
Hinski2

Untitled

May 22nd, 2024
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.41 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. enum {black, white, blank};
  5. typedef pair<int, int> pii;
  6. typedef vector<vector<int>> vvi;
  7. int max_tree_deep = 3;
  8. const int inf = 1e9 + 7;
  9. const int max_player = black;
  10. const int min_player = white;
  11.  
  12. struct State{
  13.     vvi board;
  14.     int deep;
  15.     int player;
  16.     int alfa;
  17.     int beta;
  18.     int val;
  19.     vector<pii> black_poss;
  20.     vector<pii> white_poss;
  21. };
  22.  
  23.  
  24. void set_initial_state(State &state, int player){
  25.     state.board.resize(8);
  26.     for(int i = 0; i < 8; i++){
  27.         state.board[i].resize(8);
  28.         for(int j = 0; j < 8; j++)
  29.             state.board[i][j] = blank;
  30.     }
  31.  
  32.     state.board[3][3] = state.board[4][4] = black;
  33.     state.board[3][4] = state.board[4][3] = white;
  34.     state.black_poss.push_back({3, 3});
  35.     state.black_poss.push_back({4, 4});
  36.     state.white_poss.push_back({3, 4});
  37.     state.white_poss.push_back({4, 3});
  38.    
  39.     state.deep = 0;
  40.     state.player = player;
  41.     state.alfa = -inf;
  42.     state.beta = inf;
  43.     state.val = (player == max_player ? -inf : inf);
  44. }
  45.  
  46. bool valid_coord(const pii &poss){
  47.     return 0 <= poss.first && poss.first < 8 && 0 <= poss.second && poss.second < 8;
  48. }
  49.  
  50. void make_move(State &child, const pii &move){
  51.     //zmiana na chwile
  52.     child.player ^= 1;
  53.  
  54.     const int &x = move.first, &y = move.second;
  55.     vector<pii> &my_poss = (child.player == black ? child.black_poss : child.white_poss);
  56.     vector<pii> &his_poss = (child.player == black ? child.white_poss : child.black_poss);
  57.  
  58.     child.board[x][y] = child.player;
  59.     my_poss.push_back(move);
  60.  
  61.     for(int i: {-1, 0, 1}){
  62.         for(int j: {-1, 0, 1}){
  63.             if(!i && !j) continue;
  64.             pii poss = {x + i, y + j};
  65.             vector<pii> to_flip;
  66.  
  67.             while(valid_coord(poss) && child.board[poss.first][poss.second] == child.player ^ 1){
  68.                 to_flip.push_back(poss);
  69.                 poss.first += i, poss.second += j;
  70.             }
  71.  
  72.             if(valid_coord(poss) && child.board[poss.first][poss.second] == child.player){
  73.                 for(auto [a, b]: to_flip){
  74.                     child.board[a][b] = child.player;
  75.                     my_poss.push_back({a, b});
  76.                     auto rm = find(his_poss.begin(), his_poss.end(), make_pair(a, b));
  77.  
  78.                     if(rm != his_poss.end()) his_poss.erase(rm);
  79.                 }
  80.             }
  81.         }
  82.     }
  83.  
  84.     child.player ^= 1;
  85. }
  86.  
  87. void make_child_from_state(const State &state, State &child, const pii &move){
  88.     child.board = state.board; // to jest kopia
  89.     child.deep = state.deep + 1;
  90.     child.player = state.player ^ 1;
  91.     child.alfa = state.alfa;
  92.     child.beta = state.beta;
  93.     child.val = (child.player == max_player ? -inf : inf);
  94.     child.black_poss = state.black_poss;
  95.     child.white_poss = state.white_poss;
  96.  
  97.     make_move(child, move);
  98. }
  99.  
  100. int eval_state(const State &state){
  101.     // return state.black_poss.size() - state.white_poss.size();
  102.     const vector<vector<int>> val = {
  103.        {4,0,2,2,2,2,0,4},
  104.        {0,0,2,1,1,2,0,0},
  105.        {2,2,2,1,1,2,2,2},
  106.        {2,1,1,1,1,1,1,2},
  107.        {2,1,1,1,1,1,1,2},
  108.        {2,2,2,1,1,2,2,2},
  109.        {0,0,2,1,1,2,0,0},
  110.        {4,0,2,2,2,2,0,4},
  111.     };
  112.  
  113.     int b = 0, w = 0;
  114.     for(auto [x, y]: state.black_poss)
  115.         b += val[x][y];
  116.     for(auto [x, y]: state.white_poss)
  117.         w += val[x][y];
  118.    
  119.     return b - w;
  120. }
  121.  
  122.  
  123. vector<pii> generate_moves(const State &state){
  124.     vector<pii> possible_moves;
  125.     for(auto u: (state.player == black ? state.black_poss : state.white_poss)){
  126.         for(int i: {-1, 0, 1}){
  127.             for(int j: {-1, 0, 1}){
  128.                 if(!i and !j) continue;
  129.                 pii poss = {u.first + i, u.second + j};
  130.                 bool captured = false;
  131.  
  132.                 while(valid_coord(poss) && state.board[poss.first][poss.second] == (state.player ^ 1))
  133.                     captured = true, poss.first += i, poss.second += j;
  134.  
  135.                 if(valid_coord(poss) && state.board[poss.first][poss.second] == blank && captured)
  136.                     possible_moves.push_back(poss);
  137.             }
  138.         }
  139.     }
  140.  
  141.     return possible_moves;
  142. }
  143.  
  144. State min_max(State state){
  145.     // sprawdzanie czy można grać
  146.     if(state.deep >= max_tree_deep){
  147.         state.val = eval_state(state);
  148.         return state;
  149.     }
  150.  
  151.     vector<pii> possible_moves = generate_moves(state);
  152.     if(possible_moves.size() == 0){
  153.         state.val = eval_state(state);
  154.         return state;
  155.     }
  156.  
  157.     // moge grać
  158.     for(const auto move: possible_moves){
  159.         State child; make_child_from_state(state, child, move);
  160.         child = min_max(child);
  161.        
  162.         if(state.player == max_player){
  163.             state.val = max(state.val, child.val);
  164.             state.alfa = max(state.alfa, state.val);
  165.  
  166.             if(state.val >= state.beta)
  167.                 break;
  168.         }
  169.         else if(state.player == min_player){
  170.             state.val = min(state.val, child.val);
  171.             state.beta = min(state.beta, state.val);
  172.             if(state.val <= state.alfa)
  173.                 break;
  174.         }
  175.     }
  176.  
  177.     return state;
  178. }
  179.  
  180. State choose_random(const State &state){
  181.     vector<pii> possible_moves = generate_moves(state);
  182.     int idx = rand() % possible_moves.size();
  183.     State child; make_child_from_state(state, child, possible_moves[idx]);
  184.     return child;
  185. }
  186.  
  187. long seed()
  188. {
  189.     auto t=chrono::system_clock::now();
  190.     return std::chrono::duration_cast<std::chrono::milliseconds>(t.time_since_epoch()).count();
  191. }
  192.  
  193. int eval_end_board(State state){
  194.     if(state.black_poss.size() > state.white_poss.size()) return black;
  195.     return white;
  196. }
  197.  
  198. // czy a jest lepszy od b
  199. bool cmp(const State &a, const State &b){
  200.     return eval_state(a) > eval_state(b);
  201. }
  202.  
  203. State choose_smart(State state){
  204.     State best_child;
  205.     vector<pii> possible_moves = generate_moves(state);
  206.     vector<State> children;
  207.     for(auto move: possible_moves){
  208.         State child; make_child_from_state(state, child, move);
  209.         children.push_back(child);
  210.     }
  211.  
  212.     // sort(children.begin(), children.end(), cmp);
  213.  
  214.     for(auto child: children){
  215.         child = min_max(child);
  216.        
  217.         if(state.player == max_player){
  218.             if(child.val > state.val){
  219.                 state.val = child.val;
  220.                 best_child = child;
  221.             }
  222.  
  223.             state.alfa = max(state.alfa, state.val);
  224.             if(state.val >= state.beta)
  225.                 break;
  226.        
  227.         }
  228.         else if(state.player == min_player){
  229.             if(child.val < state.val){
  230.                 state.val = child.val;
  231.                 best_child = child;
  232.             }
  233.  
  234.             state.beta = min(state.beta, state.val);
  235.             if(state.val <= state.alfa)
  236.                 break;
  237.         }
  238.     }
  239.  
  240.     return best_child;
  241. }
  242.  
  243. void tidy_state(State &state){
  244.     state.deep = 0;
  245.     state.alfa = -inf;
  246.     state.beta = inf;
  247.     state.val = (state.player == max_player ? -inf : inf);
  248. }
  249.  
  250. // debug
  251. void print_board(const State state);
  252.  
  253. int main(){    
  254.     srand(seed());
  255.     pii score = {0, 0};
  256.     for(int i = 0; i < 1000; i++){
  257.  
  258.         // ustawianie gry
  259.         State state;
  260.         set_initial_state(state, black);
  261.  
  262.         // gra dopuki ktoś nie wygra
  263.         int cnt = 0;
  264.         for(int turn = 1; !generate_moves(state).empty(); turn ^= 1){
  265.             if(turn == max_player)
  266.                 state = choose_smart(state);
  267.             else
  268.                 state = choose_random(state);
  269.  
  270.             tidy_state(state);
  271.             cnt++;
  272.             if(cnt == 3 && max_tree_deep < 5) cnt = 0, max_tree_deep++;
  273.  
  274.             // debug
  275.             // cout << visited << endl; visited = 0;
  276.             // print_board(state); //debug
  277.         }
  278.         max_tree_deep = 1;
  279.        
  280.  
  281.         if(eval_end_board(state) == black) score.first += 1;
  282.         else score.second += 1;
  283.         cout << "black: " << score.first << " white: " << score.second << endl;
  284.     }
  285. }
  286.  
  287. void print_board(const State state){
  288.     cout << (state.player == black ^ 1 ? "black" : "white") << endl;
  289.     for(int i = 0; i < 8; i++){
  290.         for(int j = 0; j < 8; j++)
  291.             if(state.board[i][j] == black) cout << 'B' << ' ';
  292.             else if(state.board[i][j] == white) cout << 'W' << ' ';
  293.             else cout << '.' << ' ';
  294.         cout << endl;
  295.     }
  296.     cout << endl;
  297. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement