Крестики-нолики

Мой первый проект на Java. Говорят - код читабельный, табуляция расставлена по правилам. Можно скачать с github.
Буду рад услышать замечания и подсказки, как улучшить код:)
https://github.com/Vsailor/TicTac2




Иерархия классов:


Прямая ссылка: http://imgdepo.ru/id/i6692234

Form.java
abstract public class Form {

    protected static final int SIZE_OF_MATRIX = 8;

    protected static final char BORDER_MATERIAL = '#';

    protected static final char EMPTY_CELL = ' ';

    protected static char[][] matrix = new char[SIZE_OF_MATRIX][SIZE_OF_MATRIX];

    protected static final char FIRST_TOP_COORD = 'a';

    protected static final char FIRST_LEFT_COORD = '1';

    protected static final char MARK_X = 'X';

    protected static final char MARK_O = 'O';

    protected static final int WINNER_SCORE = 3;

    protected static final int STRINGS_MATRIX_COUNT = 3;

    protected static final int TOP_AND_LEFT_BORDER_SIZE = 2;

    protected static final int DOWN_AND_RIGHT_BORDER_SIZE = 1;

    protected static final String COMPUTER_NAME = "Computer";

    protected static final void wrongInputMessage () {

        System.out.println("Wrong input. Please, repeat input.");

    }

    protected static final void notEmptyCellMessage () {

        System.out.println("This cell isn't empty. Please, repeat input.");

    }

}

IPlayer.java
public interface IPlayer {

    public char getMark ();

    public void setMark (char mark);

    public String getPlayerName();

    public void setPlayerName(String playerName);

    public void go (Square square, Round round);

}

Human.java
import java.util.Scanner;

public class Human extends Form implements IPlayer {

    private String playerName = "Player";

    public void setPlayerName (String playerName) {
        this.playerName = playerName;
    }

    public String getPlayerName () {
        return playerName;
    }

    private char mark;

    public Human (char mark) {

        this.mark = mark;

    }

    public Human () {}

    public void setMark (char mark) {

        this.mark = mark;

    };

    public void go (Square square, Round round) {

        Mark playerMark = new Mark(mark);
        Scanner input= new Scanner(System.in);
        String str;

        do {
            do {

                str = input.next();
                playerMark.consoleInput(str);

            } while(!playerMark.cinGood(str));

            if (!square.emptyCell(playerMark.getLeftCoord(), playerMark.getTopCoord())) {

                notEmptyCellMessage();

            }

        } while (!square.emptyCell(playerMark.getLeftCoord(), playerMark.getTopCoord()));

        square.putMark(playerMark);


    };

    public char getMark () {

        return mark;

    };


}

Computer.java
import java.util.Random;

public class Computer extends Form implements IPlayer {

    private char mark;

    private String playerName = "Computer";

    public void setPlayerName (String playerName) {
        this.playerName = playerName;
    }

    public String getPlayerName () {
        return playerName;
    }

    public Computer (char mark) {

        setMark(mark);

    }

    public Computer () {}

    private boolean canPutMarkInTheCenterOfTheMatrix (Square square) {

        if (square.emptyCell('2', 'b')) {

            return true;

        } else {

            return false;

        }

    }

    private void putMarkInCenterOfTheMatrix (Square square, Mark mark) {

        mark.setLeftCoord('2');
        mark.setTopCoord('b');

        if (square.emptyCell(mark.getLeftCoord(), mark.getTopCoord())) {

            square.putMark(mark);

        }

    }


    private boolean canPutMarkInTheConnerOfTheMatrix (Square square) {

        if (square.emptyCell('1','a') || square.emptyCell('1','c') || square.emptyCell('3','a') || square.emptyCell('3','c')) {

            return true;

        } else {

            return false;

        }

    }

    private void putMarkInTheConnerOfTheMatrix (Square square, Mark mark) {

        Random rand = new Random(System.currentTimeMillis());

        do {
            switch (rand.nextInt(4)) {

                case 0:
                    mark.setLeftCoord('1');
                    mark.setTopCoord('a');
                    break;
                case 1:
                    mark.setLeftCoord('1');
                    mark.setTopCoord('c');
                    break;
                case 2:
                    mark.setLeftCoord('3');
                    mark.setTopCoord('a');
                    break;
                case 3:
                    mark.setLeftCoord('3');
                    mark.setTopCoord('c');
                    break;
                default:
            }

        } while (!square.emptyCell(mark.getLeftCoord(),mark.getTopCoord()));

        square.putMark(mark);

    }



    private void putMarkInTheRandomPlace (Square square, Mark mark) {

        Random rand = new Random(System.currentTimeMillis());

        do {

            switch (rand.nextInt(3)) {

                case 0:
                    mark.setLeftCoord('1');
                    break;
                case 1:
                    mark.setLeftCoord('2');
                    break;
                case 2:
                    mark.setLeftCoord('3');
                    break;
                default:
            }

            switch (rand.nextInt(3)) {

                case 0:
                    mark.setTopCoord('a');
                    break;
                case 1:
                    mark.setTopCoord('b');
                    break;
                case 2:
                    mark.setTopCoord('c');
                    break;
                default:
            }
        } while (!square.emptyCell(mark.getLeftCoord(),mark.getTopCoord()));

        square.putMark(mark);

    }


    private boolean playerWillBeWinnerInTheNextStep (Square square, IPlayer player) {

        Mark mark = new Mark(player.getMark());

        for (char i=FIRST_LEFT_COORD; i<FIRST_LEFT_COORD + STRINGS_MATRIX_COUNT; i++) {

            for (char j=FIRST_TOP_COORD; j<FIRST_TOP_COORD + STRINGS_MATRIX_COUNT; j++) {

                mark.setLeftCoord(i);
                mark.setTopCoord(j);

                if (square.emptyCell(mark.getLeftCoord(), mark.getTopCoord())) {

                    square.putMark(mark);

                    if (square.winner(player)) {

                        square.clearCell(mark.getLeftCoord(), mark.getTopCoord());

                        return true;

                    } else {

                        square.clearCell(mark.getLeftCoord(), mark.getTopCoord());

                    }


                }


            }
        }

        return false;

    }

    private void blockCellThatPlayerWillNotBeWinnerInTheNextStep (Square square, Human human) {

        Mark mark = new Mark(human.getMark());

        for (char i=FIRST_LEFT_COORD; i<FIRST_LEFT_COORD + STRINGS_MATRIX_COUNT; i++) {

            for (char j=FIRST_TOP_COORD; j<FIRST_TOP_COORD + STRINGS_MATRIX_COUNT; j++) {

                mark.setLeftCoord(i);
                mark.setTopCoord(j);

                if (square.emptyCell(mark.getLeftCoord(), mark.getTopCoord())) {

                    square.putMark(mark);

                    if (square.winner(human)) {

                        square.clearCell(mark.getLeftCoord(), mark.getTopCoord());

                        if (human.getMark() == MARK_X) {

                            mark.setMark(MARK_O);

                        } else {

                            mark.setMark(MARK_X);

                        }


                        square.putMark(mark);

                        return;


                    } else {

                        square.clearCell(mark.getLeftCoord(), mark.getTopCoord());

                    }


                }


            }
        }

    }


    private void chooseCellToWinInTheNextStep (Square square, IPlayer player) {

        Mark mark = new Mark(player.getMark());

        for (char i=FIRST_LEFT_COORD; i<FIRST_LEFT_COORD + STRINGS_MATRIX_COUNT; i++) {

            for (char j=FIRST_TOP_COORD; j<FIRST_TOP_COORD + STRINGS_MATRIX_COUNT; j++) {

                mark.setLeftCoord(i);
                mark.setTopCoord(j);

                if (square.emptyCell(mark.getLeftCoord(), mark.getTopCoord())) {

                    square.putMark(mark);

                    if (!square.winner(player)) {

                        square.clearCell(mark.getLeftCoord(), mark.getTopCoord());

                    } else {

                        return;

                    }


                }


            }
        }

    }


    public void setMark (char mark) {

        this.mark = mark;

    }

    public char getMark () {

        return mark;

    };

    private boolean cleverRandom (Square square, Human human, Mark mark) {

        Mark humanMark = new Mark(human.getMark());
        if (square.belongs(humanMark, '2', 'a') && square.belongs(humanMark, '1', 'b')) {
            mark.setLeftCoord('1');
            mark.setTopCoord('a');
            square.putMark(mark);
            return true;

        }

        if (square.belongs(humanMark, '1', 'b') && square.belongs(humanMark, '2', 'c')) {
            mark.setLeftCoord('1');
            mark.setTopCoord('c');
            square.putMark(mark);
            return true;

        }

        if (square.belongs(humanMark, '3', 'b') && square.belongs(humanMark, '2', 'c')) {
            mark.setLeftCoord('3');
            mark.setTopCoord('c');
            square.putMark(mark);
            return true;

        }

        if (square.belongs(humanMark, '3', 'b') && square.belongs(humanMark, '2', 'a')) {
            mark.setLeftCoord('3');
            mark.setTopCoord('a');
            square.putMark(mark);
            return true;

        }

        return false;
    }

    public void go (Square square, Round round) {

        Mark humanMark;
        Mark computerMark = new Mark(this.getMark());

        Human fakeHuman;

        if (round.start == 1) {
            if (this.getMark() == MARK_X) {
                fakeHuman = new Human(MARK_O);
                humanMark = new Mark(MARK_O);
            } else {

                fakeHuman = new Human(MARK_X);
                humanMark = new Mark(MARK_X);
            }



        } else {
            if (this.getMark() == MARK_O) {
                fakeHuman = new Human(MARK_X);
                humanMark = new Mark(MARK_X);
            } else {

                fakeHuman = new Human(MARK_O);
                humanMark = new Mark(MARK_O);
            }

        }


        if (playerWillBeWinnerInTheNextStep(square, this)) {

            chooseCellToWinInTheNextStep(square, this);
            return;

        }

        if (playerWillBeWinnerInTheNextStep(square, fakeHuman)) {

            blockCellThatPlayerWillNotBeWinnerInTheNextStep(square, fakeHuman);
            return;

        }

        computerMark.setLeftCoord('2');
        computerMark.setTopCoord('b');

        if (square.emptyCell(computerMark.getLeftCoord(), computerMark.getTopCoord())) {

            square.putMark(computerMark);

            return;

        }

        if (!cleverRandom(square, fakeHuman, computerMark)) {

            if (square.emptyCell('1', 'a') || square.emptyCell('1', 'c') || square.emptyCell('3', 'a') || square.emptyCell('3', 'c')) {

                putMarkInTheConnerOfTheMatrix(square, computerMark);
                return;

            }


        }
        putMarkInTheRandomPlace(square, computerMark);
    }

}

Round.java
import java.util.Scanner;

public class Round extends Form {

    public int start = 0;

    private char typeOfGame;

    public char getTypeOfGame() {
        return typeOfGame;
    }

    public void registration (IPlayer player1, IPlayer player2) {

        Scanner input= new Scanner(System.in);

        if (player1.getPlayerName() == COMPUTER_NAME) {

            System.out.println("Enter your name:");

            player2.setPlayerName(input.next());


        } else if (player2.getPlayerName() == COMPUTER_NAME) {

            System.out.println("Enter your name:");

            player1.setPlayerName(input.next());


        } else {

            System.out.println("Name of first player:");
            player1.setPlayerName(input.next());
            System.out.println("Hello " + player1.getPlayerName() + "!");
            System.out.println("Name of second player:");
            player2.setPlayerName(input.next());
            System.out.println("Hello " + player2.getPlayerName() + "!");

        }

    }

    public void setMarksForPlayers (IPlayer player1, IPlayer player2) {

        Scanner input= new Scanner(System.in);
        String str;
        System.out.println("Who will be playing X?");
        System.out.println();

        if (player1.getPlayerName() == COMPUTER_NAME || player2.getPlayerName() == COMPUTER_NAME) {

            System.out.println("1. Me");
            System.out.println("2. " + COMPUTER_NAME);
            System.out.println();
            char answer = '0';

            do {

                str = input.next();

                if (str.length() == 1) {

                    char []var = str.toCharArray();

                    answer = var[0];

                    if (!((var[0] == '1' ) || (var[0] == '2'))) {

                        wrongInputMessage();

                    }

                    if (answer == '1') {

                        this.start = 1;
                    }
                    if (answer == '2') {

                        this.start = 2;
                    }

                } else {

                    wrongInputMessage();

                }

            } while(!(answer == '1' || answer == '2'));


        } else {

            System.out.println("1. " + player1.getPlayerName());
            System.out.println("2. " + player2.getPlayerName());
            System.out.println();
            char answer = '0';

            do {

                str = input.next();

                if (str.length() == 1) {

                    char []var = str.toCharArray();

                    answer = var[0];

                    if (!((var[0] == '1' ) || (var[0] == '2'))) {

                        wrongInputMessage();

                    }

                    if (answer == '1') {

                        start = 1;
                    } else {

                        start = 2;

                    }

                } else {

                    wrongInputMessage();

                }

            } while(!(answer == '1' || answer == '2'));

        }

    }

    public void hello() {

        String str;

        System.out.println();
        System.out.println("***************************************************************");
        System.out.println("*                                                             *");
        System.out.println("*                            TIC TAC                          *");
        System.out.println("*                                                             *");
        System.out.println("*                             ALPHA                           *");
        System.out.println("*                                                             *");
        System.out.println("***************************************************************");
        System.out.println();
        System.out.println("Choose the type of the game:");
        System.out.println();
        System.out.println("1. Player VS Player");
        System.out.println("2. Player VS Computer");
        System.out.println();

        Scanner input= new Scanner(System.in);

        do {

            str = input.next();

            if (str.length() == 1) {

                char []var = str.toCharArray();

                typeOfGame = var[0];

                if (!((var[0] == '1' ) || (var[0] == '2'))) {

                    wrongInputMessage();

                }

            } else {

                wrongInputMessage();

            }

        } while(!(typeOfGame == '1' || typeOfGame == '2'));


    }

    public boolean restartGame() {

        Scanner input= new Scanner(System.in);

        System.out.println("Do you want to restart the game?[y/n] ");
        String str;

        char ans = 0;

        do {

            str = input.next();
            if (str.length() == 1) {

                char []var = str.toCharArray();

                ans = var[0];

                if (!((var[0] == 'y' ) || (var[0] == 'n'))) {

                    wrongInputMessage();

                }
            } else {

                wrongInputMessage();

            }

        } while(!(ans == 'y' || ans == 'n'));

        if (ans == 'y') {

            return true;

        } else {
            System.out.println("Good bye!");

            return false;

        }


    }

}

Mark.java

public class Mark extends Form {

    private char mark;

    private char leftCoord;

    private char topCoord;

    public Mark (char mark) {

        setMark(mark);

    }


    public void setMark (char mark) {

        if (mark == MARK_X || mark == MARK_O) {

            this.mark = mark;

        } else {

            System.out.println("Wrong mark input.");

        }

    }

    public Mark () {}

    public char getMark() {
        return mark;
    }

    public char getTopCoord() {
        return topCoord;
    }

    public char getLeftCoord() {
        return leftCoord;
    }

    public void setLeftCoord(char leftCoord) {

        if (leftCoord>=FIRST_LEFT_COORD && leftCoord<=FIRST_LEFT_COORD+SIZE_OF_MATRIX/2-TOP_AND_LEFT_BORDER_SIZE) {

            this.leftCoord = leftCoord;

        }
    }

    public void setTopCoord(char topCoord) {

        if (topCoord>=FIRST_TOP_COORD && topCoord<=FIRST_TOP_COORD+SIZE_OF_MATRIX/2-TOP_AND_LEFT_BORDER_SIZE){
            this.topCoord = topCoord;
        }

    }


    public void consoleInput(String str) {

        char []string = str.toCharArray();

        setTopCoord(string[0]);

        setLeftCoord(string[1]);

    }

    public boolean cinGood(String str) {

        char []string = str.toCharArray();

        if (str.length()==2) {

            if (string[0] >= FIRST_TOP_COORD && string[0] <= FIRST_TOP_COORD+SIZE_OF_MATRIX/2-TOP_AND_LEFT_BORDER_SIZE) {

                if (string[1] >= FIRST_LEFT_COORD && string[1] <= FIRST_LEFT_COORD+SIZE_OF_MATRIX/2-DOWN_AND_RIGHT_BORDER_SIZE) {

                    return true;

                } else {

                    wrongInputMessage();

                    return false;

                }
            } else {

                wrongInputMessage();

                return false;
            }

        } else {

            wrongInputMessage();

            return false;
        }


    }

}

Square.java
import java.util.Scanner;

public class Square extends Form {

    public Square() {

        for (int i=0; i< SIZE_OF_MATRIX; i++) {

            eraseLine(i);

        }

        setBorder();

    }

    private void eraseLine (int line_number) {

        for (int i=0; i< SIZE_OF_MATRIX; i++){
            matrix[line_number][i] = EMPTY_CELL;
        }

    }

    private boolean winnerScore (int count) {

        if (count == WINNER_SCORE) {

            return true;

        } else {

            return false;

        }

    }

    private void setBorder() {

        for (int i=TOP_AND_LEFT_BORDER_SIZE-1; i< SIZE_OF_MATRIX; i+=2) {

            for (int k=TOP_AND_LEFT_BORDER_SIZE-1; k< SIZE_OF_MATRIX; k++) {

                matrix[i][k] = BORDER_MATERIAL;

            }

            for (int k=TOP_AND_LEFT_BORDER_SIZE; k< SIZE_OF_MATRIX; k++) {

                matrix[k][i] = BORDER_MATERIAL;

            }

        }

        char topCoord = FIRST_TOP_COORD;

        for (int i=TOP_AND_LEFT_BORDER_SIZE; i< SIZE_OF_MATRIX; i+=2) {

            matrix[0][i] = topCoord;
            topCoord++;

        }

        char leftCoord = FIRST_LEFT_COORD;

        for (int i=TOP_AND_LEFT_BORDER_SIZE; i< SIZE_OF_MATRIX; i+=2) {

            matrix[i][0] = leftCoord;
            leftCoord++;

        }

    }

    public int countOfMarks (char mark) {

        int count = 0;


        for (int i=0; i<SIZE_OF_MATRIX; i++) {

            for (int k=0; k<SIZE_OF_MATRIX; k++) {

                if (matrix[i][k] == mark) {

                    count++;

                }



            }
        }

        return count;

    }

    private boolean checkWinInHorizontalAndVerticalLines (IPlayer player) {

        int leftLineCount = 0;

        int topLineCount = 0;

        for (int i=0; i<SIZE_OF_MATRIX; i++) {

            for (int k=0; k<SIZE_OF_MATRIX; k++) {

                if (matrix[i][k] == player.getMark()) {

                    leftLineCount++;

                }

                if (matrix[k][i] == player.getMark()) {

                    topLineCount++;

                }

                if (winnerScore(leftLineCount) || winnerScore(topLineCount)) {

                    return true;

                }

            }

            leftLineCount = 0;

            topLineCount = 0;
        }

        return false;

    }


    private boolean checkWinInDiagonalLines (IPlayer player) {

        int count1 = 0;

        for (int i=0; i<SIZE_OF_MATRIX; i++) {

            if (matrix[i][i] == player.getMark()) {

                count1++;

            }

        }

        int count2 = 0;

        for (int i=SIZE_OF_MATRIX-DOWN_AND_RIGHT_BORDER_SIZE, j=TOP_AND_LEFT_BORDER_SIZE-1; i>=TOP_AND_LEFT_BORDER_SIZE; i--, j++) {

            if (matrix[i][j] == player.getMark()) {

                count2++;

            }

        }


        if (count1 == WINNER_SCORE || count2 == WINNER_SCORE) {

            return true;

        }   else {

            return false;

        }
    }

    private boolean playerWillBeWinnerInTheNextStep (IPlayer player) {

        Mark mark = new Mark(player.getMark());

        for (char i=FIRST_LEFT_COORD; i<FIRST_LEFT_COORD + STRINGS_MATRIX_COUNT; i++) {

            for (char j=FIRST_TOP_COORD; j<FIRST_TOP_COORD + STRINGS_MATRIX_COUNT; j++) {


                mark.setLeftCoord(i);
                mark.setTopCoord(j);


                if (emptyCell(mark.getLeftCoord(), mark.getTopCoord())) {

                    putMark(mark);

                    if (winner(player)) {

                        clearCell(mark.getLeftCoord(), mark.getTopCoord());

                        return true;

                    } else {

                        clearCell(mark.getLeftCoord(), mark.getTopCoord());

                    }


                }


            }
        }

        return false;

    }


    private void showMatrixLine (int line_number) {

        for (int i=0; i< SIZE_OF_MATRIX; i++) {

            System.out.print(matrix[line_number][i]);

        }

    }


    public void showMatrix () {

        for (int i=0; i< SIZE_OF_MATRIX; i++) {

            showMatrixLine(i);
            System.out.println();

        }

    }

    public void winMessage (IPlayer player) {

        System.out.print(player.getPlayerName() + " is winner!");

    }


    public boolean winner (IPlayer player) {

        if (checkWinInHorizontalAndVerticalLines(player) || checkWinInDiagonalLines(player)) {

            return true;

        } else {

            return false;

        }

    }

    public boolean belongs (Mark mark, char leftCoord, char topCoord) {

        if (matrix[(leftCoord-FIRST_LEFT_COORD)*2+TOP_AND_LEFT_BORDER_SIZE][(topCoord-FIRST_TOP_COORD)*2+TOP_AND_LEFT_BORDER_SIZE] == mark.getMark()) {

            return true;

        }
        return false;


    }

    public boolean endWithoutWinner () {

        for (int i=TOP_AND_LEFT_BORDER_SIZE; i<SIZE_OF_MATRIX; i++) {

            for (int k=TOP_AND_LEFT_BORDER_SIZE; k<SIZE_OF_MATRIX; k++) {

                if (matrix[i][k] == EMPTY_CELL) {

                    return false;

                }

            }


        }

        return true;

    }


    public void endWithoutWinnerMessage () {

        System.out.println("Game over. Winner is absent.");

    }


    public boolean emptyCell (char leftCoord, char topCoord) {

        if (matrix[(leftCoord-FIRST_LEFT_COORD)*2+TOP_AND_LEFT_BORDER_SIZE][(topCoord-FIRST_TOP_COORD)*2+TOP_AND_LEFT_BORDER_SIZE] == EMPTY_CELL) {

            return true;

        } else {

            return false;

        }
    }


    public void clearCell(char leftCoord, char topCoord) {

        matrix[(leftCoord-FIRST_LEFT_COORD)*2+TOP_AND_LEFT_BORDER_SIZE][(topCoord-FIRST_TOP_COORD)*2+TOP_AND_LEFT_BORDER_SIZE] = EMPTY_CELL;

    }


    public void putMark (Mark mark) {

        if (matrix[(mark.getLeftCoord()-FIRST_LEFT_COORD)*2+TOP_AND_LEFT_BORDER_SIZE][(mark.getTopCoord()-FIRST_TOP_COORD)*2+TOP_AND_LEFT_BORDER_SIZE] == EMPTY_CELL) {

            matrix[(mark.getLeftCoord()-FIRST_LEFT_COORD)*2+TOP_AND_LEFT_BORDER_SIZE][(mark.getTopCoord()-FIRST_TOP_COORD)*2+TOP_AND_LEFT_BORDER_SIZE] = mark.getMark();

        }

    }

}

Main.java
import java.util.Scanner;

public class Main extends Form {
    public static void main(String[] args) {

        Round round;

        do {
            round = new Round();
            Square square = new Square();
            round.hello();
            IPlayer player1 = new Human();
            IPlayer player2;
            if (round.getTypeOfGame() == '2') {

                player2 = new Computer();

            } else {

                player2 = new Human();

            }
            round.registration(player1,player2);
            round.setMarksForPlayers(player1, player2);

            if (round.start == 1) {
                player1.setMark(MARK_X);
                player2.setMark(MARK_O);

            } else {

                player1.setMark(MARK_O);
                player2.setMark(MARK_X);

            }
            square.showMatrix();
            while (true) {

                if (round.start == 1) {
                    player1.go(square,round);
                    square.showMatrix();
                    if (square.winner(player1)) {

                        square.winMessage(player1);
                        break;
                    }

                    if (square.endWithoutWinner()) {

                        square.endWithoutWinnerMessage();
                        break;

                    }
                    round.start = 2;

                } else {
                    player2.go(square, round);
                    square.showMatrix();
                    if (square.winner(player2)) {

                        square.winMessage(player2);
                        break;
                    }

                    if (square.endWithoutWinner()) {

                        square.endWithoutWinnerMessage();
                        break;

                    }
                    round.start = 1;
                }


            }
        } while (round.restartGame());
    }
}

Теги:
Крестики-нолики, XO, TicTac, Tic Tac, tic-tac, Крестики нолики, хрестики нулики, хрестики-нулики
Добавлено: 20 Мая 2014 01:57:42 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...