00001 #ifndef __XO_H__ 00002 #define __XO_H__ 00003 00004 #pragma once 00005 00006 #include <iostream> 00007 #include <fstream> 00008 00009 #define PACK(x,y) ((x)*3+(y)) 00010 00011 class XOBoard{ 00012 00013 private: 00014 int movesX, movesO, moves; 00015 00016 static const int winConfigs[8]; 00017 00018 public: 00019 00020 enum Player{ 00021 PlayerX, 00022 PlayerO 00023 }; 00024 00027 XOBoard() : movesX(0), movesO(0), moves(0) { } 00028 00034 inline bool is_empty(int x, int y) const { 00035 return (moves & (1 << PACK(x,y))) ? false : true; 00036 } 00037 00043 inline char get(int x, int y) const { 00044 if (x < 0 || x > 2 || y < 0 || y > 2) { 00045 std::cerr << "ERROR! The cell at (" << x << "," << y << ") does not exist!\n Ignoring GET operation!"; 00046 return '\0'; 00047 } else { 00048 return (moves & (1 << PACK(x,y))) == 0 ? '_' : ((movesX & (1 << PACK(x,y))) == 0 ? 'O' : 'X'); 00049 } 00050 } 00051 00057 inline void put(Player player, int x, int y) { 00058 if (x < 0 || x > 2 || y < 0 || y > 2) { 00059 std::cerr << "ERROR! The cell at (" << x << "," << y << ") does not exist!\n Ignoring GET operation!"; 00060 } else { 00061 moves |= (1 << (PACK(x,y))); 00062 if (player == PlayerX){ 00063 movesX |= (1 << (PACK(x,y))); 00064 } else { 00065 movesO |= (1 << (PACK(x,y))); 00066 } 00067 } 00068 } 00069 00073 inline bool is_full() const { 00074 return (moves & 0x1FF) == 0x1FF; 00075 } 00076 00081 inline int get_score(Player player = PlayerX) const { 00082 int myMoves = (moves & (player == PlayerX ? movesX : movesO )); 00083 int hisMoves = (moves & (player == PlayerX ? movesO : movesX )); 00084 for (int i = 0; i < 8; i++){ 00085 if ((myMoves & winConfigs[i]) == winConfigs[i]) { 00086 return 1; 00087 } else if ((hisMoves & winConfigs[i]) == winConfigs[i]) { 00088 return -1; 00089 } 00090 } 00091 return 0; 00092 } 00093 00097 inline bool game_over() const { 00098 return is_full() || get_score() != 0; 00099 } 00100 00101 friend std::ostream& operator<< (std::ostream&, const XOBoard&); 00102 }; 00103 00104 class XOGame{ 00105 00106 private: 00107 typedef XOBoard ComputerAI(XOBoard::Player, XOBoard); 00108 00109 ComputerAI * computerAI; 00110 00111 typedef XOBoard (XOGame::*PlayerInterface)(XOBoard::Player, XOBoard); 00112 00113 XOBoard humanInterface(XOBoard::Player player, XOBoard board); 00114 XOBoard computerInterface(XOBoard::Player player, XOBoard board); 00115 00116 inline void gameEngine(XOBoard board, PlayerInterface interfacePlayerX, PlayerInterface interfacePlayerO) { 00117 do { 00118 board = (this->*interfacePlayerX)(XOBoard::PlayerX, board); 00119 if (board.game_over()) return; 00120 board = (this->*interfacePlayerO)(XOBoard::PlayerO, board); 00121 if (board.game_over()) return; 00122 } while(1); 00123 } 00124 00125 public: 00129 XOGame(ComputerAI computerAI) : computerAI(computerAI) { } 00130 00133 inline void humanVScomputer() { 00134 if (computerAI == NULL) { 00135 std::cout << "ERROR! You can't launch a Human VS Computer game without a game AI!\n"; 00136 } else { 00137 std::cout << "The board is:\n" << XOBoard(); 00138 gameEngine(XOBoard(), &XOGame::humanInterface, &XOGame::computerInterface); 00139 } 00140 } 00141 00144 inline void computerVShuman() { 00145 if (computerAI == NULL) { 00146 std::cout << "ERROR! You can't launch a Computer VS Human game without a game AI!\n"; 00147 } else { 00148 gameEngine(XOBoard(), &XOGame::computerInterface, &XOGame::humanInterface); 00149 } 00150 } 00151 00154 inline void humanVShuman() { 00155 gameEngine(XOBoard(), &XOGame::humanInterface, &XOGame::humanInterface); 00156 } 00157 00160 inline void computerVScomputer() { 00161 if (computerAI == NULL) { 00162 std::cout << "ERROR! You can't launch a Computer VS Computer game without a game AI!\n"; 00163 } else { 00164 gameEngine(XOBoard(), &XOGame::computerInterface, &XOGame::computerInterface); 00165 } 00166 } 00167 }; 00168 00169 std::ostream& operator<< (std::ostream&, const XOBoard&); 00170 00171 #endif 00172