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