Checkers AI with minimaxing

I'm having trouble writing a minimax algorithm for my checkers game. Currently the code is written to be a two player game, but im trying to create a minimax ai function in my header file to play as 'r'. I get the basics of minimaxing and how it could potentially be done, I'm just stuck on how to evaluate the board at all or assign any sort of "values" to the board spaces based on each player's piece's positions. I've included the code for my Checkers.h file but had to cut out some functions due to post length


Checkers.h
============
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#include <iostream>
#include <ctime>

using namespace std;

//variables
char turn = 'B';
bool leap;
bool gameStatus = true;
int row1, row2, col1, col2;

//functions
void minimax();
void input();
void move();
bool legalMove();
void doLeap();
void dispBoard();
void king();
void endGame();

char board[8][8] =
{
    {' ', 'b', ' ', 'b', ' ', 'b', ' ', 'b'},
    {'b', ' ', 'b', ' ', 'b', ' ', 'b', ' '},
    {' ', 'b', ' ', 'b', ' ', 'b', ' ', 'b'},
    {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
    {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
    {'r', ' ', 'r', ' ', 'r', ' ', 'r', ' '},
    {' ', 'r', ' ', 'r', ' ', 'r', ' ', 'r'},
    {'r', ' ', 'r', ' ', 'r', ' ', 'r', ' '},
};

void minimax()
{
//STUCK ON THIS FUNCTION
}

void input()
{
    cout << "Move piece\n";
    cout << "Row: ";
    cin >> row1;
    cout << "Column: ";
    cin >> col1;

    while (row1 < 0 || row1 > 7 || col1 < 0 || col1 > 7) //handles errors
    {
        cout << "Incorrect input. Enter numbers between 0 and 7.\n";
        cout << "Move piece\n";
        cout << "Row: ";
        cin >> row1;
        cout << "Column: ";
        cin >> col1;
    }

    cout << "To box\n";
    cout << "Row: ";
    cin >> row2;
    cout << "Column: ";
    cin >> col2;

    while (row2 < 0 || row2 > 7 || col2 < 0 || col2 > 7)
    {
        cout << "Incorrect input. Enter numbers between 0 and 7.\n";
        cout << "To box\n";
        cout << "Row: ";
        cin >> row2;
        cout << "Column: ";
        cin >> col2;
    }

    while (legalMove() == false)
    {
        cout << "Illegal Move. Please try again. Remember, rows first then columns (left hand side then the top)\n";
        input();
    }
}

void move()
{
    bool king_piece = false;
    if (board[row1][col1] == 'B' || board[row1][col1] == 'R')
    {
        king_piece = true;
    }

    board[row1][col1] = ' ';

    if (turn == 'B')
    {
        if (king_piece == false)
        {
            board[row2][col2] = 'b';
        }
        else if (king_piece == true)
        {
            board[row2][col2] = 'B';
        }

        turn = 'R';
    }
    else if (turn == 'R')
    {
        if (king_piece == false)
        {
            board[row2][col2] = 'r';
        }
        else if (king_piece == true)
        {
            board[row2][col2] = 'R';
        }

        turn = 'B';
    }

    if (leap == true)
    {
        doLeap();
    }
}

bool legalMove() //constructs restrictions based on rules of checkers and handles errors associated with it.
{
    //checks if a non-king piece is moving backwards.
    if (board[row1][col1] != 'B' && board[row1][col1] != 'R')
    {
        if ((turn == 'B' && row2 < row1) || (turn == 'R' && row2 > row1))
        {
            leap = false;
            return false;
        }
    }

    //checks if the location the piece is moving to is already taken.
    if (board[row2][col2] != ' '){leap = false; return false;}

    //checks if location entered by the user contains a piece to be moved.
    if (board[row1][col1] == ' '){leap = false; return false;}

    //checks if the piece isn't moving diagonally.
    if (col1 == col2 || row1 == row2){leap = false; return false;}

    //checks if the piece is moving by more than 1 column and only 1 row
    if ((col2 > col1 + 1 || col2 < col1 - 1) && (row2 == row1 +1 || row2 == row1 - 1)) {leap = false; return false;}

    //checks if the piece is leaping.
    if (row2 > row1 + 1 || row2 < row1 - 1)
    {
        //checks if the piece is leaping too far.
        if (row2 > row1 + 2 || row2 < row1 - 2){leap = false; return false;}

        //checks if the piece isn't moving by exactly 2 columns
        if (col2 != col1 + 2 && col2 != col1 - 2){leap = false; return false;}

        //checks if the piece is leaping over another piece.
        if (row2 > row1 && col2 > col1)
        {if (board[row2 - 1][col2 - 1] == ' '){leap = false; return false;}}
        else if (row2 > row1 && col2 < col1)
        {if (board[row2 - 1][col2 + 1] == ' '){leap = false; return false;}}
        else if (row2 < row1 && col2 > col1)
        {if (board[row2 + 1][col2 - 1] == ' '){leap = false; return false;}}
        else if (row2 < row1 && col2 < col1)
        {if (board[row2 + 1][col2 + 1] == ' '){leap = false; return false;}}
        leap = true; return true;}
    leap = false; return true;
}


void doLeap()
{
    char answer;

    //removes the checker piece after leap.
    if (row2 > row1 && col2 > col1)
    {
        board[row2 - 1][col2 - 1] = ' ';
    }
    else if (row2 > row1 && col2 < col1)
    {
        board[row2 - 1][col2 + 1] = ' ';
    }
    else if (row2 < row1 && col2 > col1)
    {
        board[row2 + 1][col2 - 1] = ' ';
    }
    else if (row2 < row1 && col2 < col1)
    {
        board[row2 + 1][col2 + 1] = ' ';
    }

    dispBoard();//displays/ refreshes the board after the changes

    //asks if the user wants to leap again.
    do
    {
        cout << "You just leaped once. Do you want to do a second leap IF YOU CAN? (y/n): ";
        cin >> answer;
    }
    while (answer != 'Y' && answer != 'y' && answer != 'N' && answer != 'n');

    if (answer == 'y' || answer == 'Y')
    {
        row1 = row2;
        col1 = col2;
        cout << "Leap piece: row: " << row1 << ", column: " << col1 << endl;
        cout << "To box\n";
        cout << "row: ";
        cin >> row2;
        cout << "column: ";
        cin >> col2;

        while (row2 < 0 || row2 > 7 || col2 < 0 || col2 > 7)
        {
            cout << "Incorrect input. Enter numbers between 0 and 7.\n";
            cout << "To box\n";
            cout << "Row: ";
            cin >> row2;
            cout << "Column: ";
            cin >> col2;
        }

        if (turn == 'B')
        {
            turn = 'R';
        }
        else if (turn == 'R')
        {
            turn = 'B';
        }

        legalMove();

        if (leap == false)
        {
            cout << "INVALID LEAP!!\n";

            if (turn == 'B')
            {
                turn = 'R';
            }
            else if (turn == 'R')
            {
                turn = 'B';
            }
        }
        else if (leap == true)
        {
            move();
        }
    }
}



Last edited on
Please edit for readability.
https://www.cplusplus.com/articles/jEywvCM9/
Sorry about that, first time posting on the forums
Start with a 4 x 4 board. Run the minimax to a win/loss/tie.

1
2
3
4
5
6
7
8
9
const int Size = 4;

char board[Size][Size+1] =  // +1 for '\0' at end of strings
{
    "-b-b",
    " - -",
    "- - ",
    "r-r-"
};

1
2
3
4
5
//variables
char turn = 'B';
bool leap;
bool gameStatus = true;
int row1, row2, col1, col2;

All of these should be in main.
Along with the board itself.

1
2
3
4
5
6
7
8
9
//functions
void minimax();
void input();
void move();
bool legalMove();
void doLeap();
void dispBoard();
void king();
void endGame();

All of these need a board parameter, and maybe some others.

> //STUCK ON THIS FUNCTION
Well you need to make some kind of numeric quantity for each position.
Like
+1 - moving into this square has a chance to capture a piece on the next turn.
-1 - moving into this square risks capture by the opponent on the next turn.
+2 - moving into this square is king.

Like for example, this
1
2
    "- -r",
    "r- -"

is safer than this
1
2
    "-r- ",
    " -r-"

It has the same opportunity, but less risk.


Topic archived. No new replies allowed.