9. Игра "Крестики-нолики" 2.

(открыть в новой вкладке)

Условие:

Нужно написать программу, которая реализует популярную игру "крестики-нолики", используя ООП. И путём наследования расширить игру до 16 клеток.

Код:

# создание супер-класса
class Field:
    def __init__(self, BLANK, answer):                                                                                                      # входящие аргументы для класса - пустой знак " ", количество клеток                     
        self._blank = BLANK
        self._answer = answer
        self._field = dict.fromkeys([str(i) for i in range(1,10)] if self._answer == 9 else [str(i) for i in range(1,17)], self._blank)     # создадим пустое игровое поле

    def method_show_field(self):                                                                                                            # метод выводит текстовое представление игрового поля        
        return f"""
        {self._field["1"]}|{self._field["2"]}|{self._field["3"]} 1 2 3
        -+-+-
        {self._field["4"]}|{self._field["5"]}|{self._field["6"]} 4 5 6
        -+-+-
        {self._field["7"]}|{self._field["8"]}|{self._field["9"]} 7 8 9"""

    def method_test_free(self, move):                                                                                                       # проверка: вернёт True, если клетка есть среди ключей словаря self.__field и она пуста
        return self._field.get(move) == self._blank                     

    def method_update_field(self, move, player):                                                                                            # заполняет словарь после очередного хода
        self._field[move] = player

    def method_win(self, player):                                                                                                           # проверяет победу
        result = True if (self._field["1"] == self._field["2"] == self._field["3"] == player) \
            or (self._field["4"] == self._field["5"] == self._field["6"] == player) \
            or (self._field["7"] == self._field["8"] == self._field["9"] == player) \
            or (self._field["1"] == self._field["4"] == self._field["7"] == player) \
            or (self._field["2"] == self._field["5"] == self._field["8"] == player) \
            or (self._field["3"] == self._field["6"] == self._field["9"] == player) \
            or (self._field["3"] == self._field["5"] == self._field["7"] == player) \
            or (self._field["1"] == self._field["5"] == self._field["9"] == player) else False
        return result
    
    def method_no_win(self):                                                                                                                # проверяет ничью
        result = True if self._blank not in self._field.values() else False
        return result        

# класс-наследник
class Big_field(Field):
    def __init__(self, BLANK, answer):
        super().__init__(BLANK, answer)
    
    def method_show_field(self):                                                                                                            # метод выводит текстовое представление игрового поля        
        return f"""
        {self._field["1"]}|{self._field["2"]}|{self._field["3"]}|{self._field["4"]}     1  2  3  4
        -+-+-+-
        {self._field["5"]}|{self._field["6"]}|{self._field["7"]}|{self._field["8"]}     5  6  7  8
        -+-+-+-
        {self._field["9"]}|{self._field["10"]}|{self._field["11"]}|{self._field["12"]}     9 10 11 12
        -+-+-+-
        {self._field["13"]}|{self._field["14"]}|{self._field["15"]}|{self._field["16"]}    13 14 15 16"""
    
    def method_win(self, player):                                                                                                           # проверяет победу
        result = True if (self._field["1"] == self._field["2"] == self._field["3"] == self._field["4"] == player) \
            or (self._field["5"] == self._field["6"] == self._field["7"] == self._field["8"] == player) \
            or (self._field["9"] == self._field["10"] == self._field["11"] == self._field["12"] == player) \
            or (self._field["13"] == self._field["14"] == self._field["15"] == self._field["16"] == player) \
            or (self._field["1"] == self._field["5"] == self._field["9"] == self._field["13"] == player) \
            or (self._field["2"] == self._field["6"] == self._field["10"] == self._field["14"] == player) \
            or (self._field["3"] == self._field["7"] == self._field["11"] == self._field["15"] == player) \
            or (self._field["4"] == self._field["8"] == self._field["12"] == self._field["16"] == player) \
            or (self._field["1"] == self._field["6"] == self._field["11"] == self._field["16"] == player) \
            or (self._field["4"] == self._field["7"] == self._field["10"] == self._field["13"] == player) else False
        return result
        
# основная функция
def function_main_2(X, O, BLANK, answer):
    if answer == 9:
        field = Field(BLANK, answer)                                                                                                         # создадим объект класса Field
    else:
        field = Big_field(BLANK, answer)                                                                                                     # создадим объект класса Big_field (наследник Field)
    print(field.method_show_field())                                                                                                         # вывести поле на печать
    player_1, player_2 = X, O
    while True:        
        move = 0                                                                                                                             # это значение недопустимо и требует коррекции
        while not field.method_test_free(move):                                                                                              # цикл гарантирует, что клетка в очередном ходе существует и пуста
            print()
            move = input("Игрок 1, Ваш ход: ")
        field.method_update_field(move, player_1)                                                                                            # заполним поле после очередного хода
        print(field.method_show_field())                                                                                                     # вывести поле на печать
        if field.method_win(player_1):                                                                                                       # проверка выиграл ли первый игрок
            print("Игрок 1 победил.")
            print()
            print("Конец игры.")
            break
        elif field.method_no_win():                                                                                                          # условие для проверки ничьи
            print()
            print("Ничья.")
            print()
            print("Конец игры.")
            break        
        move = 0                                                                                                                             # это значение недопустимо и требует коррекции
        while not field.method_test_free(move):                                                                                              # цикл гарантирует, что клетка в очередном ходе существует и пуста
            print()
            move = input("Игрок 2, Ваш ход: ")
        field.method_update_field(move, player_2)                                                                                            # заполним поле после очередного хода
        print(field.method_show_field())                                                                                                     # вывести поле на печать
        if field.method_win(player_2):                                                                                                       # проверка выиграл ли первый игрок
            print()
            print("Игрок 2 победил.")
            print()
            print("Конец игры.")
            break
        elif field.method_no_win():                                                                                                          # условие для проверки ничьи
            print()
            print("Ничья.")
            print()
            print("Конец игры.")
            break        

# проверка ввода и создание входных данных
def function_main():
    print()
    print("Игра \"Креcтики-нолики\".")    
    X, O, BLANK = "X", "O", " "
    while True:
        try:
            print()
            answer = int(input("Введите на каком поле хотите играть 9 или 16: "))
            if answer == 9 or answer == 16:
                break
            else:
                print()
                print("Вы ввели не тот размер поля.")
        except:
            print()
            print("Повторите ввод. Вы ввели недопустимые символы. ") 
    function_main_2(X, O, BLANK, answer)


if __name__ == "__main__":    
    print("Скрипт запущен напрямую.")
    function_main()
else:    
    print("Скрипт импортирован.")