PythonMiddle: Игра «Гонки»

Итак, суть игры в том, что вначале мы конфигурируем автомобили (несколько) выбирая их производителя, модель и год выпуска, снабжаем их двигателем из списка.

Затем конфигурируем длину трассы..

и запускаем заезд:

После заезда программа пишет нам итоговое время каждого участника.

Итак, программа разделена на 5 файлов: Car.py, CarComponent.py, CarFabrick.py, Track.py и main.py

Файл CarComponent.py отвечает за компоненты автомобиля. У нас он пока что один — Двигатель. Поэтому в файле определяется БАЗОВЫЙ абстрактный класс CarComponent, который хранит Имя компонента и метод GetName(), возвращающий это имя в виде строки.

Также тут определён класс-наследник Engine, которыя является потомком CarComponent и содержит конструктор (позволяющий задать основные характеристики: имя и мощность) и метод, возвращающий мощность мотора — GetPower()

Содержимое CarComponent.py:

class CarComponent():
    _name: str

    def GetName(self):
        return self._name
    
class Engine(CarComponent):
    def __init__(self, name, power):
        self._name = name
        self._power = power

    def GetPower(self):
        return self._power

Содержимое Car.py

Файл содержит описание класса автомобиля: конструктор, и методы, позволяющие добавлять компоненты, возвращающие максимальную скорость авто. а также 2 метода позволяющие СОХРАНИТЬ и ПОЛУЧИТЬ последний результат последней гонки на треке.

from CarComponent import Engine
from math import pi

class Car():
    def __init__(self, maker, model, year):
        self._maker = maker
        self._model = model
        self._year = year
        self._lastTrackResult = 0

    def AddComponentsToCar(self, **components):
        compKeys = components.keys()
        if("engine") in compKeys:
            self._engine = components["engine"]
        else:
            raise ValueError("No engine!")
        self._speed = 2 * pi * 12 * self._engine.GetPower()
    def GetSpeed(self):
        return self._speed

    def GetName(self):
        return f"Тачка: {self._maker} - {self._model} Год выпуска: {self._year}"

    def GetLastTrackResult(self):
        return self._lastTrackResult
    
    def SetLastTrackResult(self, result):
        self._lastTrackResult = result

Содержимое CarFabrick.py

Файл содержит описание класса-фабрики, которая будет нам «собирать» автомобили. В её задачи входит: хранение списка машин, хранение списка моторов, хранение СЛОВАРЯ ключ-значение вида 1 : {Марка : Мощность}

2 : {Марка : Мощность}

и т.д. Т.е. по факту это словарь словарей.

Также представлены методы, отвечающие за печать списка двигателей, метод, спрашивающий Пользователя о желаемом моторе и метод создающий Автомобиль, на основе пользовательского ввода. И самый главный метод — возвращающий список созданных машин



from Car import Car

from CarComponent import Engine

class CarFabrick():
_cars = []
_engineList = [
Engine(«Форд», 1.5),
Engine(«Фиат», 1.4),
Engine(«BMW», 3.0),
Engine(«Lamborgini», 6.0)
]

_engineDict = {index : value for index,value in enumerate(_engineList)}

def _printEngine(self):
for index,engine in self._engineDict.items():
print(f»{index}. Производитель: {engine.GetName()}. Мощность: {engine.GetPower()}»)

def _pickEngine(self):
try:
indexEngine = int(input(«Enter engine number: «))
except Exception as e:
print(«Wrong number! Error: «,e)

return self._engineDict[indexEngine]


def CreateCar(self):
self._printEngine()
while True:
print(«Создание авто № «, len(self._cars)+1)
maker = input(«Кто производитель? Ответ: «)
model = input(«Какая модель? Ответ: «)
year = input(«Год выпуска:»)
car = Car(maker, model, year)
car.AddComponentsToCar(engine = self._pickEngine())
self._cars.append(car)

userChoice = input(«Введите слово \»Выход\» для выхода из констурктора или нажмите Enter для создание ещё одного авто…»)
if(userChoice.strip().lower() == «выход»):
break

def GetCars(self):
return self._cars

Содержимое Track.py

Класс Track содежит саму трассу: конструктор, получающий список машин (выставляем маштины на старт) и длину страссы. Второй метод непосредственно реализует сам заезд и выводит результаты.

import time

class Track():
    def __init__(self, length, cars):
        self._length = length
        self._cars = cars

    def Ride(self):
        print("Наш заезд: ")
        print("Участники: ")
        for car in self._cars:
            print(car.GetName())
        
        print("Идёт заезд...")
        time.sleep(3)

        print("...")
        time.sleep(2
                   )
        
        for i in range(len(self._cars)):
            self._cars[i].SetLastTrackResult(self._length / self._cars[i].GetSpeed())
        # resultTable = sorted(self._cars, key=lambda car: self._length / car.GetSpeed())
        resultTable = sorted(self._cars, key=lambda car: (car.SetLastTrackResult(self._length / car.GetSpeed()), self._length / car.GetSpeed())  )

        print("Результаты заезда: ")
        for i in range(len(resultTable)):
            print(f"{i+1} место: {resultTable[i].GetName()} Время: {resultTable[i].GetLastTrackResult()}")

Содержимое main.py

Все файлы до этого содержали только описание классов, соответственно программа не начнётся, если мы не создалим нужные объекты созданных нами классов и не вызовем какие-то методы этих объектов. Чем мы и занимаемся в файле main,py

from Track import Track
from CarFabric import CarFabrick

carFab = CarFabrick() #создаём фабрику машин
carFab.CreateCar() # Создаём машины, опрашивая пользователя
tLength = 1000 # Длина трассы по умолчанию, если ввод длины будет некорректный
try:
    tLength = int(input("Введите длину трассы, метры: "))
except:
    print("Неправильный ввод! Поедем стандартную трассу 1000 м") # Вот как раз на этот некорректный случай!


track = Track(tLength, carFab.GetCars()) # Создаём Трассу
track.Ride() # Запускаем гонку

В целом вот такая небольшая программка. Вопросы можно задавать на сайте myClass.team

Структура проекта в VSCode выглядит вот так: