2010-03-28 4 views
0

Notez le commentaire ci-dessous. Il ne peut pas être compilé sur UVA à cause d'un bug dans GCC.Comment puis-je obtenir ce qui suit compilé sur UVA?

#include <cstdio> 
#include <cstring> 
#include <cctype> 
#include <map> 
#include <stdexcept> 

class Board { 
public: 
    bool read(FILE *); 
    enum Colour {none, white, black}; 
    Colour check() const; 
private: 
    struct Index { 
      size_t x; 
      size_t y; 
      Index &operator+=(const Index &) throw(std::range_error); 
      Index operator+(const Index &) const throw(std::range_error); 
    }; 
    const static std::size_t size = 8; 
    char data[size][size]; 
    // Cannot be compiled on GCC 4.1.2 due to GCC bug 29993 
    // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29993 
    typedef bool CheckFunction(Colour, const Index &) const; 
    CheckFunction pawn, knight, bishop, king, rook; 

    bool queen(const Colour c, const Index &location) const { 
      return rook(c, location) || bishop(c, location); 
    } 

    static char get_king(Colour c) { 
      return c == white ? 'k' : 'K'; 
    } 

    template<std::size_t n> 
    bool check_consecutive(Colour c, const Index &location, const Index (&offsets)[n]) const { 
      for(const Index *p = offsets; p != (&offsets)[1]; ++p) { 
        try { 
          Index target = location + *p; 
          for(; data[target.x][target.y] == '.'; target += *p) { 
          } 
          if(data[target.x][target.y] == get_king(c)) return true; 
        } catch(std::range_error &) { 
        } 
      } 
      return false; 
    } 

    template<std::size_t n> 
    bool check_distinct(Colour c, const Index &location, const Index (&offsets)[n]) const { 
      for(const Index *p = offsets; p != (&offsets)[1]; ++p) { 
        try { 
          Index target = location + *p; 
          if(data[target.x][target.y] == get_king(c)) return true; 
        } catch(std::range_error &) { 
        } 
      } 
      return false; 
    } 
}; 

int main() { 
    Board board; 
    for(int d = 1; board.read(stdin); ++d) { 
      Board::Colour c = board.check(); 
      const char *sp; 
      switch(c) { 
      case Board::black: 
        sp = "white"; 
        break; 
      case Board::white: 
        sp = "black"; 
        break; 
      case Board::none: 
        sp = "no"; 
        break; 
      } 
      std::printf("Game #%d: %s king is in check.\n", d, sp); 
      std::getchar(); // discard empty line 
    } 
} 

bool Board::read(FILE *f) { 
    static const char empty[] = 
      "........" 
      "........" 
      "........" 
      "........" 
      "........" 
      "........" 
      "........" 
      "........";  // 64 dots 
    for(char (*p)[size] = data; p != (&data)[1]; ++p) { 
      std::fread(*p, size, 1, f); 
      std::fgetc(f); // discard new-line 
    } 
    return std::memcmp(empty, data, sizeof data); 
} 

Board::Colour Board::check() const { 
    std::map<char, CheckFunction Board::*> fp; 
    fp['P'] = &Board::pawn; 
    fp['N'] = &Board::knight; 
    fp['B'] = &Board::bishop; 
    fp['Q'] = &Board::queen; 
    fp['K'] = &Board::king; 
    fp['R'] = &Board::rook; 
    for(std::size_t i = 0; i != size; ++i) { 
      for(std::size_t j = 0; j != size; ++j) { 
        CheckFunction Board::* p = fp[std::toupper(data[i][j])]; 
        if(p) { 
          Colour ret; 
          if(std::isupper(data[i][j])) ret = white; 
          else ret = black; 
          if((this->*p)(ret, (Index){i, j}/* C99 extension */)) return ret; 
        } 
      } 
    } 
    return none; 
} 

bool Board::pawn(const Colour c, const Index &location) const { 
    const std::ptrdiff_t sh = c == white ? -1 : 1; 
    const Index offsets[] = { 
      {sh, 1}, 
      {sh, -1} 
    }; 
    return check_distinct(c, location, offsets); 
} 

bool Board::knight(const Colour c, const Index &location) const { 
    static const Index offsets[] = { 
      {1, 2}, 
      {2, 1}, 
      {2, -1}, 
      {1, -2}, 
      {-1, -2}, 
      {-2, -1}, 
      {-2, 1}, 
      {-1, 2} 
    }; 
    return check_distinct(c, location, offsets); 
} 

bool Board::bishop(const Colour c, const Index &location) const { 
    static const Index offsets[] = { 
      {1, 1}, 
      {1, -1}, 
      {-1, -1}, 
      {-1, 1} 
    }; 
    return check_consecutive(c, location, offsets); 
} 

bool Board::rook(const Colour c, const Index &location) const { 
    static const Index offsets[] = { 
      {1, 0}, 
      {0, -1}, 
      {0, 1}, 
      {-1, 0} 
    }; 
    return check_consecutive(c, location, offsets); 
} 

bool Board::king(const Colour c, const Index &location) const { 
    static const Index offsets[] = { 
      {-1, -1}, 
      {-1, 0}, 
      {-1, 1}, 
      {0, 1}, 
      {1, 1}, 
      {1, 0}, 
      {1, -1}, 
      {0, -1} 
    }; 
    return check_distinct(c, location, offsets); 
} 

Board::Index &Board::Index::operator+=(const Index &rhs) throw(std::range_error) { 
    if(x + rhs.x >= size || y + rhs.y >= size) throw std::range_error("result is larger than size"); 
    x += rhs.x; 
    y += rhs.y; 
    return *this; 
} 

Board::Index Board::Index::operator+(const Index &rhs) const throw(std::range_error) { 
    Index ret = *this; 
    return ret += rhs; 
} 
+0

Quelle est l'erreur/le bogue spécifique à l'origine du problème? –

Répondre

1

Le code qui ne compile pas est tout simplement un raccourci pour déclarer pion, chevalier, évêque, roi, et freux comme étant des fonctions constantes qui prennent une couleur et référence const à un indice, le retour d'un bool. Il suffit de remplacer:

 
typedef bool CheckFunction(Colour, const Index &) const; 
    CheckFunction pawn, knight, bishop, king, rook; 

Avec:

 
bool pawn(Colour, const Index &) const; 
bool knight(Colour, const Index &) const; 
bool bishop(Colour, const Index &) const; 
bool king(Colour, const Index &) const; 
bool rook(Colour, const Index &) const; 

Franchement, je suis surpris que quelqu'un était si paresseux qu'ils ont utilisé l'ancienne plutôt que celle-ci. À mon humble avis, ce dernier est nettement plus lisible que le premier, et le dernier n'est pas beaucoup plus long.

+0

Merci, mais les déclarations dans Board :: check() const en utilisant CheckFunction deviennent beaucoup plus laides qu'avant. –

Questions connexes