Программа «Шахматы»

В мире компьютерных настольных игр одной из самых популярных и увлекательных являются шахматы. Эта древняя игра, богатая историей и стратегическими глубинами, давно стала объектом изучения и вдохновения для программистов по всему миру. Создание программы для шахмат — это не только техническое испытание, но и возможность погрузиться в мир логических решений, тактики и стратегии. В данной статье мы исследуем процесс создания программы «Шахматы», начиная с основных правил и структуры доски, и заканчивая реализацией пользовательского интерфейса и проверкой условий окончания игры.

Теория

Создание алгоритма для программы «Шахматы» — это сложная и многозадачная задача, которая включает в себя обработку ходов, проверку правил игры, а также отображение доски и взаимодействие с игроками. Вот общий алгоритм, который может служить основой для вашей программы «Шахматы»:

  • Инициализация доски. Создайте двумерный массив, представляющий доску шахмат. Расставьте фигуры на начальные позиции (пешки, ладьи, кони, слоны, ферзь, король).
  • Отображение доски. Создайте функцию для вывода текущего состояния доски на экран в текстовом виде. Это поможет игрокам видеть расположение фигур.
  • Получение хода от игроков. Считывайте ходы игроков с клавиатуры (или другого источника ввода). Проверяйте формат хода и валидность хода с помощью функции проверки валидности.
  • Проверка валидности хода. Напишите функцию, которая будет проверять, является ли введенный ход допустимым с учетом правил шахмат. Проверяйте такие правила, как ход фигур, ходы пешек (включая взятие на проходе), рокировка и другие особенности.
  • Выполнение хода. Если ход был правильным, обновите состояние доски в соответствии с новым положением фигур.
  • Проверка условий окончания игры. После каждого хода проверяйте, не наступило ли условие окончания игры, такое как мат, пат или ничья.
  • Переключение хода между игроками. После каждого успешного хода переключайте ход к другому игроку.
  • Повторение шагов. Продолжайте цикл, пока игра не завершится.

Это общий алгоритм, который может служить отправной точкой для создания программы «Шахматы» на любом языке программирования. В зависимости от вашего опыта и амбиций, вы можете добавить более сложные функции, такие как рокировка, взятие на проходе, искусственный интеллект для компьютерного противника и многие другие.

C++

Простой пример программы «шахматы» на C++. Эта программа создает доску 8×8 и позволяет двум игрокам делать ходы с помощью ввода с клавиатуры. Программа проверяет правильность ходов и отображает доску после каждого хода.

#include <iostream>
using namespace std;

// Функция для отображения шахматной доски
void DisplayBoard(char board[8][8]) {
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            cout << board[i][j] << " ";
        }
        cout << endl;
    }
}

// Функция для проверки допустимости хода
bool IsValidMove(char board[8][8], int fromX, int fromY, int toX, int toY) {
    // Проверяем, находится ли начальная клетка на доске и содержит ли фигуру
    if (fromX < 0 || fromX >= 8 || fromY < 0 || fromY >= 8 || board[fromX][fromY] == ' ') {
        return false;
    }

    // Проверяем, находится ли целевая клетка на доске
    if (toX < 0 || toX >= 8 || toY < 0 || toY >= 8) {
        return false;
    }

    // Проверяем, является ли целевая клетка пустой или содержит фигуру противника
    return (board[toX][toY] == ' ' || islower(board[fromX][fromY]) != islower(board[toX][toY]));
}

int main() {
    char board[8][8] = {
        {'r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'},
        {'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'},
        {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
        {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
        {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
        {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
        {'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'},
        {'R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R'}
    };

    int fromX, fromY, toX, toY;

    while (true) {
        // Отображаем доску
        DisplayBoard(board);

        // Ввод хода игрока
        cout << "Введите координаты хода (от 0 до 7) в формате (начальная_x начальная_y конечная_x конечная_y): ";
        cin >> fromX >> fromY >> toX >> toY;

        // Проверяем допустимость хода
        if (!IsValidMove(board, fromX, fromY, toX, toY)) {
            cout << "Недопустимый ход! Попробуйте еще раз." << endl;
            continue;
        }

        // Выполняем ход
        board[toX][toY] = board[fromX][fromY];
        board[fromX][fromY] = ' ';

        // Завершение игры (пример: мат)
        // Добавьте соответствующие условия для проверки окончания игры

        // Переключение хода к другому игроку (просто меняет регистр фигуры)
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                if (islower(board[i][j])) {
                    board[i][j] = toupper(board[i][j]);
                } else if (isupper(board[i][j])) {
                    board[i][j] = tolower(board[i][j]);
                }
            }
        }
    }

    return 0;
}

Это очень простой пример шахматной программы на C++. Вы можете дополнить этот код для реализации более сложных правил и возможностей, таких как рокировка, взятие на проходе, а также проверку на шах и мат.

C#

Простой пример программы «шахматы» на C# с текстовым интерфейсом.

using System;

class ChessGame
{
    static char[,] board = new char[8, 8];

    static void InitializeBoard()
    {
        // Начальная расстановка фигур на доске
        char[] initialPieces = { 'r', 'n', 'b', 'q', 'k', 'b', 'n', 'r' };

        for (int i = 0; i < 8; i++)
        {
            board[0, i] = char.ToUpper(initialPieces[i]);
            board[1, i] = 'p';
            board[6, i] = 'P';
            board[7, i] = initialPieces[i];
        }
    }

    static void DisplayBoard()
    {
        Console.WriteLine("  a b c d e f g h");
        Console.WriteLine("  ---------------");

        for (int row = 0; row < 8; row++)
        {
            Console.Write(8 - row + " ");
            for (int col = 0; col < 8; col++)
            {
                Console.Write("|" + board[row, col]);
            }
            Console.WriteLine("|");
            Console.WriteLine("  ---------------");
        }
    }

    static bool IsValidMove(int fromX, int fromY, int toX, int toY)
    {
        // Проверяем, находится ли начальная клетка на доске и содержит ли фигуру
        if (fromX < 0 || fromX >= 8 || fromY < 0 || fromY >= 8 || board[fromX, fromY] == ' ')
        {
            return false;
        }

        // Проверяем, находится ли целевая клетка на доске
        if (toX < 0 || toX >= 8 || toY < 0 || toY >= 8)
        {
            return false;
        }

        // Проверяем, является ли целевая клетка пустой или содержит фигуру противника
        return (board[toX, toY] == ' ' || char.IsLower(board[fromX, fromY]) != char.IsLower(board[toX, toY]));
    }

    static void Main(string[] args)
    {
        InitializeBoard();

        while (true)
        {
            Console.Clear();
            DisplayBoard();

            Console.WriteLine("Введите ход (откуда куда, например 'e2 e4'): ");
            string move = Console.ReadLine();
            if (move.Length != 5)
            {
                Console.WriteLine("Недопустимый формат хода. Повторите ввод.");
                continue;
            }

            int fromX = 7 - (move[1] - '1');
            int fromY = move[0] - 'a';
            int toX = 7 - (move[4] - '1');
            int toY = move[3] - 'a';

            if (!IsValidMove(fromX, fromY, toX, toY))
            {
                Console.WriteLine("Недопустимый ход! Повторите ввод.");
                continue;
            }

            // Выполняем ход
            board[toX, toY] = board[fromX, fromY];
            board[fromX, fromY] = ' ';

            // Завершение игры (пример: мат)
            // Добавьте соответствующие условия для проверки окончания игры

            // Переключение хода к другому игроку (просто меняет регистр фигуры)
            for (int row = 0; row < 8; row++)
            {
                for (int col = 0; col < 8; col++)
                {
                    if (char.IsLower(board[row, col]))
                    {
                        board[row, col] = char.ToUpper(board[row, col]);
                    }
                    else if (char.IsUpper(board[row, col]))
                    {
                        board[row, col] = char.ToLower(board[row, col]);
                    }
                }
            }
        }
    }
}

Python

def initialize_board():
    board = [['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'],
             ['p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'],
             [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
             [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
             [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
             [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
             ['P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'],
             ['R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R']]
    return board

def display_board(board):
    for row in board:
        print(' '.join(row))
    print()

def is_valid_move(board, from_x, from_y, to_x, to_y):
    # Проверяем, находится ли начальная клетка на доске и содержит ли фигуру
    if from_x < 0 or from_x >= 8 or from_y < 0 or from_y >= 8 or board[from_x][from_y] == ' ':
        return False

    # Проверяем, находится ли целевая клетка на доске
    if to_x < 0 or to_x >= 8 or to_y < 0 or to_y >= 8:
        return False

    # Проверяем, является ли целевая клетка пустой или содержит фигуру противника
    return board[to_x][to_y] == ' ' or board[from_x][from_y].islower() != board[to_x][to_y].islower()

def main():
    board = initialize_board()
    is_player1_turn = True

    while True:
        display_board(board)

        if is_player1_turn:
            print("Ход игрока 1 (белые):")
        else:
            print("Ход игрока 2 (черные):")

        move = input("Введите ход (в формате 'e2 e4'): ").strip().split()
        
        if len(move) != 2 or len(move[0]) != 2 or len(move[1]) != 2:
            print("Недопустимый формат хода. Попробуйте еще раз.")
            continue

        from_x, from_y = ord(move[0][0]) - ord('a'), int(move[0][1]) - 1
        to_x, to_y = ord(move[1][0]) - ord('a'), int(move[1][1]) - 1

        if not is_valid_move(board, from_x, from_y, to_x, to_y):
            print("Недопустимый ход! Попробуйте еще раз.")
            continue

        # Выполняем ход
        board[to_x][to_y] = board[from_x][from_y]
        board[from_x][from_y] = ' '

        # Завершение игры (пример: мат)
        # Добавьте соответствующие условия для проверки окончания игры

        # Переключение хода к другому игроку (просто меняет регистр фигуры)
        for i in range(8):
            for j in range(8):
                if board[i][j].islower():
                    board[i][j] = board[i][j].upper()
                elif board[i][j].isupper():
                    board[i][j] = board[i][j].lower()

        is_player1_turn = not is_player1_turn

if __name__ == "__main__":
    main()

Java

import java.util.Scanner;

public class ChessGame {
    public static char[][] board = new char[8][8];

    public static void initializeBoard() {
        // Начальная расстановка фигур на доске
        char[] initialPieces = {'r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'};

        for (int i = 0; i < 8; i++) {
            board[0][i] = Character.toUpperCase(initialPieces[i]);
            board[1][i] = 'p';
            board[6][i] = 'P';
            board[7][i] = initialPieces[i];
        }
    }

    public static void displayBoard() {
        System.out.println("  a b c d e f g h");
        System.out.println("  ---------------");

        for (int row = 0; row < 8; row++) {
            System.out.print(8 - row + " ");
            for (int col = 0; col < 8; col++) {
                System.out.print("|" + board[row][col]);
            }
            System.out.println("|");
            System.out.println("  ---------------");
        }
    }

    public static boolean isValidMove(int fromX, int fromY, int toX, int toY) {
        // Проверяем, находится ли начальная клетка на доске и содержит ли фигуру
        if (fromX < 0 || fromX >= 8 || fromY < 0 || fromY >= 8 || board[fromX][fromY] == ' ') {
            return false;
        }

        // Проверяем, находится ли целевая клетка на доске
        if (toX < 0 || toX >= 8 || toY < 0 || toY >= 8) {
            return false;
        }

        // Проверяем, является ли целевая клетка пустой или содержит фигуру противника
        return board[toX][toY] == ' ' || Character.isLowerCase(board[fromX][fromY]) != Character.isLowerCase(board[toX][toY]);
    }

    public static void main(String[] args) {
        initializeBoard();
        boolean isPlayer1Turn = true;

        Scanner scanner = new Scanner(System.in);

        while (true) {
            displayBoard();

            if (isPlayer1Turn) {
                System.out.println("Ход игрока 1 (белые):");
            } else {
                System.out.println("Ход игрока 2 (черные):");
            }

            System.out.print("Введите ход (в формате 'e2 e4'): ");
            String move = scanner.nextLine().trim();
            String[] parts = move.split(" ");

            if (parts.length != 2 || parts[0].length() != 2 || parts[1].length() != 2) {
                System.out.println("Недопустимый формат хода. Попробуйте еще раз.");
                continue;
            }

            int fromX = 7 - (parts[0].charAt(1) - '1');
            int fromY = parts[0].charAt(0) - 'a';
            int toX = 7 - (parts[1].charAt(1) - '1');
            int toY = parts[1].charAt(0) - 'a';

            if (!isValidMove(fromX, fromY, toX, toY)) {
                System.out.println("Недопустимый ход! Попробуйте еще раз.");
                continue;
            }

            // Выполняем ход
            board[toX][toY] = board[fromX][fromY];
            board[fromX][fromY] = ' ';

            // Завершение игры (пример: мат)
            // Добавьте соответствующие условия для проверки окончания игры

            // Переключение хода к другому игроку (просто меняет регистр фигуры)
            for (int row = 0; row < 8; row++) {
                for (int col = 0; col < 8; col++) {
                    if (Character.isLowerCase(board[row][col])) {
                        board[row][col] = Character.toUpperCase(board[row][col]);
                    } else if (Character.isUpperCase(board[row][col])) {
                        board[row][col] = Character.toLowerCase(board[row][col]);
                    }
                }
            }

            isPlayer1Turn = !isPlayer1Turn;
        }
    }
}

Pascal

program ChessGame;

type
  ChessBoard = array [1..8, 1..8] of Char;

var
  board: ChessBoard;

procedure InitializeBoard;
var
  initialPieces: string;
  i, j: Integer;
begin
  // Начальная расстановка фигур на доске
  initialPieces := 'rnbqkbnr';

  for i := 1 to 8 do
  begin
    for j := 1 to 8 do
    begin
      if i = 1 then
        board[i, j] := initialPieces[j]
      else if i = 2 then
        board[i, j] := 'p'
      else if i = 7 then
        board[i, j] := 'P'
      else if i = 8 then
        board[i, j] := initialPieces[j]
      else
        board[i, j] := ' ';
    end;
  end;
end;

procedure DisplayBoard;
var
  i, j: Integer;
begin
  WriteLn('  a b c d e f g h');
  WriteLn('  ---------------');

  for i := 1 to 8 do
  begin
    Write(9 - i, ' ');
    for j := 1 to 8 do
    begin
      Write('|', board[i, j]);
    end;
    WriteLn('|');
    WriteLn('  ---------------');
  end;
end;

function IsValidMove(fromX, fromY, toX, toY: Integer): Boolean;
begin
  // Проверяем, находится ли начальная клетка на доске и содержит ли фигуру
  if (fromX < 1) or (fromX > 8) or (fromY < 1) or (fromY > 8) or (board[fromX, fromY] = ' ') then
  begin
    IsValidMove := False;
    Exit;
  end;

  // Проверяем, находится ли целевая клетка на доске
  if (toX < 1) or (toX > 8) or (toY < 1) or (toY > 8) then
  begin
    IsValidMove := False;
    Exit;
  end;

  // Проверяем, является ли целевая клетка пустой или содержит фигуру противника
  IsValidMove := (board[toX, toY] = ' ') or (LowerCase(board[fromX, fromY]) <> LowerCase(board[toX, toY]));
end;

var
  isPlayer1Turn: Boolean;
  move: string;
  fromX, fromY, toX, toY: Integer;
begin
  InitializeBoard;
  isPlayer1Turn := True;

  while True do
  begin
    DisplayBoard;

    if isPlayer1Turn then
      WriteLn('Ход игрока 1 (белые):')
    else
      WriteLn('Ход игрока 2 (черные):');

    Write('Введите ход (в формате ''e2 e4''): ');
    ReadLn(move);

    if Length(move) <> 5 then
    begin
      WriteLn('Недопустимый формат хода. Попробуйте еще раз.');
      Continue;
    end;

    fromY := Ord(move[1]) - Ord('a') + 1;
    fromX := 9 - StrToInt(move[2]);
    toY := Ord(move[4]) - Ord('a') + 1;
    toX := 9 - StrToInt(move[5]);

    if not IsValidMove(fromX, fromY, toX, toY) then
    begin
      WriteLn('Недопустимый ход! Попробуйте еще раз.');
      Continue;
    end;

    // Выполняем ход
    board[toX, toY] := board[fromX, fromY];
    board[fromX, fromY] := ' ';

    // Завершение игры (пример: мат)
    // Добавьте соответствующие условия для проверки окончания игры

    // Переключение хода к другому игроку (просто меняет регистр фигуры)
    for i := 1 to 8 do
    begin
      for j := 1 to 8 do
      begin
        if board[i, j] = LowerCase(board[i, j]) then
          board[i, j] := UpperCase(board[i, j])
        else if board[i, j] = UpperCase(board[i, j]) then
          board[i, j] := LowerCase(board[i, j]);
      end;
    end;

    isPlayer1Turn := not isPlayer1Turn;
  end;
end.

JavaScript

const readline = require('readline');

const board = [
  ['r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'],
  ['p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'],
  [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
  [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
  [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
  [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
  ['P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'],
  ['R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R'],
];

function displayBoard(board) {
  console.log('  a b c d e f g h');
  console.log('  ---------------');

  for (let i = 0; i < 8; i++) {
    process.stdout.write(8 - i + ' ');
    for (let j = 0; j < 8; j++) {
      process.stdout.write('|' + board[i][j]);
    }
    console.log('|');
    console.log('  ---------------');
  }
}

function isValidMove(board, fromX, fromY, toX, toY) {
  // Проверяем, находится ли начальная клетка на доске и содержит ли фигуру
  if (
    fromX < 0 ||
    fromX >= 8 ||
    fromY < 0 ||
    fromY >= 8 ||
    board[fromX][fromY] === ' '
  ) {
    return false;
  }

  // Проверяем, находится ли целевая клетка на доске
  if (toX < 0 || toX >= 8 || toY < 0 || toY >= 8) {
    return false;
  }

  // Проверяем, является ли целевая клетка пустой или содержит фигуру противника
  return (
    board[toX][toY] === ' ' ||
    board[fromX][fromY].toLowerCase() !== board[toX][toY].toLowerCase()
  );
}

function main() {
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });

  let isPlayer1Turn = true;

  function makeMove(move) {
    const fromX = 8 - parseInt(move[1]);
    const fromY = move[0].charCodeAt(0) - 'a'.charCodeAt(0);
    const toX = 8 - parseInt(move[4]);
    const toY = move[3].charCodeAt(0) - 'a'.charCodeAt(0);

    if (!isValidMove(board, fromX, fromY, toX, toY)) {
      console.log('Недопустимый ход! Попробуйте еще раз.');
      return;
    }

    // Выполняем ход
    board[toX][toY] = board[fromX][fromY];
    board[fromX][fromY] = ' ';

    // Завершение игры (пример: мат)
    // Добавьте соответствующие условия для проверки окончания игры

    // Переключение хода к другому игроку (просто меняет регистр фигуры)
    for (let i = 0; i < 8; i++) {
      for (let j = 0; j < 8; j++) {
        if (board[i][j].toLowerCase() === board[i][j]) {
          board[i][j] = board[i][j].toUpperCase();
        } else if (board[i][j].toUpperCase() === board[i][j]) {
          board[i][j] = board[i][j].toLowerCase();
        }
      }
    }

    isPlayer1Turn = !isPlayer1Turn;
    displayBoard(board);
  }

  displayBoard(board);

  rl.on('line', (input) => {
    const move = input.trim();
    if (move.length !== 5) {
      console.log('Недопустимый формат хода. Повторите ввод.');
    } else {
      makeMove(move);
    }
  });
}

main();

PHP

<?php

function initializeBoard() {
    // Начальная расстановка фигур на доске
    $board = array(
        array('r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'),
        array('p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'),
        array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '),
        array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '),
        array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '),
        array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '),
        array('P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'),
        array('R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R')
    );

    return $board;
}

function displayBoard($board) {
    echo "  a b c d e f g h\n";
    echo "  ---------------\n";

    for ($i = 0; $i < 8; $i++) {
        echo 8 - $i . ' ';
        for ($j = 0; $j < 8; $j++) {
            echo '|' . $board[$i][$j];
        }
        echo "|\n";
        echo "  ---------------\n";
    }
}

function isValidMove($board, $fromX, $fromY, $toX, $toY) {
    // Проверяем, находится ли начальная клетка на доске и содержит ли фигуру
    if ($fromX < 0 || $fromX >= 8 || $fromY < 0 || $fromY >= 8 || $board[$fromX][$fromY] === ' ') {
        return false;
    }

    // Проверяем, находится ли целевая клетка на доске
    if ($toX < 0 || $toX >= 8 || $toY < 0 || $toY >= 8) {
        return false;
    }

    // Проверяем, является ли целевая клетка пустой или содержит фигуру противника
    return ($board[$toX][$toY] === ' ' || strtolower($board[$fromX][$fromY]) !== strtolower($board[$toX][$toY]));
}

$board = initializeBoard();
$isPlayer1Turn = true;

while (true) {
    displayBoard($board);

    if ($isPlayer1Turn) {
        echo "Ход игрока 1 (белые):\n";
    } else {
        echo "Ход игрока 2 (черные):\n";
    }

    echo "Введите ход (в формате 'e2 e4'): ";
    $move = trim(fgets(STDIN));

    if (strlen($move) !== 5) {
        echo "Недопустимый формат хода. Попробуйте еще раз.\n";
        continue;
    }

    $fromY = ord($move[0]) - ord('a');
    $fromX = 8 - intval($move[1]);
    $toY = ord($move[3]) - ord('a');
    $toX = 8 - intval($move[4]);

    if (!isValidMove($board, $fromX, $fromY, $toX, $toY)) {
        echo "Недопустимый ход! Попробуйте еще раз.\n";
        continue;
    }

    // Выполняем ход
    $board[$toX][$toY] = $board[$fromX][$fromY];
    $board[$fromX][$fromY] = ' ';

    // Завершение игры (пример: мат)
    // Добавьте соответствующие условия для проверки окончания игры

    // Переключение хода к другому игроку (просто меняет регистр фигуры)
    for ($i = 0; $i < 8; $i++) {
        for ($j = 0; $j < 8; $j++) {
            if (ctype_lower($board[$i][$j])) {
                $board[$i][$j] = strtoupper($board[$i][$j]);
            } elseif (ctype_upper($board[$i][$j])) {
                $board[$i][$j] = strtolower($board[$i][$j]);
            }
        }
    }

    $isPlayer1Turn = !$isPlayer1Turn;
}
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...
Давайте поможем друг другу! Если вы нашли ошибку или хотите предложить лучшее решение, пожалуйста, напишите об этом в комментариях.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *