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

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

Условие:

Нужно написать программу, которая реализует популярную игру "крестики-нолики", используя ООП. Только поле в игре будет большим 20х20. Выигрывает тот, кто сможет по вертикали, горизонтали или диагонали собрать вместе 5 крестиков или ноликов подряд.

Код:

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

    def method_show_field(self):                                                                                                            # метод выводит текстовое представление игрового поля                        
        temp, temp_2 = 1, (self._cells + 1)
        for a in range(1, self._cells + 1):            
            for b in range(temp, temp_2):
                print(f"|{self._field[str(b)]}", end="")
            print("|     ", end="")
            for b in range(temp, temp_2):
                print(f"|{b:<3}", end="")
            print("|")
            temp += self._cells; temp_2 += self._cells
        return "Игровое поле"

    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, move, WIN):                                                                                                # проверяет победу
        move = int(move)        
        result = False
        # проверка на выигрыш по горизонтали        
        if result == False:
            if move % self._cells != 0:
                left_limit = move - move % self._cells + 1                                                                                  # левая граница поля
                right_limit = self._cells + left_limit - 1                                                                                  # правая граница поля
            else:
                left_limit = move - self._cells + 1                                                                                         # левая граница поля
                right_limit = move                                                                                                          # правая граница поля        
            set_gorizont_1 = set(range(left_limit, right_limit + 1))                                                                        # составим множество клеток в реальных границах поля
            set_gorizont_2 = set(range((move - WIN + 1), (move + WIN)))                                                                     # составим множество клеток + и - выигрышное количетсво клеток от настоящей клетки
            list_gorizont = sorted(set_gorizont_1 & set_gorizont_2)                                                                         # найдём клетки в горизонтальной плоскости, которое необходимо проверить
            count = 0                                                                                                                                   
            for i in list_gorizont:            
                count = (count + 1) if self._field[str(i)] == player else 0                
                result = True if count == WIN else False                
                if result == True:
                    break              
        # проверка на выигрыш по вертикали
        if result == False:
            set_vertikal = set()                                                                                                                
            set_vertikal.add(move)                                                                                                          
            temp = move
            for i in range(WIN - 1):
                temp -= self._cells
                set_vertikal.add(temp)
            temp = move
            for i in range(WIN - 1):
                temp += self._cells
                set_vertikal.add(temp)            
            set_total_cells = set(range(1, self._cells ** 2 + 1))
            list_vertikal = sorted(set_vertikal & set_total_cells)            
            count = 0                                                                                                                                   
            for i in list_vertikal:            
                count = (count + 1) if self._field[str(i)] == player else 0
                result = True if count == WIN else False                
                if result == True:
                    break          
        # проверка на выигрыш по диагонали №1
        if result == False:
            set_diagonal = set()                                                                                                                
            set_diagonal.add(move)                   
            temp = move
            for i in range(WIN - 1):
                temp -= (self._cells + 1)
                set_diagonal.add(temp)                
            temp = move
            for i in range(WIN - 1):
                temp += (self._cells + 1)
                set_diagonal.add(temp)                            
            set_total_cells = set(range(1, self._cells ** 2 + 1))
            list_diagonal = sorted(set_diagonal & set_total_cells)                        
            count = 0                                                                                                                                   
            for i in list_diagonal:            
                count = (count + 1) if self._field[str(i)] == player else 0
                result = True if count == WIN else False                
                if result == True:
                    break         
        # проверка на выигрыш по диагонали №2
        if result == False:
            set_diagonal = set()                                                                                                                
            set_diagonal.add(move)                   
            temp = move
            for i in range(WIN - 1):
                temp -= (self._cells - 1)
                set_diagonal.add(temp)                
            temp = move
            for i in range(WIN - 1):
                temp += (self._cells - 1)
                set_diagonal.add(temp)                            
            set_total_cells = set(range(1, self._cells ** 2 + 1))
            list_diagonal = sorted(set_diagonal & set_total_cells)                        
            count = 0                                                                                                                                   
            for i in list_diagonal:            
                count = (count + 1) if self._field[str(i)] == player else 0
                result = True if count == WIN else False                
                if result == True:
                    break            
        return result
    
    def method_no_win(self):                                                                                                                # проверяет ничью
        result = True if self._blank not in self._field.values() else False
        return result        
        
# основная функция
def function_main_2(X, O, BLANK, CELLS, WIN):
    field = Field(BLANK, CELLS)                                                                                                             # создадим объект "поле" класса 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, move, WIN):                                                                                           # проверка выиграл ли первый игрок
            print()
            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, move, WIN):                                                                                           # проверка выиграл ли первый игрок
            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, CELLS, WIN = "X", "O", " ", 20, 5
    function_main_2(X, O, BLANK, CELLS, WIN)


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