/
mob1le
/
qt-chess
Обзор
Документация
Войти
/
mob1le
/
qt-chess
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/core/board_model.cpp
522 строки
16 KB
mob1le
Реализован "мат".
18 июн 2026, 14:48
18 июн 2026, 14:48
87fe49d
Код
Авторство
О чём код?
#include "include/core/board_model.hpp" BoardModel::BoardModel(PieceColor player_color) : m_cur_piece_pos(-1, -1), m_targ_piece_pos(-1, -1), player_white(true), m_is_check(false), m_is_check_and_mate(false) { if (player_color == PieceColor::Black) { player_white = false; m_turn = PieceColor::Black; } else if (player_color == PieceColor::White) { player_white = true; m_turn = PieceColor::White; } setupInitialPosition(); } void BoardModel::isValidatingMove(Position base_pos, Position target_pos) { int valid_move = false; currentPieceConfig(base_pos); targetPieceConfig(target_pos); if ((m_targ_piece_pos.getY() < 0 || m_targ_piece_pos.getY() > 7) || (m_targ_piece_pos.getX() < 0 || m_targ_piece_pos.getX() > 7) || (m_cur_piece_pos == m_targ_piece_pos) || (m_turn != m_cur_piece_color)) { return; } switch (m_cur_piece_type) { case PieceType::Pawn: { if (rulesPawn()) { valid_move = true; if (m_cur_piece->getAble2Cells()) { m_cur_piece->setAble2Cells(false); } movePieceOnModel(m_cur_piece_pos, m_targ_piece_pos); } break; } case PieceType::Rook: { if (rulesRook()) { valid_move = true; movePieceOnModel(m_cur_piece_pos, m_targ_piece_pos); } } break; case PieceType::Bishop: { if (rulesBishop()) { valid_move = true; movePieceOnModel(m_cur_piece_pos, m_targ_piece_pos); } } break; case PieceType::Queen: { if (rulesQueen()) { valid_move = true; movePieceOnModel(m_cur_piece_pos, m_targ_piece_pos); } } break; case PieceType::King: { if (rulesKing()) { valid_move = true; movePieceOnModel(m_cur_piece_pos, m_targ_piece_pos); } break; } case PieceType::Knight: { if (rulesKnight()) { valid_move = true; movePieceOnModel(m_cur_piece_pos, m_targ_piece_pos); } break; } default: break; } if (valid_move) { nextTurn(); m_is_check = isCheck(m_turn); m_is_check_and_mate = isCheckAndMate(m_turn); if (m_is_check_and_mate) { // Тут вывод сообщения об окончании игры } } } PieceColor BoardModel::getPlayerColor() { if (player_white) { return PieceColor::White; } return PieceColor::Black; } void BoardModel::setupInitialPosition() { for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { if (y == (player_white ? 7 : 0)) { if (x == Column::A || x == Column::H) { m_board[x][y] = std::make_unique<Piece>(PieceType::Rook, PieceColor::White, Position(x, y)); } else if (x == Column::B || x == Column::G) { m_board[x][y] = std::make_unique<Piece>(PieceType::Knight, PieceColor::White, Position(x, y)); } else if (x == Column::C || x == Column::F) { m_board[x][y] = std::make_unique<Piece>(PieceType::Bishop, PieceColor::White, Position(x, y)); } else if (x == Column::D) { m_board[x][y] = std::make_unique<Piece>(PieceType::Queen, PieceColor::White, Position(x, y)); } else if (x == Column::E) { m_board[x][y] = std::make_unique<Piece>(PieceType::King, PieceColor::White, Position(x, y)); } } else if (y == (player_white ? 6 : 1)) { m_board[x][y] = std::make_unique<Piece>(PieceType::Pawn, PieceColor::White, Position(x, y)); } else if (y == (player_white ? 1 : 6)) { m_board[x][y] = std::make_unique<Piece>(PieceType::Pawn, PieceColor::Black, Position(x, y)); } else if (y == (player_white ? 0 : 7)) { if (x == Column::A || x == Column::H) { m_board[x][y] = std::make_unique<Piece>(PieceType::Rook, PieceColor::Black, Position(x, y)); } else if (x == Column::B || x == Column::G) { m_board[x][y] = std::make_unique<Piece>(PieceType::Knight, PieceColor::Black, Position(x, y)); } else if (x == Column::C || x == Column::F) { m_board[x][y] = std::make_unique<Piece>(PieceType::Bishop, PieceColor::Black, Position(x, y)); } else if (x == Column::D) { m_board[x][y] = std::make_unique<Piece>(PieceType::Queen, PieceColor::Black, Position(x, y)); } else if (x == Column::E) { m_board[x][y] = std::make_unique<Piece>(PieceType::King, PieceColor::Black, Position(x, y)); } } else { m_board[x][y] = std::make_unique<Piece>(PieceType::Empty, PieceColor::None, Position(x, y)); } } } } bool BoardModel::checkMovableCell(Position target_pos) { Piece *target_cell = m_board[target_pos.getX()][target_pos.getY()].get(); if (target_cell->getColor() == PieceColor::None) { return true; } return false; } void BoardModel::capturePiece(Position enemy_pos) { Piece *defeated_enemy = m_board[enemy_pos.getX()][enemy_pos.getY()].get(); m_captured_pieces.push_back(*defeated_enemy); defeated_enemy->destroyPiece(); this->removePieceFromScene(defeated_enemy); } bool BoardModel::isCheck(PieceColor color) { bool is_check = false; // Проверки шаха Position king_pos(-1, -1); for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { Piece *piece = m_board[x][y].get(); if (piece->getColor() == color && piece->getType() == PieceType::King) { king_pos = piece->getPosition(); break; } } if (king_pos.getX() != -1) break; } for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { Piece *piece = m_board[x][y].get(); if (piece->getColor() != PieceColor::None && piece->getColor() != color && piece->getType() != PieceType::Empty) { currentPieceConfig(piece->getPosition()); targetPieceConfig(king_pos); switch (piece->getType()) { case PieceType::Pawn: is_check = rulesPawn(); break; case PieceType::Rook: is_check = rulesRook(); break; case PieceType::Bishop: is_check = rulesBishop(); break; case PieceType::Queen: is_check = rulesQueen(); break; case PieceType::King: is_check = rulesKing(); break; case PieceType::Knight: is_check = rulesKnight(); break; default: break; } } if (is_check) break; } if (is_check) break; } return is_check; } bool BoardModel::isCheckAndMate(PieceColor color) { if (!m_is_check) return false; for (int from_x = 0; from_x < 8; from_x++) { for (int from_y = 0; from_y < 8; from_y++) { for (int to_x = 0; to_x < 8; to_x++) { for (int to_y = 0; to_y < 8; to_y++) { Piece *piece = m_board[from_x][from_y].get(); if (piece->getColor() != PieceColor::None && piece->getColor() != color && piece->getType() != PieceType::Empty) continue; Position base_pos(from_x, from_y); currentPieceConfig(base_pos); Position target_pos(to_x, to_y); targetPieceConfig(target_pos); bool move_ok = false; switch (m_cur_piece_type) { case PieceType::Pawn: move_ok = rulesPawn(); break; case PieceType::Rook: move_ok = rulesRook(); break; case PieceType::Bishop: move_ok = rulesBishop(); break; case PieceType::Queen: move_ok = rulesQueen(); break; case PieceType::King: move_ok = rulesKing(); break; case PieceType::Knight: move_ok = rulesKnight(); break; default: break; } if (move_ok) { Position temp_base_pos = m_cur_piece_pos; Position temp_target_pos = m_targ_piece_pos; m_board[temp_base_pos.getX()][temp_base_pos.getY()]->setPosition(temp_target_pos); m_board[temp_target_pos.getX()][temp_target_pos.getY()]->setPosition(temp_base_pos); std::swap(m_board[temp_base_pos.getX()][temp_base_pos.getY()], m_board[temp_target_pos.getX()][temp_target_pos.getY()]); if (!isCheck(color)) { m_board[temp_target_pos.getX()][temp_target_pos.getY()]->setPosition(temp_base_pos); m_board[temp_base_pos.getX()][temp_base_pos.getY()]->setPosition(temp_target_pos); std::swap(m_board[temp_target_pos.getX()][temp_target_pos.getY()], m_board[temp_base_pos.getX()][temp_base_pos.getY()]); return false; } m_board[temp_target_pos.getX()][temp_target_pos.getY()]->setPosition(temp_base_pos); m_board[temp_base_pos.getX()][temp_base_pos.getY()]->setPosition(temp_target_pos); std::swap(m_board[temp_target_pos.getX()][temp_target_pos.getY()], m_board[temp_base_pos.getX()][temp_base_pos.getY()]); } } } } } return true; } void BoardModel::nextTurn() { if (m_turn == PieceColor::Black) { m_turn = PieceColor::White; } else if (m_turn == PieceColor::White) { m_turn = PieceColor::Black; } } bool BoardModel::isPathClear(Position start, Position end) { int dx = end.getX() - start.getX(); int dy = end.getY() - start.getY(); // Проверка, что это прямое движение (по горизонтали, вертикали или диагонали) if (dx != 0 && dy != 0 && abs(dx) != abs(dy)) return false; int stepX = (dx == 0) ? 0 : dx / abs(dx); int stepY = (dy == 0) ? 0 : dy / abs(dy); for (int i = 1; i < abs(dx == 0 ? dy : dx); ++i) { Position intermediate(start.getX() + i * stepX, start.getY() + i * stepY); if (!checkMovableCell(intermediate)) { return false; } } return true; } void BoardModel::currentPieceConfig(Position curr_pos) { m_cur_piece = this->getPiece(curr_pos.getX(), curr_pos.getY()); m_cur_piece_pos = m_cur_piece->getPosition(); m_cur_piece_color = m_cur_piece->getColor(); m_cur_piece_type = m_cur_piece->getType(); } void BoardModel::targetPieceConfig(Position target_pos) { m_targ_piece = this->getPiece(target_pos.getX(), target_pos.getY()); m_targ_piece_pos = m_targ_piece->getPosition(); m_targ_piece_color = m_targ_piece->getColor(); m_targ_piece_type = m_targ_piece->getType(); int base_x = m_cur_piece_pos.getX(); int base_y = m_cur_piece_pos.getY(); int target_x = m_targ_piece_pos.getX(); int target_y = m_targ_piece_pos.getY(); m_dx = target_x - base_x; m_dy = target_y - base_y; } void BoardModel::movePieceOnModel(Position base_pos, Position target_pos) { if ((m_targ_piece->getColor() != m_cur_piece->getColor()) && (m_targ_piece->getColor() != PieceColor::None)) { capturePiece(m_targ_piece_pos); } m_board[base_pos.getX()][base_pos.getY()]->setPosition(target_pos); m_board[target_pos.getX()][target_pos.getY()]->setPosition(base_pos); std::swap(m_board[base_pos.getX()][base_pos.getY()], m_board[target_pos.getX()][target_pos.getY()]); } bool BoardModel::rulesPawn() { if (m_cur_piece_color == PieceColor::White && (m_targ_piece_pos.getY() < m_cur_piece_pos.getY())) { if (m_targ_piece_pos.getX() == m_cur_piece_pos.getX()) { if ((abs(m_dy) <= (m_cur_piece->getAble2Cells() ? 2 : 1))) { if (isPathClear(m_cur_piece_pos, m_targ_piece_pos) && checkMovableCell(m_targ_piece_pos)) { return true; } } } else if ((abs(m_dx) == 1) && (abs(m_dy) == 1) && (m_targ_piece->getColor() == PieceColor::Black)) { return true; } } else if (m_cur_piece_color == PieceColor::Black && (m_targ_piece_pos.getY() > m_cur_piece_pos.getY())) { if (m_dx == 0) { if ((abs(m_dy) <= (m_cur_piece->getAble2Cells() ? 2 : 1))) { if (isPathClear(m_cur_piece_pos, m_targ_piece_pos) && checkMovableCell(m_targ_piece_pos)) { return true; } } } else if ((abs(m_dx) == 1) && (abs(m_dy) == 1) && (m_targ_piece->getColor() == PieceColor::White)) { return true; } } return false; } bool BoardModel::rulesKing() { if ((abs(m_dx) == 1) || (abs(m_dy) == 1)) { if (abs(m_dx) == abs(m_dy) || (m_dx == 0) || (m_dx == 0)) { if (isPathClear(m_cur_piece_pos, m_targ_piece_pos) && (m_cur_piece_color != m_targ_piece_color)) { return true; } } } return false; } bool BoardModel::rulesQueen() { if (abs(m_dx) == abs(m_dy) || (m_dx == 0) || (m_dy == 0)) { if (isPathClear(m_cur_piece_pos, m_targ_piece_pos) && (m_cur_piece_color != m_targ_piece_color)) { return true; } } return false; } bool BoardModel::rulesBishop() { if (abs(m_dx) == abs(m_dy)) { if (isPathClear(m_cur_piece_pos, m_targ_piece_pos) && (m_cur_piece_color != m_targ_piece_color)) { return true; } } return false; } bool BoardModel::rulesKnight() { if (abs(m_dx) == 2) { if (abs(m_dy) == 1) { return true; } } else if (abs(m_dy) == 2) { if (abs(m_dx) == 1) { return true; } } return false; } bool BoardModel::rulesRook() { if ((m_dx == 0) || (m_dy == 0)) { if (isPathClear(m_cur_piece_pos, m_targ_piece_pos) && (m_cur_piece_color != m_targ_piece_color)) { return true; } } return false; }