目前正在为我的班级做一个奥赛罗项目,我们只是试图让第一个合法的举动可用。在专门显示我的棋盘和检查输入动作是否合法的功能时,我一直遇到同样的问题。当我运行我的程序时,我的棋盘随机显示不正确,直到程序停止,当我尝试进行合法移动时,程序不会将其视为合法移动。这是我对奥赛罗课的看法;对可能出现的问题非常困惑,任何帮助都会很棒!
#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);
}
}