Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

How do I create this? Design a program to display the game board for \"Reversi\"

ID: 3880030 • Letter: H

Question

How do I create this?

Design a program to display the game board for "Reversi" (also known as Othello), using OpenGL, GLUT and C++. The board should be an 8 by 8 grid of squares as shown below. The board should be a "neutral" color with dark grid lines. Add the four initial pieces in their starting positions. Make the piece colors black and white. A sample board with starting pieces is shown below.

"Reversi" Board

Your program should draw the board and the initial pieces, and should respond to callbacks to automatically redraw the window if the board display is covered and then uncovered. The program should not quit until quit is selected from the window menu.

Explanation / Answer

  

                #include <string.h>

                #include <stdio.h>

                #include <stdlib.h>

                #include <vector>

                #include <utility>

               

                //returns a pair <direction, coordinate> where direction is North, Northeast, etc (clockwise)

                //and coordinate is in the form x*8 + y

                std::vector< std::pair<int, int> > get_directions(int board[][8], int x, int y, int color) {

                    std::vector< std::pair<int, int> > directions;

                    if(board[x][y]) {

                        return directions;

                    }

                    //north

                    if((y < 6) && (board[x][y+1] == -color)) {

                        for(int i=y+2; i < 8; i++) {

                            if(!board[x][i]) {

                                break;

                            } else if(board[x][i] == color) {

                                directions.push_back(std::make_pair<int, int>(0, x*8+i));

                                break;

                            }

                        }

                    }

                    //northeast

                    if((y < 6) && (x < 6) && (board[x+1][y+1] == -color)) {

                        for(int i=0; (x+i+2 < 8) && (y+i+2 < 8); i++) {

                            if(!board[x+i+2][y+i+2]) {

                                break;

                            } else if(board[x+i+2][y+i+2] == color) {

                                directions.push_back(std::make_pair<int, int>(1, (x+i+2)*8+(y+i+2)));

                                break;

                            }

                        }

                    }

                    //east

                    if((x < 6) && (board[x+1][y] == -color)) {

                        for(int i=x+2; i < 8; i++) {

                            if(!board[i][y]) {

                                break;

                            } else if(board[i][y] == color) {

                                directions.push_back(std::make_pair<int, int>(2, i*8+y));

                                break;

                            }

                        }

                    }

                    //southeast

                    if((y > 1) && (x < 6) && (board[x+1][y-1] == -color)) {

                        for(int i=0; (x+i+2 < 8) && (y-i-2 >= 0); i++) {

                            if(!board[x+i+2][y-i-2]) {

                                break;

                            } else if(board[x+i+2][y-i-2] == color) {

                                directions.push_back(std::make_pair<int, int>(3, (x+i+2)*8+(y-i-2)));

                                break;

                            }

                        }

                    }

                    //south

                    if((y > 1) && (board[x][y-1] == -color)) {

                        for(int i=y-2; i >= 0; i--) {

                            if(!board[x][i]) {

                                break;

                            } else if(board[x][i] == color) {

                                directions.push_back(std::make_pair<int, int>(4, x*8+i));

                                break;

                            }

                        }

                    }

                    //southwest

                    if((y > 1) && (x > 1) && (board[x-1][y-1] == -color)) {

                        for(int i=0; (x-i-2 >= 0) && (y-i-2 >= 0); i++) {

                            if(!board[x-i-2][y-i-2]) {

                                break;

                            } else if(board[x-i-2][y-i-2] == color) {

                                directions.push_back(std::make_pair<int, int>(5, (x-i-2)*8+(y-i-2)));

                                break;

                            }

                        }

                    }

                    //west

                    if((x > 1) && (board[x-1][y] == -color)) {

                        for(int i=x-2; i >= 0; i--) {

                            if(!board[i][y]) {

                                break;

                            } else if(board[i][y] == color) {

                                directions.push_back(std::make_pair<int, int>(6, i*8+y));

                                break;

                            }

                        }

                    }

                    //northwest

                    if((y < 6) && (x > 1) && (board[x-1][y+1] == -color)) {

                        for(int i=0; (x-i-2 >= 0) && (y+i+2 < 8); i++) {

                            if(!board[x-i-2][y+i+2]) {

                                break;

                            } else if(board[x-i-2][y+i+2] == color) {

                                directions.push_back(std::make_pair<int, int>(7, (x-i-2)*8+(y+i+2)));

                                break;

                            }

                        }

                    }

                    return directions;

                }

               

                //returns all moves for a players on the current board. Each pair has a coordinate in the form

                //x*8+y, and a vector of pairs, each pair contains a direction and an endpoint in the form x*8+y

                std::vector< std::pair<int, std::vector< std::pair<int, int> > > > get_moves(int board[][8], int color) {

                    std::vector< std::pair<int, std::vector< std::pair<int, int> > > > moves;

                    for(int i=0; i < 8; i++) {

                        for(int j=0; j < 8; j++) {

                            moves.push_back(std::make_pair<int, std::vector< std::pair<int, int> > >(i*8+j, get_directions(board, i, j, color)));

                            if(!moves.back().second.size()) {

                                moves.pop_back();

                            }

                        }

                    }

                    return moves;

                }

               

                //makes a move and flips the appropriate pieces

                void make_move(int board[][8], int x, int y, int color, std::vector< std::pair<int, int> > directions) {

                    for(auto it=directions.begin(); it != directions.end(); it++) {

                        int i = x;

                        int j = y;

                        while((i != ((*it).second/8)) || (j != ((*it).second&7))) {

                            board[i][j] = color;

                            if(i < ((*it).second/8)) {

                                i++;

                            } else if((i > (*it).second/8)) {

                                i--;

                            }

                            if(j < ((*it).second&7)) {

                                j++;

                            } else if(j > ((*it).second&7)) {

                                j--;

                            }

                        }

                    }

                }

               

                //undoes a move (needs directions data so it can unflip stuff)

                void undo_move(int board[][8], int x, int y, int color, std::vector< std::pair<int, int> > directions) {

                    for(auto it=directions.begin(); it != directions.end(); it++) {

                        int i = x;

                        int j = y;

                        while((i != ((*it).second/8)) || (j != ((*it).second&7))) {

                            board[i][j] = -color;

                            if(i < ((*it).second/8)) {

                                i++;

                            } else if((i > (*it).second/8)) {

                                i--;

                            }

                            if(j < ((*it).second&7)) {

                                j++;

                            } else if(j > ((*it).second&7)) {

                                j--;

                            }

                        }

                        board[i][j] = color;

                    }

                    board[x][y] = 0;

                }

               

                void print(int board[][8]) {

                    for(int i=7; i >= 0; i--) {

                        printf("%d ", i);

                        for(int j=0; j < 8; j++) {

                            if(!board[j][i]) {

                                printf("-");

                            } else if(board[j][i] == 1) {

                                printf("O");

                            } else {

                                printf("X");

                            }

                        }

                        printf(" ");

                    }

                    printf(" ");

                    for(int i=0; i < 8; i++) {

                        printf("%d", i);

                    }

                    printf(" ");

                }

               

                int score(int board[][8], int color) {

                    int sum = 0;

                    for(int i=0; i < 8; i++) {

                        for(int j=0; j < 8; j++) {

                            sum += board[i][j];

                        }

                    }

                    return sum * color;

                }

               

                //Largely the same pseudocode from the negamax wikipedia article,

                int negamax_aux(int board[][8], int color, int depth, int alpha, int beta) {

                    if(depth == 0) {

                        return score(board, color);

                    }

                    std::vector< std::pair<int, std::vector< std::pair<int, int> > > > moves = get_moves(board, color);

                    if(moves.size() == 0) {

                        if(get_moves(board, -color).size() == 0) {

                            return score(board, color);

                        }

                        int val = -negamax_aux(board, -color, depth-1, -beta, -alpha);

                        if(val >= beta) {

                            return val;

                        }

                        if(val > alpha) {

                            alpha = val;

                        }

                    } else {

                        for(auto it=moves.begin(); it != moves.end(); it++) {

                            make_move(board, (*it).first/8, (*it).first&7, color, (*it).second);

                            int val = -negamax_aux(board, -color, depth-1, -beta, -alpha);

                            undo_move(board, (*it).first/8, (*it).first&7, color, (*it).second);

                            if(val >= beta) {

                                return val;

                            }

                            if(val > alpha) {

                                alpha = val;

                            }

                        }

                    }

                    return alpha;

                }

               

                //parent function to negamax_aux, this function actually maintains the current move

                int negamax(int board[][8], int color, int depth) {

                    int alpha = -65;

                    int beta = 65;

                    std::vector< std::pair<int, std::vector< std::pair<int, int> > > > moves = get_moves(board, color);

                    int move = moves[0].first;

                    for(auto it=moves.begin(); it != moves.end(); it++) {

                        make_move(board, (*it).first/8, (*it).first&7, color, (*it).second);

                        int val = -negamax_aux(board, -color, depth-1, -beta, -alpha);

                        undo_move(board, (*it).first/8, (*it).first&7, color, (*it).second);

                        if(val >= beta) {

                            return (*it).first;

                        }

                        if(val > alpha) {

                            alpha = val;

                            move = (*it).first;

                        }

                    }

                    return move;

                }

               

                //run with ./reversi [int] where int is the number of ply the AI searches deep.

                int main(int argc, char **argv) {

                    int depth = 3;

                    if(argc > 1) {

                        depth = atol(argv[1]);

                    }

                    depth *= 2;

               

                    int board[8][8];

                    memset(board, 0, sizeof(board));

                    board[3][3] = board[4][4] = -1;

                    board[3][4] = board[4][3] = 1;

                    int turn = -1;

                    while(true) {

                        print(board);

                        std::vector< std::pair<int, std::vector< std::pair<int, int> > > > moves= get_moves(board, turn);

                        printf("available moves: ");

                        for(auto it=moves.begin(); it != moves.end(); it++) {

                            printf("(%d, %d) ", (*it).first/8, (*it).first%8);

                        }

                        printf(" ");

                        if(moves.size() == 0) {

                            turn = -turn;

                            moves = get_moves(board, turn);

                            if(moves.size() == 0) {

                                printf("final score: %d ", score(board, -1));

                                return 0;

                            }

                        } else {

                            int x, y;

                            if(turn == -1) {

                                scanf("%d %d", &x, &y);

                              for(auto it=moves.begin(); it != moves.end(); it++) {

                                    if(x*8+y == ((*it).first)) {

                                        printf("chose: %d %d ", x, y);

                                        make_move(board, x, y, turn, (*it).second);

                                        turn = -turn;

                                        break;

                                    }

                                }

                            } else {

                                x = negamax(board, turn, depth);

                                for(auto it=moves.begin(); it != moves.end(); it++) {

                                    if(x == ((*it).first)) {

                                        printf("chose: %d %d ", x/8, x%8);

                                        make_move(board, x/8, x%8, turn, (*it).second);

                                        turn = -turn;

                                        break;

                                    }

                                }

                            }

                        }

                    }

                    return 0;

                }

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote