├── CheckersGame.cpp ├── CheckersGame.h ├── Checkers_LZ_YY.txt ├── ChessDesign.cpp ├── ChessDesign.h ├── ChessGame.cpp ├── ChessGame.h ├── GameBase.cpp ├── GameBase.h ├── Games.cpp ├── MagicSquare.txt ├── MagicSquareGame.cpp ├── MagicSquareGame.h ├── Makefile ├── NineAlmonds.txt ├── NineAlmondsGame.cpp ├── NineAlmondsGame.h ├── OtherFunctions.cpp ├── OtherFunctions.h ├── README.txt ├── ReversiGame.cpp ├── ReversiGame.h ├── Reversi_LZ_YY.txt ├── TicTacToeBase.cpp ├── TicTacToeBase.h ├── TicTacToeGame.cpp ├── TicTacToeGame.h ├── TicTacToeState.cpp └── TicTacToeState.h /CheckersGame.h: -------------------------------------------------------------------------------- 1 | // Checkers.h 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 03/25/14. 4 | 5 | #ifndef CHECKER_H 6 | #define CHECKER_H 7 | 8 | class CheckersGame : public GameBase { 9 | 10 | friend ostream &operator<<(ostream &out, const CheckersGame &n); 11 | 12 | public: 13 | CheckersGame(unsigned int h, unsigned int v, piece_color color, 14 | string name, string symbol, string first, string second); 15 | virtual ~CheckersGame(){}; 16 | //set function 17 | virtual void initialize_game(); 18 | virtual void initialize_game_from_start(){}; 19 | //set function 20 | virtual void push_v (checkers_game_piece cgp); 21 | //set function 22 | virtual void set_v (unsigned int x,unsigned int y , 23 | checkers_game_piece cgp); 24 | // check whether the game is done 25 | virtual bool done(); 26 | // prompt the user to input the value 27 | virtual int prompt(unsigned int &a, unsigned int &b); 28 | // check and make a valid move in the game 29 | virtual void turn(); 30 | // the print method 31 | virtual void print(); 32 | // play the game by calling turn() 33 | virtual int play(); 34 | // save the current state 35 | virtual void save_current_state(); 36 | // abort the current state 37 | virtual void abort_current_state(); 38 | // checks if this puting position is valid 39 | virtual bool valid_put_position_black(unsigned int i, unsigned int j, 40 | unsigned int m, unsigned int n); 41 | // checks if this puting position is valid 42 | virtual bool valid_put_position_white(unsigned int i, unsigned int j, 43 | unsigned int m, unsigned int n); 44 | // complete the play's turn and change the board according to the rules 45 | virtual void complete_black_turn(unsigned int i, unsigned int j, 46 | unsigned int m, unsigned int n); 47 | // complete the play's turn and change the board according to the rules 48 | virtual void complete_white_turn(unsigned int i, unsigned int j, 49 | unsigned int m, unsigned int n); 50 | // count the number of plack pieces 51 | virtual unsigned int count_black_pieces(); 52 | // count the number of white piece 53 | virtual unsigned int count_white_pieces(); 54 | // check if there is a put position for black piece 55 | virtual bool check_available_move_black(); 56 | // check if there is a put position for white piece 57 | virtual bool check_available_move_white(); 58 | // decide whether the piece on the board should be change into the King 59 | virtual void whether_change_into_king(); 60 | // check if the continuous move is valid 61 | virtual bool check_continuous_move_current_black(unsigned int i, 62 | unsigned int j); 63 | // check if the continuous move is valid 64 | virtual bool check_continuous_move_current_white(unsigned int i, 65 | unsigned int j); 66 | 67 | protected: 68 | // hold the game pieces, it represents the gameboard, 69 | // the index correspond to the position of the board 70 | vector v; 71 | // store the name of the player who moves first 72 | string first_person; 73 | // store the name of the player who moves second 74 | string second_person; 75 | 76 | }; 77 | 78 | #endif -------------------------------------------------------------------------------- /Checkers_LZ_YY.txt: -------------------------------------------------------------------------------- 1 | Checkers 2 | LZ 3 | YY 4 | E X E X E X E X 5 | X E X E X E X E 6 | E E E X E X E X 7 | E E E E E E E E 8 | E E E O E E E E 9 | O E O E E E O E 10 | E O E O E E E O 11 | O E O E O E O E 12 | 2 13 | 2 14 | LZ 15 | -------------------------------------------------------------------------------- /ChessDesign.cpp: -------------------------------------------------------------------------------- 1 | // ChessBoardPiece.cpp 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 04/29/14. 4 | // http://inst.eecs.berkeley.edu/~cs162/sp07/Nachos/chess.shtml 5 | 6 | #include "OtherFunctions.h" 7 | #include "GameBase.h" 8 | #include "ChessDesign.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | // Implementation of the History class 15 | History::History(Point f, Point t, Board* b, History *p) 16 | { 17 | board = b; 18 | from = f; 19 | to = t; 20 | killed_piece = NULL; 21 | prev = next = NULL; 22 | } 23 | 24 | // Implementation of the Board class 25 | Board::Board() 26 | :en_passant(Point(x_empty,y_empty)),can_en_passant(false),N(8) 27 | { 28 | first_history = last_history = NULL; 29 | 30 | // Allocate memory for the chess_board 31 | chess_board = new Piece** [N]; 32 | for (unsigned int i = 0; i < N; i++) 33 | chess_board[i] = new Piece* [N]; 34 | 35 | // Initialize chess_board piece to NULL 36 | for (unsigned int i = 0; i < N; i++) 37 | for (unsigned int j = 0; j < N; j++) 38 | chess_board[i][j] = NULL; 39 | 40 | // Initialize chess board with pieces 41 | chess_board[0][0] = new Rook (Point(0,0), black, this, "R"); 42 | chess_board[0][1] = new Knight(Point(0,1), black, this, "N"); 43 | chess_board[0][2] = new Bishop(Point(0,2), black, this, "B"); 44 | chess_board[0][3] = new Queen (Point(0,3), black, this, "Q"); 45 | chess_board[0][4] = new King (Point(0,4), black, this, "K"); 46 | chess_board[0][5] = new Bishop(Point(0,5), black, this, "B"); 47 | chess_board[0][6] = new Knight(Point(0,6), black, this, "N"); 48 | chess_board[0][7] = new Rook (Point(0,7), black, this, "R"); 49 | 50 | for (unsigned int i = 0; i < N; i++) 51 | chess_board[1][i] = new Pawn(Point(1,i), black, this, 1, "P"); 52 | 53 | chess_board[7][0] = new Rook (Point(7,0), white, this, "r"); 54 | chess_board[7][1] = new Knight(Point(7,1), white, this, "n"); 55 | chess_board[7][2] = new Bishop(Point(7,2), white, this, "b"); 56 | chess_board[7][3] = new Queen (Point(7,3), white, this, "q"); 57 | chess_board[7][4] = new King (Point(7,4), white, this, "k"); 58 | chess_board[7][5] = new Bishop(Point(7,5), white, this, "b"); 59 | chess_board[7][6] = new Knight(Point(7,6), white, this, "n"); 60 | chess_board[7][7] = new Rook (Point(7,7), white, this, "r"); 61 | 62 | for (unsigned int i = 0; i < N; i++) 63 | chess_board[6][i] = new Pawn(Point(6,i), white, this, -1, "p"); 64 | } 65 | 66 | Board::~Board() 67 | { 68 | for (unsigned int i = 0; i < N; i++) 69 | delete [] chess_board[i]; 70 | delete [] chess_board; 71 | } 72 | 73 | Piece* Board::PieceAt(Point p) 74 | { 75 | return chess_board[p.x][p.y]; 76 | } 77 | 78 | // Set the Piece 79 | void Board::PlacePieceAt(Piece* piece, Point p) 80 | { 81 | chess_board[p.x][p.y] = piece; 82 | } 83 | 84 | void Board::Move(Point p1, Point p2) 85 | { 86 | Move(p1, p2, Point()); 87 | } 88 | 89 | // This method moves the piece occupying p1 to p2, 90 | // without any check as to whether the move is legal 91 | void Board::Move(Point p1, Point p2, Point ep) 92 | { 93 | //add the move from p1 to p2 to the history; 94 | //en_passant = ep; 95 | //if there is a piece at p2 96 | if (chess_board[p2.x][p2.y] != NULL) 97 | delete chess_board[p2.x][p2.y]; 98 | 99 | //set location p2 on the board to point to the piece that is at p1 now; 100 | chess_board[p2.x][p2.y] = chess_board[p1.x][p1.y]; 101 | chess_board[p2.x][p2.y]->SetLocation(p2); 102 | 103 | //set location p1 to NULL 104 | chess_board[p1.x][p1.y] = NULL; 105 | } 106 | 107 | void Board::TryToMove(Point p1, Point p2) 108 | { 109 | // If you don't move this ENPASSANT turn 110 | // We can not move it next time 111 | if (PieceAt(p1) != NULL && 112 | PieceAt(p1)->CanMove(p2) != ESCAPE) 113 | { 114 | PieceAt(p1)->TryToMove(p2); 115 | can_en_passant = false; 116 | } 117 | else 118 | { 119 | PieceAt(p1)->TryToMove(p2); 120 | } 121 | } 122 | 123 | bool Board::CanMove(Point p1, Point p2) 124 | { 125 | if (PieceAt(p1) != NULL && 126 | PieceAt(p1)->CanMove(p2) != ILLEGAL) 127 | return true; 128 | 129 | return false; 130 | } 131 | 132 | Point Board::GetEnPassant() 133 | { 134 | return en_passant; 135 | } 136 | 137 | void Board::SetEnPassant(Point p) 138 | { 139 | en_passant = p; 140 | } 141 | 142 | bool Board::GetCanEnPassant() 143 | { 144 | return can_en_passant; 145 | } 146 | 147 | void Board::SetCanEnPassant(bool flag) 148 | { 149 | can_en_passant = flag; 150 | } 151 | 152 | unsigned int Board::GetDimenstion() 153 | { 154 | return N; 155 | } 156 | 157 | // Implementation of the Piece class 158 | Piece::Piece(Point p, Color c, Board *b, string s) 159 | :chess_game_piece(p.x,p.y,c,s),board(b){} 160 | 161 | Point Piece::GetLocation() 162 | { 163 | return Point(x,y); 164 | } 165 | 166 | Color Piece::GetColor() 167 | { 168 | return color; 169 | } 170 | 171 | string Piece::GetSymbol() 172 | { 173 | return symbol; 174 | } 175 | 176 | void Piece::SetLocation(Point p) 177 | { 178 | x = p.x; 179 | y = p.y; 180 | } 181 | 182 | void Piece::TryToMove(Point p) 183 | { 184 | // get the current location 185 | int current_x = GetLocation().x; 186 | int current_y = GetLocation().y; 187 | 188 | board->Move(Point(current_x,current_y), p); 189 | } 190 | 191 | // returns ILLEGAL for illegal moves, ENPASSANT 192 | // when the move kills a pawn by the en passant rule 193 | MoveType Piece::CanMove(Point p) 194 | { 195 | // p is on the board 196 | if (p.x < board->GetDimenstion() && 197 | p.y < board->GetDimenstion()) 198 | { 199 | // there is no piece at p 200 | if (board->PieceAt(p) == NULL) 201 | return NORMAL; 202 | if (board->GetEnPassant() == p) 203 | return ENPASSANT; 204 | // the color of the piece at point p is different 205 | if (board->PieceAt(p)->GetColor() != GetColor()) 206 | return NORMAL; 207 | } 208 | return ILLEGAL; 209 | } 210 | 211 | // Implementation of the Pawn class 212 | // redefine CanMove according the rules of pawn movement 213 | Pawn::Pawn(Point p, Color c, Board * b, int d, string s) 214 | :Piece(p,c,b,s),direction(d),can_double_step(true) {} 215 | 216 | // moves the piece to p only if the move is legal 217 | // kills the en passant pawn if necessary 218 | void Pawn::TryToMove(Point p) 219 | { 220 | if (CanMove(p) != ILLEGAL) 221 | { 222 | // get the current location 223 | int current_x = GetLocation().x; 224 | int current_y = GetLocation().y; 225 | 226 | // get the difference 227 | int dx = p.x - current_x; 228 | int dy = p.y - current_y; 229 | 230 | // get the direction 231 | int direction_x = (dx == 0) ? 0 : abs(dx) / dx; 232 | 233 | if (CanMove(p) == ENPASSANT) 234 | { 235 | // kill pawn 236 | if (dy < 0) 237 | { 238 | delete board->PieceAt(Point(current_x,current_y-1)); 239 | board->PlacePieceAt(NULL,Point(current_x,current_y-1)); 240 | } 241 | else 242 | { 243 | delete board->PieceAt(Point(current_x,current_y+1)); 244 | board->PlacePieceAt(NULL,Point(current_x,current_y+1)); 245 | } 246 | } 247 | 248 | if (CanMove(p) == ESCAPE) 249 | { 250 | board->SetEnPassant(Point(p.x-direction_x,p.y)); 251 | board->SetCanEnPassant(true); 252 | } 253 | 254 | if (CanMove(p) == PROMOTION) 255 | { 256 | GetPromotion(Point(current_x,current_y)); 257 | } 258 | can_double_step = false; 259 | board->Move(Point(current_x,current_y), p); 260 | } 261 | } 262 | 263 | MoveType Pawn::CanMove(Point p) 264 | { 265 | if(Piece::CanMove(p) == ILLEGAL) 266 | return ILLEGAL; 267 | 268 | // get the current location 269 | int current_x = GetLocation().x; 270 | int current_y = GetLocation().y; 271 | 272 | // get the difference 273 | int dx = p.x - current_x; 274 | int dy = p.y - current_y; 275 | 276 | if(dx == direction) 277 | { 278 | // if we're killing diagonally or 279 | // we move one space forward 280 | if ( (abs(dy) == 1 && 281 | board->PieceAt(p) != NULL && 282 | GetColor() != board->PieceAt(p)->GetColor() ) || 283 | (dy == 0 && 284 | board->PieceAt(p) == NULL) ) 285 | { 286 | if ((dx > 0 && p.x == board->GetDimenstion() - 1) || 287 | (dx < 0 && p.x == 0)) 288 | return PROMOTION; 289 | else 290 | return NORMAL; 291 | } 292 | 293 | // if the enpassant happens 294 | if ( abs(dy) == 1 && 295 | board->GetEnPassant() == p && 296 | board->GetCanEnPassant() ) 297 | return ENPASSANT; 298 | } 299 | 300 | // the double step move 301 | if (can_double_step && 302 | dx == 2 * direction && 303 | dy == 0 && 304 | board->PieceAt(p) == NULL && 305 | board->PieceAt(Point(current_x + direction, current_y)) == NULL) 306 | { 307 | // check the probably enpassant position see if there are 308 | // pawns of different color are next to this piece 309 | if ( ( p.y > 0 && board->PieceAt(Point(p.x,p.y-1)) != NULL && 310 | ( board->PieceAt(Point(p.x,p.y-1))->GetSymbol() == "P" || 311 | board->PieceAt(Point(p.x,p.y-1))->GetSymbol() == "p") && 312 | board->PieceAt(Point(p.x,p.y-1))->GetColor() != GetColor() ) || 313 | ( p.y < board->GetDimenstion() -1 && 314 | board->PieceAt(Point(p.x,p.y+1)) != NULL && 315 | ( board->PieceAt(Point(p.x,p.y+1))->GetSymbol() == "P" || 316 | board->PieceAt(Point(p.x,p.y+1))->GetSymbol() == "p") && 317 | board->PieceAt(Point(p.x,p.y+1))->GetColor() != GetColor() ) ) 318 | return ESCAPE; 319 | 320 | return DOUBLESTEP; 321 | } 322 | 323 | return ILLEGAL; 324 | } 325 | 326 | void Pawn::GetPromotion(Point p) 327 | { 328 | while (true) 329 | { 330 | cout << "Please type the which piece you want the pawn " 331 | "be promoted to Q means Queen, N mean Knight, " 332 | "B mean Bishop, R means Rook.\n"; 333 | 334 | string s; // Temp virable to read command line data 335 | getline(cin, s); 336 | char select = s[0]; 337 | Piece *piece = NULL; 338 | Color c = board->PieceAt(p)->GetColor(); 339 | // check the option 340 | switch (select) 341 | { 342 | case 'Q': 343 | cout << "Promoted to Queen !!!\n"; 344 | s = (c == black) ? "Q" : "q"; 345 | piece = new Queen(p, c, board, s); 346 | delete board->PieceAt(p); 347 | board->PlacePieceAt(piece,p); 348 | return; 349 | case 'N': 350 | cout << "Promoted to Knight !!!\n"; 351 | s = (c == black) ? "N" : "n"; 352 | piece = new Knight(p, c, board, s); 353 | delete board->PieceAt(p); 354 | board->PlacePieceAt(piece,p); 355 | return; 356 | case 'B': 357 | cout << "Promoted to Bishop !!!\n"; 358 | s = (c == black) ? "B" : "b"; 359 | piece = new Bishop(p, c, board, s); 360 | delete board->PieceAt(p); 361 | board->PlacePieceAt(piece,p); 362 | return; 363 | case 'R': 364 | cout << "Promoted to Rook !!!\n"; 365 | s = (c == black) ? "R" : "r"; 366 | piece = new Rook(p, c, board, s); 367 | delete board->PieceAt(p); 368 | board->PlacePieceAt(piece,p); 369 | return; 370 | default: 371 | break; 372 | } 373 | 374 | cout << "Invalid input, please try again" << endl; 375 | } 376 | } 377 | 378 | // Implementation of the Bishop class 379 | Bishop::Bishop(Point p, Color c, Board * b, string s) 380 | :Piece(p,c,b,s) {} 381 | 382 | void Bishop::TryToMove(Point p) 383 | { 384 | if (CanMove(p) != ILLEGAL) 385 | board->Move(Point(GetLocation().x,GetLocation().y), p); 386 | } 387 | 388 | MoveType Bishop::CanMove(Point p) 389 | { 390 | if(Piece::CanMove(p) == ILLEGAL) 391 | return ILLEGAL; 392 | 393 | // get the current location 394 | int current_x = GetLocation().x; 395 | int current_y = GetLocation().y; 396 | 397 | // get the difference 398 | int dx = p.x - current_x; 399 | int dy = p.y - current_y; 400 | 401 | // get the direction 402 | int direction_x = abs(dx) / dx; 403 | int direction_y = abs(dy) / dy; 404 | 405 | // same distance in x and y dirs 406 | if (abs(dx) == abs(dy)) 407 | { 408 | // no pieces between location and p 409 | while (Point(current_x + direction_x, 410 | current_y + direction_y) != p) 411 | { 412 | if (board->PieceAt(Point(current_x + direction_x, 413 | current_y + direction_y)) != NULL) 414 | return ILLEGAL; 415 | 416 | // update the current x and y 417 | current_x += direction_x; 418 | current_y += direction_y; 419 | } 420 | 421 | return NORMAL; 422 | } 423 | 424 | return ILLEGAL; 425 | } 426 | 427 | // Implementation of the Rook class 428 | Rook::Rook(Point p, Color c, Board * b, string s) 429 | :Piece(p,c,b,s), can_castling(true) {} 430 | 431 | void Rook::TryToMove(Point p) 432 | { 433 | if (CanMove(p) != ILLEGAL) 434 | { 435 | can_castling = false; 436 | board->Move(Point(GetLocation().x,GetLocation().y), p); 437 | } 438 | } 439 | 440 | MoveType Rook::CanMove(Point p) 441 | { 442 | if(Piece::CanMove(p) == ILLEGAL) 443 | return ILLEGAL; 444 | 445 | // get the current location 446 | int current_x = GetLocation().x; 447 | int current_y = GetLocation().y; 448 | 449 | // get the difference 450 | int dx = p.x - current_x; 451 | int dy = p.y - current_y; 452 | 453 | // get the direction 454 | int direction_x = (dx == 0) ? 0 : abs(dx) / dx; 455 | int direction_y = (dy == 0) ? 0 : abs(dy) / dy; 456 | 457 | // only moves in x or y direction 458 | if (dx == 0 || dy == 0) 459 | { 460 | // no pieces between location and p 461 | while (Point(current_x + direction_x, 462 | current_y + direction_y) != p) 463 | { 464 | if (board->PieceAt(Point(current_x + direction_x, 465 | current_y + direction_y)) != NULL) 466 | return ILLEGAL; 467 | 468 | // update the current x and y 469 | current_x += direction_x; 470 | current_y += direction_y; 471 | } 472 | 473 | return NORMAL; 474 | } 475 | 476 | return ILLEGAL; 477 | } 478 | 479 | bool Rook::GetCanCastling() 480 | { 481 | return can_castling; 482 | } 483 | 484 | // Implementation of the Knight class 485 | Knight::Knight(Point p, Color c, Board * b, string s) 486 | :Piece(p,c,b,s) {} 487 | 488 | void Knight::TryToMove(Point p) 489 | { 490 | if (CanMove(p) != ILLEGAL) 491 | board->Move(Point(GetLocation().x,GetLocation().y), p); 492 | } 493 | 494 | MoveType Knight::CanMove(Point p) 495 | { 496 | if(Piece::CanMove(p) == ILLEGAL) 497 | return ILLEGAL; 498 | 499 | // get the difference 500 | int dx = p.x - GetLocation().x; 501 | int dy = p.y - GetLocation().y; 502 | 503 | // move one step, L shape or 504 | // killing a piece of different color 505 | if ( (abs(dx) == 2 && abs(dy) == 1) || 506 | (abs(dx) == 1 && abs(dy) == 2) ) 507 | return NORMAL; 508 | 509 | return ILLEGAL; 510 | } 511 | 512 | // Implementation of the King class 513 | King::King(Point p, Color c, Board * b, string s) 514 | :Piece(p,c,b,s), can_castling(true) {} 515 | 516 | void King::TryToMove(Point p) 517 | { 518 | if (CanMove(p) != ILLEGAL) 519 | { 520 | // get the current location 521 | int current_x = GetLocation().x; 522 | int current_y = GetLocation().y; 523 | 524 | if (CanMove(p) == CASTLE) 525 | { 526 | int dy = p.y - GetLocation().y; 527 | int direction_y = (dy == 0) ? 0 : abs(dy) / dy; 528 | 529 | if (direction_y > 0) 530 | board->Move(Point(current_x,7), Point(current_x,5)); 531 | else 532 | board->Move(Point(current_x,0), Point(current_x,3)); 533 | } 534 | 535 | can_castling = false; 536 | board->Move(Point(current_x,current_y), p); 537 | } 538 | } 539 | 540 | MoveType King::CanMove(Point p) 541 | { 542 | if(Piece::CanMove(p) == ILLEGAL) 543 | return ILLEGAL; 544 | 545 | // get the current location 546 | int current_x = GetLocation().x; 547 | int current_y = GetLocation().y; 548 | 549 | int dx = p.x - current_x; 550 | int dy = p.y - current_y; 551 | 552 | //int direction_x = (dx == 0) ? 0 : abs(dx) / dx; 553 | int direction_y = (dy == 0) ? 0 : abs(dy) / dy; 554 | 555 | // move one step, L or 556 | // killing a piece of different color 557 | if ( (abs(dx) == 0 && abs(dy) == 1) || 558 | (abs(dx) == 1 && abs(dy) == 0) || 559 | (abs(dx) == 1 && abs(dy) == 1) ) 560 | return NORMAL; 561 | // check if the move is the castling 562 | if (can_castling && 563 | (abs(dx) == 0 && abs(dy) == 2)) 564 | { 565 | // if the king moves right 566 | if (direction_y > 0) 567 | if (dynamic_cast(board->PieceAt(Point(current_x,7))) 568 | ->GetCanCastling() && 569 | board->PieceAt(Point(current_x,6)) == NULL && 570 | board->PieceAt(Point(current_x,5)) == NULL) 571 | return CASTLE; 572 | 573 | // if the king moves left 574 | if (direction_y < 0) 575 | if (dynamic_cast(board->PieceAt(Point(current_x,0))) 576 | ->GetCanCastling() && 577 | board->PieceAt(Point(current_x,1)) == NULL && 578 | board->PieceAt(Point(current_x,2)) == NULL && 579 | board->PieceAt(Point(current_x,3)) == NULL) 580 | return CASTLE; 581 | } 582 | 583 | return ILLEGAL; 584 | } 585 | 586 | // Implementation of the Queen class 587 | Queen::Queen(Point p, Color c, Board * b, string s) 588 | :Piece(p,c,b,s) {} 589 | 590 | void Queen::TryToMove(Point p) 591 | { 592 | if (CanMove(p) != ILLEGAL) 593 | board->Move(Point(GetLocation().x,GetLocation().y), p); 594 | } 595 | 596 | MoveType Queen::CanMove(Point p) 597 | { 598 | if(Piece::CanMove(p) == ILLEGAL) 599 | return ILLEGAL; 600 | 601 | // get the current location 602 | int current_x = GetLocation().x; 603 | int current_y = GetLocation().y; 604 | 605 | // get the difference 606 | int dx = p.x - current_x; 607 | int dy = p.y - current_y; 608 | 609 | // get the direction 610 | int direction_x = (dx == 0) ? 0 : abs(dx) / dx; 611 | int direction_y = (dy == 0) ? 0 : abs(dy) / dy; 612 | 613 | // only moves in x or y direction 614 | // same distance in x and y dirs 615 | if (dx == 0 || dy == 0 || 616 | abs(dx) == abs(dy)) 617 | { 618 | // no pieces between location and p 619 | while (Point(current_x + direction_x, 620 | current_y + direction_y) != p) 621 | { 622 | if (board->PieceAt(Point(current_x + direction_x, 623 | current_y + direction_y)) != NULL) 624 | return ILLEGAL; 625 | 626 | // update the current x and y 627 | current_x += direction_x; 628 | current_y += direction_y; 629 | } 630 | 631 | return NORMAL; 632 | } 633 | 634 | return ILLEGAL; 635 | } 636 | 637 | -------------------------------------------------------------------------------- /ChessDesign.h: -------------------------------------------------------------------------------- 1 | // ChessDesign.h 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 04/29/14. 4 | // http://inst.eecs.berkeley.edu/~cs162/sp07/Nachos/chess.shtml 5 | 6 | #ifndef CHESS_DESIGN_H 7 | #define CHESS_DESIGN_H 8 | 9 | class Piece; // just declaration for compiler 10 | class Board; // just declaration for compiler 11 | 12 | // Declaration of the History class 13 | class History { 14 | public: 15 | History(Point f, Point t, Board* b, History *p); 16 | void SetNext(History *n){}; 17 | void UndoLastMove(){}; 18 | void RedoUndoneMove(){}; 19 | private: 20 | Board *board; 21 | // the point a piece was moved from 22 | Point from; 23 | // the point a piece was moved to 24 | Point to; 25 | // remembers what piece was killed 26 | Piece *killed_piece; 27 | // history on this move. 28 | History *next; 29 | History *prev; 30 | }; 31 | 32 | // Declaration of the Board class 33 | class Board { 34 | public: 35 | // creates board with pieces in initial configuration 36 | Board(); 37 | // delete the piece on the board 38 | ~Board(); 39 | // return the piece at location p 40 | Piece* PieceAt(Point p); 41 | // Set the Piece 42 | void PlacePieceAt(Piece* piece, Point p); 43 | // move piece at p1 to p2 44 | void Move(Point p1, Point p2); 45 | // move piece at p1 to p2, remembering 46 | void Move(Point p1, Point p2, Point ep); 47 | // check to move piece at p1 to p2 48 | void TryToMove(Point p1, Point p2); 49 | // check whether can move 50 | bool CanMove(Point p1, Point p2); 51 | // get Enpassant 52 | Point GetEnPassant(); 53 | // set Enpassant 54 | void SetEnPassant(Point p); 55 | // get whether can enpassant 56 | bool GetCanEnPassant(); 57 | // set cab_enpassant 58 | void SetCanEnPassant(bool flag); 59 | // get the dimenstion 60 | unsigned int GetDimenstion(); 61 | private: 62 | Piece*** chess_board; 63 | History* first_history; 64 | History* last_history; 65 | Point en_passant; 66 | bool can_en_passant; 67 | unsigned int N; // board dimension 68 | }; 69 | 70 | // Declaration of the Piece class 71 | // Here we use the PRIVATE inheritance 72 | // The definition of the chess game_piece 73 | class Piece : private chess_game_piece { 74 | public: 75 | Piece(Point p, Color c, Board *b, string s); 76 | virtual ~Piece(){}; 77 | Point GetLocation(); 78 | Color GetColor(); 79 | string GetSymbol(); 80 | void SetLocation(Point p); 81 | virtual void TryToMove(Point p); 82 | virtual MoveType CanMove(Point p); 83 | protected: 84 | Board* board; 85 | }; 86 | 87 | // THe specific piece of the Pawn piece 88 | class Pawn : public Piece { 89 | public: 90 | Pawn(Point p, Color c, Board * b, int d, string s); 91 | virtual void TryToMove(Point p); 92 | virtual MoveType CanMove(Point p); 93 | private: 94 | void GetPromotion(Point p); 95 | int direction; // 1 for up, -1 for down 96 | bool can_double_step; 97 | }; 98 | 99 | // THe specific piece of the Bishop piece 100 | class Bishop : public Piece { 101 | public: 102 | Bishop(Point p, Color c, Board * b, string s); 103 | virtual void TryToMove(Point p); 104 | virtual MoveType CanMove(Point p); 105 | }; 106 | 107 | // THe specific piece of the Rook piece 108 | class Rook : public Piece { 109 | public: 110 | Rook(Point p, Color c, Board * b, string s); 111 | virtual void TryToMove(Point p); 112 | virtual MoveType CanMove(Point p); 113 | bool GetCanCastling(); 114 | private: 115 | bool can_castling; 116 | }; 117 | 118 | // THe specific piece of the Knight piece 119 | class Knight : public Piece { 120 | public: 121 | Knight(Point p, Color c, Board * b, string s); 122 | virtual void TryToMove(Point p); 123 | virtual MoveType CanMove(Point p); 124 | }; 125 | 126 | // THe specific piece of the King piece 127 | class King : public Piece { 128 | public: 129 | King(Point p, Color c, Board * b, string s); 130 | virtual void TryToMove(Point p); 131 | virtual MoveType CanMove(Point p); 132 | bool can_castling; 133 | }; 134 | 135 | // THe specific piece of the Queen piece 136 | class Queen : public Piece { 137 | public: 138 | Queen(Point p, Color c, Board * b, string s); 139 | virtual void TryToMove(Point p); 140 | MoveType CanMove(Point p); 141 | }; 142 | 143 | #endif -------------------------------------------------------------------------------- /ChessGame.cpp: -------------------------------------------------------------------------------- 1 | // ChessGame.cpp 2 | // Author : Zheng Luo 3 | // Created by Zheng Luo on 04/29/14. 4 | 5 | #include "OtherFunctions.h" 6 | #include "GameBase.h" 7 | #include "ChessDesign.h" 8 | #include "ChessGame.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | //constructor of ChessGame 17 | ChessGame::ChessGame(unsigned int h, unsigned int v, piece_color color, 18 | string name, string symbol, string first, string second) 19 | :GameBase(h, v, color, name, symbol), // assume black go first 20 | first_person(first),second_person(second),player(first),player_color(black),N(h) 21 | { 22 | // initialize the baord 23 | chess_board = new Board(); 24 | } 25 | 26 | ChessGame::~ChessGame() 27 | { 28 | delete chess_board; 29 | } 30 | 31 | // check whether the game is done 32 | bool ChessGame::done() 33 | { 34 | for (unsigned int i = 0; i < N; i++) 35 | for (unsigned int j = 0; j < N; j++) 36 | if (chess_board->PieceAt(Point(i,j)) != NULL && 37 | ( chess_board->PieceAt(Point(i,j))->GetSymbol() == "K" || 38 | chess_board->PieceAt(Point(i,j))->GetSymbol() == "k" ) && 39 | chess_board->PieceAt(Point(i,j))->GetColor() != player_color) 40 | return false; 41 | return true; 42 | } 43 | 44 | // check and make a valid move in the game 45 | void ChessGame::turn() 46 | { 47 | // move the piece 48 | chess_board->TryToMove(from,to); 49 | } 50 | 51 | // print method 52 | void ChessGame::print() 53 | { 54 | cout << endl << *this << endl << endl; 55 | } 56 | 57 | // play the game by calling turn() 58 | int ChessGame::play() 59 | { 60 | while (true) 61 | { 62 | // Read the where the player wants to place a piece 63 | read_position(from, to); 64 | // Make a turn 65 | turn(); 66 | // Print the board 67 | print(); 68 | // Check if there is a winner 69 | if (done()) 70 | break; 71 | // Change a player 72 | change_current_player(); 73 | } 74 | cout << "Congratulations to " << player 75 | << "\nYou win the game." << endl; 76 | return success; 77 | }; 78 | 79 | // read position from commandline 80 | void ChessGame::read_position(Point &from, Point &to) 81 | { 82 | while (true) 83 | { 84 | cout << "\n\n\nPlayer " << player 85 | << ", please enter the from to of your move.\n" 86 | "For example 1,1 2,2 meaning from (1,1) to (2,2), " 87 | "and the input range should be less or equal to " 88 | << N -1 << endl; 89 | string s; // Temp virable to read command line data 90 | getline(cin, s); 91 | // Replace comma with space 92 | replace(s.begin(), s.end(), ',', ' '); 93 | // This code converts from string to number safely. 94 | stringstream strStream(s); 95 | // Extrace the number and assign to point from and to 96 | if (strStream >> from.x && strStream >> from.y && 97 | strStream >> to.x && strStream >> to.y) 98 | if(chess_board->CanMove(from, to)) 99 | break; 100 | 101 | cout << "Invalid select or move, please try again" << endl; 102 | } 103 | } 104 | 105 | void ChessGame::change_current_player() 106 | { 107 | if (player_color == black) 108 | { 109 | player = second_person; 110 | player_color = white; 111 | } 112 | else 113 | { 114 | player = first_person; 115 | player_color = black; 116 | } 117 | } 118 | 119 | // Overloading the operator << for Checkers Game 120 | ostream &operator<< (ostream &out, const ChessGame &r) 121 | { 122 | // store the value of the dimension 123 | unsigned int d = r.horizontal_dimension; 124 | 125 | // Draw the X coordinate 126 | out << "X" << " "; 127 | for(unsigned int j = 0; j < d; ++j) 128 | { 129 | // Draw the X coordinate with the space between them 130 | out << setiosflags(ios_base::left) 131 | << setw(r.longest_string_length+1) << j; 132 | } 133 | out << "X" << endl; 134 | 135 | for(unsigned int i = 0; i < d; ++i) 136 | { 137 | // Draw the Y coordinate 138 | out << i << " "; 139 | // Print the board 140 | for(unsigned int j = 0; j < d; ++j) 141 | { 142 | // check whether it is empty 143 | // If there is no piece there, print out the space 144 | if(r.chess_board->PieceAt(Point(i,j)) == NULL) 145 | { 146 | out << setiosflags(ios_base::left) 147 | << setw(r.longest_string_length+1) << " "; 148 | } 149 | else 150 | { 151 | // print out the symbol 152 | out << setiosflags(ios_base::left) 153 | << setw(r.longest_string_length+1) 154 | << r.chess_board->PieceAt(Point(i,j))->GetSymbol(); 155 | } 156 | // Draw the Y coordinate and change the line 157 | if(j == d-1) 158 | out << i << endl; 159 | } 160 | } 161 | 162 | // Draw the X coordinate 163 | out << "X" << " "; 164 | for(unsigned int j = 0; j < d; ++j) 165 | { 166 | // Draw the X coordinate with the space between them 167 | out << setiosflags(ios_base::left) 168 | << setw(r.longest_string_length+1) << j; 169 | } 170 | out << "X" << endl; 171 | 172 | return out; 173 | } 174 | -------------------------------------------------------------------------------- /ChessGame.h: -------------------------------------------------------------------------------- 1 | // ChessGame.h 2 | // Author : Zheng Luo 3 | // Created by Zheng Luo on 04/29/14. 4 | 5 | #ifndef CHESS_H 6 | #define CHESS_H 7 | 8 | #include "ChessDesign.h" 9 | 10 | class ChessGame : public GameBase { 11 | // support insertion operator 12 | friend ostream &operator<<(ostream &out, const ChessGame &n); 13 | 14 | public: 15 | ChessGame(unsigned int h, unsigned int v, piece_color color, 16 | string name, string symbol, string first, string second); 17 | virtual ~ChessGame(); 18 | // set function, not implemented 19 | virtual void initialize_game(){}; 20 | virtual void initialize_game_from_start(){}; 21 | // check whether the game is done 22 | virtual bool done(); 23 | // check and make a valid move in the game 24 | virtual void turn(); 25 | // the print method 26 | virtual void print(); 27 | // play the game by calling turn() 28 | virtual int play(); 29 | // save the current state, not implemented 30 | virtual void save_current_state(){}; 31 | // abort the current state, not implemented 32 | virtual void abort_current_state(){}; 33 | 34 | protected: 35 | // read position from commandline 36 | void read_position(Point &from, Point &to); 37 | // change the player symbol 38 | void change_current_player(); 39 | // A pointer for ChessBoard 40 | Board *chess_board; 41 | // store the name of the player who moves first 42 | string first_person; 43 | // store the name of the player who moves second 44 | string second_person; 45 | // store current player name 46 | string player; 47 | // store the current player color 48 | Color player_color; 49 | // chessboard dimension 50 | unsigned int N; 51 | // move a piece from point 52 | Point from; 53 | // move a piece to point 54 | Point to; 55 | }; 56 | 57 | #endif -------------------------------------------------------------------------------- /GameBase.cpp: -------------------------------------------------------------------------------- 1 | // GameBase.cpp 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 03/24/14. 4 | 5 | #include "OtherFunctions.h" 6 | #include "GameBase.h" 7 | #include "CheckersGame.h" 8 | #include "ChessGame.h" 9 | #include "NineAlmondsGame.h" 10 | #include "MagicSquareGame.h" 11 | #include "ReversiGame.h" 12 | #include "TicTacToeGame.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | // initalize the static virable 26 | GameBase * GameBase::instance_ = 0; 27 | 28 | // constructor of the GameBase class 29 | GameBase::GameBase(unsigned int h,unsigned int v,piece_color color, 30 | string name,string symbol) 31 | :horizontal_dimension(h),vertical_dimension(v),color(color), 32 | name(name), symbol(symbol),longest_string_length(symbol.length()){} 33 | 34 | //retun the value of horizontal_dimension 35 | unsigned int GameBase::get_horizontal_dimension() const 36 | { 37 | return horizontal_dimension; 38 | } 39 | 40 | //retun the value of vertical_dimension 41 | unsigned int GameBase::get_vertical_dimension() const 42 | { 43 | return vertical_dimension; 44 | } 45 | 46 | // check the argument and creat the object 47 | void GameBase::check_create(int argc , char * argv[]) 48 | { 49 | char * game_name=argv[1]; 50 | // check whether the instance exist 51 | if(instance_ == 0) 52 | { 53 | if(argc == 4 && 54 | strcmp (game_name,"Checkers") == 0) 55 | { 56 | int checkersGame_dim = 8; 57 | char * first_player = argv[2]; 58 | char * second_player = argv[3]; 59 | instance_ = new CheckersGame(checkersGame_dim, checkersGame_dim, 60 | black_or_white, "checker", "C", 61 | first_player, second_player); 62 | } 63 | else if(argc == 4 && 64 | strcmp (game_name,"Chess") == 0) 65 | { 66 | int chessGame_dim = 8; 67 | char * first_player = argv[2]; 68 | char * second_player = argv[3]; 69 | instance_ = new ChessGame(chessGame_dim, chessGame_dim, 70 | black_or_white, "chess", "C", 71 | first_player, second_player); 72 | } 73 | else if(argc == 2 && 74 | strcmp (game_name,"NineAlmonds") == 0) 75 | { 76 | int nineAlmondsGame_dim = 5; 77 | instance_ = new NineAlmondsGame(nineAlmondsGame_dim, 78 | nineAlmondsGame_dim, brown, 79 | "almond", "A"); 80 | } 81 | else if(argc == 2 && 82 | strcmp (game_name,"MagicSquare") == 0) 83 | { 84 | int magicSquareGame_dim = 3; 85 | instance_ = new MagicSquareGame(magicSquareGame_dim, 86 | magicSquareGame_dim, brown, 87 | "square", "S"); 88 | } 89 | else if(argc == 4 && 90 | strcmp (game_name,"Reversi") == 0) 91 | { 92 | int reversiGame_dim = 8; 93 | char * first_player = argv[2]; 94 | char * second_player = argv[3]; 95 | instance_ = new ReversiGame(reversiGame_dim,reversiGame_dim, 96 | black_or_white, "reversi","R", 97 | first_player, second_player); 98 | } 99 | else if(argc == 2 && 100 | strcmp (game_name,"TicTacToe") == 0) 101 | { 102 | int ticTacToe_dim = 3; 103 | bool computer_first = true; 104 | bool play_with_computer = true; 105 | string mode = "hard"; 106 | 107 | // Get the ticTacToe_dim from the commandline 108 | string s; // Temp virable to read command line data 109 | // Get the play_with_computer from the commandline 110 | cout << "Do you want to play with computer?\n" 111 | "Please type yes or no. Default option is yes. \n"; 112 | getline(cin, s); 113 | play_with_computer = (s == "no") ? false : true; 114 | 115 | // Get the mode from the commandline 116 | if (play_with_computer) 117 | { 118 | cout << "Do you want to play easy or hard or impossible mode?\n" 119 | "Please type easy or hard or impossible. " 120 | "Default option is hard. \n"; 121 | getline(cin, s); 122 | if (s == "easy") 123 | mode = "easy"; 124 | else if (s == "impossible") 125 | mode = "impossible"; 126 | else 127 | mode = "hard"; 128 | 129 | cout << "Do you want the computer to play first or second?\n" 130 | "Please type first or second. " 131 | "Default option is computer first. \n"; 132 | getline(cin, s); 133 | computer_first = (s == "second") ? false : true; 134 | } 135 | else 136 | { 137 | cout << "Please enter the dimenstion for the board.\n" 138 | "Default is 3.\n"; 139 | getline(cin, s); 140 | stringstream strStream(s); 141 | strStream >> ticTacToe_dim; 142 | if (ticTacToe_dim < 2) 143 | { 144 | cout << "Input dimenstion invalid, set to default 3\n"; 145 | ticTacToe_dim = 3; 146 | } 147 | } 148 | instance_ = new TicTacToeGame(ticTacToe_dim, ticTacToe_dim, 149 | black_or_white, "tictactoe", 150 | "T", 'X', 'O', computer_first, 151 | play_with_computer, mode); 152 | } 153 | } 154 | // if the instance already exist 155 | else 156 | throw instance_exist; 157 | } 158 | 159 | // instance method 160 | GameBase * GameBase ::instance() 161 | { 162 | if (instance_ != 0) 163 | return instance_; 164 | else 165 | throw instance_not_exist; 166 | } 167 | 168 | -------------------------------------------------------------------------------- /GameBase.h: -------------------------------------------------------------------------------- 1 | // GameBase.h 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 03/25/14. 4 | 5 | #ifndef GAME_BASE_H 6 | #define GAME_BASE_H 7 | 8 | class GameBase { 9 | 10 | public : 11 | GameBase(unsigned int h,unsigned int v,piece_color color, 12 | string name,string symbol); 13 | virtual ~GameBase() {}; 14 | virtual void print() = 0; 15 | // check whether the game is done 16 | virtual bool done() = 0; 17 | // prompt the user to input the value 18 | virtual void turn() = 0; 19 | // play the game by calling turn() 20 | virtual int play() = 0; 21 | // check the argument and creat the object 22 | static void check_create(int argc , char * argv[]); 23 | //retun the value of horizontal_dimension 24 | unsigned int get_horizontal_dimension() const; 25 | //retun the value of vertical_dimension 26 | unsigned int get_vertical_dimension() const; 27 | // initialize the board 28 | virtual void initialize_game() = 0; 29 | // initialize the board if the user doesn't save the previous game 30 | virtual void initialize_game_from_start() = 0; 31 | // instance method 32 | static GameBase * instance(); 33 | // save current state 34 | virtual void save_current_state() = 0; 35 | // abort the current state 36 | virtual void abort_current_state() = 0; 37 | 38 | protected : 39 | unsigned int horizontal_dimension; 40 | unsigned int vertical_dimension; 41 | piece_color color; 42 | string name; 43 | string symbol; 44 | unsigned int longest_string_length; 45 | static GameBase * instance_; 46 | 47 | }; 48 | 49 | #endif -------------------------------------------------------------------------------- /Games.cpp: -------------------------------------------------------------------------------- 1 | // Games.cpp 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 03/25/14. 4 | 5 | #include "OtherFunctions.h" 6 | #include "GameBase.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | // used to store the argv[] globely 15 | char ** argv_globle; 16 | // flag out whehter to return the last state 17 | int last_state = 0; // 0 means not to return 18 | 19 | int main(int argc, char * argv[]) 20 | { 21 | // indicating the condition of the game 22 | int play_condition = failure; 23 | argv_globle = argv; 24 | // creat objects according to users input 25 | GameBase * ptr = 0; 26 | try 27 | { 28 | GameBase::check_create(argc, argv); 29 | ptr = GameBase::instance(); 30 | } 31 | // check if the memory allocation is successful. 32 | catch(bad_alloc & ba) 33 | { 34 | cout << "Caught" << ba.what() << "exception" << endl; 35 | return bad_memory_allocation; 36 | } 37 | // check if the input value is valid 38 | catch(return_value & rv) 39 | { 40 | if (rv == instance_not_exist) 41 | { 42 | return call_usage_function();//return bad_command_line 43 | } 44 | else 45 | { 46 | return rv; // return instance_exist 47 | } 48 | 49 | } 50 | // use a smart pointer to point to the object, 51 | // it will delete automatically so we don't need to 52 | // delete it explicitly. 53 | shared_ptr g_ptr(ptr); 54 | // if an object of NineAlmondsGame or MagicSquareGame 55 | // or ReversiGame class is created, 56 | // the value of the pointer must not be zero and the object 57 | // which the pointer points to must be the instance. 58 | if (g_ptr.get() != 0) 59 | { 60 | //initialize the board 61 | try 62 | { 63 | g_ptr->initialize_game(); 64 | } 65 | catch(string s) 66 | { 67 | cout << s << endl;//cout the error 68 | cout << "The game is quit!" << endl; 69 | return invalid_file_state; 70 | } 71 | catch (...) 72 | { 73 | // Catch everything else 74 | cout << "Other exceptions are caught. " << endl; 75 | return other_exceptions; 76 | } 77 | 78 | // check whether a previous game is saved or not 79 | if(last_state == 0) 80 | { 81 | cout << "The initial state is: " << endl; 82 | } 83 | else 84 | { 85 | cout << "The last state before quitting is: " << endl; 86 | } 87 | 88 | // print the board just after initialization 89 | g_ptr->print(); 90 | try 91 | { 92 | // call the play function to play the game 93 | play_condition = g_ptr->play(); 94 | cout << endl; 95 | } 96 | 97 | // catches the quit exception 98 | catch(string &) 99 | { 100 | cout << "and the game quits." << endl; 101 | return quit_game; 102 | } 103 | catch (...) // Catch everything else 104 | { 105 | cout << "Other exceptions are caught. " << endl; 106 | return other_exceptions; 107 | } 108 | } 109 | return play_condition; 110 | } 111 | 112 | -------------------------------------------------------------------------------- /MagicSquare.txt: -------------------------------------------------------------------------------- 1 | MagicSquare 2 | E E E 3 | E E E 4 | 4 E E 5 | AVP_START 6 | 1 7 | 2 8 | 3 9 | 5 10 | 6 11 | 7 12 | 8 13 | 9 14 | AVP_END 15 | -------------------------------------------------------------------------------- /MagicSquareGame.cpp: -------------------------------------------------------------------------------- 1 | // MagicSquareGame.cpp 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 03/25/14. 4 | 5 | #include "OtherFunctions.h" 6 | #include "GameBase.h" 7 | #include "MagicSquareGame.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // globe value of argv[] 21 | extern char ** argv_globle; 22 | // flag out whehter to return the last state 23 | extern int last_state; // 0 means not to return 24 | 25 | // push function 26 | void MagicSquareGame::push_v (numbered_game_piece ngp) 27 | { 28 | v.push_back(ngp); 29 | } 30 | 31 | //set function 32 | void MagicSquareGame::set_v (unsigned int x,unsigned int y , 33 | numbered_game_piece ngp) 34 | { 35 | v[horizontal_dimension*y+x] = ngp; 36 | } 37 | 38 | // Define the initial state of the piece on the board 39 | // for initialize_game() function. 40 | // x_empty,y_empty is defined in other_functions.h 41 | numbered_game_piece empty_ngp(x_empty,y_empty,0); 42 | 43 | //Initialize the board 44 | void MagicSquareGame::initialize_game() 45 | { 46 | string first_line; // store the first line 47 | string board_line; // store the one line in the file 48 | string current_piece; // store the current piece 49 | int current_piece_value;// store the current piece value 50 | //=1 if it is needed to initialize game from start because the 51 | // file is edited without permission.Otherwise =0. 52 | string turn_s; // store the value of turn_times 53 | int flag_initialize_game_from_start=0; 54 | unsigned int avp_value; //store the value of avp_piece 55 | string check_avp; // store the flag of the trace 56 | string game_name = argv_globle[1]; 57 | string file_name = game_name + ".txt"; 58 | // first try to read from file 59 | ifstream infile (file_name.c_str()); 60 | if (infile.is_open ()) 61 | { 62 | infile >> first_line; 63 | } 64 | //1.initialize the piece on the MagicSquare set them all empty 65 | for(unsigned int i = get_vertical_dimension()-1; i+1 != 0; --i ) 66 | { 67 | for(unsigned int j = 0; j > current_piece; 84 | // check if there is a piece there 85 | if(current_piece != "E") 86 | { 87 | //change a string to an integer 88 | istringstream ( current_piece ) >> current_piece_value ; 89 | if (current_piece_value > 90 | int(horizontal_dimension*horizontal_dimension) || 91 | current_piece_value <1 ) 92 | { 93 | cout<<"The saved file has been edited without permission." << endl; 94 | cout<<"So, a new game will be initialized." << endl; 95 | initialize_game_from_start(); 96 | flag_initialize_game_from_start=1; 97 | break; 98 | } 99 | 100 | // set the current location with pieces 101 | set_v(j,i,numbered_game_piece(j,i,current_piece_value)); 102 | 103 | } 104 | } 105 | } 106 | //2. initialize the trace vector 107 | if (flag_initialize_game_from_start==0) 108 | { 109 | infile>>check_avp; 110 | // set the flag 111 | if(check_avp == "AVP_START") 112 | { 113 | while(infile.good()) 114 | { 115 | string piece_value; // store the value of coordinate 116 | //getline(ifs,piece_value); 117 | infile>>piece_value; 118 | if(piece_value == "AVP_END") 119 | { 120 | break; 121 | } 122 | istringstream coordinate_ss(piece_value); 123 | coordinate_ss >> avp_value; 124 | // store the game_piece to the file 125 | push_avp(numbered_game_piece(x_empty,y_empty,avp_value)); 126 | } 127 | } 128 | // set the last_state to 1 in order to change the print in main() 129 | last_state = 1; 130 | } 131 | 132 | } 133 | // do not read from file, initialize the board by default 134 | else 135 | { 136 | initialize_game_from_start(); 137 | } 138 | // close the file stream 139 | infile.close(); 140 | } 141 | 142 | void MagicSquareGame::initialize_game_from_start() 143 | { 144 | // initialize the avp 145 | for (int i=lowest_piece_val; 146 | i<=int(get_horizontal_dimension()*get_horizontal_dimension()) 147 | -(1-lowest_piece_val);++i) 148 | { 149 | push_avp(numbered_game_piece(x_empty,y_empty,i)); 150 | } 151 | } 152 | 153 | 154 | // Overloading the operator << for MagicSquare Game 155 | ostream &operator<< (ostream &out, const MagicSquareGame &m) 156 | { 157 | int piece_existing = 0; 158 | // store the value of the dimension 159 | unsigned int d = m.horizontal_dimension; 160 | for(unsigned int i = m.vertical_dimension-1; i +1 != 0; --i ) 161 | { 162 | // Draw the Y coordinate 163 | out<< i <<" "; 164 | // Print the board 165 | for(unsigned int j = 0; j < m.horizontal_dimension; ++j) 166 | { 167 | //check whether it is empty 168 | if (m.v[d*i+j] != empty_ngp) 169 | { 170 | // print out the symbol 171 | out<< setiosflags(ios_base::left) 172 | << setw(m.longest_string_length+1) << m.v[d*i+j].value; 173 | piece_existing = 1; 174 | } 175 | // If there is no piece there, print out the space 176 | if(piece_existing == 0) 177 | { 178 | cout << setiosflags(ios_base::left) 179 | << setw(m.longest_string_length+1) << " "; 180 | } 181 | piece_existing = 0; 182 | //change the line 183 | if(j == m.horizontal_dimension-1) 184 | { 185 | out<< endl; 186 | } 187 | } 188 | } 189 | // Draw the X coordinate 190 | out<<"X"<<" "; 191 | for(unsigned int j = 0; j < m.horizontal_dimension; ++j) 192 | { 193 | // Draw the X coordinate with the space between them 194 | out<< setiosflags(ios_base::left) 195 | << setw(m.longest_string_length+1) << j; 196 | } 197 | out << endl<< endl<< "Available pieces: "; 198 | // iterate through the available pieces 199 | vector ::const_iterator iter; 200 | for(iter = m.avp.begin(); iter != m.avp.end(); iter++ ) 201 | { 202 | out << iter->value << " "; 203 | } 204 | return out; 205 | } 206 | 207 | // print method 208 | void MagicSquareGame::print() 209 | { 210 | cout << endl <<*this<< endl<< endl; 211 | } 212 | 213 | //set function 214 | void MagicSquareGame::push_avp (numbered_game_piece ngp) 215 | { 216 | avp.push_back(ngp); 217 | } 218 | 219 | // check whether the game is done 220 | bool MagicSquareGame::done() 221 | { 222 | //int count_empty = 0; 223 | //int status = 0; // The status flag, 0 means not true 224 | int size = horizontal_dimension * vertical_dimension; 225 | for (int i = 0; i< size ; ++i) 226 | { 227 | // check if there is an empty piece 228 | if(v[i] == empty_ngp) 229 | { 230 | return false; 231 | } 232 | } 233 | 234 | //Compute magicNumber. If the lowest_piece_value=1,magicNumber=n(n^2+1)/2, where n 235 | // is the order of the magic number (from Wiki). 236 | //When the lowest_piece_value=i, the value of each piece is (1-i) smaller than 1. 237 | // So the magicNumber should be n(n^2+1)/2-(1-i)*n=(n^3-n+2n*i)/2. 238 | int magicNumber=(int(powf(double(horizontal_dimension),3.0))- 239 | horizontal_dimension+2*horizontal_dimension*lowest_piece_val)/2; 240 | 241 | // Compute the sum of each row, column and diagnoal. 242 | int * s_row=new int[vertical_dimension](); //s_row[i] is the sum of the i-th row 243 | int * s_column=new int[horizontal_dimension](); //s_column[i] is the sum of the i-th column 244 | int s_diagonal_LtR=0; //sum of the piece on the diagonal from top left to bottom right 245 | int s_diagonal_RtL=0; //sum of the piece on the diagonal from top right to bottom left 246 | 247 | //Compute s_row[] 248 | for (unsigned int j=0;j>temp) 361 | { 362 | count_string ++; 363 | } 364 | // check whether the input command line is valid and if the input is quit 365 | if(count_string == 1 && command_line == quit) 366 | { 367 | // check whether need to save the game 368 | cout << "Do you want to save the game? Enter \"yes\" to save the " 369 | "game and quit, enter \"no\" to quit without saving." << endl; 370 | // define viarbles 371 | string user_input; 372 | int user_input_valid = 0; 373 | int count_string_q = 0; 374 | string temp_q; 375 | // get the input from user 376 | // get the input from the input stream 377 | getline(cin,user_input); 378 | istringstream counts_q (user_input); 379 | // count the input string 380 | while(counts_q >> temp_q) 381 | { 382 | ++count_string_q; 383 | } 384 | while(user_input_valid != 1 || count_string_q !=1 ) 385 | { 386 | if (user_input == "yes" && count_string_q == 1) 387 | { 388 | // set user_input_valid to 1 to get out of the loop 389 | user_input_valid = 1; 390 | // save current state 391 | save_current_state(); 392 | cout << "The game has been saved, "; 393 | } 394 | else if(user_input == "no" && count_string_q == 1 ) 395 | { 396 | // set user_input_valid to 1 to get out of the loop 397 | user_input_valid = 1; 398 | // abort the current state 399 | abort_current_state(); 400 | cout << "The game has NOT been saved, "; 401 | } 402 | else 403 | { 404 | cout << "Input not correct, please input the command again." 405 | "Enter \"yes\" to save the game and quit, " 406 | "enter \"no\" to quit with saving. " << endl; 407 | getline(cin,user_input); 408 | count_string_q = 0; 409 | istringstream counts_q (user_input); 410 | // count the input string 411 | while(counts_q>>temp_q) 412 | { 413 | ++count_string_q; 414 | } 415 | } 416 | throw quit; 417 | return quit_game; 418 | } 419 | } 420 | // if the input is not quit 421 | else if(count_string == 2) 422 | { 423 | // convert command_line into istringstream 424 | istringstream cmd(command_line); 425 | cmd >> coordinate; 426 | // Check if there is comma in the begining or in the end 427 | if(coordinate[0] == ',' || coordinate[coordinate.length()-1] == ',') 428 | { 429 | command_valid = 0; 430 | } 431 | // Check how many comma there are and replace comma with white space 432 | for (unsigned int i = 0; i < coordinate.length(); ++i) 433 | { 434 | if (coordinate[i] == ',') 435 | { 436 | ++count_comma; 437 | coordinate[i] = ' '; 438 | } 439 | } 440 | //define iss as istringstream 441 | istringstream iss (coordinate); 442 | // check the input format and if it is correct, 443 | // assign the value to int &a, int &b, int &c 444 | if(count_comma == 1 && 445 | command_valid ==1 && 446 | iss >> m && iss >>n && cmd >> p) 447 | { 448 | //check the boundary 449 | if( m <= horizontal_dimension-1 && 450 | n<= vertical_dimension -1 && 451 | p<= int(horizontal_dimension * vertical_dimension) 452 | ) 453 | { 454 | //set value to those arguments. 455 | a = m; 456 | b = n; 457 | c = p; 458 | return success; 459 | } 460 | else 461 | { 462 | cout << "Error: The input coordinate is out of the " 463 | "boundary or the input value is out of range." << endl; 464 | cout <<" The coordinate x should <= "<< horizontal_dimension-1 465 | << " and y should <= "< ::iterator iter = avp.begin(); 490 | iter != avp.end(); iter++ ) 491 | { 492 | if(iter->value == piece_value) 493 | { 494 | // set the flag to one, if piece is found 495 | piece_found = 1; 496 | } 497 | } 498 | // check the format and get the input value 499 | while( (input_valid != success) || 500 | piece_found == 0 || 501 | (v[horizontal_dimension*position_y+position_x] != empty_ngp) ) 502 | { 503 | // check whether the input is valid 504 | if(input_valid != success) 505 | { 506 | cout << "Bad command line, Please input the coordinate position and the " 507 | "value of the available piece. For example: \"1,1 3\" or" 508 | " input \"quit\" to quit the game." << endl; 509 | input_valid = prompt(position_x,position_y,piece_value); 510 | // check whether there is the piece whose value is piece_value 511 | for(vector ::iterator iter = avp.begin(); 512 | iter != avp.end(); iter++ ) 513 | { 514 | if(iter->value == piece_value) 515 | { 516 | // set the flag to one 517 | piece_found = 1; 518 | } 519 | } 520 | } 521 | // check whether the position on the board is empty 522 | else if(v[horizontal_dimension*position_y+position_x] != empty_ngp) 523 | { 524 | cout << "The current position is not EMPTY. Please input the coordinate " 525 | "position and the value of the available piece. " 526 | "For example: \"1,1 3\" or input \"quit\" to quit the game." << endl; 527 | input_valid = prompt(position_x,position_y,piece_value); 528 | // check whether there is the piece whose value is piece_value 529 | for(vector ::iterator iter = avp.begin(); 530 | iter != avp.end(); iter++ ) 531 | { 532 | if(iter->value == piece_value) 533 | { 534 | // set the flag to one 535 | piece_found = 1; 536 | } 537 | } 538 | } 539 | else // check whether there is the piece whose value is piece_value 540 | { 541 | cout << "There is NO piece which value is "<< piece_value 542 | << " in the available piece list. ""Please input the coordinate" 543 | " position and the value of the available piece. For " 544 | "example: \"1,1 3\" or input \"quit\" to quit the game." << endl; 545 | input_valid = prompt(position_x,position_y,piece_value); 546 | // check whether there is the piece whose value is piece_value 547 | for(vector ::iterator iter = avp.begin(); 548 | iter != avp.end(); iter++ ) 549 | { 550 | if(iter->value == piece_value) 551 | { 552 | // set the flag to one 553 | piece_found = 1; 554 | } 555 | } 556 | } 557 | } 558 | // update the board 559 | v[horizontal_dimension*position_y+position_x].x = position_x; 560 | v[horizontal_dimension*position_y+position_x].y = position_y; 561 | v[horizontal_dimension*position_y+position_x].value = piece_value; 562 | find_display_length(piece_value); 563 | // delete the vector in the available piece list 564 | int i = 0; 565 | for(vector ::iterator iter = avp.begin(); 566 | iter != avp.end(); iter++ ) 567 | { 568 | if(iter->value == piece_value) 569 | { 570 | break; 571 | } 572 | ++i; 573 | } 574 | // delete the vector in the available piece list 575 | avp.erase(avp.begin()+i); 576 | // print out the gameboard and each piece on the board 577 | // by calling print() function 578 | print(); 579 | } 580 | 581 | // Update longest_string_length 582 | void MagicSquareGame::find_display_length(int piece_value) 583 | { 584 | string piece_value_str; 585 | stringstream iss; 586 | iss << piece_value; 587 | piece_value_str = iss.str(); 588 | unsigned int piece_value_length = piece_value_str.length(); 589 | if (piece_value_length>longest_string_length) 590 | { 591 | longest_string_length = piece_value_length; 592 | } 593 | } 594 | 595 | // check whether the user finished inputing, 596 | // return ture if there is empty sapce for input 597 | bool MagicSquareGame::check_is_empty() 598 | { 599 | int size = horizontal_dimension * vertical_dimension; 600 | for (int i = 0; i< size ; ++i) 601 | { 602 | // check if there is an empty piece 603 | if(v[i] == empty_ngp) 604 | { 605 | return true; 606 | } 607 | } 608 | return false; 609 | } 610 | 611 | // save the current state 612 | void MagicSquareGame::save_current_state() 613 | { 614 | // make the file name 615 | string game_name = argv_globle[1]; 616 | string file_name = game_name + ".txt"; 617 | // write to the files 618 | ofstream ofs (file_name.c_str()); 619 | if (ofs.is_open ()) 620 | { 621 | ofs << game_name << endl; 622 | // 1. store the board state 623 | int piece_existing = 0; 624 | // store the value of the dimension 625 | unsigned int d = horizontal_dimension; 626 | for(unsigned int i = vertical_dimension-1; i+1 != 0; --i ) 627 | { 628 | // Print the board 629 | for(unsigned int j = 0; j < horizontal_dimension; ++j) 630 | { 631 | //check whether it is empty 632 | if (v[d*i+j] != empty_ngp) 633 | { 634 | // print out the symbol 635 | ofs << setiosflags(ios_base::left) 636 | << setw(longest_string_length+1) << v[d*i+j].value; 637 | piece_existing = 1; 638 | } 639 | // If there is no piece there, print out the the symbol E 640 | if(piece_existing == 0) 641 | { 642 | ofs << setiosflags(ios_base::left) 643 | << setw(longest_string_length+1) << "E"; 644 | } 645 | piece_existing = 0; 646 | //change the line 647 | if(j == horizontal_dimension-1) 648 | { 649 | ofs<< endl; 650 | } 651 | } 652 | } 653 | // insert the symbol in the file 654 | ofs << "AVP_START" << endl; 655 | // iterate through the available pieces 656 | for(vector ::const_iterator iter = avp.begin(); 657 | iter != avp.end(); iter++ ) 658 | { 659 | ofs << iter->value << endl ; 660 | } 661 | // insert the symbol in the file 662 | ofs << "AVP_END" << endl; 663 | } 664 | // close the file 665 | ofs.close(); 666 | } 667 | 668 | // abort the current state 669 | void MagicSquareGame ::abort_current_state() 670 | { 671 | // make the file name 672 | string information = "NO DATA"; 673 | string game_name = argv_globle[1]; 674 | string file_name = game_name + ".txt"; 675 | // write to the files 676 | ofstream ofs (file_name.c_str()); 677 | if (ofs.is_open ()) 678 | { 679 | ofs << information << endl; 680 | } 681 | // close the file 682 | ofs.close(); 683 | } 684 | -------------------------------------------------------------------------------- /MagicSquareGame.h: -------------------------------------------------------------------------------- 1 | // MagicSquareGame.h 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 03/25/14. 4 | 5 | #ifndef MAGIC_SQUAREGAME_H 6 | #define MAGIC_SQUAREGAME_H 7 | 8 | class MagicSquareGame : public GameBase { 9 | 10 | friend ostream &operator<<(ostream &out, const MagicSquareGame &m); 11 | 12 | public: 13 | MagicSquareGame(unsigned int h, unsigned int v, piece_color color, 14 | string name, string symbol, int lowest_piece_val_ =1) 15 | :GameBase(h, v, color, name, symbol), 16 | lowest_piece_val(lowest_piece_val_){}; 17 | 18 | virtual ~MagicSquareGame() {}; 19 | //set function 20 | virtual void initialize_game(); 21 | virtual void initialize_game_from_start(); 22 | //set function 23 | virtual void push_v (numbered_game_piece ngp); 24 | //set function 25 | virtual void set_v (unsigned int x,unsigned int , 26 | numbered_game_piece ngp); 27 | // check whether the game is done 28 | virtual bool done(); 29 | // prompt the user to input the value 30 | virtual int prompt(unsigned int &a, unsigned int &b, int &c); 31 | // check and make a valid move in the game 32 | virtual void turn(); 33 | // the play method 34 | virtual int play(); 35 | // the print method 36 | virtual void print(); 37 | // set function 38 | virtual void push_avp (numbered_game_piece ngp); 39 | // Update longest_string_length 40 | virtual void find_display_length(int); 41 | // check whether the user finished inputing, 42 | // return ture if there is empty sapce for input 43 | virtual bool check_is_empty(); 44 | // save the current state 45 | virtual void save_current_state(); 46 | // abort the current state 47 | virtual void abort_current_state(); 48 | 49 | protected: 50 | // hold the game pieces, it represents the gameboard, 51 | // the index corresponds to the position of the board 52 | vector v; 53 | // store the vector of the available piece list 54 | vector avp; 55 | int lowest_piece_val; 56 | }; 57 | 58 | #endif -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for Games 3 | # Modified by Zheng Luo on 03/25/14. 4 | 5 | ############################################################## 6 | # Compiler and flags to use 7 | ############################################################## 8 | 9 | CXX = g++ 10 | CXXFLAGS = -g -Wall -Werror -std=c++11 11 | 12 | ############################################################## 13 | # You shouldn't have to change anything below this line. 14 | ############################################################## 15 | 16 | GAMES_EXE = Games 17 | GAMES_OBJS = Games.o GameBase.o \ 18 | CheckersGame.o ChessGame.o ChessDesign.o \ 19 | NineAlmondsGame.o MagicSquareGame.o ReversiGame.o \ 20 | TicTacToeBase.o TicTacToeGame.o TicTacToeState.o \ 21 | OtherFunctions.o 22 | 23 | ### 24 | 25 | $(GAMES_EXE): $(GAMES_OBJS) 26 | $(CXX) $(CXXFLAGS) -o $@ $(GAMES_OBJS) 27 | 28 | clean: 29 | rm -f $(GAMES_EXE) $(GAMES_OBJS) 30 | 31 | 32 | ### 33 | 34 | .cpp.o: 35 | $(CXX) $(CXXFLAGS) -c $< 36 | 37 | ### 38 | 39 | CheckersGame.o: CheckersGame.cpp CheckersGame.h \ 40 | OtherFunctions.cpp OtherFunctions.h GameBase.h 41 | 42 | ChessGame.o: ChessGame.cpp ChessGame.h \ 43 | ChessDesign.h OtherFunctions.h GameBase.h 44 | 45 | NineAlmondsGame.o: NineAlmondsGame.cpp NineAlmondsGame.h \ 46 | OtherFunctions.h GameBase.h 47 | 48 | MagicSquareGame.o: MagicSquareGame.cpp MagicSquareGame.h \ 49 | OtherFunctions.h GameBase.h 50 | 51 | ReversiGame.o: ReversiGame.cpp ReversiGame.h \ 52 | OtherFunctions.h GameBase.h 53 | 54 | TicTacToeBase.o: TicTacToeBase.cpp TicTacToeBase.h 55 | 56 | TicTacToeGame.o: TicTacToeBase.cpp TicTacToeBase.h \ 57 | TicTacToeState.h TicTacToeGame.h OtherFunctions.h GameBase.h 58 | 59 | TicTacToeState.o: TicTacToeState.cpp TicTacToeState.h 60 | 61 | OtherFunctions.o: OtherFunctions.cpp OtherFunctions.h 62 | 63 | GameBase.o: GameBase.cpp GameBase.h \ 64 | OtherFunctions.h CheckersGame.h ChessGame.h NineAlmondsGame.h MagicSquareGame.h ReversiGame.h TicTacToeGame.h 65 | 66 | Games.o: Games.cpp GameBase.h 67 | -------------------------------------------------------------------------------- /NineAlmonds.txt: -------------------------------------------------------------------------------- 1 | NineAlmonds 2 | E E E E E 3 | E A A A E 4 | E A E E A 5 | E A A A E 6 | E E E E E 7 | 0 8 | START TRACE 9 | 2 2 10 | 4 2 11 | END TRACE 12 | -------------------------------------------------------------------------------- /NineAlmondsGame.cpp: -------------------------------------------------------------------------------- 1 | // NineAlmondsGame.cpp 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 03/25/14. 4 | 5 | #include "OtherFunctions.h" 6 | #include "GameBase.h" 7 | #include "NineAlmondsGame.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | // globe value of argv[] 20 | extern char ** argv_globle; 21 | // store the continues move in file 22 | vector trace_store_file; 23 | // store the value of turn time 24 | int turn_times = 0; 25 | // tracing flag , indicate whether to initialize the tracing vector 26 | int tracing_flag = 0; 27 | // store the value reading from file 28 | vector trace_read_from_file; 29 | // flag out whehter to return the last state 30 | extern int last_state; // 0 means not to return 31 | 32 | //constructor of NineAlmondsGame 33 | NineAlmondsGame::NineAlmondsGame(unsigned int h,unsigned int v, 34 | piece_color color,string name, 35 | string symbol) 36 | :GameBase( h, v, color, name, symbol) {} 37 | 38 | // Define the initial state of the piece on the board for initialize_game() 39 | // function. x_empty,y_empty is defined in other_functions.h 40 | game_piece empty(x_empty,y_empty); 41 | 42 | 43 | //Initialize the board 44 | void NineAlmondsGame::initialize_game() 45 | { 46 | string first_line; // store the first line 47 | string board_line; // store the one line in the file 48 | string current_piece; // store the current piece 49 | string turn_s; // store the value of turn_times 50 | string x_s,y_s; //store the value of coordinate 51 | unsigned int x_,y_; //store the value of coordinate 52 | string check_trace_1; // store the flag of the trace 53 | string check_trace_2; // store the flag of the trace 54 | //=1 if it is needed to initialize game from start because 55 | // the file is edited without permission.Otherwise =0. 56 | int flag_initialize_game_from_start=0; 57 | string game_name = argv_globle[1]; 58 | string file_name = game_name + ".txt"; 59 | // first try to read from file 60 | ifstream ifs (file_name.c_str()); 61 | if (ifs.is_open ()) 62 | { 63 | ifs>>first_line; 64 | } 65 | //1.initialize the piece on the NineAlmondsGame 66 | for(unsigned int i = get_vertical_dimension()-1; i +1 != 0; --i ) 67 | { 68 | for(unsigned int j = 0; j < get_horizontal_dimension(); ++j) 69 | { 70 | push_v(empty); 71 | } 72 | } 73 | // initialize the board with saved value from the file 74 | if(first_line == game_name) 75 | { 76 | 77 | // iterate through the board 78 | for(unsigned int i = get_vertical_dimension()-1; i+1!= 0; --i ) 79 | { 80 | // read the board information 81 | // iterate through each piece on the line 82 | for(unsigned int j = 0; j < get_horizontal_dimension(); ++j) 83 | { 84 | // extract the value from each pieces 85 | ifs >> current_piece; 86 | // check if the state is valid (check if the symbol 87 | // has been edited without permission) 88 | if(current_piece != "A" && current_piece != "E" ) 89 | { 90 | cout<<"The saved file has been edited without permission." << endl; 91 | cout<<"So, a new game will be initialized." << endl; 92 | initialize_game_from_start(); 93 | flag_initialize_game_from_start=1; 94 | break; 95 | } 96 | // check if there is a piece there 97 | if(current_piece == "A" && flag_initialize_game_from_start==0) 98 | { 99 | // set the current location with pieces 100 | set_v(j,i,game_piece(j,i)); 101 | } 102 | } 103 | } 104 | 105 | //2. initialize the turn_times; 106 | if (flag_initialize_game_from_start==0) 107 | { 108 | ifs>> turn_times; 109 | //3. initialize the trace vector 110 | ifs>>check_trace_1; 111 | ifs>>check_trace_2; 112 | string check_trace = check_trace_1+check_trace_2; 113 | // set the flag 114 | if(check_trace!= "NO TRACE") 115 | //if(strcmp (check_trace_1,"NO") != 0 && 116 | //strcmp (check_trace_2,"TRACE") != 0) 117 | { 118 | // set the flag to 1, in order to read in the turn() 119 | tracing_flag = 1; 120 | while(ifs.good()) 121 | { 122 | ifs >> x_s ;// store the value of coordinate 123 | ifs >> y_s; 124 | if( x_s == "END" && y_s== "TRACE") 125 | { 126 | break; 127 | } 128 | 129 | // store the game_piece to the file 130 | istringstream(x_s)>>x_; 131 | istringstream(y_s)>>y_; 132 | trace_read_from_file.push_back(game_piece(x_,y_)); 133 | } 134 | } 135 | // set the last_state to 1 in order to change the print in main() 136 | last_state = 1; 137 | } 138 | 139 | } 140 | // do not read from file, initialize the board by default 141 | else 142 | { 143 | initialize_game_from_start(); 144 | } 145 | // close the file stream 146 | ifs.close(); 147 | } 148 | 149 | void NineAlmondsGame::initialize_game_from_start() 150 | { 151 | // clear the board 152 | for(unsigned int i = get_vertical_dimension()-1; i+1!= 0; --i ) 153 | { 154 | for(unsigned int j = 0; j < get_horizontal_dimension(); ++j) 155 | { 156 | set_v(j,i,empty); 157 | } 158 | } 159 | // initiallize the pieces on the board 160 | set_v(1,1,game_piece(1,1)); 161 | set_v(2,1,game_piece(2,1)); 162 | set_v(3,1,game_piece(3,1)); 163 | set_v(1,2,game_piece(1,2)); 164 | set_v(2,2,game_piece(2,2)); 165 | set_v(3,2,game_piece(3,2)); 166 | set_v(1,3,game_piece(1,3)); 167 | set_v(2,3,game_piece(2,3)); 168 | set_v(3,3,game_piece(3,3)); 169 | } 170 | 171 | //set function 172 | void NineAlmondsGame::push_v (game_piece gp) 173 | { 174 | v.push_back(gp); 175 | } 176 | 177 | //set function 178 | void NineAlmondsGame::set_v (unsigned int x,unsigned int y ,game_piece gp) 179 | { 180 | v[horizontal_dimension*y+x] = gp; 181 | } 182 | 183 | // check whether the game is done 184 | bool NineAlmondsGame::done() 185 | { 186 | int count_empty = 0; 187 | int status = 0; // The status flag, 0 means not true 188 | int size = horizontal_dimension * vertical_dimension; 189 | for (int i = 0; i< size ; ++i) 190 | { 191 | // check if there is a piece on the board not in the middle 192 | if(i != 12 && v[i] == empty) 193 | { 194 | ++count_empty; 195 | } 196 | // check if there is a piece on the board in the middle 197 | if(i == 12 && v[i] != empty) 198 | { 199 | status = 1; 200 | } 201 | } 202 | if(status == 1 && count_empty == 24) 203 | { 204 | return true; 205 | } 206 | else 207 | { 208 | return false; 209 | } 210 | } 211 | 212 | // check and make a valid move in the game 213 | void NineAlmondsGame::turn() 214 | { 215 | unsigned int d = horizontal_dimension;// the dimenstion of the board 216 | unsigned int current_position_x = 0;// the position of the current selected almond 217 | unsigned int current_position_y = 0;// the position of the current selected almond 218 | unsigned int move_to_x = 0;// the position where the user wants to move 219 | unsigned int move_to_y = 0;// the position where the user wants to move 220 | int input_valid = 1; // 0 means valid, 1 means invalid 221 | int distance_square = 0; // calculate distance between two points 222 | int middle_point_x = 0; // calculate middle point two points 223 | int middle_point_y = 0; // calculate middle point two points 224 | int module_x = 0; // check the module value 225 | int module_y = 0; // check the module value 226 | int move_times = 0; // record the time of move 227 | vector trace; 228 | string quit = "quit"; 229 | string whether_to_conitue = "continue"; 230 | // the flag used to indicate whether to continue, 0 means false, 1 means true 231 | // print the trace_read_from_file vector which is used to store the value 232 | // and restore the trace vector 233 | if(tracing_flag == 1) 234 | { 235 | // set the move_times to 0 236 | move_times = 1; 237 | //print out of the record of the moving 238 | for(vector::iterator iter = trace_read_from_file.begin(); 239 | iter != trace_read_from_file.end(); ++iter) 240 | { 241 | if(iter != trace_read_from_file.end()-1) 242 | { 243 | //print the move 244 | cout << iter->x <<","<y<<" to "; 245 | } 246 | else 247 | { 248 | //print the move 249 | cout << iter->x <<","<y<< endl; 250 | // assign the value to the positions 251 | current_position_x = iter->x; 252 | current_position_y = iter->y; 253 | } 254 | } 255 | //store the value and restore the trace vector 256 | trace = trace_read_from_file; 257 | // assign value of trace to the trace_store_file 258 | trace_store_file = trace; 259 | // if the tracing_flag is 0, means the turn does not need to continue 260 | } 261 | else 262 | { 263 | cout <<"Please select an almond by specifying its " 264 | "coordinate position or quit. " << endl; 265 | // prompt the user to input the value 266 | input_valid = prompt(current_position_x,current_position_y); 267 | // check whether the current posisiton is empty and check whether the input is valid 268 | while((input_valid != success) || 269 | (v[d*current_position_y+current_position_x] == empty) ) 270 | { 271 | // check whether the input is valid 272 | if(input_valid != success) 273 | { 274 | cout<<"Bad command line, please select a almond by specifying " 275 | "its coordinate position, for example: \"0,0\" or " 276 | "input \"quit\" to quit the game." << endl; 277 | input_valid = prompt(current_position_x,current_position_y); 278 | } 279 | else // check whether the input is empty 280 | { 281 | cout<<"The current position is EMPTY, please re-select a " 282 | "almond by specifying its coordinate position." << endl; 283 | input_valid = prompt(current_position_x,current_position_y); 284 | } 285 | } 286 | } 287 | // check whether_to_continue 288 | while (whether_to_conitue != "end") 289 | { 290 | if(tracing_flag == 0) 291 | { 292 | // prompt the user to input the destination 293 | cout << "Please select a destination by specifying " 294 | "its coordinate position." << endl; 295 | input_valid = prompt(move_to_x,move_to_y); 296 | //check whether the input is quit_turn 297 | if (input_valid == quit_turn) 298 | { 299 | break; 300 | } 301 | // check whether the current posisiton is empty and 302 | // check whether the input is valid 303 | while((input_valid != success) || (v[d*move_to_y+move_to_x] != empty) ) 304 | { 305 | // check whether the input is valid 306 | if(input_valid != success) 307 | { 308 | cout<<"Bad command line, please select a destination by specifying " 309 | "its coordinate position, for example: \"0,0\" or input \"quit\" to " 310 | "quit the game or \"quit_turn\" to quit the turn\"." << endl; 311 | input_valid = prompt(move_to_x,move_to_y); 312 | //check whether the input is quit_turn 313 | if (input_valid == quit_turn) 314 | { 315 | break; 316 | } 317 | } 318 | else // check whether the input is not empty 319 | { 320 | cout << "The destination position is NOT empty, " 321 | "please re-select a destination " 322 | "by specifying its coordinate position." << endl; 323 | input_valid = prompt(move_to_x,move_to_y); 324 | //check whether the input is quit_turn 325 | if (input_valid == quit_turn) 326 | { 327 | break; 328 | } 329 | } 330 | } 331 | //check whether the input is quit_turn 332 | if (input_valid == quit_turn) 333 | { 334 | break; 335 | } 336 | // calculate the distance square 337 | distance_square = (current_position_x - move_to_x) * 338 | (current_position_x - move_to_x) + 339 | (current_position_y - move_to_y) * 340 | (current_position_y - move_to_y); 341 | //calculate the module 342 | module_x = (current_position_x + move_to_x) % 2; 343 | module_y = (current_position_y + move_to_y) % 2; 344 | //calculate the middle point 345 | middle_point_x = (current_position_x + move_to_x) / 2; 346 | middle_point_y = (current_position_y + move_to_y) / 2; 347 | // check whether this is a valid move 348 | if((distance_square <= 8) && 349 | (module_x == 0) && 350 | (module_y == 0) && 351 | (v[d*middle_point_y+middle_point_x] != empty)) 352 | { 353 | // delete the almond been jumped 354 | v[d*middle_point_y+middle_point_x] = empty; 355 | // delete the almond where it jumped from 356 | v[d*current_position_y+current_position_x] = empty; 357 | // move a almond to the new destination 358 | v[d*move_to_y+move_to_x] = game_piece(move_to_x,move_to_y); 359 | // record the input value 360 | if (move_times == 0) 361 | { 362 | trace.push_back(game_piece(current_position_x, 363 | current_position_y)); 364 | } 365 | trace.push_back(game_piece(move_to_x,move_to_y)); 366 | // assign value of trace to the trace_store_file 367 | if(tracing_flag == 0) 368 | { 369 | trace_store_file = trace; 370 | } 371 | // set the position to the current almond 372 | current_position_x = move_to_x; 373 | current_position_y = move_to_y; 374 | // set the flag of move times 375 | move_times = 1; 376 | } 377 | else 378 | { 379 | cout <<"This is not valid move." << endl; 380 | } 381 | // print out the gameboard and each piece on the 382 | // board by calling print() function 383 | print(); 384 | //print out of the record of the moving 385 | for(vector::iterator iter = trace.begin(); 386 | iter != trace.end(); ++iter) 387 | { 388 | if(iter != trace.end()-1) 389 | { 390 | //print the move 391 | cout << iter->x <<","<y<<" to "; 392 | } 393 | else 394 | { 395 | //print the move 396 | cout << iter->x <<","<y<< endl; 397 | } 398 | } 399 | } 400 | // check if the game can not continue or it has finished 401 | if(done()!= true && no_valid_move(v) == false) 402 | { 403 | cout << endl << "Enter \"continue\" to continue to make " 404 | "additional valid jumps " 405 | "with the same almond during this turn and " 406 | "enter \"end\" to quit this turn"<< 407 | " or \"quit\" to quit the game." << endl; 408 | // get the value of whether_to_conitue 409 | getline(cin,whether_to_conitue); 410 | // check the value of whether_to_conitue is valid 411 | while((whether_to_conitue != "continue") && 412 | (whether_to_conitue !="end") && 413 | (whether_to_conitue !="quit")) 414 | { 415 | cout << "Input is invalid, enter \"continue\" to continue to make " 416 | "additional valid jumps with the same almond during " 417 | "this turn and enter \"end\"" 418 | " to quit this turn or \"quit\" to quit the game." << endl; 419 | getline(cin,whether_to_conitue); 420 | } 421 | // print the last jumped almomd, because we can only continue to move 422 | // the last moved almond 423 | if(whether_to_conitue == "continue") 424 | { 425 | cout << "The current position of last jumped almond is (" 426 | << current_position_x<<"," 427 | << current_position_y<<")." << endl; 428 | } 429 | else if(whether_to_conitue == "quit") 430 | { 431 | // check whehter need to save the game 432 | cout << "Do you want to save the game? Enter \"yes\" to " 433 | "save the game and quit, " 434 | "enter \"no\" to quit with saving." << endl; 435 | // define viarbles 436 | string user_input; 437 | int user_input_valid = 0; 438 | int count_string_q = 0; 439 | string temp_q; 440 | // get the input from user 441 | // get the input from the input stream 442 | getline(cin,user_input); 443 | istringstream counts_q (user_input); 444 | // count the input string 445 | while(counts_q >> temp_q) 446 | { 447 | ++count_string_q; 448 | } 449 | while(user_input_valid != 1 || count_string_q !=1 ) 450 | { 451 | if (user_input == "yes" && count_string_q == 1) 452 | { 453 | // set user_input_valid to 1 to get out of the loop 454 | user_input_valid = 1; 455 | // save current state 456 | save_current_state(); 457 | cout << "The game has been saved, "; 458 | } 459 | else if(user_input == "no" && count_string_q == 1 ) 460 | { 461 | // set user_input_valid to 1 to get out of the loop 462 | user_input_valid = 1; 463 | // abort the current state 464 | abort_current_state(); 465 | cout << "The game has NOT been saved, "; 466 | } 467 | else 468 | { 469 | cout <<"Input not correct, please input the command again." 470 | "Enter \"yes\" to save the game and quit, enter \"no\" to " 471 | "quit with saving. " << endl; 472 | getline(cin,user_input); 473 | count_string_q = 0; 474 | istringstream counts_q (user_input); 475 | // count the input string 476 | while(counts_q>>temp_q) 477 | { 478 | ++count_string_q; 479 | } 480 | } 481 | } 482 | throw quit; 483 | } 484 | } 485 | else 486 | { 487 | break; 488 | } 489 | // set the flag to 0 490 | tracing_flag = 0; 491 | } 492 | // if it is end of the turn, clear trace_store_file 493 | trace_store_file.clear(); 494 | } 495 | 496 | // Overloading the operator << for NineAlmonds Game 497 | ostream &operator<< (ostream &out, const NineAlmondsGame &n) 498 | { 499 | //define the empty piece 500 | int piece_existing = 0; 501 | // store the value of the dimension 502 | unsigned int d = n.horizontal_dimension; 503 | for(unsigned int i = n.vertical_dimension-1; i+1!= 0; --i ) 504 | { 505 | // Draw the Y coordinate 506 | out<< i<<" "; 507 | // Print the board 508 | for(unsigned int j = 0; j < n.horizontal_dimension; ++j) 509 | { 510 | //check whether it is empty 511 | if (n.v[d*i+j] != empty) 512 | { 513 | // print out the symbol 514 | out << setiosflags(ios_base::left) 515 | << setw(n.longest_string_length+1) << n.symbol; 516 | piece_existing = 1; 517 | } 518 | // If there is no piece there, print out the space 519 | if(piece_existing == 0) 520 | { 521 | cout << setiosflags(ios_base::left) 522 | << setw(n.longest_string_length+1) << " "; 523 | } 524 | piece_existing = 0; 525 | //change the line 526 | if(j == n.horizontal_dimension-1) 527 | { 528 | out<< endl; 529 | } 530 | } 531 | } 532 | // Draw the X coordinate 533 | out<<"X"<<" "; 534 | for(unsigned int j = 0; j < n.horizontal_dimension; ++j) 535 | { 536 | // Draw the X coordinate with the space between them 537 | out<< setiosflags(ios_base::left) 538 | << setw(n.longest_string_length+1) << j; 539 | } 540 | return out; 541 | } 542 | 543 | // print method 544 | void NineAlmondsGame::print() 545 | { 546 | cout << endl <<*this<< endl<< endl; 547 | } 548 | 549 | // play the game by calling turn() 550 | int NineAlmondsGame::play() 551 | { 552 | int no_move = 0; 553 | while(done()!= true) 554 | { 555 | // check if there is valid move 556 | if(no_valid_move(v)) 557 | { 558 | no_move = 1; 559 | break; 560 | } 561 | // call the function turn() 562 | turn(); 563 | 564 | // increment the turn_times 565 | ++turn_times; 566 | } 567 | if(no_move == 0) 568 | { 569 | cout << "Congratulations! You finish the game. It takes " 570 | << turn_times <<" turns to complete the game." << endl; 571 | // overwrite the game's file to let the game start from the 572 | // beginning next time. 573 | abort_current_state(); 574 | return success; 575 | } 576 | else 577 | { 578 | cout<<"Sorry, the game is failed, because " 579 | "there are no more valid moves." << endl; 580 | // overwrite the game's file to let the game start from the 581 | // beginning next time. 582 | abort_current_state(); 583 | return no_more_valid_move; 584 | } 585 | } 586 | 587 | // check if there will be valid move of the pieces 588 | bool NineAlmondsGame::no_valid_move(vector board_state) 589 | { 590 | unsigned int d = horizontal_dimension; 591 | // iterate the board to find pieces 592 | for(unsigned int i = vertical_dimension-1; i+1!= 0; --i ) 593 | { 594 | for(unsigned int j = 0; j < horizontal_dimension; ++j) 595 | { 596 | //check whether it is empty 597 | if (board_state[d*i+j] != empty) 598 | { 599 | // a move may have 8 directions 600 | //case #1 601 | if( i<=2 && j>=2) 602 | { 603 | if(board_state[d*(i+2)+(j-2)] == empty && 604 | board_state[d*(i+1)+(j-1)] != empty 605 | ) 606 | { 607 | return false; 608 | } 609 | } 610 | 611 | // a move may have 8 directions 612 | //case #2 613 | if(i<=2) 614 | { 615 | if(board_state[d*(i+2)+j] == empty && 616 | board_state[d*(i+1)+j] != empty 617 | ) 618 | { 619 | return false; 620 | } 621 | } 622 | 623 | // a move may have 8 directions 624 | //case #3 625 | if((i<=2) && (j<=2)) 626 | { 627 | if(board_state[d*(i+2)+(j+2)] == empty && 628 | board_state[d*(i+1)+(j+1)] != empty 629 | ) 630 | { 631 | return false; 632 | } 633 | } 634 | 635 | // a move may have 8 directions 636 | //case #4 637 | if(j>=2) 638 | { 639 | if(board_state[d*i+(j-2)] == empty && 640 | board_state[d*i+(j-1)] != empty 641 | ) 642 | { 643 | return false; 644 | } 645 | } 646 | 647 | // a move may have 8 directions 648 | //case #d 649 | if(j<=2) 650 | { 651 | if(board_state[d*i+(j+2)] == empty && 652 | board_state[d*i+(j+1)] != empty 653 | ) 654 | { 655 | return false; 656 | } 657 | } 658 | 659 | // a move may have 8 directions 660 | //case #6 661 | if(j>=2 && i>=2 ) 662 | { 663 | if(board_state[d*(i-2)+(j-2)] == empty && 664 | board_state[d*(i-1)+(j-1)] != empty 665 | ) 666 | { 667 | return false; 668 | } 669 | } 670 | 671 | // a move may have 8 directions 672 | //case #7 673 | if(i>=2) 674 | { 675 | if(board_state[d*(i-2)+j] == empty && 676 | board_state[d*(i-1)+j] != empty 677 | ) 678 | { 679 | return false; 680 | } 681 | } 682 | 683 | // a move may have 8 directions 684 | //case #8 685 | if(i>=2 && j<=2) 686 | { 687 | if(board_state[d*(i-2)+(j+2)] == empty && 688 | board_state[d*(i-1)+(j+2)] != empty 689 | ) 690 | { 691 | return false; 692 | } 693 | } 694 | } 695 | } 696 | } 697 | return true; 698 | } 699 | 700 | // prompt function 701 | int NineAlmondsGame::prompt(unsigned int &a, unsigned int &b) 702 | { 703 | int count_string = 0; 704 | int count_comma = 0; 705 | int command_valid = 1; 706 | string quit = "quit"; 707 | string command_line; 708 | string command_original; 709 | string temp; 710 | unsigned int m; // temporarily storing the integer value of commandline 711 | unsigned int n; // temporarily storing the integer value of commandline 712 | // get the input from the input stream 713 | getline(cin,command_line); 714 | command_original = command_line; 715 | istringstream counts (command_original); 716 | // count the input string 717 | while(counts>>temp) 718 | { 719 | count_string ++; 720 | } 721 | // check whether the input command line is valid 722 | if(count_string == 1) 723 | { 724 | // if the input is quit 725 | if (command_line == quit) 726 | { 727 | // check whehter need to save the game 728 | cout <<"Do you want to save the game? Enter \"yes\" to save the " 729 | "game and quit, enter \"no\" to quit without saving." << endl; 730 | // define viarbles 731 | string user_input; 732 | int user_input_valid = 0; 733 | int count_string_q = 0; 734 | string temp_q; 735 | // get the input from user 736 | // get the input from the input stream 737 | getline(cin,user_input); 738 | istringstream counts_q (user_input); 739 | // count the input string 740 | while(counts_q >> temp_q) 741 | { 742 | ++count_string_q; 743 | } 744 | while(user_input_valid != 1 || count_string_q !=1 ) 745 | { 746 | if (user_input == "yes" && count_string_q == 1) 747 | { 748 | // set user_input_valid to 1 to get out of the loop 749 | user_input_valid = 1; 750 | // save current state 751 | save_current_state(); 752 | cout << "The game has been saved, "; 753 | } 754 | else if(user_input == "no" && count_string_q == 1 ) 755 | { 756 | // set user_input_valid to 1 to get out of the loop 757 | user_input_valid = 1; 758 | // abort the current state 759 | abort_current_state(); 760 | cout << "The game has NOT been saved, "; 761 | } 762 | else 763 | { 764 | cout <<"Input not correct, please input the command again." 765 | "Enter \"yes\" to save the game and quit, " 766 | "enter \"no\" to quit with saving. " << endl; 767 | getline(cin,user_input); 768 | count_string_q = 0; 769 | istringstream counts_q (user_input); 770 | // count the input string 771 | while(counts_q>>temp_q) 772 | { 773 | ++count_string_q; 774 | } 775 | } 776 | } 777 | 778 | throw quit; 779 | return quit_game; 780 | } 781 | else if(command_line == "quit_turn") 782 | { 783 | return quit_turn; 784 | } 785 | // if the input is not quit 786 | else 787 | { 788 | // Check how many comma there are and replace comma with white space 789 | for (unsigned int i = 0; i < command_line.length(); ++i) 790 | { 791 | if (command_line[i] == ',') 792 | { 793 | ++count_comma; 794 | command_line[i] = ' '; 795 | } 796 | } 797 | // Check if there is comma in the begining or in the end 798 | if(command_original[0] == ',' || 799 | command_original[command_line.length()-1] == ',') 800 | { 801 | command_valid = 0; 802 | } 803 | //define iss as istringstream 804 | istringstream iss (command_line); 805 | // check the input format and if it is correct, 806 | // assign the value to int &a, int &b 807 | if(count_comma == 1 && 808 | command_valid ==1 && 809 | iss >> m && iss >>n) 810 | { 811 | //check the boundary 812 | if(m <= horizontal_dimension-1 && 813 | n<= vertical_dimension -1) 814 | { 815 | //set value of those to arguments. 816 | a = m; 817 | b = n; 818 | return success; 819 | } 820 | else 821 | { 822 | cout << "The input is out of boundary x <=" 823 | << horizontal_dimension-1 << " y <=" 824 | << vertical_dimension-1<< endl; 825 | } 826 | } 827 | } 828 | } 829 | return bad_command_line; 830 | } 831 | 832 | // Save the board state 833 | void NineAlmondsGame::save_current_state() 834 | { 835 | // make the file name 836 | string game_name = argv_globle[1]; 837 | string file_name = game_name + ".txt"; 838 | // write to the files 839 | ofstream ofs (file_name.c_str()); 840 | if (ofs.is_open ()) 841 | { 842 | ofs << game_name << endl; 843 | // 1. store the board state 844 | // flag whether the piece exists 845 | int piece_existing = 0; 846 | for(unsigned int i = vertical_dimension-1; i+1 != 0; --i ) 847 | { 848 | // Print the board 849 | for(unsigned int j = 0; j < horizontal_dimension; ++j) 850 | { 851 | //check whether it is empty 852 | if (v[horizontal_dimension*i+j] != empty) 853 | { 854 | // print out the symbol 855 | ofs << symbol <<" "; 856 | piece_existing = 1; 857 | } 858 | // If there is no piece there, print out the space 859 | if(piece_existing == 0) 860 | { 861 | ofs << "E" << " "; 862 | } 863 | piece_existing = 0; 864 | //change the line 865 | if(j == horizontal_dimension-1) 866 | { 867 | ofs<< endl; 868 | } 869 | } 870 | } 871 | // 2. store the number of turns 872 | ofs<< turn_times << endl; 873 | // 3. store the continue move state 874 | // if the vector is empty 875 | if(trace_store_file.empty()) 876 | { 877 | ofs << "NO TRACE"; 878 | } 879 | // if the vector is not empty 880 | else 881 | { 882 | // set the flag 883 | ofs << "START TRACE" << endl; 884 | for(vector::iterator iter = trace_store_file.begin(); 885 | iter != trace_store_file.end(); ++iter) 886 | { 887 | ofs << iter->x <<" "<y<< endl; 888 | } 889 | // set the flag 890 | ofs << "END TRACE" << endl; 891 | } 892 | } 893 | // close the file 894 | ofs.close(); 895 | } 896 | 897 | // abort the current state 898 | void NineAlmondsGame::abort_current_state() 899 | { 900 | // make the file name 901 | string information = "NO DATA"; 902 | string game_name = argv_globle[1]; 903 | string file_name = game_name + ".txt"; 904 | // write to the files 905 | ofstream ofs (file_name.c_str()); 906 | if (ofs.is_open ()) 907 | { 908 | ofs << information << endl; 909 | } 910 | // close the file 911 | ofs.close(); 912 | } 913 | -------------------------------------------------------------------------------- /NineAlmondsGame.h: -------------------------------------------------------------------------------- 1 | // NineAlmondsGame.h 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 03/25/14. 4 | 5 | #ifndef NINE_ALMODS_GAME_H 6 | #define NINE_ALMODS_GAME_H 7 | 8 | class NineAlmondsGame : public GameBase { 9 | 10 | friend ostream &operator<<(ostream &out, const NineAlmondsGame &n); 11 | 12 | public: 13 | NineAlmondsGame(unsigned int h, unsigned int v, 14 | piece_color color, string name, string symbol); 15 | virtual ~NineAlmondsGame() {}; 16 | //set function 17 | virtual void initialize_game(); 18 | //set function 19 | virtual void initialize_game_from_start(); 20 | //set function 21 | virtual void push_v (game_piece gp); 22 | //set function 23 | virtual void set_v (unsigned int x,unsigned int ,game_piece gp); 24 | // check whether the game is done 25 | virtual bool done(); 26 | // prompt the user to input the value 27 | virtual int prompt(unsigned int &a, unsigned int &b); 28 | // check and make a valid move in the game 29 | virtual void turn(); 30 | // the print method 31 | virtual void print(); 32 | // play the game by calling turn() 33 | virtual int play(); 34 | // checks if there is valid move 35 | bool no_valid_move(vector board_state); 36 | // save the current state 37 | virtual void save_current_state(); 38 | // abort the current state 39 | virtual void abort_current_state(); 40 | 41 | protected: 42 | // hold the game pieces, it represents the gameboard, 43 | // the index correspond to the position of the board 44 | vector v; 45 | 46 | }; 47 | 48 | #endif -------------------------------------------------------------------------------- /OtherFunctions.cpp: -------------------------------------------------------------------------------- 1 | // OtherFunctions.cpp 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 03/25/14. 4 | 5 | #include "OtherFunctions.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | return_value call_usage_function() 19 | { 20 | cout << "Command line error! Please input:\n" 21 | "\"Games Checkers Alice Bob\" OR \n" 22 | "\"Games Chess Alice Bob\" OR \n" 23 | "\"Games NineAlmonds\" OR \n" 24 | "\"Games MagicSquare\" OR \n" 25 | "\"Games Reversi Alice Bob\" OR \n" 26 | "\"Games TicTacToe\" AND\n" 27 | "WHERE Alice is the person in Reversi Game (or Checkers) " 28 | "who moves first,\nand Bob is the person who moves second.\n"; 29 | 30 | return bad_command_line; 31 | } 32 | 33 | //constructor of game_piece with no arguments 34 | game_piece::game_piece () {} 35 | 36 | //constructor of game_piece with arguments 37 | game_piece::game_piece (unsigned int m, unsigned int n) 38 | : x(m), row(m), y(n), col(n) {} 39 | 40 | // overload the != operator 41 | bool game_piece::operator!= (const game_piece & gp) const 42 | { 43 | return (x != gp.x || y != gp.y); 44 | } 45 | 46 | // overload the == operator 47 | bool game_piece::operator== (const game_piece & gp) const 48 | { 49 | return (x == gp.x && y == gp.y); 50 | } 51 | 52 | // constructor of numbered_game_piece 53 | numbered_game_piece::numbered_game_piece (unsigned int m, 54 | unsigned int n, unsigned int v) 55 | : game_piece(m,n), value(v) {} 56 | 57 | // constructor of reversi_game_piece 58 | reversi_game_piece::reversi_game_piece (unsigned int m, unsigned int n, 59 | piece_color c, string s) 60 | : game_piece(m,n), color(c), symbol(s) {} 61 | -------------------------------------------------------------------------------- /OtherFunctions.h: -------------------------------------------------------------------------------- 1 | // OtherFunctions.h 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 03/25/14. 4 | 5 | #ifndef OTHER_FUNCTION_H 6 | #define OTHER_FUNCTION_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | // The empty represents there is no piece there, 17 | // if the x == 10 and y == 10, it means there is no piece there 18 | const unsigned int x_empty = 10; 19 | const unsigned int y_empty = 10; 20 | 21 | // The color of the pieces 22 | typedef enum piece_color { 23 | brown, black_or_white, black, white 24 | } Color; 25 | 26 | // The enumtype of return value 27 | enum return_value { 28 | success, bad_command_line, bad_memory_allocation, 29 | quit_turn, quit_game, failure, no_more_valid_move, 30 | other_exceptions, instance_not_exist, instance_exist, 31 | invalid_file_state 32 | }; 33 | 34 | // Call usage function when the input is not correct 35 | return_value call_usage_function(); 36 | 37 | // The move type of the chess piece 38 | enum MoveType { 39 | ILLEGAL, NORMAL, CASTLE, DOUBLESTEP, 40 | ENPASSANT, ESCAPE, PROMOTION 41 | }; 42 | 43 | // The definition of each piece 44 | typedef struct game_piece { 45 | // default constructor with no arguments 46 | game_piece(); 47 | // default constructor with arguments 48 | game_piece(unsigned int m, unsigned int n); 49 | bool operator!= (const game_piece & gp) const; 50 | bool operator== (const game_piece & gp) const; 51 | unsigned int x, row; // x means the row 52 | unsigned int y, col; // y means the column 53 | } Point, position; 54 | 55 | // The definition of the numbered_game_piece 56 | struct numbered_game_piece : public game_piece { 57 | numbered_game_piece(unsigned int m, unsigned int n, 58 | unsigned int v); 59 | int value; 60 | }; 61 | 62 | // The definition of the reversi_game_piece 63 | typedef struct reversi_game_piece : public game_piece { 64 | reversi_game_piece(unsigned int m, unsigned int n, 65 | piece_color c, string s); 66 | piece_color color; 67 | string symbol; 68 | } checkers_game_piece, chess_game_piece; 69 | 70 | #endif -------------------------------------------------------------------------------- /ReversiGame.cpp: -------------------------------------------------------------------------------- 1 | // ReversiGame.cpp 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 03/25/14. 4 | 5 | #include "OtherFunctions.h" 6 | #include "GameBase.h" 7 | #include "ReversiGame.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | // globe value of argv[] 20 | extern char ** argv_globle; 21 | // flag out whehter to return the last state 22 | extern int last_state; // 0 means not to return 23 | //Define the initial state of the piece on the board for initialize_game() 24 | // function. x_empty,y_empty is defined in other_functions.h 25 | reversi_game_piece empty_rgp(x_empty,y_empty,black_or_white,"E"); 26 | // symbol for the black peice 27 | string X = "X"; 28 | // symbol for the white peice 29 | string O = "O"; 30 | // store the value of turn time 31 | int first_person_turn_times = 0; 32 | // store the value of turn time 33 | int second_person_turn_times = 0; 34 | // store the whose turn 35 | string whose_turn; 36 | 37 | //constructor of ReversiGame 38 | ReversiGame::ReversiGame(unsigned int h,unsigned int v,piece_color color, 39 | string name,string symbol, string first, string second) 40 | :GameBase( h, v, color, name, symbol), 41 | first_person(first),second_person(second) {} 42 | 43 | //set function 44 | void ReversiGame::push_v (reversi_game_piece rgp) 45 | { 46 | v.push_back(rgp); 47 | } 48 | 49 | //set function 50 | void ReversiGame::set_v (unsigned int x,unsigned int y ,reversi_game_piece rgp) 51 | { 52 | v[horizontal_dimension*y+x] = rgp; 53 | } 54 | 55 | // print method 56 | void ReversiGame::print() 57 | { 58 | cout << endl << *this << endl << endl; 59 | // print the number of pieces 60 | cout << "Total number of X = "<< count_black_pieces()<< endl; 61 | cout << "Total number of O = "<< count_white_pieces()<< endl; 62 | cout << endl; 63 | } 64 | 65 | // Overloading the operator << for NineAlmonds Game 66 | ostream &operator<< (ostream &out, const ReversiGame &r) 67 | { 68 | //define the empty piece 69 | int piece_existing = 0; 70 | // store the value of the dimension 71 | unsigned int d = r.horizontal_dimension; 72 | for(unsigned int i = r.vertical_dimension-1; i+1!= 0; --i ) 73 | { 74 | // Draw the Y coordinate 75 | out<< i<<" "; 76 | // Print the board 77 | for(unsigned int j = 0; j < r.horizontal_dimension; ++j) 78 | { 79 | //check whether it is empty 80 | if (r.v[d*i+j] != empty_rgp) 81 | { 82 | // print out the symbol 83 | out << setiosflags(ios_base::left) 84 | << setw(r.longest_string_length+1) 85 | << r.v[d*i+j].symbol; 86 | piece_existing = 1; 87 | } 88 | // If there is no piece there, print out the space 89 | if(piece_existing == 0) 90 | { 91 | cout << setiosflags(ios_base::left) 92 | << setw(r.longest_string_length+1) << " "; 93 | } 94 | piece_existing = 0; 95 | //change the line 96 | if(j == r.horizontal_dimension-1) 97 | { 98 | out<< endl; 99 | } 100 | } 101 | } 102 | // Draw the X coordinate 103 | out<<"X"<<" "; 104 | for(unsigned int j = 0; j < r.horizontal_dimension; ++j) 105 | { 106 | // Draw the X coordinate with the space between them 107 | out << setiosflags(ios_base::left) 108 | << setw(r.longest_string_length+1) << j; 109 | } 110 | return out; 111 | } 112 | 113 | //Initialize the board 114 | void ReversiGame::initialize_game() 115 | { 116 | string first_line; // store the first line 117 | string first_person_file; // store the first person 118 | string second_person_file; // store the first person 119 | string board_line; // store the one line in the file 120 | string current_piece; // store the current piece 121 | string turn_s; // store the value of turn_times 122 | string game_name = argv_globle[1]; 123 | //=1 if it is needed to initialize game from start because 124 | // the file is edited without permission.Otherwise =0. 125 | int flag_initialize_game_from_start=0; 126 | string first_person_program = argv_globle[2]; 127 | string second_perosn_program = argv_globle[3]; 128 | string file_name = game_name +"_"+ first_person_program +"_"+ 129 | second_perosn_program + ".txt"; 130 | // first try to read from file 131 | ifstream ifs (file_name.c_str()); 132 | if (ifs.is_open ()) 133 | { 134 | ifs>>first_line; 135 | ifs>>first_person_file; 136 | ifs>>second_person_file; 137 | } 138 | //1.initialize the piece on the NineAlmondsGame 139 | for(unsigned int i = get_vertical_dimension()-1; i+1 != 0; --i ) 140 | { 141 | for(unsigned int j = 0; j < get_horizontal_dimension(); ++j) 142 | { 143 | push_v(empty_rgp); 144 | } 145 | } 146 | // initialize the board with saved value from the file 147 | if( first_line == game_name && 148 | first_person_file == first_person_program && 149 | second_person_file == second_perosn_program) 150 | { 151 | 152 | // iterate through the board 153 | for(unsigned int i = get_vertical_dimension()-1; i+1 != 0; --i ) 154 | { 155 | // read the board information 156 | // iterate through each piece on the line 157 | for(unsigned int j = 0; j < get_horizontal_dimension(); ++j) 158 | { 159 | // extract the value from each pieces 160 | ifs >> current_piece; 161 | // check if there is a piece there 162 | if (current_piece != X && 163 | current_piece != O && 164 | current_piece != "E") 165 | { 166 | cout<<"The saved file has been edited without permission." 167 | << endl <<"So, a new game will be initialized." << endl; 168 | initialize_game_from_start(); 169 | flag_initialize_game_from_start=1; 170 | break; 171 | } 172 | 173 | if(current_piece == X && flag_initialize_game_from_start==0) 174 | { 175 | // set the current location with pieces 176 | set_v(j,i,reversi_game_piece(j,i,black,X)); 177 | } 178 | else if(current_piece == O && flag_initialize_game_from_start==0) 179 | { 180 | // set the current location with pieces 181 | set_v(j,i,reversi_game_piece(j,i,white,O)); 182 | } 183 | } 184 | } 185 | // 2. initialize the turn_times; 186 | ifs >> first_person_turn_times; 187 | ifs >> second_person_turn_times; 188 | // 3.specify the turn 189 | ifs >> whose_turn; 190 | // set the last_state to 1 in order to change the print in main() 191 | last_state = 1; 192 | } 193 | // do not read from file, initialize the board by default 194 | else 195 | { 196 | initialize_game_from_start(); 197 | } 198 | ifs.close(); 199 | } 200 | 201 | void ReversiGame::initialize_game_from_start() 202 | { 203 | // clear the board 204 | for(unsigned int i = get_vertical_dimension()-1; i+1 != 0; --i ) 205 | { 206 | for(unsigned int j = 0; j < get_horizontal_dimension(); ++j) 207 | { 208 | set_v(j,i,empty_rgp); 209 | } 210 | } 211 | // initiallize the pieces on the board 212 | set_v(3,3,reversi_game_piece(3,3,black,X)); 213 | set_v(4,4,reversi_game_piece(4,4,black,X)); 214 | set_v(3,4,reversi_game_piece(3,4,white,O)); 215 | set_v(4,3,reversi_game_piece(4,3,white,O)); 216 | // specify the turn 217 | whose_turn = argv_globle[2]; 218 | } 219 | 220 | // check whether the game is done 221 | bool ReversiGame::done() 222 | { 223 | //1. if all the square are filled 224 | if(count_black_pieces() + count_white_pieces() == 225 | horizontal_dimension * vertical_dimension) 226 | { 227 | return true; 228 | } 229 | // 2, if all the pieces on the board is the same color 230 | else if(count_black_pieces() == 0 || count_white_pieces() == 0) 231 | { 232 | return true; 233 | } 234 | else if( check_available_square_black() == false && 235 | check_available_square_white() == false) 236 | { 237 | return true; 238 | } 239 | // if not finished 240 | return false; 241 | } 242 | 243 | // prompt the user to input the value 244 | int ReversiGame::prompt(unsigned int &a, unsigned int &b) 245 | { 246 | int count_string = 0; 247 | int count_comma = 0; 248 | int command_valid = 1; 249 | string quit = "quit"; 250 | string command_line; 251 | string command_original; 252 | string temp; 253 | unsigned int m; // temporarily storing the integer value of commandline 254 | unsigned int n; // temporarily storing the integer value of commandline 255 | // get the input from the input stream 256 | getline(cin,command_line); 257 | command_original = command_line; 258 | istringstream counts (command_original); 259 | // count the input string 260 | while(counts>>temp) 261 | { 262 | count_string ++; 263 | } 264 | // check whether the input command line is valid 265 | if(count_string == 1) 266 | { 267 | // if the input is quit 268 | if (command_line == quit) 269 | { 270 | // check whehter need to save the game 271 | cout << "Do you want to save the game? Enter \"yes\" to save the " 272 | "game and quit, enter \"no\" to quit without saving." << endl; 273 | // define viarbles 274 | string user_input; 275 | int user_input_valid = 0; 276 | int count_string_q = 0; 277 | string temp_q; 278 | // get the input from user 279 | // get the input from the input stream 280 | getline(cin,user_input); 281 | istringstream counts_q (user_input); 282 | // count the input string 283 | while(counts_q >> temp_q) 284 | { 285 | ++count_string_q; 286 | } 287 | while(user_input_valid != 1 || count_string_q !=1 ) 288 | { 289 | if (user_input == "yes" && count_string_q == 1) 290 | { 291 | // set user_input_valid to 1 to get out of the loop 292 | user_input_valid = 1; 293 | // save current state 294 | save_current_state(); 295 | cout << "The game has been saved, "; 296 | } 297 | else if(user_input == "no" && count_string_q == 1 ) 298 | { 299 | // set user_input_valid to 1 to get out of the loop 300 | user_input_valid = 1; 301 | // abort the current state 302 | abort_current_state(); 303 | cout << "The game has NOT been saved, "; 304 | } 305 | else 306 | { 307 | cout << "Input not correct, please input the command again." 308 | "Enter \"yes\" to save the game and quit, " 309 | "enter \"no\" to quit with saving. " << endl; 310 | getline(cin,user_input); 311 | count_string_q = 0; 312 | istringstream counts_q (user_input); 313 | // count the input string 314 | while(counts_q>>temp_q) 315 | { 316 | ++count_string_q; 317 | } 318 | } 319 | } 320 | 321 | throw quit; 322 | return quit_game; 323 | } 324 | // if the input is not quit 325 | else 326 | { 327 | // Check how many comma there are and replace comma with white space 328 | for (unsigned int i = 0; i < command_line.length(); ++i) 329 | { 330 | if (command_line[i] == ',') 331 | { 332 | ++count_comma; 333 | command_line[i] = ' '; 334 | } 335 | } 336 | // Check if there is comma in the begining or in the end 337 | if(command_original[0] == ',' || 338 | command_original[command_line.length()-1] == ',') 339 | { 340 | command_valid = 0; 341 | } 342 | //define iss as istringstream 343 | istringstream iss (command_line); 344 | // check the input format and if it is correct, 345 | // assign the value to int &a, int &b 346 | if(count_comma == 1 && 347 | command_valid ==1 && 348 | iss >> m && iss >>n) 349 | { 350 | //check the boundary 351 | if(m <= horizontal_dimension-1 && 352 | n<= vertical_dimension -1) 353 | { 354 | //set value of those to arguments. 355 | a = m; 356 | b = n; 357 | return success; 358 | } 359 | else 360 | { 361 | cout << "The input is out of boundary x <=" 362 | << horizontal_dimension-1 << " y <=" 363 | << vertical_dimension-1<< endl; 364 | } 365 | } 366 | } 367 | } 368 | return bad_command_line; 369 | } 370 | 371 | // check and make a valid move in the game 372 | void ReversiGame::turn() 373 | { 374 | unsigned int d = horizontal_dimension;// the dimenstion of the board 375 | unsigned int first_person_x = 0;// the position of the first_person selected piece 376 | unsigned int first_person_y = 0;// the position of the first_person selected piece 377 | unsigned int second_person_x = 0;// the position of the second_person selected piece 378 | unsigned int second_person_y = 0;// the position of the second_person selected piece 379 | int input_valid = 1; // 0 means valid, 1 means invalid 380 | // if it is the first person's (X) turn 381 | if(whose_turn == argv_globle[2]) 382 | { 383 | // check if there is valid square for the first person 384 | if(check_available_square_black() == true) 385 | { 386 | cout << first_person << "'s turn, the symbol is " << X 387 | << ". Please put your game piece by specifying its " 388 | "coordinate position or quit. " << endl; 389 | // prompt the user to input the value 390 | input_valid = prompt(first_person_x,first_person_y); 391 | // check whether the current posisiton is empty and 392 | // check whether the input is valid 393 | while((input_valid != success) || 394 | (v[d*first_person_y+first_person_x] != empty_rgp) || 395 | valid_put_position_black(first_person_x,first_person_y) != true ) 396 | { 397 | // check whether the input is valid 398 | if(input_valid != success) 399 | { 400 | cout << "Bad command line, please put your game piece by " 401 | "specifying its coordinate position, for " 402 | "example: \"0,0\" or input \"quit\" to quit " 403 | "the game." << endl; 404 | input_valid = prompt(first_person_x,first_person_y); 405 | } 406 | // check whether the input is empty 407 | else if(v[d*first_person_y+first_person_x] != empty_rgp) 408 | { 409 | cout << "The current position is NOT EMPTY, please re_put your " 410 | "game piece by specifying its coordinate position." << endl; 411 | input_valid = prompt(first_person_x,first_person_y); 412 | } 413 | // check if this is a valid put 414 | else 415 | { 416 | cout << "The position is NOT a valid put position, please re_put" 417 | " your game piece by specifying its coordinate position." << endl; 418 | input_valid = prompt(first_person_x,first_person_y); 419 | } 420 | } 421 | // the player play his own turn 422 | complete_black_turn(first_person_x,first_person_y); 423 | // increament the each person's turn times 424 | ++first_person_turn_times; 425 | print(); 426 | // change the turn 427 | whose_turn = argv_globle[3]; 428 | } 429 | // skip this turn for the first player 430 | else 431 | { 432 | // change the turn 433 | whose_turn = argv_globle[3]; 434 | cout << first_person << "'s turn SKIPPED, because there is no " 435 | "valid square to put." << endl<< endl; 436 | } 437 | } 438 | // if it is the second person's (O) turn 439 | if(whose_turn == argv_globle[3]) 440 | { 441 | // check if there is valid square for the second person 442 | if(check_available_square_white() == true) 443 | { 444 | cout << second_person << "'s turn, the symbol is " << O 445 | <<". Please put your game piece by specifying its " 446 | "coordinate position or quit. " << endl; 447 | // prompt the user to input the value 448 | input_valid = prompt(second_person_x,second_person_y); 449 | // check whether the current posisiton is empty and check whether the input is valid 450 | while((input_valid != success) || 451 | (v[d*second_person_y+second_person_x] != empty_rgp) || 452 | valid_put_position_white(second_person_x,second_person_y) != true) 453 | { 454 | // check whether the input is valid 455 | if(input_valid != success) 456 | { 457 | cout << "Bad command line, please put your game piece by specifying" 458 | " its coordinate position, for " 459 | "example: \"0,0\" or input \"quit\" to quit the game." << endl; 460 | input_valid = prompt(second_person_x,second_person_y); 461 | } 462 | // check whether the input is empty 463 | else if(v[d*second_person_y+second_person_x] != empty_rgp) 464 | { 465 | cout << "The current position is NOT EMPTY, please re_put your " 466 | " game piece by specifying its coordinate position." << endl; 467 | input_valid = prompt(second_person_x,second_person_y); 468 | } 469 | else 470 | { 471 | cout << "The position is NOT a valid put position, please re_put " 472 | "your game piece by specifying its coordinate position." << endl; 473 | input_valid = prompt(second_person_x,second_person_y); 474 | } 475 | } 476 | // the player play his own turn 477 | complete_white_turn(second_person_x,second_person_y); 478 | // increament the each person's turn times 479 | ++second_person_turn_times; 480 | print(); 481 | // change the turn 482 | whose_turn = argv_globle[2]; 483 | } 484 | // skip this turn for the second player 485 | else 486 | { 487 | // change the turn 488 | whose_turn = argv_globle[2]; 489 | cout << second_person << "'s turn SKIPPED, because there is" 490 | "no valid square to put." << endl<< endl; 491 | } 492 | } 493 | } 494 | 495 | // play the game by calling turn() 496 | int ReversiGame::play() 497 | { 498 | while(done()!= true) 499 | { 500 | // call the function turn() 501 | turn(); 502 | } 503 | // check who is the winner 504 | // if first person is the winner 505 | if(count_black_pieces() > count_white_pieces()) 506 | { 507 | cout << first_person << " is the WINNER! Congratulation! " << 508 | first_person <<" took "<< first_person_turn_times 509 | << " turns to finish the game." << endl; 510 | } 511 | // if second person is the winner 512 | else if(count_black_pieces() < count_white_pieces()) 513 | { 514 | cout << second_person << " is the WINNER! Congratulation! " << 515 | second_person <<" took "<< second_person_turn_times 516 | << " turns to finish the game." << endl; 517 | } 518 | // if it is a tie 519 | else 520 | { 521 | cout <<"This is a TIE." << endl; 522 | } 523 | // the next time the game should start from the beginning 524 | abort_current_state(); 525 | return success; 526 | } 527 | 528 | // save the current state 529 | void ReversiGame::save_current_state() 530 | { 531 | // make the file name 532 | string game_name = argv_globle[1]; 533 | string first_person = argv_globle[2]; 534 | string second_perosn = argv_globle[3]; 535 | string file_name = game_name +"_"+ first_person + 536 | "_"+ second_person + ".txt"; 537 | // write to the files 538 | ofstream ofs (file_name.c_str()); 539 | if (ofs.is_open ()) 540 | { 541 | // 1. store the name of the game and the name of the player 542 | ofs << game_name << endl; 543 | ofs << argv_globle[2] << endl; 544 | ofs << argv_globle[3] << endl; 545 | // 2. store the board state 546 | // flag whether the piece exists 547 | int piece_existing = 0; 548 | for(unsigned int i = vertical_dimension-1; i+1 != 0; --i ) 549 | { 550 | // Print the board 551 | for(unsigned int j = 0; j < horizontal_dimension; ++j) 552 | { 553 | //check whether it is empty 554 | if (v[horizontal_dimension*i+j] != empty_rgp) 555 | { 556 | // print out the symbol 557 | ofs << v[horizontal_dimension*i+j].symbol <<" "; 558 | piece_existing = 1; 559 | } 560 | // If there is no piece there, print out the space 561 | if(piece_existing == 0) 562 | { 563 | ofs << "E" << " "; 564 | } 565 | piece_existing = 0; 566 | //change the line 567 | if(j == horizontal_dimension-1) 568 | { 569 | ofs<< endl; 570 | } 571 | } 572 | } 573 | // 3. store the number of turns 574 | ofs<< first_person_turn_times << endl; 575 | ofs<< second_person_turn_times << endl; 576 | // 4. store the current turn of the player 577 | ofs<< whose_turn; 578 | // close the file 579 | ofs.close(); 580 | } 581 | } 582 | 583 | // abort the current state 584 | void ReversiGame::abort_current_state() 585 | { 586 | // make the file name 587 | string information = "NO DATA"; 588 | string game_name = argv_globle[1]; 589 | string first_person = argv_globle[2]; 590 | string second_perosn = argv_globle[3]; 591 | string file_name = game_name +"_"+ first_person +"_"+ 592 | second_person + ".txt"; 593 | // write to the files 594 | ofstream ofs (file_name.c_str()); 595 | if (ofs.is_open ()) 596 | { 597 | ofs << information << endl; 598 | } 599 | // close the file 600 | ofs.close(); 601 | } 602 | 603 | // checks if this puting position is valid 604 | bool ReversiGame::valid_put_position_black(unsigned int i, unsigned int j) 605 | { 606 | unsigned int d = horizontal_dimension;// the dimenstion of the board 607 | int x = 0; // hold the value of i 608 | int y = 0; // hold the value of j 609 | // when you put your piece on the borad,for example in the middle, 610 | // there should be eight position to be checked 611 | 612 | // case 1 , direction 11 o'clock 613 | if(i>=1 && j<= 6) 614 | { 615 | x = i-1; 616 | y = j+1; 617 | // if the piece is white piece 618 | if(v[d*y+x].symbol == O) 619 | { 620 | //continue searching 621 | --x; 622 | ++y; 623 | while(x>=0 && y<=7) 624 | { 625 | // black piece found 626 | if(v[d*y+x].symbol == X) 627 | { 628 | return true; 629 | } 630 | // if empty piece is found 631 | else if (v[d*y+x] == empty_rgp) 632 | { 633 | break; 634 | } 635 | // if the piece is white continue searching 636 | --x; 637 | ++y; 638 | } 639 | } 640 | } 641 | 642 | // case 2 , direction 12 o'clock 643 | if(j<= 6) 644 | { 645 | x = i; 646 | y = j+1; 647 | // if the piece is white piece 648 | if(v[d*y+x].symbol == O) 649 | { 650 | //continue searching 651 | ++y; 652 | while(y<=7) 653 | { 654 | // black piece found 655 | if(v[d*y+x].symbol == X) 656 | { 657 | return true; 658 | } 659 | // if empty piece is found 660 | else if (v[d*y+x] == empty_rgp) 661 | { 662 | break; 663 | } 664 | // if the piece is white continue searching 665 | ++y; 666 | } 667 | } 668 | } 669 | 670 | // case 3 , direction 1 o'clock 671 | if(i<=6 && j<= 6) 672 | { 673 | x = i+1; 674 | y = j+1; 675 | // if the piece is white piece 676 | if(v[d*y+x].symbol == O) 677 | { 678 | //continue searching 679 | ++x; 680 | ++y; 681 | while(x<=7 && y<=7) 682 | { 683 | // black piece found 684 | if(v[d*y+x].symbol == X) 685 | { 686 | return true; 687 | } 688 | // if empty piece is found 689 | else if (v[d*y+x] == empty_rgp) 690 | { 691 | break; 692 | } 693 | // if the piece is white continue searching 694 | ++x; 695 | ++y; 696 | } 697 | } 698 | } 699 | 700 | // case 4 , direction 3 o'clock 701 | if(i<=6) 702 | { 703 | x = i+1; 704 | y = j; 705 | // if the piece is white piece 706 | if(v[d*y+x].symbol == O) 707 | { 708 | //continue searching 709 | ++x; 710 | while(x<=7) 711 | { 712 | // black piece found 713 | if(v[d*y+x].symbol == X) 714 | { 715 | return true; 716 | } 717 | // if empty piece is found 718 | else if (v[d*y+x] == empty_rgp) 719 | { 720 | break; 721 | } 722 | // if the piece is white continue searching 723 | ++x; 724 | } 725 | } 726 | } 727 | 728 | // case 5 , direction 5 o'clock 729 | if(i<=6 && j>=1) 730 | { 731 | x = i+1; 732 | y = j-1; 733 | // if the piece is white piece 734 | if(v[d*y+x].symbol == O) 735 | { 736 | //continue searching 737 | ++x; 738 | --y; 739 | while(x<=7 && y>=0) 740 | { 741 | // black piece found 742 | if(v[d*y+x].symbol == X) 743 | { 744 | return true; 745 | } 746 | // if empty piece is found 747 | else if (v[d*y+x] == empty_rgp) 748 | { 749 | break; 750 | } 751 | // if the piece is white continue searching 752 | ++x; 753 | --y; 754 | } 755 | } 756 | } 757 | 758 | // case 6 , direction 6 o'clock 759 | if(j>=1) 760 | { 761 | x = i; 762 | y = j-1; 763 | // if the piece is white piece 764 | if(v[d*y+x].symbol == O) 765 | { 766 | //continue searching 767 | --y; 768 | while(y>=0) 769 | { 770 | // black piece found 771 | if(v[d*y+x].symbol == X) 772 | { 773 | return true; 774 | } 775 | // if empty piece is found 776 | else if (v[d*y+x] == empty_rgp) 777 | { 778 | break; 779 | } 780 | // if the piece is white continue searching 781 | --y; 782 | } 783 | } 784 | } 785 | 786 | // case 7 , direction 7 o'clock 787 | if(i>=1 && j>= 1) 788 | { 789 | x = i-1; 790 | y = j-1; 791 | // if the piece is white piece 792 | if(v[d*y+x].symbol == O) 793 | { 794 | //continue searching 795 | --x; 796 | --y; 797 | while(x>=0 && y>=0) 798 | { 799 | // black piece found 800 | if(v[d*y+x].symbol == X) 801 | { 802 | return true; 803 | } 804 | // if empty piece is found 805 | else if (v[d*y+x] == empty_rgp) 806 | { 807 | break; 808 | } 809 | // if the piece is white continue searching 810 | --x; 811 | --y; 812 | } 813 | } 814 | } 815 | 816 | // case 8 , direction 9 o'clock 817 | if(i>=1) 818 | { 819 | x = i-1; 820 | y = j; 821 | // if the piece is white piece 822 | if(v[d*y+x].symbol == O) 823 | { 824 | //continue searching 825 | --x; 826 | while(x>=0) 827 | { 828 | // black piece found 829 | if(v[d*y+x].symbol == X) 830 | { 831 | return true; 832 | } 833 | // if empty piece is found 834 | else if (v[d*y+x] == empty_rgp) 835 | { 836 | break; 837 | } 838 | // if the piece is white continue searching 839 | --x; 840 | } 841 | } 842 | } 843 | // after all the checking, if there is no true case, return false 844 | return false; 845 | } 846 | 847 | // checks if this puting position is valid 848 | bool ReversiGame::valid_put_position_white(unsigned int i, unsigned int j) 849 | { 850 | unsigned int d = horizontal_dimension;// the dimenstion of the board 851 | int x = 0; // hold the value of i 852 | int y = 0; // hold the value of j 853 | // when you put your piece on the borad,for example in the middle, 854 | // there should be eight position to be checked 855 | 856 | // case 1 , direction 11 o'clock 857 | if(i>=1 && j<= 6) 858 | { 859 | x = i-1; 860 | y = j+1; 861 | // if the piece is black piece 862 | if(v[d*y+x].symbol == X) 863 | { 864 | //continue searching 865 | --x; 866 | ++y; 867 | while(x>=0 && y<=7) 868 | { 869 | // white piece found 870 | if(v[d*y+x].symbol == O) 871 | { 872 | return true; 873 | } 874 | // if empty piece is found 875 | else if (v[d*y+x] == empty_rgp) 876 | { 877 | break; 878 | } 879 | // if the piece is white continue searching 880 | --x; 881 | ++y; 882 | } 883 | } 884 | } 885 | 886 | // case 2 , direction 12 o'clock 887 | if(j<= 6) 888 | { 889 | x = i; 890 | y = j+1; 891 | // if the piece is black piece 892 | if(v[d*y+x].symbol == X) 893 | { 894 | //continue searching 895 | ++y; 896 | while(y<=7) 897 | { 898 | // whtie piece found 899 | if(v[d*y+x].symbol == O) 900 | { 901 | return true; 902 | } 903 | // if empty piece is found 904 | else if (v[d*y+x] == empty_rgp) 905 | { 906 | break; 907 | } 908 | // if the piece is white continue searching 909 | ++y; 910 | } 911 | } 912 | } 913 | 914 | // case 3 , direction 1 o'clock 915 | if(i<=6 && j<= 6) 916 | { 917 | x = i+1; 918 | y = j+1; 919 | // if the piece is black piece 920 | if(v[d*y+x].symbol == X) 921 | { 922 | //continue searching 923 | ++x; 924 | ++y; 925 | while(x<=7 && y<=7) 926 | { 927 | // white piece found 928 | if(v[d*y+x].symbol == O) 929 | { 930 | return true; 931 | } 932 | // if empty piece is found 933 | else if (v[d*y+x] == empty_rgp) 934 | { 935 | break; 936 | } 937 | // if the piece is white continue searching 938 | ++x; 939 | ++y; 940 | } 941 | } 942 | } 943 | 944 | // case 4 , direction 3 o'clock 945 | if(i<=6) 946 | { 947 | x = i+1; 948 | y = j; 949 | // if the piece is black piece 950 | if(v[d*y+x].symbol == X) 951 | { 952 | //continue searching 953 | ++x; 954 | while(x<=7) 955 | { 956 | // white piece found 957 | if(v[d*y+x].symbol == O) 958 | { 959 | return true; 960 | } 961 | // if empty piece is found 962 | else if (v[d*y+x] == empty_rgp) 963 | { 964 | break; 965 | } 966 | // if the piece is white continue searching 967 | ++x; 968 | } 969 | } 970 | } 971 | 972 | // case 5 , direction 5 o'clock 973 | if(i<=6 && j>=1) 974 | { 975 | x = i+1; 976 | y = j-1; 977 | // if the piece is black piece 978 | if(v[d*y+x].symbol == X) 979 | { 980 | //continue searching 981 | ++x; 982 | --y; 983 | while(x<=7 && y>=0) 984 | { 985 | // white piece found 986 | if(v[d*y+x].symbol == O) 987 | { 988 | return true; 989 | } 990 | // if empty piece is found 991 | else if (v[d*y+x] == empty_rgp) 992 | { 993 | break; 994 | } 995 | // if the piece is white continue searching 996 | ++x; 997 | --y; 998 | } 999 | } 1000 | } 1001 | 1002 | // case 6 , direction 6 o'clock 1003 | if(j>=1) 1004 | { 1005 | x = i; 1006 | y = j-1; 1007 | // if the piece is black piece 1008 | if(v[d*y+x].symbol == X) 1009 | { 1010 | //continue searching 1011 | --y; 1012 | while(y>=0) 1013 | { 1014 | // white piece found 1015 | if(v[d*y+x].symbol == O) 1016 | { 1017 | return true; 1018 | } 1019 | // if empty piece is found 1020 | else if (v[d*y+x] == empty_rgp) 1021 | { 1022 | break; 1023 | } 1024 | // if the piece is white continue searching 1025 | --y; 1026 | } 1027 | } 1028 | } 1029 | 1030 | // case 7 , direction 7 o'clock 1031 | if(i>=1 && j>= 1) 1032 | { 1033 | x = i-1; 1034 | y = j-1; 1035 | // if the piece is black piece 1036 | if(v[d*y+x].symbol == X) 1037 | { 1038 | //continue searching 1039 | --x; 1040 | --y; 1041 | while(x>=0 && y>=0) 1042 | { 1043 | // white piece found 1044 | if(v[d*y+x].symbol == O) 1045 | { 1046 | return true; 1047 | } 1048 | // if empty piece is found 1049 | else if (v[d*y+x] == empty_rgp) 1050 | { 1051 | break; 1052 | } 1053 | // if the piece is white continue searching 1054 | --x; 1055 | --y; 1056 | } 1057 | } 1058 | } 1059 | 1060 | // case 8 , direction 9 o'clock 1061 | if(i>=1) 1062 | { 1063 | x = i-1; 1064 | y = j; 1065 | // if the piece is black piece 1066 | if(v[d*y+x].symbol == X) 1067 | { 1068 | //continue searching 1069 | --x; 1070 | while(x>=0) 1071 | { 1072 | // white piece found 1073 | if(v[d*y+x].symbol == O) 1074 | { 1075 | return true; 1076 | } 1077 | // if empty piece is found 1078 | else if (v[d*y+x] == empty_rgp) 1079 | { 1080 | break; 1081 | } 1082 | // if the piece is white continue searching 1083 | --x; 1084 | } 1085 | } 1086 | } 1087 | // after all the checking, if there is no true case, return false 1088 | return false; 1089 | } 1090 | 1091 | // complete the play's turn and change the board according to the rules 1092 | void ReversiGame::complete_black_turn(unsigned int i, unsigned int j) 1093 | { 1094 | unsigned int d = horizontal_dimension;// the dimenstion of the board 1095 | int x = 0; // hold the value of i 1096 | int y = 0; // hold the value of j 1097 | int n = 0; // record the number of O between the X 1098 | // put the piece on the borad 1099 | v[d*j+i] = reversi_game_piece(i,j,black,X); 1100 | // when you put your piece on the borad,for example in the middle, 1101 | // there should be eight position to be checked 1102 | 1103 | // case 1 , direction 11 o'clock 1104 | if(i>=1 && j<= 6) 1105 | { 1106 | x = i-1; 1107 | y = j+1; 1108 | // if the piece is white piece 1109 | if(v[d*y+x].symbol == O) 1110 | { 1111 | //continue searching 1112 | --x; 1113 | ++y; 1114 | while(x>=0 && y<=7) 1115 | { 1116 | // black piece found 1117 | if(v[d*y+x].symbol == X) 1118 | { 1119 | // calculate the number of white pieces 1120 | n = y-j-1; 1121 | for(int k = 0; k < n; ++k) 1122 | { 1123 | // change the color of the pieces 1124 | v[d*(y-1)+(x+1)] = reversi_game_piece(x+1,y-1,black,X); 1125 | --y; 1126 | ++x; 1127 | } 1128 | break; 1129 | } 1130 | // if empty piece is found 1131 | else if (v[d*y+x] == empty_rgp) 1132 | { 1133 | break; 1134 | } 1135 | // if the piece is white continue searching 1136 | --x; 1137 | ++y; 1138 | } 1139 | } 1140 | } 1141 | 1142 | // case 2 , direction 12 o'clock 1143 | if(j<= 6) 1144 | { 1145 | x = i; 1146 | y = j+1; 1147 | // if the piece is white piece 1148 | if(v[d*y+x].symbol == O) 1149 | { 1150 | //continue searching 1151 | ++y; 1152 | while(y<=7) 1153 | { 1154 | // black piece found 1155 | if(v[d*y+x].symbol == X) 1156 | { 1157 | // calculate the number of white pieces 1158 | n = y-j-1; 1159 | for(int k = 0; k < n; ++k) 1160 | { 1161 | // change the color of the pieces 1162 | v[d*(y-1)+x] = reversi_game_piece(x,y-1,black,X); 1163 | --y; 1164 | } 1165 | break; 1166 | } 1167 | // if empty piece is found 1168 | else if (v[d*y+x] == empty_rgp) 1169 | { 1170 | break; 1171 | } 1172 | // if the piece is white continue searching 1173 | ++y; 1174 | } 1175 | } 1176 | } 1177 | 1178 | // case 3 , direction 1 o'clock 1179 | if(i<=6 && j<= 6) 1180 | { 1181 | x = i+1; 1182 | y = j+1; 1183 | // if the piece is white piece 1184 | if(v[d*y+x].symbol == O) 1185 | { 1186 | //continue searching 1187 | ++x; 1188 | ++y; 1189 | while(x<=7 && y<=7) 1190 | { 1191 | // black piece found 1192 | if(v[d*y+x].symbol == X) 1193 | { 1194 | // calculate the number of white pieces 1195 | n = y-j-1; 1196 | for(int k = 0; k < n; ++k) 1197 | { 1198 | // change the color of the pieces 1199 | v[d*(y-1)+(x-1)] = reversi_game_piece(x-1,y-1,black,X); 1200 | --y; 1201 | --x; 1202 | } 1203 | break; 1204 | } 1205 | // if empty piece is found 1206 | else if (v[d*y+x] == empty_rgp) 1207 | { 1208 | break; 1209 | } 1210 | // if the piece is white continue searching 1211 | ++x; 1212 | ++y; 1213 | } 1214 | } 1215 | } 1216 | 1217 | // case 4 , direction 3 o'clock 1218 | if(i<=6) 1219 | { 1220 | x = i+1; 1221 | y = j; 1222 | // if the piece is white piece 1223 | if(v[d*y+x].symbol == O) 1224 | { 1225 | //continue searching 1226 | ++x; 1227 | while(x<=7) 1228 | { 1229 | // black piece found 1230 | if(v[d*y+x].symbol == X) 1231 | { 1232 | // calculate the number of white pieces 1233 | n = x-i-1; 1234 | for(int k = 0; k < n; ++k) 1235 | { 1236 | // change the color of the pieces 1237 | v[d*y+(x-1)] = reversi_game_piece(x-1,y,black,X); 1238 | --x; 1239 | } 1240 | break; 1241 | } 1242 | // if empty piece is found 1243 | else if (v[d*y+x] == empty_rgp) 1244 | { 1245 | break; 1246 | } 1247 | // if the piece is white continue searching 1248 | ++x; 1249 | } 1250 | } 1251 | } 1252 | 1253 | // case 5 , direction 5 o'clock 1254 | if(i<=6 && j>=1) 1255 | { 1256 | x = i+1; 1257 | y = j-1; 1258 | // if the piece is white piece 1259 | if(v[d*y+x].symbol == O) 1260 | { 1261 | //continue searching 1262 | ++x; 1263 | --y; 1264 | while(x<=7 && y>=0) 1265 | { 1266 | // black piece found 1267 | if(v[d*y+x].symbol == X) 1268 | { 1269 | // calculate the number of white pieces 1270 | n = x-i-1; 1271 | for(int k = 0; k < n; ++k) 1272 | { 1273 | // change the color of the pieces 1274 | v[d*(y+1)+(x-1)] = reversi_game_piece(x-1,y+1,black,X); 1275 | --x; 1276 | ++y; 1277 | } 1278 | break; 1279 | } 1280 | // if empty piece is found 1281 | else if (v[d*y+x] == empty_rgp) 1282 | { 1283 | break; 1284 | } 1285 | // if the piece is white continue searching 1286 | ++x; 1287 | --y; 1288 | } 1289 | } 1290 | } 1291 | 1292 | // case 6 , direction 6 o'clock 1293 | if(j>=1) 1294 | { 1295 | x = i; 1296 | y = j-1; 1297 | // if the piece is white piece 1298 | if(v[d*y+x].symbol == O) 1299 | { 1300 | //continue searching 1301 | --y; 1302 | while(y>=0) 1303 | { 1304 | // black piece found 1305 | if(v[d*y+x].symbol == X) 1306 | { 1307 | // calculate the number of white pieces 1308 | n = j-y-1; 1309 | for(int k = 0; k < n; ++k) 1310 | { 1311 | // change the color of the pieces 1312 | v[d*(y+1)+x] = reversi_game_piece(x,y+1,black,X); 1313 | ++y; 1314 | } 1315 | break; 1316 | } 1317 | // if empty piece is found 1318 | else if (v[d*y+x] == empty_rgp) 1319 | { 1320 | break; 1321 | } 1322 | // if the piece is white continue searching 1323 | --y; 1324 | } 1325 | } 1326 | } 1327 | 1328 | // case 7 , direction 7 o'clock 1329 | if(i>=1 && j>= 1) 1330 | { 1331 | x = i-1; 1332 | y = j-1; 1333 | // if the piece is white piece 1334 | if(v[d*y+x].symbol == O) 1335 | { 1336 | //continue searching 1337 | --x; 1338 | --y; 1339 | while(x>=0 && y>=0) 1340 | { 1341 | // black piece found 1342 | if(v[d*y+x].symbol == X) 1343 | { 1344 | // calculate the number of white pieces 1345 | n = j-y-1; 1346 | for(int k = 0; k < n; ++k) 1347 | { 1348 | // change the color of the pieces 1349 | v[d*(y+1)+(x+1)] = reversi_game_piece(x+1,y+1,black,X); 1350 | ++x; 1351 | ++y; 1352 | } 1353 | break; 1354 | } 1355 | // if empty piece is found 1356 | else if (v[d*y+x] == empty_rgp) 1357 | { 1358 | break; 1359 | } 1360 | // if the piece is white continue searching 1361 | --x; 1362 | --y; 1363 | } 1364 | } 1365 | } 1366 | 1367 | // case 8 , direction 9 o'clock 1368 | if(i>=1) 1369 | { 1370 | x = i-1; 1371 | y = j; 1372 | // if the piece is white piece 1373 | if(v[d*y+x].symbol == O) 1374 | { 1375 | //continue searching 1376 | --x; 1377 | while(x>=0) 1378 | { 1379 | // black piece found 1380 | if(v[d*y+x].symbol == X) 1381 | { 1382 | // calculate the number of white pieces 1383 | n = i-x-1; 1384 | for(int k = 0; k < n; ++k) 1385 | { 1386 | // change the color of the pieces 1387 | v[d*y+(x+1)] = reversi_game_piece(x+1,y,black,X); 1388 | ++x; 1389 | } 1390 | break; 1391 | } 1392 | // if empty piece is found 1393 | else if (v[d*y+x] == empty_rgp) 1394 | { 1395 | break; 1396 | } 1397 | // if the piece is white continue searching 1398 | --x; 1399 | } 1400 | } 1401 | } 1402 | } 1403 | 1404 | // complete the play's turn and change the board according to the rules 1405 | void ReversiGame::complete_white_turn(unsigned int i, unsigned int j) 1406 | { 1407 | unsigned int d = horizontal_dimension;// the dimenstion of the board 1408 | int x = 0; // hold the value of i 1409 | int y = 0; // hold the value of j 1410 | int n = 0; // record the number of O between the X 1411 | // put the piece on the borad 1412 | v[d*j+i] = reversi_game_piece(i,j,white,O); 1413 | 1414 | // when you put your piece on the borad,for example in the middle, 1415 | // there should be eight position to be checked 1416 | 1417 | // case 1 , direction 11 o'clock 1418 | if(i>=1 && j<= 6) 1419 | { 1420 | x = i-1; 1421 | y = j+1; 1422 | // if the piece is black piece 1423 | if(v[d*y+x].symbol == X) 1424 | { 1425 | //continue searching 1426 | --x; 1427 | ++y; 1428 | while(x>=0 && y<=7) 1429 | { 1430 | // white piece found 1431 | if(v[d*y+x].symbol == O) 1432 | { 1433 | // calculate the number of white pieces 1434 | n = y-j-1; 1435 | for(int k = 0; k < n; ++k) 1436 | { 1437 | // change the color of the pieces 1438 | v[d*(y-1)+(x+1)] = reversi_game_piece(x+1,y-1,white,O); 1439 | --y; 1440 | ++x; 1441 | } 1442 | break; 1443 | } 1444 | // if empty piece is found 1445 | else if (v[d*y+x] == empty_rgp) 1446 | { 1447 | break; 1448 | } 1449 | // if the piece is white continue searching 1450 | --x; 1451 | ++y; 1452 | } 1453 | } 1454 | } 1455 | 1456 | // case 2 , direction 12 o'clock 1457 | if(j<= 6) 1458 | { 1459 | x = i; 1460 | y = j+1; 1461 | // if the piece is black piece 1462 | if(v[d*y+x].symbol == X) 1463 | { 1464 | //continue searching 1465 | ++y; 1466 | while(y<=7) 1467 | { 1468 | // white piece found 1469 | if(v[d*y+x].symbol == O) 1470 | { 1471 | // calculate the number of white pieces 1472 | n = y-j-1; 1473 | for(int k = 0; k < n; ++k) 1474 | { 1475 | // change the color of the pieces 1476 | v[d*(y-1)+x] = reversi_game_piece(x,y-1,white,O); 1477 | --y; 1478 | } 1479 | break; 1480 | } 1481 | // if empty piece is found 1482 | else if (v[d*y+x] == empty_rgp) 1483 | { 1484 | break; 1485 | } 1486 | // if the piece is white continue searching 1487 | ++y; 1488 | } 1489 | } 1490 | } 1491 | 1492 | // case 3 , direction 1 o'clock 1493 | if(i<=6 && j<= 6) 1494 | { 1495 | x = i+1; 1496 | y = j+1; 1497 | // if the piece is black piece 1498 | if(v[d*y+x].symbol == X) 1499 | { 1500 | //continue searching 1501 | ++x; 1502 | ++y; 1503 | while(x<=7 && y<=7) 1504 | { 1505 | // white piece found 1506 | if(v[d*y+x].symbol == O) 1507 | { 1508 | // calculate the number of white pieces 1509 | n = y-j-1; 1510 | for(int k = 0; k < n; ++k) 1511 | { 1512 | // change the color of the pieces 1513 | v[d*(y-1)+(x-1)] = reversi_game_piece(x-1,y-1,white,O); 1514 | --y; 1515 | --x; 1516 | } 1517 | break; 1518 | } 1519 | // if empty piece is found 1520 | else if (v[d*y+x] == empty_rgp) 1521 | { 1522 | break; 1523 | } 1524 | // if the piece is white continue searching 1525 | ++x; 1526 | ++y; 1527 | } 1528 | } 1529 | } 1530 | 1531 | // case 4 , direction 3 o'clock 1532 | if(i<=6) 1533 | { 1534 | x = i+1; 1535 | y = j; 1536 | // if the piece is black piece 1537 | if(v[d*y+x].symbol == X) 1538 | { 1539 | //continue searching 1540 | ++x; 1541 | while(x<=7) 1542 | { 1543 | // whtie piece found 1544 | if(v[d*y+x].symbol == O) 1545 | { 1546 | // calculate the number of white pieces 1547 | n = x-i-1; 1548 | for(int k = 0; k < n; ++k) 1549 | { 1550 | // change the color of the pieces 1551 | v[d*y+(x-1)] = reversi_game_piece(x-1,y,white,O); 1552 | --x; 1553 | } 1554 | break; 1555 | } 1556 | // if empty piece is found 1557 | else if (v[d*y+x] == empty_rgp) 1558 | { 1559 | break; 1560 | } 1561 | // if the piece is white continue searching 1562 | ++x; 1563 | } 1564 | } 1565 | } 1566 | 1567 | // case 5 , direction 5 o'clock 1568 | if(i<=6 && j>=1) 1569 | { 1570 | x = i+1; 1571 | y = j-1; 1572 | // if the piece is black piece 1573 | if(v[d*y+x].symbol == X) 1574 | { 1575 | //continue searching 1576 | ++x; 1577 | --y; 1578 | while(x<=7 && y>=0) 1579 | { 1580 | // white piece found 1581 | if(v[d*y+x].symbol == O) 1582 | { 1583 | // calculate the number of white pieces 1584 | n = x-i-1; 1585 | for(int k = 0; k < n; ++k) 1586 | { 1587 | // change the color of the pieces 1588 | v[d*(y+1)+(x-1)] = reversi_game_piece(x-1,y+1,white,O); 1589 | --x; 1590 | ++y; 1591 | } 1592 | break; 1593 | } 1594 | // if empty piece is found 1595 | else if (v[d*y+x] == empty_rgp) 1596 | { 1597 | break; 1598 | } 1599 | // if the piece is white continue searching 1600 | ++x; 1601 | --y; 1602 | } 1603 | } 1604 | } 1605 | 1606 | // case 6 , direction 6 o'clock 1607 | if(j>=1) 1608 | { 1609 | x = i; 1610 | y = j-1; 1611 | // if the piece is black piece 1612 | if(v[d*y+x].symbol == X) 1613 | { 1614 | //continue searching 1615 | --y; 1616 | while(y>=0) 1617 | { 1618 | // white piece found 1619 | if(v[d*y+x].symbol == O) 1620 | { 1621 | // calculate the number of white pieces 1622 | n = j-y-1; 1623 | for(int k = 0; k < n; ++k) 1624 | { 1625 | // change the color of the pieces 1626 | v[d*(y+1)+x] = reversi_game_piece(x,y+1,white,O); 1627 | ++y; 1628 | } 1629 | break; 1630 | } 1631 | // if empty piece is found 1632 | else if (v[d*y+x] == empty_rgp) 1633 | { 1634 | break; 1635 | } 1636 | // if the piece is white continue searching 1637 | --y; 1638 | } 1639 | } 1640 | } 1641 | 1642 | // case 7 , direction 7 o'clock 1643 | if(i>=1 && j>= 1) 1644 | { 1645 | x = i-1; 1646 | y = j-1; 1647 | // if the piece is black piece 1648 | if(v[d*y+x].symbol == X) 1649 | { 1650 | //continue searching 1651 | --x; 1652 | --y; 1653 | while(x>=0 && y>=0) 1654 | { 1655 | // white piece found 1656 | if(v[d*y+x].symbol == O) 1657 | { 1658 | // calculate the number of white pieces 1659 | n = j-y-1; 1660 | for(int k = 0; k < n; ++k) 1661 | { 1662 | // change the color of the pieces 1663 | v[d*(y+1)+(x+1)] = reversi_game_piece(x+1,y+1,white,O); 1664 | ++x; 1665 | ++y; 1666 | } 1667 | break; 1668 | } 1669 | // if empty piece is found 1670 | else if (v[d*y+x] == empty_rgp) 1671 | { 1672 | break; 1673 | } 1674 | // if the piece is white continue searching 1675 | --x; 1676 | --y; 1677 | } 1678 | } 1679 | } 1680 | 1681 | // case 8 , direction 9 o'clock 1682 | if(i>=1) 1683 | { 1684 | x = i-1; 1685 | y = j; 1686 | // if the piece is black piece 1687 | if(v[d*y+x].symbol == X) 1688 | { 1689 | //continue searching 1690 | --x; 1691 | while(x>=0) 1692 | { 1693 | // white piece found 1694 | if(v[d*y+x].symbol == O) 1695 | { 1696 | // calculate the number of white pieces 1697 | n = i-x-1; 1698 | for(int k = 0; k < n; ++k) 1699 | { 1700 | // change the color of the pieces 1701 | v[d*y+(x+1)] = reversi_game_piece(x+1,y,white,O); 1702 | ++x; 1703 | } 1704 | break; 1705 | } 1706 | // if empty piece is found 1707 | else if (v[d*y+x] == empty_rgp) 1708 | { 1709 | break; 1710 | } 1711 | // if the piece is white continue searching 1712 | --x; 1713 | } 1714 | } 1715 | } 1716 | } 1717 | 1718 | // count the number of plack pieces 1719 | unsigned int ReversiGame::count_black_pieces() 1720 | { 1721 | unsigned total_number_of_black_pieces = 0; 1722 | // store the value of the dimension 1723 | unsigned int d = horizontal_dimension; 1724 | for(unsigned int i = vertical_dimension-1; i+1 != 0; --i ) 1725 | { 1726 | for(unsigned int j = 0; j < horizontal_dimension; ++j) 1727 | { 1728 | //check whether it is empty 1729 | if (v[d*i+j] != empty_rgp) 1730 | { 1731 | // count the black pieces 1732 | if(v[d*i+j].symbol == X) 1733 | { 1734 | ++total_number_of_black_pieces; 1735 | } 1736 | } 1737 | } 1738 | } 1739 | return total_number_of_black_pieces; 1740 | } 1741 | 1742 | // count the number of white piece 1743 | unsigned int ReversiGame::count_white_pieces() 1744 | { 1745 | unsigned total_number_of_white_pieces = 0; 1746 | // store the value of the dimension 1747 | unsigned int d = horizontal_dimension; 1748 | for(unsigned int i = vertical_dimension-1; i+1 != 0; --i ) 1749 | { 1750 | for(unsigned int j = 0; j < horizontal_dimension; ++j) 1751 | { 1752 | //check whether it is empty 1753 | if (v[d*i+j] != empty_rgp) 1754 | { 1755 | //cout the white pieces 1756 | if(v[d*i+j].symbol == O) 1757 | { 1758 | ++total_number_of_white_pieces; 1759 | } 1760 | } 1761 | } 1762 | } 1763 | return total_number_of_white_pieces; 1764 | } 1765 | 1766 | // check if there is a put position for black piece 1767 | bool ReversiGame::check_available_square_black() 1768 | { 1769 | // store the value of the dimension 1770 | unsigned int d = horizontal_dimension; 1771 | for(unsigned int i = vertical_dimension-1; i+1 != 0; --i ) 1772 | { 1773 | for(unsigned int j = 0; j < horizontal_dimension; ++j) 1774 | { 1775 | //check whether it is empty 1776 | if (v[d*i+j] == empty_rgp) 1777 | { 1778 | // check position 1779 | if(valid_put_position_black(j,i) == true) 1780 | { 1781 | return true; 1782 | } 1783 | } 1784 | } 1785 | } 1786 | return false; 1787 | } 1788 | 1789 | // check if there is a put position for white piece 1790 | bool ReversiGame::check_available_square_white() 1791 | { 1792 | // store the value of the dimension 1793 | unsigned int d = horizontal_dimension; 1794 | for(unsigned int i = vertical_dimension-1; i+1 != 0; --i ) 1795 | { 1796 | for(unsigned int j = 0; j < horizontal_dimension; ++j) 1797 | { 1798 | //check whether it is empty 1799 | if (v[d*i+j] == empty_rgp) 1800 | { 1801 | // check position 1802 | if(valid_put_position_white(j,i) == true) 1803 | { 1804 | return true; 1805 | } 1806 | } 1807 | } 1808 | } 1809 | return false; 1810 | } 1811 | -------------------------------------------------------------------------------- /ReversiGame.h: -------------------------------------------------------------------------------- 1 | // ReversiGame.h 2 | // Author : Zheng Luo 3 | // Modified by Zheng Luo on 03/25/14. 4 | 5 | #ifndef REVERSI_GAME_H 6 | #define REVERSI_GAME_H 7 | 8 | class ReversiGame : public GameBase { 9 | 10 | friend ostream &operator<<(ostream &out, const ReversiGame &n); 11 | 12 | public: 13 | ReversiGame(unsigned int h, unsigned int v, piece_color color, 14 | string name, string symbol, string first, string second); 15 | virtual ~ReversiGame() {}; 16 | //set function 17 | virtual void initialize_game(); 18 | //set function 19 | virtual void initialize_game_from_start(); 20 | //set function 21 | virtual void push_v (reversi_game_piece rgp); 22 | //set function 23 | virtual void set_v (unsigned int x,unsigned int y , 24 | reversi_game_piece rgp); 25 | // check whether the game is done 26 | virtual bool done(); 27 | // prompt the user to input the value 28 | virtual int prompt(unsigned int &a, unsigned int &b); 29 | // check and make a valid move in the game 30 | virtual void turn(); 31 | // the print method 32 | virtual void print(); 33 | // play the game by calling turn() 34 | virtual int play(); 35 | // save the current state 36 | virtual void save_current_state(); 37 | // abort the current state 38 | virtual void abort_current_state(); 39 | // checks if this puting position is valid 40 | virtual bool valid_put_position_black(unsigned int i, unsigned int j); 41 | // checks if this puting position is valid 42 | virtual bool valid_put_position_white(unsigned int i, unsigned int j); 43 | // complete the play's turn and change the board according to the rules 44 | virtual void complete_black_turn(unsigned int i, unsigned int j); 45 | // complete the play's turn and change the board according to the rules 46 | virtual void complete_white_turn(unsigned int i, unsigned int j); 47 | // count the number of plack pieces 48 | virtual unsigned int count_black_pieces(); 49 | // count the number of white piece 50 | virtual unsigned int count_white_pieces(); 51 | // check if there is a put position for black piece 52 | virtual bool check_available_square_black(); 53 | // check if there is a put position for white piece 54 | virtual bool check_available_square_white(); 55 | 56 | protected: 57 | // hold the game pieces, it represents the gameboard, 58 | // the index correspond to the position of the board 59 | vector v; 60 | // store the name of the player who moves first 61 | string first_person; 62 | // store the name of the player who moves second 63 | string second_person; 64 | 65 | }; 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /Reversi_LZ_YY.txt: -------------------------------------------------------------------------------- 1 | Reversi 2 | LZ 3 | YY 4 | E E E X X X E E 5 | E E E E X E E E 6 | E E E X O X E E 7 | E E E O O E E E 8 | E E O X O X E E 9 | E E E X O E E E 10 | E E E E E E E E 11 | E E E E E E E E 12 | 6 13 | 5 14 | YY -------------------------------------------------------------------------------- /TicTacToeBase.cpp: -------------------------------------------------------------------------------- 1 | // TicTacToeBase.cpp 2 | // This class abstracts common elemnts 3 | // Author : Zheng Luo 4 | // Created by Zheng Luo on 04/14/14. 5 | 6 | #include "OtherFunctions.h" 7 | #include "TicTacToeBase.h" 8 | 9 | #include 10 | 11 | TicTacToeBase::TicTacToeBase(unsigned int h,unsigned int v, 12 | char first, char second, 13 | bool turn_of_com, bool play_with_com, 14 | string lev, unsigned int t_count) 15 | : board_rows(h),board_cols(v),N(h),init_char(' '), 16 | p1_symbol(first),p2_symbol(second), 17 | player(second),turn_of_computer(turn_of_com), 18 | play_with_computer(play_with_com),mode(lev),turn_count(t_count) 19 | { 20 | new_board_and_state(game_board, state); 21 | } 22 | 23 | TicTacToeBase:: ~TicTacToeBase() 24 | { 25 | delete_board_and_state(game_board, state); 26 | } 27 | 28 | bool TicTacToeBase::done() 29 | { 30 | for (int i = 0; i < 2; i++) 31 | { 32 | int p_number = i; 33 | 34 | if (state[p_number][current_move_row] == N || 35 | state[p_number][N+current_move_col] == N || 36 | state[p_number][2*N] == N || 37 | state[p_number][2*N+1] == N || 38 | turn_count == N * N) 39 | return true; 40 | } 41 | 42 | return false; 43 | } 44 | 45 | char TicTacToeBase::winner() 46 | { 47 | for (int i = 0; i < 2; i++) 48 | { 49 | int p_number = i; 50 | 51 | if (state[p_number][current_move_row] == N || 52 | state[p_number][N+current_move_col] == N || 53 | state[p_number][2*N] == N || 54 | state[p_number][2*N+1] == N) 55 | return p_number == 0? p1_symbol : p2_symbol; 56 | } 57 | 58 | // N means no winner 59 | return 'N'; 60 | } 61 | 62 | void TicTacToeBase::print() 63 | { 64 | for (unsigned int row = 0; row < board_rows; row++) 65 | { 66 | if (row == 0) 67 | { 68 | cout << " "; 69 | for (unsigned int i = 0; i < board_cols; i++) 70 | cout << " " << i+1 << " "; 71 | cout << "\n\n"; 72 | } 73 | 74 | for (unsigned int col = 0; col < board_cols; col++) 75 | { 76 | if (col == 0) 77 | cout << row+1 << " "; 78 | cout << " " << game_board[row][col] << " "; 79 | if (col < board_cols-1) 80 | cout << "|"; 81 | } 82 | 83 | cout << "\n"; 84 | 85 | if (row < board_rows-1) 86 | { 87 | for(unsigned int i = 0; i< board_cols-1; i++) 88 | { 89 | if(i == 0) 90 | cout << " ----"; 91 | else 92 | cout << "----"; 93 | } 94 | cout << "---\n"; 95 | } 96 | } 97 | } 98 | 99 | void TicTacToeBase::print_state_array() 100 | { 101 | // Used for print state array 102 | for (unsigned int i = 0; i < 2; i++) 103 | for (unsigned int j = 0; j < 2*N+2; j++) 104 | cout << "state[" << i << "]" << "[" << j 105 | << "]" << state[i][j] << endl; 106 | } 107 | 108 | void TicTacToeBase::increase_state_array(unsigned int &c_row, 109 | unsigned int &c_col, 110 | unsigned int **state) 111 | { 112 | int p_number; 113 | 114 | if (player == p1_symbol) 115 | p_number = 0; 116 | else 117 | p_number = 1; 118 | 119 | // Increment the row state 120 | state[p_number][c_row]++; 121 | 122 | // Increment the column state 123 | state[p_number][N+c_col]++; 124 | 125 | // Increment the diagonal state 126 | if (c_row == c_col) 127 | state[p_number][2*N]++; 128 | 129 | // Increment the diagonal state 130 | if (c_row + c_col == N-1) 131 | state[p_number][2*N+1]++; 132 | } 133 | 134 | void TicTacToeBase::new_board_and_state(char** &game_board, 135 | unsigned int** &state) 136 | { 137 | // Allocate memory for the game_board 138 | game_board = new char* [N]; 139 | for (unsigned int i = 0; i < N; i++) 140 | game_board[i] = new char [N]; 141 | 142 | // Allocate memory for the state 143 | state = new unsigned int*[2]; 144 | for (unsigned int i = 0; i < 2; i++) 145 | state[i] = new unsigned int [2*N+2]; 146 | } 147 | 148 | void TicTacToeBase::copy_board_and_state(char **game_board, 149 | char **board, 150 | unsigned int **state, 151 | unsigned int **s_array) 152 | { 153 | // Copy the game_board from the Game 154 | for (unsigned int i = 0; i < N; i++) 155 | for (unsigned int j = 0; j < N; j++) 156 | game_board[i][j] = board[i][j]; 157 | 158 | // Copy the state_array 159 | for (unsigned int i = 0; i < 2; i++) 160 | for (unsigned int j = 0; j < 2*N+2; j++) 161 | state[i][j] = s_array[i][j]; 162 | } 163 | 164 | // delete board and state array 165 | void TicTacToeBase::delete_board_and_state(char** &game_board, 166 | unsigned int** &state) 167 | { 168 | for (unsigned int i = 0; i < N; i++) 169 | delete [] game_board[i]; 170 | delete [] game_board; 171 | 172 | for (unsigned int i = 0; i < 2; i++) 173 | delete [] state[i]; 174 | delete [] state; 175 | } -------------------------------------------------------------------------------- /TicTacToeBase.h: -------------------------------------------------------------------------------- 1 | // TicTacToeBase.h 2 | // This class abstracts common elemnts 3 | // Author : Zheng Luo 4 | // Created by Zheng Luo on 04/14/14. 5 | 6 | #ifndef TIC_TAC_TOE_BASE_H 7 | #define TIC_TAC_TOE_BASE_H 8 | 9 | #include "OtherFunctions.h" 10 | #include 11 | 12 | using namespace std; 13 | 14 | class TicTacToeBase { 15 | 16 | public: 17 | TicTacToeBase(unsigned int h,unsigned int v, 18 | char first, char second, bool turn_of_com, 19 | bool play_with_com, string lev, unsigned int t_count); 20 | virtual ~TicTacToeBase(); 21 | 22 | protected: 23 | // print the value in the array 24 | virtual void print_state_array(); 25 | // increase the current move in state array 26 | virtual void increase_state_array(unsigned int &c_row, 27 | unsigned int &c_col, 28 | unsigned int **state); 29 | // check whether the game is done 30 | virtual bool done(); 31 | // return the winner of the game 32 | virtual char winner(); 33 | // print board 34 | virtual void print(); 35 | // new board and state array 36 | virtual void new_board_and_state(char** &game_board, 37 | unsigned int** &state); 38 | // copy board and state array 39 | virtual void copy_board_and_state(char **game_board, char **temp_board, 40 | unsigned int **state, unsigned int **temp_state); 41 | 42 | // delete board and state array 43 | virtual void delete_board_and_state(char** &game_board, 44 | unsigned int** &state); 45 | // virables 46 | unsigned int board_rows; 47 | unsigned int board_cols; 48 | unsigned int N; // number of contiguous marks a player to win 49 | char init_char; 50 | char p1_symbol; 51 | char p2_symbol; 52 | char **game_board; 53 | char player; 54 | unsigned int current_move_row; 55 | unsigned int current_move_col; 56 | unsigned int **state; 57 | bool turn_of_computer; 58 | bool play_with_computer; 59 | string mode; 60 | unsigned int turn_count; 61 | }; 62 | 63 | #endif -------------------------------------------------------------------------------- /TicTacToeGame.cpp: -------------------------------------------------------------------------------- 1 | // TicTacToeGame.cpp 2 | // This class is a implementation of TicTacToe Game 3 | // Author : Zheng Luo 4 | // Modified by Zheng Luo on 04/14/14. 5 | 6 | #include "OtherFunctions.h" 7 | #include "GameBase.h" 8 | #include "TicTacToeBase.h" 9 | #include "TicTacToeGame.h" 10 | #include "TicTacToeState.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | // Use the MULTIPLE inheritance here 18 | // Derived from two base classes 19 | TicTacToeGame::TicTacToeGame(unsigned int h, unsigned int v, 20 | piece_color color, string name, string symbol, 21 | char first, char second, bool turn_of_com, 22 | bool play_with_com, string lev) 23 | :GameBase( h, v, color, name, symbol), 24 | TicTacToeBase(h, v, first, second, turn_of_com, play_with_com, lev, 0) {} 25 | 26 | void TicTacToeGame::initialize_game() 27 | { 28 | for (unsigned int row = 0; row < board_rows; row++) 29 | for (unsigned int col = 0; col < board_cols; col++) 30 | game_board[row][col] = init_char; 31 | 32 | for (unsigned int i = 0; i < 2; i++) 33 | for (unsigned int j = 0; j < 2*N+2; j++) 34 | state[i][j] = 0; 35 | } 36 | 37 | int TicTacToeGame::play() 38 | { 39 | // Initialize the board and state array 40 | initialize_game(); 41 | 42 | while (true) 43 | { 44 | // Flip the symbol each turn 45 | if (player == p2_symbol) 46 | player = p1_symbol; 47 | else 48 | player = p2_symbol; 49 | 50 | cout << "\n\n\n\n\n"; 51 | // The turn may be either a computer or human 52 | if (turn_of_computer && 53 | play_with_computer) 54 | { 55 | cout << "Computer " << player << "'s Turn NOW!" << endl; 56 | turn_computer(); 57 | turn_of_computer = false; 58 | } 59 | else 60 | { 61 | cout << "Player " << player << "'s Turn NOW!" << endl; 62 | turn(); 63 | turn_of_computer = true; 64 | } 65 | 66 | cout << "\n"; 67 | print(); 68 | turn_count++; 69 | 70 | // Use the Base class method 71 | if (done()) 72 | { 73 | if (winner() != 'N') 74 | { 75 | cout << "\n\n\n\n\nCongratulations Player " << winner() 76 | << ", you've won with " << N << " in a row!\n\n"; 77 | break; 78 | } 79 | // The board is full and the game is over 80 | else 81 | { 82 | cout << "\n\nGame Over!\n\nThere is no Winner :-(\n"; 83 | break; 84 | } 85 | } 86 | } 87 | return success; 88 | } 89 | 90 | void TicTacToeGame::turn() 91 | { 92 | unsigned int row = 0, col = 0; 93 | 94 | // Read the position from the command line 95 | read_position(row, col); 96 | 97 | // Store information for state array 98 | increase_state_array(row, col, state); 99 | 100 | // Finally, we store the correct mark into the given location 101 | game_board[row][col] = player; 102 | } 103 | 104 | void TicTacToeGame::turn_computer() 105 | { 106 | cout << "\n\n"; 107 | if (turn_count != 0) 108 | { 109 | // Use the MinMax Search to find optimal solution 110 | TicTacToeState game_state(board_rows, board_cols, p1_symbol, 111 | p2_symbol, turn_of_computer, 112 | play_with_computer, mode, game_board, 113 | state, current_move_row, 114 | current_move_col, turn_count); 115 | 116 | // Get the optimal move position 117 | position *p = game_state.get_move(); 118 | 119 | // Store information for state array 120 | increase_state_array(p->row, p->col, state); 121 | 122 | // Set the current mvoe 123 | current_move_row = p->row; 124 | current_move_col = p->col; 125 | 126 | // Finally, we store the correct mark into the given location 127 | game_board[p->row][p->col] = player; 128 | } 129 | else 130 | { 131 | // Place the 'X' piece on the center of the board 132 | unsigned int row = 1, col = 1; 133 | increase_state_array(row, col, state); 134 | game_board[1][1] = player; 135 | } 136 | } 137 | 138 | void TicTacToeGame::read_position(unsigned int &row, unsigned int &col) 139 | { 140 | while (true) 141 | { 142 | cout << "\n\n\nPlayer " << player 143 | << ", please enter the row column of your move.\n" 144 | "For example 1,1 meaning (1,1), " 145 | "the input range should be less or equal to " 146 | << N << endl; 147 | string s; // Temp virable to read command line data 148 | getline(cin, s); 149 | // Replace comma with space 150 | replace(s.begin(), s.end(), ',', ' '); 151 | // This code converts from string to number safely. 152 | stringstream strStream(s); 153 | if (strStream >> row && row <= N && 154 | strStream >> col && col <= N && 155 | game_board[row-1][col-1] == init_char) 156 | break; 157 | cout << "Invalid number, please try again" << endl; 158 | } 159 | row--; // Translate the user's board_rows and columns numbering 160 | col--; // (starting with 1) to the computer's (starting with 0) 161 | // Set the current mvoe 162 | current_move_row = row; 163 | current_move_col = col; 164 | } -------------------------------------------------------------------------------- /TicTacToeGame.h: -------------------------------------------------------------------------------- 1 | // TicTacToeGame.h 2 | // This class is a implementation of TicTacToe Game 3 | // Author : Zheng Luo 4 | // Modified by Zheng Luo on 03/25/14. 5 | // Combied with Lab5, original url of the program 6 | // http://stackoverflow.com/questions/1056316/ 7 | // algorithm-for-determining-tic-tac-toe-game-over 8 | 9 | #ifndef TIC_TAC_TOE_GAME_H 10 | #define TIC_TAC_TOE_GAME_H 11 | 12 | #include "TicTacToeBase.h" 13 | 14 | // Use the MULTIPLE inheritance here 15 | // Derived from two base classes 16 | class TicTacToeGame : public GameBase , public TicTacToeBase { 17 | // not support insertion operator 18 | friend ostream &operator<<(ostream &out, const TicTacToeGame &n); 19 | 20 | public: 21 | TicTacToeGame(unsigned int h,unsigned int v, 22 | piece_color color, string name, string symbol, 23 | char first, char second, 24 | bool turn_of_com, bool play_with_com, string lev); 25 | virtual ~TicTacToeGame() {}; 26 | // set function 27 | virtual void initialize_game(); 28 | // not implemented 29 | virtual void initialize_game_from_start() {}; 30 | // the done is implemented in the TicTacToeBase 31 | virtual bool done() { return TicTacToeBase::done(); }; 32 | // check and make a valid move for human in the game 33 | virtual void turn(); 34 | // check and make a valid move for computer in the game 35 | virtual void turn_computer(); 36 | // the print method 37 | virtual void print() { TicTacToeBase::print(); }; 38 | // play the game by calling turn() 39 | virtual int play(); 40 | // save the current state, not implemented 41 | virtual void save_current_state() {}; 42 | // abort the current state, not implemented 43 | virtual void abort_current_state() {}; 44 | 45 | protected: 46 | // read position from commandline 47 | void read_position(unsigned int &row, unsigned int &col); 48 | }; 49 | 50 | #endif -------------------------------------------------------------------------------- /TicTacToeState.cpp: -------------------------------------------------------------------------------- 1 | // TicTacToeState.cpp 2 | // This class mainly deals with minimax search 3 | // Author : Zheng Luo 4 | // Created by Zheng Luo on 04/14/14. 5 | // http://www.neverstopbuilding.com/minimax 6 | 7 | #include "TicTacToeBase.h" 8 | #include "TicTacToeState.h" 9 | 10 | #include // srand, rand 11 | #include // time 12 | #include 13 | #include 14 | #include 15 | 16 | TicTacToeState::TicTacToeState(unsigned int h,unsigned int v, 17 | char first, char second, 18 | bool turn_of_com, bool play_with_com, 19 | string lev, char **board, 20 | unsigned int **s_array, 21 | unsigned int c_row, unsigned int c_col, unsigned int t_count) 22 | :TicTacToeBase(h, v, first, second, turn_of_com, play_with_com, lev, t_count) 23 | { 24 | new_board_and_state(temp_board, temp_state); 25 | 26 | // Copy the information 27 | copy_board_and_state(game_board, board, state, s_array); 28 | 29 | // Store the number of possible action 30 | for (unsigned int i = 0; i < N; i++) 31 | for (unsigned int j = 0; j < N; j++) 32 | if (game_board[i][j] == init_char) 33 | actions.push_back(position(i,j)); 34 | 35 | // Set the currentmove for state array use 36 | current_move_row = c_row; 37 | current_move_col = c_col; 38 | } 39 | 40 | TicTacToeState::~TicTacToeState() 41 | { 42 | delete_board_and_state(temp_board, temp_state); 43 | } 44 | 45 | int TicTacToeState::utility(unsigned int depth) 46 | { 47 | // Only support X is human, 48 | // O is computer now 49 | if (winner() == p1_symbol) 50 | return 10 - (int)depth; 51 | else if (winner() == p2_symbol) 52 | return (int)depth - 10; 53 | // If it is a tie 54 | return 0; 55 | } 56 | 57 | TicTacToeState TicTacToeState::result(position p) 58 | { 59 | // Copy the information 60 | copy_board_and_state(temp_board, game_board, temp_state, state); 61 | 62 | // Increase temp_state 63 | increase_state_array(p.row, p.col, temp_state); 64 | 65 | // Set p2_or p1 symbol on the board 66 | if (player == p2_symbol) 67 | temp_board[p.row][p.col] = p2_symbol; 68 | else 69 | temp_board[p.row][p.col] = p1_symbol; 70 | 71 | // Construct a new object for return 72 | TicTacToeState result_state(board_rows, board_cols, p1_symbol, 73 | p2_symbol, turn_of_computer, 74 | play_with_computer, mode, temp_board, 75 | temp_state, p.row, p.col, 76 | turn_count + 1); 77 | 78 | return result_state; 79 | } 80 | 81 | int TicTacToeState::max_value(unsigned int depth) 82 | { 83 | if (done()) 84 | return utility(depth); 85 | 86 | depth++; // Increase depth by one 87 | int v = -10; // Smaller than possible utility return 88 | for (unsigned int i = 0; i < actions.size(); i++) 89 | { 90 | player = p1_symbol; // p1 gets the max value 91 | 92 | TicTacToeState next_state = result(actions[i]); 93 | int temp = next_state.min_value(depth); 94 | // For debuging purpose 95 | //if (depth == 2) 96 | // print_debug_info(next_state, depth, temp); 97 | // Get the max from mins 98 | if (v < temp) 99 | { 100 | v = temp; 101 | index = i; 102 | } 103 | } 104 | return v; 105 | } 106 | 107 | int TicTacToeState::min_value(unsigned int depth) 108 | { 109 | if (done()) 110 | return utility(depth); 111 | 112 | depth++; // Increase depth by one 113 | int v = 10; // larger than possible utility return 114 | for (unsigned int i = 0; i < actions.size(); i++) 115 | { 116 | player = p2_symbol; // p2 gets the min value 117 | 118 | TicTacToeState next_state = result(actions[i]); 119 | int temp = next_state.max_value(depth); 120 | // For debuging purpose 121 | //if (depth == 1) 122 | // print_debug_info(next_state, depth, temp); 123 | // Get the min from maxs 124 | if (v > temp) 125 | { 126 | v = temp; 127 | index = i; 128 | } 129 | } 130 | return v; 131 | } 132 | 133 | position* TicTacToeState::get_move() 134 | { 135 | position* p = NULL; 136 | // Initialize random seed 137 | srand (time(NULL)); 138 | // Get a random number for a move 139 | int r = rand() % 10; 140 | 141 | // esay mode will have 70% random moves 142 | // hard mode will have 50% random moves 143 | // impossivle mode will no random moves 144 | if ((mode == "easy" && r >= 3) || 145 | (mode == "hard" && r >= 5) ) 146 | index = rand() % actions.size(); 147 | else 148 | { 149 | unsigned int depth = 0; 150 | // 'O' always tries to minimize the value 151 | // 'X' always tries to maximize the value 152 | if (player == p2_symbol) 153 | min_value(depth); 154 | else 155 | max_value(depth); 156 | } 157 | 158 | p = &actions[index]; 159 | return p; 160 | } 161 | 162 | void TicTacToeState::print_debug_info(TicTacToeState &next_state, 163 | int depth, int temp) 164 | { 165 | cout << "--------------------------------------" << endl; 166 | cout << "depth = " << depth << ", " 167 | << "next_state_move:" << next_state.current_move_row + 1 168 | << "," << next_state.current_move_col + 1 << ", " << endl 169 | << "winner = " << next_state.winner() << ", " 170 | << "state value = " << temp << endl; 171 | next_state.print_state_array(); 172 | next_state.print(); 173 | cout << "--------------------------------------" << endl; 174 | cout << endl; 175 | } -------------------------------------------------------------------------------- /TicTacToeState.h: -------------------------------------------------------------------------------- 1 | // TicTacToeState.h 2 | // This class mainly deals with minimax search 3 | // Author : Zheng Luo 4 | // Created by Zheng Luo on 04/14/14. 5 | // http://www.neverstopbuilding.com/minimax 6 | 7 | #ifndef TIC_TAC_TOE_STATE_H 8 | #define TIC_TAC_TOE_STATE_H 9 | 10 | #include "OtherFunctions.h" 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | // Game state representing a state of the Tic-Tac-Toe-puzzle 17 | class TicTacToeState : public TicTacToeBase { 18 | 19 | public: 20 | TicTacToeState(unsigned int h, unsigned int v, 21 | char first, char second, bool turn_of_com, 22 | bool play_with_com, string lev, 23 | char **board, unsigned int **s_array, 24 | unsigned int c_row, unsigned int c_col, unsigned int c_count); 25 | virtual ~TicTacToeState(); 26 | // Get the optimal move position 27 | virtual position* get_move(); 28 | 29 | protected: 30 | // Store the set of legal moves in a state. 31 | vector actions; 32 | // Index of next action 33 | unsigned int index; 34 | // The transition model, which defines the result of a move. 35 | // After take a set of actions. 36 | TicTacToeState result(position); 37 | // A utility function (also called an objective function or 38 | // payoff function), defines the final numeric value for a 39 | // game that ends in terminal state s for a player p. 40 | int utility(unsigned int depth); 41 | // The min for max value returned for this state 42 | int max_value(unsigned int depth); 43 | int min_value(unsigned int depth); 44 | // Temp virables 45 | char **temp_board; 46 | unsigned int **temp_state; 47 | void print_debug_info(TicTacToeState &next_state, 48 | int depth, int temp); 49 | }; 50 | 51 | #endif --------------------------------------------------------------------------------