Проект Отелло, доска отображается неправильно, пока программа не остановлена, и проблема с проверкой, является ли первый шаг законным - PullRequest
0 голосов
/ 22 апреля 2020

В настоящее время работаю над проектом Отелло для моего класса, где мы просто пытаемся сделать первый легальный ход доступным. Я продолжаю сталкиваться с одними и теми же проблемами, связанными с определенным отображением моей доски и моей функции, чтобы проверить, допустимы ли ходы ввода. Когда я запускаю свою программу, моя доска отображается неправильно, до тех пор, пока она не остановится, и когда я попытаюсь сделать законный ход, программа не будет считаться легальным ходом. Это взгляд на мой класс отелло, очень запутанный в том, что может быть проблемой, и любая помощь будет отличной!

#include "othello.h"
#include "game.h"
#include "colors.h"
#include "piece.h"
#include <iostream>
#include <iomanip>

using namespace main_savitch_14;

Othello::Othello(){
    for(int i = 0; i < 8; i++){
        for(int j= 0; j < 8; j++){
            board[i][j] = 'e';
            wScore = 2;
            bScore = 2;
        }
    }
    board[3][3].setColor('b');
    board[3][4].setColor('w');
    board[4][3].setColor('w');
    board[4][4].setColor('b');
    cout << "Board has been set\n";
}

//display the board
void Othello::display_status() const{
    cout << BLUE << "   A   B   C   D   E   F   G   H   " << endl;
    for (int i = 0 , j = 0; i < 8; i++, j++){
        cout << GREEN << " ----------------------------------" << endl;
        cout << BLUE << j;
        cout << GREEN << "| " << BLUE;
        cout << board[i][0];
        cout << GREEN << " | " << BLUE;
        cout << board[i][1];
        cout << GREEN << " | " << BLUE;
        cout << board[i][2];
        cout << GREEN << " | " << BLUE;
        cout << board[i][3];
        cout << GREEN << " | " << BLUE;
        cout << board[i][4];
        cout << GREEN << " | " << BLUE;
        cout << board[i][5];
        cout << GREEN << " | " << BLUE;
        cout << board[i][6];
        cout << GREEN << " | " << BLUE;
        cout << board [i][7];
        cout << GREEN << " |" << BLUE << endl;
    }
    cout << GREEN << " ----------------------------------" << RESET << endl;
}

bool Othello::is_legal(const std::string& move){
    int row, col;
    char movePiece;
    if (move == "E2" || move == "F4"){
        return true;
    }
    else if(move == "C4" || move == "D5"){
        return true;
    }
    else{
        return false;
    }
}

void Othello::make_move(const std::string& move){
    int row, col;
    row = int (move[1] - '1');
    col = int (toupper(move[0]) - 'A');
    if (move == "E2" || move == "F4"){
        board[row][col].setColor('w');
        board[3][3].flip();
    }
    else if(move == "C4" || move == "D5"){
        board[row][col].setColor('w');
        board[4][3].flip();
    }
}

void Othello::setInitialPieces(){
    for(int i = 0; i < 8; i++){
        for(int j= 0; j < 8; j++){
            board[i][j].setColor('e');
        }
    }
}
#include "colors.h"
#include <iostream>
#include <fstream>

using namespace std;

#ifndef PIECE_H
#define PIECE_H

class piece{
    public:
    piece() { color = 'e'; }

    piece(char c){
        if(c == 'b' || c == 'w' || c == 'e'){
            color = c;
        }
        else{
            color = 'e';
        }
    }

    void isWhite() const{
        if(color == 'w'){
            return;
        }
    }

    void isBlack() const{
        if( color == 'b'){
            return;
        }
    }

    void isEmpty() const{
        if(color == 'e'){
            return;
        }
    }

    void flip(){
        if(color == 'b'){
            color = 'w';
        }
        else if(color == 'w'){
            color = 'b';
        }
    }
    void setColor(const char c){
        if(c == 'b'|| c == 'w' || c == 'e'){
        color = c;
        }
        else{
        std::cout << "ERROR color not valid.";
        }
    }
    char getColor() const{
        return color;
    }
    bool is_black() const{
        if(color == 'b'){
            return true;
        }
        else{
            return false;
        }
    }
    bool is_white() const{
        if(color == 'w'){
            return true;
        }
        else{
            return false;
        }
    }
    bool is_empty() const{
        if(color == 'e'){
            return true;
        }
        else{
            return false;
        }
    }
    friend std::ostream& operator <<(std::ostream& outs, piece p){
        p.getColor();
        if (p.getColor() == 'b'){
            outs << "x";
        }
        else if(p.getColor() == 'w'){
            outs << "o";
        }
        else{
            outs << "-";
        }
        return outs;
    }
    private:
    char color;
};

#endif

// File: game.h (part of the namespace main_savitch_14)


#ifndef MAIN_SAVITCH_GAME
#define MAIN_SAVITCH_GAME
#include <queue>   // Provides queue<string>
#include <string>  // Provides string

namespace main_savitch_14
{
    class game
    {
    public:
        // ENUM TYPE
    enum who { HUMAN, NEUTRAL, COMPUTER }; // Possible game outcomes

    // CONSTRUCTOR and DESTRUCTOR
    game( ) { move_number = 0; }
    virtual ~game( ) { }

    // PUBLIC MEMBER FUNCTIONS
    // The play function should not be overridden. It plays one game,
    // with the human player moving first and the computer second.
    // The computer uses an alpha-beta look ahead algorithm to select its
    // moves. The return value is the winner of the game (or NEUTRAL for
    // a tie).
    who play( );

    protected:
    // *******************************************************************
    // OPTIONAL VIRTUAL FUNCTIONS (overriding these is optional)
    // *******************************************************************
    virtual void display_message(const std::string& message) const;
        virtual std::string get_user_move( ) const;
    virtual who last_mover( ) const 
        { return (move_number % 2 == 1 ? HUMAN : COMPUTER); }
    virtual int moves_completed( ) const { return move_number; }
    virtual who next_mover( ) const
        { return (move_number % 2 == 0 ? HUMAN : COMPUTER); }
    virtual who opposite(who player) const
        { return (player == HUMAN) ? COMPUTER : HUMAN; }
        virtual who winning( ) const;

    // *******************************************************************
    // VIRTUAL FUNCTIONS THAT MUST BE OVERRIDDEND:
    // The overriding function should call the original when it finishes.
    // *******************************************************************
    // Have the next player make a specified move:
        virtual void make_move(const std::string& move) { ++move_number; }
        // Restart the game from the beginning:
        virtual void restart( ) { move_number = 0; }

    // *******************************************************************
        // PURE VIRTUAL FUNCTIONS
    // *******************************************************************
    // (these must be provided for each derived class)
        // Return a pointer to a copy of myself:
        virtual game* clone( ) const = 0;
        // Compute all the moves that the next player can make:
        virtual void compute_moves(std::queue<std::string>& moves) const = 0;
        // Display the status of the current game:
        virtual void display_status( ) const = 0;
        // Evaluate a board position:
    // NOTE: positive values are good for the computer.
        virtual int evaluate( ) const = 0;
        // Return true if the current game is finished:
        virtual bool is_game_over( ) const = 0;
        // Return true if the given move is legal for the next player:
        virtual bool is_legal(const std::string& move) const = 0;

    private:
        // MEMBER VARIABLES
    int move_number;                     // Number of moves made so far

    // STATIC MEMBER CONSTANT
    static const int SEARCH_LEVELS = 4;  // Levels for look-ahead evaluation

        // PRIVATE FUNCTIONS (these are the same for every game)
    int eval_with_lookahead(int look_ahead, int beat_this);
    void make_computer_move( );
    void make_human_move( );
    };
}

#endif
// File: game.cxx

#include <cassert>    // Provides assert
#include <climits>    // Provides INT_MAX and INT_MIN
#include <iostream>   // Provides cin, cout
#include <queue>      // Provides queue<string>
#include <string>     // Provides string
#include "game.h"     // Provides definition of game class
using namespace std;

namespace main_savitch_14
{
    //*************************************************************************
    // STATIC MEMBER CONSTANTS
    // const int game::SEARCH_LEVELS;

    //*************************************************************************
    // PUBLIC MEMBER FUNCTIONS

    game::who game::play( )
    // The play function should not be overridden. It plays one round of the
    // game, with the human player moving first and the computer second.
    // The return value is the winner of the game (or NEUTRAL for a tie).
    {
    restart( );
// Note that as you develop the game you will be gradually un-commenting 
// this function.   
    //while (!is_game_over( )) // un-comment this
    //{
        display_status( );
    //    if (last_mover( ) == COMPUTER)
        make_human_move( );
    //    else
    //  make_computer_move( );
    //}
    display_status( );
    return HUMAN;
    }



    //*************************************************************************
    // OPTIONAL VIRTUAL FUNCTIONS (overriding these functions is optional)

    void game::display_message(const string& message) const
    {
    cout << message;
    }

    string game::get_user_move( ) const
    {
    string answer;

    display_message("Your move, please: ");
    getline(cin, answer);
    return answer;
    }

    game::who game::winning( ) const
    {
    int value = evaluate( ); // Evaluate based on move that was just made.

    if (value > 0)
        return last_mover( );
    else if (value < 0)
        return next_mover( );
    else
        return NEUTRAL;
    }



    //*************************************************************************
    // PRIVATE FUNCTIONS (these are the same for every game)

    int game::eval_with_lookahead(int look_ahead, int beat_this)
    // Evaluate a board position with lookahead.
    // --int look_aheads:  How deep the lookahead should go to evaluate the move.
    // --int beat_this: Value of another move that we?re considering. If the
    // current board position can't beat this, then cut it short.
    // The return value is large if the position is good for the player who just
    // moved. 
    {
        queue<string> moves;   // All possible opponent moves
    int value;             // Value of a board position after opponent moves
        int best_value;        // Evaluation of best opponent move
        game* future;          // Pointer to a future version of this game

        // Base case:
    if (look_ahead == 0 || is_game_over( ))
    {
        if (last_mover( ) == COMPUTER)
                return evaluate( );
        else
        return -evaluate( );
    }

        // Recursive case:
        // The level is above 0, so try all possible opponent moves. Keep the
    // value of the best of these moves from the opponent's perspective.
        compute_moves(moves); 
    // assert(!moves.empty( ));
        best_value = INT_MIN;
        while (!moves.empty( ))
        {
        future = clone( );
        future->make_move(moves.front( ));
        value = future->eval_with_lookahead(look_ahead-1, best_value);
        delete future;
        if (value > best_value)
        {
        best_value = value;
        }
        moves.pop( );
        }

        // The value was calculated from the opponent's perspective.
        // The answer we return should be from player's perspective, so multiply times -1:
        return -best_value;
    }

    void game::make_computer_move( )
    {
    queue<string> moves;
    int value;
    int best_value;
    string best_move;
    game* future;

    // Compute all legal moves that the computer could make.
    compute_moves(moves);
    //assert(!moves.empty( ));

    // Evaluate each possible legal move, saving the index of the best
    // in best_index and saving its value in best_value.
    best_value = INT_MIN;
    while (!moves.empty( ))
    {
        future = clone( );
        future->make_move(moves.front( ));
        value = future->eval_with_lookahead(SEARCH_LEVELS, best_value);
        delete future;
        if (value >= best_value)
        {
        best_value = value;
        best_move = moves.front( );
        }
        moves.pop( );
    }

    // Make the best move.
    make_move(best_move);
    }

    void game::make_human_move( )
    {
        string move;

    move = get_user_move( );
    while (!is_legal(move))
    {
        display_message("Illegal move.\n");
        move = get_user_move( );
        }
    make_move(move);
    }
}
...