| 
					
				 | 
			
			
				@@ -0,0 +1,204 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "CheckerBoard.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void CheckerBoard::placeChecker(CheckerPosition position, CheckerPiece checker) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    board[position.y][position.x] = checker; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+CheckerBoard::CheckerBoard() {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+CheckerBoard CheckerBoard::loadFromFile(string filename) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    CheckerBoard board = CheckerBoard(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ifstream file(filename); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    string line; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int color = WHITE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    while (getline(file, line)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (line.find("White:") != string::npos) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            color = WHITE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else if (line.find("Black:") != string::npos) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            color = BLACK; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else if (!line.empty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (line[0] == 'M') board.placeChecker(CheckerPosition(line.substr(1, 2)), color == WHITE ? CheckerPiece::WHITE_KING : CheckerPiece::BLACK_KING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else board.placeChecker(CheckerPosition(line), color == WHITE ? CheckerPiece::WHITE : CheckerPiece::BLACK); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    file.close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return board; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int CheckerBoard::getCheckerAt(CheckerPosition pos) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!pos.isValid()) return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return board[pos.y][pos.x]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void CheckerBoard::moveChecker(CheckerPosition from, CheckerPosition to) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    CheckerPiece checker = board[from.y][from.x]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    board[from.y][from.x] = CheckerPiece::NONE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    board[to.y][to.x] = checker; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void CheckerBoard::print() const 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    wcout << "--------------------------------" << endl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (int y = BOARD_SIZE-1; y >= 0; y--) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (int x = 0; x < BOARD_SIZE; x++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            wcout << '|'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            switch (board[y][x]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            case CheckerPiece::BLACK: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                wcout << L" ⬤ "; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            case CheckerPiece::WHITE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                wcout << L" ◯ "; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            case CheckerPiece::BLACK_KING: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                wcout << L" ◆ "; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            case CheckerPiece::WHITE_KING: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                wcout << L" ◇ "; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                wcout << L"   "; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        wcout << '|' << endl << "--------------------------------" << endl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+std::vector<CheckerBoard> CheckerBoard::generateLegalMoves(bool isWhite) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    std::vector<CheckerBoard> moves; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (int i = 0; i < BOARD_SIZE; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (int j = 0; j < BOARD_SIZE; ++j) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ((isWhite && (board[i][j] == WHITE || board[i][j] == WHITE_KING)) || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (!isWhite && (board[i][j] == BLACK || board[i][j] == BLACK_KING))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                generateMovesForPiece(CheckerPosition(i, j), moves); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return moves; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void CheckerBoard::applyMove(const CheckerBoard& move) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (int i = 0; i < BOARD_SIZE; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (int j = 0; j < BOARD_SIZE; ++j) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            board[i][j] = move.board[i][j]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int CheckerBoard::evaluate() const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int score = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (int i = 0; i < BOARD_SIZE; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (int j = 0; j < BOARD_SIZE; ++j) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (board[i][j] == WHITE) score += 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else if (board[i][j] == WHITE_KING) score += 3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else if (board[i][j] == BLACK) score -= 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else if (board[i][j] == BLACK_KING) score -= 3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return score; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+bool CheckerBoard::isGameOver() const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bool whiteExists = false, blackExists = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (int i = 0; i < BOARD_SIZE; ++i) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (int j = 0; j < BOARD_SIZE; ++j) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (board[i][j] == WHITE || board[i][j] == WHITE_KING) whiteExists = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (board[i][j] == BLACK || board[i][j] == BLACK_KING) blackExists = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return !whiteExists || !blackExists; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void CheckerBoard::generateMovesForPiece(CheckerPosition pos, std::vector<CheckerBoard>& moves) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    CheckerPiece piece = board[pos.y][pos.x]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int directions[4][2] = { {1, 1}, {1, -1}, {-1, 1}, {-1, -1} }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (auto& dir : directions) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        CheckerPosition newpos(pos.x + dir[0], pos.y + dir[1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (isValidMove(pos, newpos, piece)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            CheckerBoard newBoard = *this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            newBoard.board[newpos.y][newpos.x] = newBoard.board[pos.y][pos.x]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            newBoard.board[pos.y][pos.x] = CheckerPiece::NONE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ((piece == WHITE && newpos.y == 0) || (piece == BLACK && newpos.y == BOARD_SIZE - 1)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                newBoard.board[newpos.y][newpos.x] = (piece == WHITE) ? WHITE_KING : BLACK_KING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            moves.push_back(newBoard); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            CheckerPosition cpos(pos.x + 2 * dir[0], pos.y + 2 * dir[1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (isValidCapture(pos, newpos, cpos, piece)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                CheckerBoard newBoard = *this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                newBoard.board[cpos.y][cpos.x] = newBoard.board[pos.y][pos.x]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                newBoard.board[pos.y][pos.x] = CheckerPiece::NONE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                newBoard.board[newpos.y][newpos.x] = CheckerPiece::NONE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if ((piece == WHITE && cpos.y == 0) || (piece == BLACK && cpos.y == BOARD_SIZE - 1)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    newBoard.board[cpos.y][cpos.x] = (piece == WHITE) ? WHITE_KING : BLACK_KING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                moves.push_back(newBoard); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                generateAdditionalCaptures(cpos, newBoard, moves); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+bool CheckerBoard::isValidMove(CheckerPosition oldPos, CheckerPosition newPos, CheckerPiece piece) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (newPos.x < 0 || newPos.x >= BOARD_SIZE || newPos.y < 0 || newPos.y >= BOARD_SIZE) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (board[newPos.y][newPos.x] != CheckerPiece::NONE) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (piece == WHITE && newPos.y <= oldPos.y) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (piece == BLACK && newPos.y >= oldPos.y) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void CheckerBoard::generateAdditionalCaptures(CheckerPosition pos, CheckerBoard& currentBoard, std::vector<CheckerBoard>& moves) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    CheckerPiece piece = currentBoard.board[pos.y][pos.x]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int directions[4][2] = { {1, 1}, {1, -1}, {-1, 1}, {-1, -1} }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (auto& dir : directions) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        CheckerPosition npos(pos.x + dir[0], pos.y + dir[1]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        CheckerPosition cpos(pos.x + 2 * dir[0], pos.y + 2 * dir[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (isValidCapture(pos, npos, cpos, piece)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            CheckerBoard newBoard = currentBoard; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            newBoard.board[cpos.y][cpos.x] = newBoard.board[pos.y][pos.x]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            newBoard.board[pos.y][pos.x] = CheckerPiece::NONE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            newBoard.board[npos.y][npos.x] = CheckerPiece::NONE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ((piece == WHITE && cpos.y == 0) || (piece == BLACK && cpos.y == BOARD_SIZE - 1)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                newBoard.board[cpos.y][cpos.x] = (piece == WHITE) ? WHITE_KING : BLACK_KING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            moves.push_back(newBoard); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            generateAdditionalCaptures(cpos, newBoard, moves); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+bool CheckerBoard::isValidCapture(CheckerPosition pos, CheckerPosition newPos, CheckerPosition cpos, CheckerPiece piece) const { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (cpos.y < 0 || cpos.y >= BOARD_SIZE || cpos.x < 0 || cpos.x >= BOARD_SIZE) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (board[cpos.y][cpos.x] != CheckerPiece::NONE) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (board[newPos.y][newPos.x] == CheckerPiece::NONE) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (piece == WHITE && (board[newPos.y][newPos.x] == BLACK || board[newPos.y][newPos.x] == BLACK_KING)) return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (piece == BLACK && (board[newPos.y][newPos.x] == WHITE || board[newPos.y][newPos.x] == WHITE_KING)) return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if ((piece == WHITE_KING || piece == BLACK_KING) && abs(cpos.y - pos.y) == 2 && abs(cpos.x - pos.x) == 2) return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |