1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
|
#include "tictactoe.h"
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <math.h>
// Ask for the user to enter its move using the keyboard
void HumanPlayer(TicTacToe *Game);
// Random selection of the move
void RandomPlayer(TicTacToe *Game);
void AIPlayer(TicTacToe *Game);
int MinMax(TicTacToe *Game,char Mark, int *ptBest_Move);
int main(int argc, char *argv[])
{
TicTacToe *Game=new TicTacToe; // Create a po inter on a TicTacToe object
srand ( time(NULL) ); // Initialyze pseudo random generaor using current time
// ::: Game core :::
Game->DrawGame(); // Show the game
while (Game->GameOver()==0) { // Play until the game is over
if (Game->CurrentPlayer()==CROSS) { // Current player is player one
cout << "\n ::: Player 1 (Crosses) :::\n";
HumanPlayer(Game); // Player 1 is the human player
Game->DrawGame(); // Draw the game after the move
}
else {
cout << "\n::: Player 2 (Circles) :::\n";
RandomPlayer(Game); // Player 2 is a random player
Game->DrawGame(); // Draw the game after the move
}
}
// ::: End of the game :::
std::cout << "\n ::: Game Over ::: \n\n";
Game->DrawGame();
switch (Game->GameOver()) { // Print the result of the game
case CROSS : cout << "\nPlayer 1 wins (CROSSES)\n"; break; // Player 1 is winning
case CIRCLE : cout << "\nPlayer 2 wins (CIRCLES)\n"; break; // Player 2 is winning
case DRAW : cout << "\nDraw !\n"; // Draw game
}
}
// ::: Play randomly a move :::
void RandomPlayer(TicTacToe *Game)
{
int Cell=random()%9+1; // Randomly select a move
while (Game->Play(Cell)==0) // while the move is not possible...
Cell=random()%9+1; // ... select a new one
}
// ::: Human player :::
void HumanPlayer(TicTacToe *Game)
{
int Cell;
do
{
cout << "Dans quelle case jouez-vous : "; // Print a message for the user
cin >> Cell; // Read the move to the keyboard
}
while (Game->Play(Cell)==0); // Until the move is possible
}
void AIPlayer(TicTacToe *Game)
{
int Move;
MinMax(Game,Game->CurrentPlayer(),&Move);
Game->Play(Move);
}
int MinMax(TicTacToe *Game,char Mark, int *ptBest_Move)
{
//je dois compléter mais par quoi????
}
//tictactoe.h
#ifndef TICTACTOE_H
#define TICTACTOE_H
/*! \def EMPTY
\brief Value set in an empty cell */
#define EMPTY 0
/*! \def CROSS
\brief Value used to describe the mark of the first player */
#define CROSS 1
/*! \def CIRCLE
\brief Value used to describe the mark of the second player */
#define CIRCLE 2
/*! \def DRAW
\brief Value used to describe a draw game */
#define DRAW 3
using namespace std;
/*! \class TicTacToe
\brief This class can managed a Tic-Tac-Toe game. The class allows basic operations like initializing the game, placing marks according to the rules,
checking if the game is over, undo a move etc ...
\example TicTacToe_Example.cpp
*/
class TicTacToe
{
public:
TicTacToe(void); // Constructor
void DrawGame(void); // Draw the game in text mode
void Reset(void); // Set the game in its initial configuration
char CurrentPlayer(void); // Return the mark of the current player (CROSS or CIRCLE)
char Play(int NumCell); // Play a move in the cell NumCell
int Undo(void); // Undo the last move
char GameOver(void); // Return the state of the game (endded, draw ...)
private:
char Grid[9]; // Playground
int NumMoves; // Number of moves since the beginning
int History[9]; // History of the game (each move)
};
#endif // TICTACTOE_H
//tictactoe.cpp
#include "tictactoe.h"
#include <iostream>
// TicTacToe
/*!
\brief Constructor of the class TicTacToe. Call the Reset method. It creates and initializes the game
*/
TicTacToe::TicTacToe(void)
{
Reset(); // Reset the game
}
// Reset
/*!
\brief Set the game in its initial configuration. Each cell is filled with the empty symbol
*/
void TicTacToe::Reset(void)
{
for (int i=0;i<9;i++) // For each cell
Grid[i]=EMPTY; // put the empty symbol inside
NumMoves=0; // Set the number of moves at zero
}
// DrawGame
/*!
\brief Draw the game in text mode (console mode). This method uses cout to draw the game, it assumes that cout can be used.
\todo It would be better to return a string
*/
void TicTacToe:rawGame(void)
{
char GridScreen[9]; // Create a copy of the game
for (int i=0;i<9;i++) // For each cell...
{
switch (Grid[i]) // ...analyze the cell
{
case 1 : {GridScreen[i]='X'; break;} // Cross
case 2 : {GridScreen[i]='O'; break;} // Circle
default : {GridScreen[i]=1+i+'0'; break;} // Empty cell (replace by the number of the cell
}
}
// Show the current game in text mode
cout <<" "<<GridScreen[0]<< " | "<< GridScreen[1]<< " | "<< GridScreen[2]<<"\n";
cout <<" "<<GridScreen[3]<< " | "<< GridScreen[4]<< " | "<< GridScreen[5]<<"\n";
cout <<" "<<GridScreen[6]<< " | "<< GridScreen[7]<< " | "<< GridScreen[8]<<"\n";
}
// CurrentPlayer
/*! \brief Return the mark of the current player (CROSS or CIRCLE).
Note that the methods returns a mark even if the game is over.
To check if the game is over, uses the \ref GameOver method.
\return Returns the mark of the current player (CROSS or CIRCLE)
*/
char TicTacToe::CurrentPlayer(void)
{
return NumMoves%2+1;
}
// Play
/*!
\brief Place the mark of the current player on the grid in the cell NumCell if it is possible.
\param NumCell : ID of the cell where the current player will place its mark
\return 1 if the move is possible.
\return 0 if the move is impossible (NumCell do not bellong to [1;9] or the cell is not empty)
*/
char TicTacToe:lay(int NumCell)
{
if (NumCell<1 || NumCell>9) // Check if it is a cell of the grid
return 0;
if (Grid[NumCell-1]!=EMPTY) // Check if th cell is empty
return 0;
Grid[NumCell-1]=NumMoves%2+1; // Place the mark in the grid
History[NumMoves]=NumCell-1; // Memorize for history
NumMoves++; // Increase the number of moves
return 1; // Success
}
// Undo
/*!
\brief Undo the last move.
\return Returns the number of moves since the beginning of the game */
int TicTacToe::Undo(void)
{
if (NumMoves>=0)
{
NumMoves--;
Grid[History[NumMoves]]=0;
}
return NumMoves;
}
// GameOver
/*!
\brief Analyse the current state of the game.
\return 0 if the game is not over.
\return CROSS if the game is over and the winner is the first player.
\return CIRCLE If the game is over and the winner is the second player.
\return DRAW if the game is over and draw.
*/
char TicTacToe::GameOver(void)
{
if (Grid[0]==Grid[1] && Grid[1]==Grid[2] && Grid[0]!=EMPTY) return Grid[0];
if (Grid[3]==Grid[4] && Grid[4]==Grid[5] && Grid[3]!=EMPTY) return Grid[3];
if (Grid[6]==Grid[7] && Grid[7]==Grid[8] && Grid[6]!=EMPTY) return Grid[6];
if (Grid[0]==Grid[3] && Grid[3]==Grid[6] && Grid[0]!=EMPTY) return Grid[0];
if (Grid[1]==Grid[4] && Grid[4]==Grid[7] && Grid[1]!=EMPTY) return Grid[1];
if (Grid[2]==Grid[5] && Grid[5]==Grid[8] && Grid[2]!=EMPTY) return Grid[2];
if (Grid[0]==Grid[4] && Grid[4]==Grid[8] && Grid[0]!=EMPTY) return Grid[0];
if (Grid[2]==Grid[4] && Grid[4]==Grid[6] && Grid[6]!=EMPTY) return Grid[6];
if (NumMoves==9) return DRAW;
return 0;
} |
Partager