Advertisement
Hasli4

Untitled

Mar 21st, 2025
351
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.88 KB | None | 0 0
  1. import random
  2. import time
  3. import math
  4. from typing import List, Tuple
  5.  
  6. class Player:
  7.     """
  8.    Базовый класс игрока
  9.    """
  10.     def __init__(self, name: str):
  11.         self.name = name
  12.    
  13.     def make_move(self, current_number: int, target_number: int) -> int:
  14.         """
  15.        Метод, который должен быть переопределен в подклассах
  16.        для реализации стратегии игрока
  17.        """
  18.         pass
  19.  
  20.  
  21. class HumanPlayer(Player):
  22.     """
  23.    Класс, представляющий игрока-человека
  24.    """
  25.     def make_move(self, current_number: int, target_number: int) -> int:
  26.         # Получаем все возможные ходы
  27.         possible_moves = self._get_possible_moves(current_number)
  28.        
  29.         # Выводим информацию о текущем состоянии игры
  30.         print(f"\nТекущее число на доске: {current_number}")
  31.         print(f"Цель: достигнуть {target_number} или больше")
  32.         print(f"Возможные ходы: {', '.join(str(move) for move in possible_moves)}")
  33.        
  34.         # Запрашиваем ход у пользователя
  35.         while True:
  36.             try:
  37.                 choice = int(input(f"{self.name}, выберите новое число: "))
  38.                 if choice in possible_moves:
  39.                     return choice
  40.                 else:
  41.                     print("Недопустимый ход! Выберите число из списка возможных ходов.")
  42.             except ValueError:
  43.                 print("Введите корректное число!")
  44.    
  45.     def _get_possible_moves(self, current_number: int) -> List[int]:
  46.         """
  47.        Вычисляет все возможные ходы для текущего числа на доске
  48.        """
  49.         moves = []
  50.         # Находим все делители текущего числа
  51.         for i in range(1, current_number + 1):
  52.             if current_number % i == 0:
  53.                 moves.append(current_number + i)
  54.         return moves
  55.  
  56.  
  57. class ComputerPlayer(Player):
  58.     """
  59.    Класс, представляющий компьютерного игрока
  60.    """
  61.     def __init__(self, name: str, difficulty: str = "medium"):
  62.         super().__init__(name)
  63.         self.difficulty = difficulty  # Уровень сложности: "easy", "medium", "hard"
  64.    
  65.     def make_move(self, current_number: int, target_number: int) -> int:
  66.         # Получаем все возможные ходы
  67.         possible_moves = self._get_possible_moves(current_number)
  68.        
  69.         print(f"\n{self.name} думает...")
  70.         time.sleep(1)  # Добавляем задержку для имитации "размышления"
  71.        
  72.         # В зависимости от уровня сложности выбираем стратегию
  73.         if self.difficulty == "easy":
  74.             # Простой уровень: выбор случайного хода
  75.             choice = random.choice(possible_moves)
  76.         elif self.difficulty == "medium":
  77.             # Средний уровень: выбор между случайным и оптимальным ходом
  78.             if random.random() < 0.5:
  79.                 choice = self._get_best_move(current_number, possible_moves, target_number)
  80.             else:
  81.                 choice = random.choice(possible_moves)
  82.         else:  # hard
  83.             # Сложный уровень: всегда выбирает наилучший ход
  84.             choice = self._get_best_move(current_number, possible_moves, target_number)
  85.        
  86.         print(f"{self.name} выбирает число: {choice}")
  87.         return choice
  88.    
  89.     def _get_possible_moves(self, current_number: int) -> List[int]:
  90.         """
  91.        Вычисляет все возможные ходы для текущего числа на доске
  92.        """
  93.         moves = []
  94.         # Находим все делители текущего числа
  95.         for i in range(1, current_number + 1):
  96.             if current_number % i == 0:
  97.                 moves.append(current_number + i)
  98.         return moves
  99.    
  100.     def _get_best_move(self, current_number: int, possible_moves: List[int], target_number: int) -> int:
  101.         """
  102.        Определяет наилучший ход с использованием стратегии
  103.        """
  104.         # Если можем выиграть - выигрываем
  105.         winning_moves = [move for move in possible_moves if move >= target_number]
  106.         if winning_moves:
  107.             return min(winning_moves)  # Выбираем наименьшее выигрышное число
  108.        
  109.         # Ищем выигрышные позиции для нас
  110.         for move in possible_moves:
  111.             if self._is_winning_position(move, target_number):
  112.                 return move
  113.        
  114.         # Если нет выигрышной стратегии, выбираем ход, дающий максимальное число
  115.         return max(possible_moves)
  116.    
  117.     def _is_winning_position(self, position: int, target_number: int) -> bool:
  118.         """
  119.        Определяет, является ли позиция выигрышной с помощью анализа игры
  120.        """
  121.         # Если позиция уже достигла или превысила целевое число - это выигрыш
  122.         if position >= target_number:
  123.             return True
  124.        
  125.         # Находим все возможные ходы противника из этой позиции
  126.         opponent_moves = []
  127.         for i in range(1, position + 1):
  128.             if position % i == 0:
  129.                 opponent_moves.append(position + i)
  130.        
  131.         # Если хотя бы один ход противника ведёт к проигрышной для нас позиции,
  132.         # то текущая позиция не является выигрышной
  133.         for opponent_move in opponent_moves:
  134.             if not self._can_win_from_position(opponent_move, target_number):
  135.                 return False
  136.        
  137.         # Если все ходы противника ведут к выигрышной для нас позиции,
  138.         # то текущая позиция является выигрышной
  139.         return True
  140.    
  141.     def _can_win_from_position(self, position: int, target_number: int) -> bool:
  142.         """
  143.        Проверяет, можно ли выиграть из данной позиции
  144.        Это упрощенная проверка для ограничения глубины анализа
  145.        """
  146.         # Если позиция уже достигла или превысила целевое число - это выигрыш
  147.         if position >= target_number:
  148.             return True
  149.        
  150.         # Рассматриваем только простые случаи для ограничения вычислительной сложности
  151.         # Проверяем, есть ли делитель, который позволит достичь целевое число за один ход
  152.         for i in range(1, position + 1):
  153.             if position % i == 0 and position + i >= target_number:
  154.                 return True
  155.        
  156.         return False
  157.  
  158.  
  159. class Game:
  160.     """
  161.    Класс, представляющий игру Strat30
  162.    """
  163.     def __init__(self, start_number: int = 10, target_number: int = 60):
  164.         self.start_number = start_number
  165.         self.target_number = target_number
  166.         self.current_number = start_number
  167.         self.players = []
  168.         self.current_player_index = 0
  169.    
  170.     def add_player(self, player: Player):
  171.         """
  172.        Добавляет игрока в игру
  173.        """
  174.         self.players.append(player)
  175.    
  176.     def start_game(self):
  177.         """
  178.        Запускает игру
  179.        """
  180.         print(f"\n=== Начало игры Strat30 ===")
  181.         print(f"Начальное число: {self.start_number}")
  182.         print(f"Цель: достигнуть {self.target_number} или больше")
  183.         print(f"Игроки: {', '.join(player.name for player in self.players)}")
  184.        
  185.         # Основной игровой цикл
  186.         while True:
  187.             current_player = self.players[self.current_player_index]
  188.            
  189.             # Игрок делает ход
  190.             new_number = current_player.make_move(self.current_number, self.target_number)
  191.            
  192.             # Обновляем число на доске
  193.             self.current_number = new_number
  194.            
  195.             # Проверяем условие победы
  196.             if self.current_number >= self.target_number:
  197.                 print(f"\n=== {current_player.name} победил! ===")
  198.                 print(f"Финальное число на доске: {self.current_number}")
  199.                 break
  200.            
  201.             # Переходим к следующему игроку
  202.             self.current_player_index = (self.current_player_index + 1) % len(self.players)
  203.  
  204.  
  205. def get_game_setup() -> Tuple[int, int, list]:
  206.     """
  207.    Функция для настройки параметров игры через консольный интерфейс
  208.    """
  209.     print("\n=== Настройка игры Strat30 ===")
  210.    
  211.     # Запрашиваем начальное число
  212.     while True:
  213.         try:
  214.             start_number = int(input("Введите начальное число n (рекомендуется 10-30): "))
  215.             if start_number > 0:
  216.                 break
  217.             else:
  218.                 print("Число должно быть положительным!")
  219.         except ValueError:
  220.             print("Введите корректное число!")
  221.    
  222.     # Запрашиваем целевое число
  223.     while True:
  224.         try:
  225.             target_number = int(input(f"Введите целевое число (рекомендуется не менее {start_number*2}): "))
  226.             if target_number > start_number:
  227.                 break
  228.             else:
  229.                 print(f"Целевое число должно быть больше начального ({start_number})!")
  230.         except ValueError:
  231.             print("Введите корректное число!")
  232.    
  233.     # Создаем список игроков
  234.     players = []
  235.    
  236.     # Запрашиваем количество человек-игроков
  237.     while True:
  238.         try:
  239.             num_human_players = int(input("Введите количество человек-игроков (0-4): "))
  240.             if 0 <= num_human_players <= 4:
  241.                 break
  242.             else:
  243.                 print("Количество должно быть от 0 до 4!")
  244.         except ValueError:
  245.             print("Введите корректное число!")
  246.    
  247.     # Создаем человек-игроков
  248.     for i in range(num_human_players):
  249.         name = input(f"Введите имя игрока {i+1}: ")
  250.         if not name:
  251.             name = f"Игрок {i+1}"
  252.         players.append(HumanPlayer(name))
  253.    
  254.     # Запрашиваем количество компьютерных игроков
  255.     while True:
  256.         try:
  257.             num_computer_players = int(input("Введите количество компьютерных игроков (0-4): "))
  258.             if 0 <= num_computer_players <= 4 and (num_human_players + num_computer_players) > 0:
  259.                 break
  260.             else:
  261.                 print("Количество должно быть от 0 до 4 и общее количество игроков должно быть не менее 1!")
  262.         except ValueError:
  263.             print("Введите корректное число!")
  264.    
  265.     # Создаем компьютерных игроков
  266.     for i in range(num_computer_players):
  267.         # Запрашиваем уровень сложности для каждого компьютерного игрока
  268.         while True:
  269.             difficulty = input(f"Выберите уровень сложности для Компьютер {i+1} (easy/medium/hard): ").lower()
  270.             if difficulty in ["easy", "medium", "hard"]:
  271.                 break
  272.             else:
  273.                 print("Неверный уровень сложности! Выберите один из: easy, medium, hard")
  274.        
  275.         players.append(ComputerPlayer(f"Компьютер {i+1}", difficulty))
  276.    
  277.     # Перемешиваем порядок игроков для случайного первого хода
  278.     random.shuffle(players)
  279.    
  280.     return start_number, target_number, players
  281.  
  282.  
  283. def main():
  284.     """
  285.    Основная функция для запуска игры
  286.    """
  287.     print("Добро пожаловать в игру Strat30!")
  288.     print("Правила игры:")
  289.     print("1. Изначально на доске написано число n.")
  290.     print("2. Игрок в свой ход может прибавить к числу на доске любой его натуральный делитель, стереть старое число и записать новое.")
  291.     print("3. Побеждает тот, кто получит после своего хода число, не меньшее заданного целевого числа.")
  292.    
  293.     # Настраиваем игру
  294.     start_number, target_number, players = get_game_setup()
  295.    
  296.     # Создаем и настраиваем игру
  297.     game = Game(start_number, target_number)
  298.     for player in players:
  299.         game.add_player(player)
  300.    
  301.     # Запускаем игру
  302.     game.start_game()
  303.    
  304.     # Спрашиваем о новой игре
  305.     while True:
  306.         play_again = input("\nХотите сыграть еще раз? (да/нет): ").lower()
  307.         if play_again in ["да", "yes", "y", "д"]:
  308.             # Настраиваем и запускаем новую игру
  309.             start_number, target_number, players = get_game_setup()
  310.             game = Game(start_number, target_number)
  311.             for player in players:
  312.                 game.add_player(player)
  313.             game.start_game()
  314.         elif play_again in ["нет", "no", "n", "н"]:
  315.             print("Спасибо за игру! До свидания!")
  316.             break
  317.         else:
  318.             print("Пожалуйста, введите 'да' или 'нет'.")
  319.  
  320.  
  321. if __name__ == "__main__":
  322.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement