Рубрики
Без рубрики

Краткое руководство Python, часть 7: классы

Красивая серия учебников Python направлена на людей без знаний о программировании и хотелось бы … Помечено Python, Учебник, начинающие, CodeNewie.

Красивая серия Caphify Python Tutorial направлена на людей без знаний о программировании и хотела бы забрать его. Как и в случае предыдущих частей, решения для упражнений доступны в Версия, размещенная на моем собственном сайте .

Мы наконец прибыли на занятия, последняя оставшаяся основная концепция Python.

Так что вы видели типы данных int , плавать , бол , ул , корпус , список , обдумывать и, наконец, файловые объекты, которые имеют свой собственный набор методов. У каждого есть свои правила. А класс в основном это пользовательский тип данных, который вы определяете и выбираете, как он работает.

Первый пример использования я исследую, это прямоугольник. Допустим, мы пишем приложение, которое делает геометрию расчетов или, может быть, какая-то физическая игра. Мы хотим тип данных для прямоугольников. План в том, что каждый прямоугольник хранит свои ширина и Высота и мы можем вычислить его периметр и область С простыми функциями вызовы. Мы также хотим, чтобы способ взять два прямоугольника и находить наименьший прямоугольник, который охватывает их обоих.

Во-первых, было бы хорошо рассмотреть, как вы сделаете это без классов. Было бы два основных варианта: списки или словари. Для подхода на основе списка вы можете использовать список [ширина, высота] представлять каждый прямоугольник. [5, 2] будет означать прямоугольник 5 единиц ширину и 2 высотой. Чтобы рассчитать свой периметр, у вас будет функция с именем периметр Или именно это приведет к прямоугольнику в качестве параметра.

Смотрите какие-либо недостатки этого подхода? Я могу подумать о нескольких:

  1. Синтаксис для доступа к ширине или высоте прямоугольника не является очень ясно . Если вы хотели получить ширину прямоугольника, вы будете делать прямо [0] , но не видит этот код, что он делает; И если вы когда-нибудь забыли, какой элемент в списке был какой, вы можете быть для многих отладки. Было бы лучше, если это выглядело как rect.width , но списки не дают нам способ сделать это так ясно, как это.

  2. Если сами прямоугольники смоделированы как списки, то как насчет списков прямоугольников? Вложенные списки работают нормально, но они склонны к ошибкам. Может быть, у вас есть функция где-то, которая принимает список прямоугольников и делает Для прямоугольников в прямоугольниках: И вы случайно пропустите просто простоугольник прямоугольника, забывая сделать его списком на одно изделий, окружая его [] .

    Ну, если сами прямоугольники были списки, это все равно будет работать сначала, так как оно закончится итерацией на размерах из одного прямоугольника, а не на каждом прямоугольнике. Худшая вероятность заключается в том, что она может не схватить, но вместо этого делать неправильную вещь, и вы будете рады расстраивающим опытом отладки.

    Даже если это произошло сбой, сообщение об ошибке, вероятно, не будет очень четко – если он пытается найти ширину каждого прямоугольника в списке, он ожидает с прямо [0] , вы бы увидели TypeError: «INT» объект не подписан потому что Reble Было бы значение ширины, а цифры не могут быть проиндексированы (или «подписан»).

  3. Что, если вы решили, что каждый прямоугольник должен хранить не только его размеры, но его положение, или, возможно, цвет или какое-либо другое свойство? Вы должны были бы изменить то, как вы хранящие прямоугольники повсюду от [ширина, высота] к [ширина, высота, х, у] Или что-то и убедитесь, что вы ничего не сделали, зависят от прямоугольников, являющихся только двумя элементами. Еще хуже, если вы хотели поставить номера позиций до Номера измерений в списке, поскольку это означало бы изменение номеров индекса везде.

  4. Подумайте о том, как вы реализуете другой тип данных для треугольников. Вы можете хранить треугольники в виде списков [Side1, Side2, Side3] Отказ Функция для получения периметра прямоугольника не может быть только названа периметр Кроме того, это должно быть названо rect_perimeter или что-то, чтобы избежать путаницы с Triangle_Perimeter Отказ

    Хуже единственный способ сказать разницу между прямоугольником и треугольником будет число элементов в списке, что, безусловно, не интуитивно (и – см. Выше – не надежно, потому что он может быть нарушен другими изменениями, которые вы могли бы сделать ), и потребуют комментарии.

Таким образом, хранение прямоугольников в виде списков, пока она будет работать, очевидно, не отличный подход.

Другой подход, который вы могли бы обойтись без классов – это словарь, основанная на основе. Вы можете представлять прямоугольники, такие как {«Ширина»: 5, «Высота»: 2} Отказ Синтаксис немного Clunkier: Прямо ['Ширина'] вместо прямо [0] Отказ Но это понятно, и это более важно.

Это решило бы большинство проблем выше, но не все они – у вас все равно будет вопрос с именами по периметру функций, когда вы добавили больше форм позже. Это означает любой код, который получает периметр формы, должен знать, какую форму это … или Вы могли бы просто иметь один периметр Функция осматривает, какие ключи в словаре формы, чтобы выяснить, какой тип это, но это все равно будет неуклюжем.

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

Решение Классы очень похоже на подход словаря, но в основном включает в себя каждый прямоугольник Знание что это прямоугольник и имея периметр Функция прилагается к нему, и треугольники знают, что они треугольники и имеют свои собственные периметр Функция прилагается, поэтому код, который нуждается в периметре формы, может просто позвонить form.perimeter () И сама форма беспокоится о том, как рассчитать ее. Вот начало того, как мы могли определить Прямоугольник тип данных:

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

Что __init__ вещь – это специальное имя функции; Это Прямоугольник класс Конструктор , который называется всякий раз, когда я делаю новый прямоугольник. Первый параметр, Я относится к Прямоугольник быть созданным. Посмотрим, что произойдет, когда я делаю некоторые прямоугольники:

>>> r1 = Rectangle(5, 7)
>>> r1.width, r1.height
(5, 7)
>>> r2 = Rectangle(4, 2)
>>> r2.width, r2.height
(4, 2)

Поэтому я только на самом деле пропускаю 2 аргумента. Вы увидите, если вы попытаетесь пройти 3, что он говорит вам, что функция занимает 3, но вы проходите 4! Я Параметр неявный. Вы не проходите вручную, это просто имя для Прямоугольник рассматриваемый объект.

Таким образом, вы можете увидеть, что когда вы делаете объект (или экземпляр ) класса, вы в основном относятся к имени класса, как если бы это было название функции. Это вид есть. И это называет конструктор. Я Начинается как пустой объект, и мы назначаем ширина и Высота Параметры мы добрались до self.width и Self.Height. . Когда конструктор возвращает Нет (который помнит по умолчанию), он на самом деле возвращает Я (И если вы попытаетесь заставить его вернуть что-то еще, это считается a jumeError ).

Если вам интересно, вы уже попробовали и нашли это, но у этого есть недостаток, что, хотя я могу напечатать его атрибуты, я не могу получить полезную информацию, печатая сам прямоугольник:

>>> r1
<__main__.Rectangle object at 0x801442310>

Ну разве это бесполезно! С словарем {«Ширина»: 5, «Высота»: 7} Я мог видеть все его атрибуты, просто печатая в самом словаре.

Python не знает автоматически, как отображаются объекты пользовательского класса. Мы можем сказать, как, но мы доберемся до этого дальше.

Во-первых: я упомянул, что Я Начинается как «пустой объект». Что такое Пустой объект как?

>>> class Thing: pass
...
>>> t1 = Thing()
>>> t1.name
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: type object 'Thing' has no attribute 'name'
>>> t1.name = 'Thing1'
>>> t1.name
'Thing1'
>>> t2 = Thing()
>>> t2.name = 'Thing2'
>>> t2.name
'Thing2'

Аналогия словарь должна быть очевидна. Я могу в основном хранить любые атрибуты, которые я хочу на него с любыми значениями, как ключевые слова на словаре. Единственное преимущество до сих пор, что я доступа к атрибутам с более удобным Отказ синтаксис вместо скобок.

Возможно, настоящая фундаментальная разница между объектом и словарем является то, как объект может вернуться к своему классу. С началом Прямоугольник Класс выше, атрибуты были прикреплены к Я Внутри конструктора означает каждый Прямоугольник было его Собственный ширина и высота . Вы также можете поставить атрибуты на сам класс, и мы посмотрим, что это делает:

>>> class Rectangle:
...   width = 4
...   height = 4
...
>>> r1 = Rectangle()
>>> r1.width
4
>>> r2 = Rectangle()
>>> r2.width
4
>>> r2.width = 5
>>> r2.width
5

Без конструктора явно определенного, я не передаю аргументов Прямоугольник () Отказ Но у них все еще есть ширина и Высота определяется непосредственно под классом. Очевидно, мы не хотели бы сделать это для измерений прямоугольника, потому что каждый прямоугольник должен иметь его Собственный Габаритные размеры. И хотя мы можем установить их отдельно после их инициализации, способнее иметь возможность пропускать их в качестве аргументов конструктора. Вы увидите, почему концепция Foxback полезна позже.

Во-первых, чтобы полностью понять, что происходит, когда мы прикладываем атрибуты на класс, давайте играть с этим немного больше:

>>> Rectangle.height
4
>>> Rectangle.height = 5
>>> r1.height, r2.height
(5, 5)

Я изменил Высота на классе, и похоже, что это изменило его на все существующие прямоугольники. Это собирается стать интереснее:

>>> r1.height = 6
>>> r1.height
6
>>> Rectangle.height
5
>>> r2.height
5
>>> Rectangle.height = 7
>>> r2.height
7
>>> r1.height
6

Таким образом, изменение атрибутов класса, кажется, обновляет объекты, которые я еще не получил собственное значение для того же атрибута. Что на самом деле происходит, это то, что без конструктора объекты начинаются без атрибутов, а когда я пытаюсь получить доступ R1.Height и у него нет одного, он возвращается к классу, что R1 является объектом, и видит, что у класса есть Высота Определяется, так что это дает мне это.

Но если объект прямоугольника имеет свой Высота это не смотрит на свой класс. Таким образом, мы не видели отступления до того, как у нас был конструктор, потому что линии self.width и Self.Height устанавливали атрибуты на каждом прямоугольнике, поскольку он был построен, поэтому им никогда не приходилось отступать.

__dict__ Атрибут объекта показывает собственные атрибуты объекта. Это чрезвычайно полезно для иллюстрации атрибута Foxback:

>>> r1.__dict__
{'height': 6}
>>> r2.__dict__
{'width': 5}

Так что вы идете. Вот как объекты работают. Объект в Python по сути является словарь в сочетании с именем класса. Когда вы пытаетесь получить доступ к атрибуту, вы получите его, если он существует, или если объект не имеет своего собственного атрибута, названного то, что он увидит, имеет ли у класса. Когда вы устанавливаете атрибут на объекте, он устанавливает его на самом объекте, а не на классе.

Безусловно, самое распространенное использование последующей связи для Методы – Те функции, прикрепленные к типу данных, как list.insert. . периметр может быть одним из тех, и мы назовем это как R1.Perimeter. () вместо Rettangle_PeriMeter (R1) . Пришло время реализовать этот метод периметра. (Я также вернул конструктор, так как мы хотели бы, если бы мы делали эту геометрию симулятора для реальных.)

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
    def perimeter(self):
        return self.width*2 + self.height*2

С классом определяется таким образом, мы могли бы получить любой Прямоугольник Периметр объекта из этого метода:

>>> r1 = Rectangle(5, 4)
>>> r1.perimeter()
18
>>> r2 = Rectangle(4, 6)
>>> r2.perimeter()
20

ДА! Синтаксис более прозрачна, чем Периметр (R1) тоже потому, что это выглядит Как и по периметру – это свойство прямоугольника, а не что-то еще, что мы делаем (что обычно есть функция), которая включает в себя прямоугольник.

Так что теперь Я Параметр может быть немного интуитивным. Наше периметр Метод на самом деле существует на классе, но когда мы получаем доступ к ним, используя объект класса вместо самого класса, этот параметр заполнен объектом, который мы его называем. Это другая существенная магия классов. В основном, obj.method (* args) переводится на Метод (Obj, * args) Отказ

Есть много намного больше, мы бы сделали бы, чтобы сделать Прямоугольник Класс действительно стоит по сравнению с использованием словарей. Вы знаете, как Прямоугольник S не печатайте как ничего полезного? Мы можем исправить это. __init__ Разве не единственный специальный метод. Если мы определим __repr__ Способ на классе, это скажет Питона, как лечить его с репре (который также также работает подсказки). Помните разницу между репре и ул ...| от части 6? Не заботятся, если вы этого не сделаете, потому что __str__ возвращается в __repr__ Если __str__ не существует (означает, что если мы определим только __repr __ , оба Rap /то быстрый а также ул …|/ Распечатать будет использовать его). Большинство типов хотят одно и то же поведение для этих методов в любом случае.

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
    def __repr__(self):
        string = '+' + '-' * (self.width-2) + '+\n'
        i = 0
        while i < self.height:
            string += '|' + ' ' * (self.width-2) + '|\n'
            i += 1
        string += '+' + '-' * (self.width-2) + '+\n'
        return string
    def perimeter(self):
        return self.width*2 + self.height*2

Попробуйте печатать Прямоугольник сейчас!

Эти особенные __...__ Методы, кстати, называются методами «Dunder». И есть еще больше, мы можем сделать с ними. Что делать, если бы мы могли использовать + на два Прямоугольник s найти самую маленькую Прямоугольник содержащий их оба?

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
    def __repr__(self):
        string = '+' + '-' * (self.width-2) + '+\n'
        i = 0
        while i < self.height:
            string += '|' + ' ' * (self.width-2) + '|\n'
            i += 1
        string += '+' + '-' * (self.width-2) + '+\n'
        return string
    def __add__(self, other):
        return Rectangle(max(other.width, self.width), max(other.height, self.height))
    def perimeter(self):
        return self.width*2 + self.height*2
    def area(self): # I'm also adding an area method while we're at it
        return self.width * self.height

__add__ Метод определяет поведение объекта, когда вы используете его с помощью + ! Попробуй это.

И обратите внимание на другое преимущество использования __repr__ Метод над типом, который только что печатает естественно, как словари: хотя требуется дополнительная работа, она позволяет нам настроить его.

Кстати, есть технически нет причин, что первый параметр метода должен быть назван Я Отказ Каждая функция может назвать его что-то другое, если вы хотите. Но Я Это традиционное имя для него в Python, и нет никаких веских причин отклоняться.

Кроме того, кстати (я намекнул на это в открытии, но теперь я собираюсь понять) Вы, возможно, уже набрали int Или один из других функций преобразования типа в подсказке без скобок, чтобы вызвать его, и заметил, что он говорит «< Class » int ‘> “- не Функция int. Теперь это должно наконец иметь смысл: int на самом деле класс, и когда вы называете это как int () Вы называете его конструктором! Эти встроенные классы являются единственными, которые не являются капитализированными Конвенцией, но они функционируют как и любой другой класс.

Классы тесно связаны с Философия под названием объектно-ориентированное программирование или Ооп. Вы столкнетесь с множеством людей с разными мнениями о том, хорошее ли ООП или плохое и даже то, что это значит. Я написал мой собственный Мысли по теме, которую вы можете прочитать, если вам это чувствуют, но есть по крайней мере одна основная концепция классов для покрытия.

Допустим, вы вышли вперед с этой программой Geometry Simulator и имели классы для кучка разных форм. Но есть хороший бит все общий – вы закончили добавить информацию о позиции к ним, поэтому у всех нас есть х и y атрибуты, что треки, где они в дополнение к тому, насколько они велики. Все они должны быть в состоянии иметь Импульс который перемещает их надлежащим образом каждым поворотом, и они также влияют гравитацию, означающие их импульс Y, увеличивается на 1 (в направлении вниз) каждый раз. У них также есть цвет атрибут.

Благодаря только инструментам, которые я дал выше, вам придется сделать это, определив общие атрибуты и методы отдельно на каждом классе. Но есть лучший способ.

Наследование – это способ повторно использовать функциональность «базового» или «родительского» класса при определении класса на основе него – подкласса или «детский» класс. Вот пример того, как вы могли это сделать:

class Shape:
    def __init__(self, x, y, color):
        self.x = x
        self.y = y
        # I didn't give the constructor parameters for momentum because
        # a shape probably never needs to start out with momentum.
        # d, by the way, is an abbreviatio for 'delta', which is used
        # in math to mean 'the change in'.
        self.dx = 0
        self.dy = 0
        self.color = color
    def pass_time(self):
        self.x += self.dx
        self.y += self.dy
        self.dy += 1

Тогда Прямоугольник будет объявлено с Прямоугольник класса (форма): вместо сорт Прямоугольник: и «наследует» Pass_time метод, чтобы вы могли назвать rect.pass_time () даже без добавления этого метода Прямоугольник определение класса.

Ну на самом деле это не совсем это делает. С Прямоугольник Определяет свой собственный конструктор (и должен, потому что он имеет атрибуты Форма не), Прямоугольник конструктор переопределяет Форма и так Когда вы делаете Прямоугольник , это называет Прямоугольник Конструктор и никогда не вызывает Форма один.

Не беспокоиться, для этого есть однострочное решение для этого, хотя и это некрасиво:

class Rectangle(Shape):
    def __init__(self, x, y, color, width, height):
        Shape.__init__(self, x, y, color)
        self.width = width
        self.height = height

С этой странной линией мы называем Форма Конструктор и пропустите его параметры, которые имеют Форма а не Прямоугольник Отказ Форма Конструктор делает все его вещи для нашего Прямоугольник объект. Так как мы называем конструктор напрямую с __init__ Вместо того, чтобы использовать имя класса, Я Параметр еще не заполнен, и мы должны передать это Я это относится к Прямоугольник объект в строительстве.

Так что это довольно крутонице? Вы можете повторно использовать общий код между классами с наследством.

Вы также можете наследовать из встроенных типов! Вы знаете, как list.remove Только удаляет первое представление? Что, если вы хотите, чтобы тип данных действует так же, как список, но также имеет метод для удаления каждый происшествие указанного значения?

class Mylist(list):
    def remove_all(self, item):
        while item in self:
            self.remove(item)

Это объявляет Милист как особый вид Список Это может также Remove_all , который охватывает это мало неудобств list.remove. . И отметить, что, поскольку мы не добавляем новые параметры конструктора, нам не нужно переопределить, поэтому нам не нужно делать это уродливые вещи, чтобы позвонить в Список конструктор – Милист просто наследует это.

Конечно, чтобы дать список это поведение, которое вам нужно явно сделать это Милист так:

>>> nums = Mylist([1, 3, 3, 5, 3, 2, 1, 3])
>>> nums.remove_all(3)
>>> nums
[1, 5, 2, 1]

Это не изменило бы поведение списков, которые вы создаете только с литеральным синтаксисом списка.

Общее использование наследства предназначено для пользовательских типов ошибок. Если вы хотите определить пользовательский Тип Ошибка, в отличие от погрешности встроенного типа ошибки с пользовательским сообщением (так что вы можете обрабатывать его с отдельной кроме Пункт), это на самом деле требуется только один линия:

class MyError(ValueError): pass

Так как мы не имели никаких атрибутов на MyError это наследует все от ValueError. так функционально MyError Работает точно так же, как ValueError и просто имеет другое имя.

Это удивительно полезно. Представьте себе MyError Используется в некотором конкретном состоянии, это подмножество значения недействительна (что является чем ValueError для). Так как это подтип ValueError Python знает, что, так что Кроме ValuceError пункт также поймает MyError (Как правило, как кроме Исключения Пункт уловит все типы ошибок, поскольку они все подтипы Исключение ). Но теперь мы могли бы сделать кроме MyError пункт, который поймал бы MyError s Но не ValueError. S в целом. Таким образом, пользовательский тип ошибок дает нам Опция справиться с этим по-разному, но не требует от нас. Разве это не аккуратно?

Непомышленность встроенных типов

Одна ловушка, которую я должен упомянуть, что сбивает с толку, учитывая, как я говорил о пустых объектах ранее: встроенные объекты являются особенными в том, что вы не можете добавлять их атрибуты. l = []; дал бы тебе AttributeError: объект «Список» не имеет атрибута «BLAH» Несмотря на то, что это будет работать для пользовательского класса, у которого не было BLAH атрибут. Вы можете сделать это путем подклассов встроенных типов, хотя.

Эй, у меня есть веселая идея проекта.

Программа, которая принимает две флоты, федерацию Млечного Пути и Альянс Андромеда и имитирует битву между ними. Каждый раунд каждый корабль принимает действие, как съемка лазера или ракеты. Он должен имитировать битву, пока она не заканчивается, а затем скажем, какой флот выиграл и какие корабли он оставил.

Управления есть корпус и щиты Отказ Shields поглощает повреждение сначала, благодаря преимуществами регенерации медленно, если они были повреждены. Если щиты корабля перегружены, оставшийся повреждение попадает в корпус.

Есть такие атаки:

  • Лазер – делайте небольшие количества урона, но обычно попадают

  • Ракету – сделать больше урона, но обычно пропускают небольшие корабли

Есть хотя бы эти типы кораблей:

  • Боец : Имейте шанс на 25% увернуться от лазеров и 75% до увернутых ракет. Каждый ход, они стреляют один лазер на случайном вражеском корабле, который касается 3 урона. 10 корпус, 10 щит, регенерирует 1 щит на поворот.

  • Бомбардировщик : Так же, как истребитель, за исключением того, что он запускает ракету на 6 уроне.

  • Фрегат : Никогда не уклоняется от чего угодно. 30 корпус, 30 щит, регенерирует 2 щит на поворот, пожалирует как 3-х повреждение лазера и 6 повреждений (которые могут быть в разных целях).

Сделайте программу объяснить, что происходит, как идет. Вот тестовый пробег моего внедрения, с 2 бойцами, 1 бомбардировщиком и 1 фрегат с каждой стороны (извините, это очень долго, но Я не могу сделать развертывающие заметки на dev.to, как я могу на моем сайте):

=== round 1 ===

Milky Way Federation Frigate #1 (hull: 30/30, shield: 30/30) firing 6-dmg missile at Andromeda Alliance Fighter #1 (hull: 10/10, shield: 10/10)
Andromeda Alliance Fighter #1 (hull: 10/10, shield: 10/10) dodged the missile

Andromeda Alliance Fighter #2 (hull: 10/10, shield: 10/10) firing 3-dmg laser at Milky Way Federation Fighter #2 (hull: 10/10, shield: 10/10)
Milky Way Federation Fighter #2 (hull: 10/10, shield: 7/10) was hit

Milky Way Federation Frigate #1 (hull: 30/30, shield: 30/30) firing 3-dmg laser at Andromeda Alliance Fighter #2 (hull: 10/10, shield: 10/10)
Andromeda Alliance Fighter #2 (hull: 10/10, shield: 7/10) was hit

Andromeda Alliance Bomber #1 (hull: 10/10, shield: 10/10) firing 6-dmg missile at Milky Way Federation Frigate #1 (hull: 30/30, shield: 30/30)
Milky Way Federation Frigate #1 (hull: 30/30, shield: 24/30) was hit

Andromeda Alliance Frigate #1 (hull: 30/30, shield: 30/30) firing 6-dmg missile at Milky Way Federation Frigate #1 (hull: 30/30, shield: 24/30)
Milky Way Federation Frigate #1 (hull: 30/30, shield: 18/30) was hit

Andromeda Alliance Fighter #1 (hull: 10/10, shield: 10/10) firing 3-dmg laser at Milky Way Federation Fighter #2 (hull: 10/10, shield: 7/10)
Milky Way Federation Fighter #2 (hull: 10/10, shield: 4/10) was hit

Andromeda Alliance Frigate #1 (hull: 30/30, shield: 30/30) firing 3-dmg laser at Milky Way Federation Frigate #1 (hull: 30/30, shield: 18/30)
Milky Way Federation Frigate #1 (hull: 30/30, shield: 15/30) was hit

Milky Way Federation Fighter #1 (hull: 10/10, shield: 10/10) firing 3-dmg laser at Andromeda Alliance Fighter #1 (hull: 10/10, shield: 10/10)
Andromeda Alliance Fighter #1 (hull: 10/10, shield: 7/10) was hit

Milky Way Federation Fighter #2 (hull: 10/10, shield: 4/10) firing 3-dmg laser at Andromeda Alliance Frigate #1 (hull: 30/30, shield: 30/30)
Andromeda Alliance Frigate #1 (hull: 30/30, shield: 27/30) was hit

Milky Way Federation Bomber #1 (hull: 10/10, shield: 10/10) firing 6-dmg missile at Andromeda Alliance Frigate #1 (hull: 30/30, shield: 27/30)
Andromeda Alliance Frigate #1 (hull: 30/30, shield: 21/30) was hit


=== round 2 ===

Milky Way Federation Frigate #1 (hull: 30/30, shield: 17/30) firing 6-dmg missile at Andromeda Alliance Frigate #1 (hull: 30/30, shield: 23/30)
Andromeda Alliance Frigate #1 (hull: 30/30, shield: 17/30) was hit

Milky Way Federation Fighter #2 (hull: 10/10, shield: 5/10) firing 3-dmg laser at Andromeda Alliance Fighter #2 (hull: 10/10, shield: 8/10)
Andromeda Alliance Fighter #2 (hull: 10/10, shield: 8/10) dodged the laser

Andromeda Alliance Fighter #2 (hull: 10/10, shield: 8/10) firing 3-dmg laser at Milky Way Federation Frigate #1 (hull: 30/30, shield: 17/30)
Milky Way Federation Frigate #1 (hull: 30/30, shield: 14/30) was hit

Andromeda Alliance Frigate #1 (hull: 30/30, shield: 17/30) firing 6-dmg missile at Milky Way Federation Frigate #1 (hull: 30/30, shield: 14/30)
Milky Way Federation Frigate #1 (hull: 30/30, shield: 8/30) was hit

Milky Way Federation Bomber #1 (hull: 10/10, shield: 10/10) firing 6-dmg missile at Andromeda Alliance Fighter #2 (hull: 10/10, shield: 8/10)
Andromeda Alliance Fighter #2 (hull: 10/10, shield: 8/10) dodged the missile

Andromeda Alliance Bomber #1 (hull: 10/10, shield: 10/10) firing 6-dmg missile at Milky Way Federation Bomber #1 (hull: 10/10, shield: 10/10)
Milky Way Federation Bomber #1 (hull: 10/10, shield: 10/10) dodged the missile

Milky Way Federation Fighter #1 (hull: 10/10, shield: 10/10) firing 3-dmg laser at Andromeda Alliance Bomber #1 (hull: 10/10, shield: 10/10)
Andromeda Alliance Bomber #1 (hull: 10/10, shield: 7/10) was hit

Andromeda Alliance Frigate #1 (hull: 30/30, shield: 17/30) firing 3-dmg laser at Milky Way Federation Bomber #1 (hull: 10/10, shield: 10/10)
Milky Way Federation Bomber #1 (hull: 10/10, shield: 10/10) dodged the laser

Andromeda Alliance Fighter #1 (hull: 10/10, shield: 8/10) firing 3-dmg laser at Milky Way Federation Fighter #2 (hull: 10/10, shield: 5/10)
Milky Way Federation Fighter #2 (hull: 10/10, shield: 2/10) was hit

Milky Way Federation Frigate #1 (hull: 30/30, shield: 8/30) firing 3-dmg laser at Andromeda Alliance Fighter #2 (hull: 10/10, shield: 8/10)
Andromeda Alliance Fighter #2 (hull: 10/10, shield: 5/10) was hit


=== round 3 ===

Milky Way Federation Fighter #1 (hull: 10/10, shield: 10/10) firing 3-dmg laser at Andromeda Alliance Fighter #1 (hull: 10/10, shield: 9/10)
Andromeda Alliance Fighter #1 (hull: 10/10, shield: 6/10) was hit

Milky Way Federation Bomber #1 (hull: 10/10, shield: 10/10) firing 6-dmg missile at Andromeda Alliance Fighter #1 (hull: 10/10, shield: 6/10)
Andromeda Alliance Fighter #1 (hull: 10/10, shield: 0/10) was hit

Milky Way Federation Frigate #1 (hull: 30/30, shield: 10/30) firing 6-dmg missile at Andromeda Alliance Frigate #1 (hull: 30/30, shield: 19/30)
Andromeda Alliance Frigate #1 (hull: 30/30, shield: 13/30) was hit

Milky Way Federation Frigate #1 (hull: 30/30, shield: 10/30) firing 3-dmg laser at Andromeda Alliance Fighter #1 (hull: 10/10, shield: 0/10)
Andromeda Alliance Fighter #1 (hull: 7/10, shield: 0/10) was hit

Andromeda Alliance Fighter #1 (hull: 7/10, shield: 0/10) firing 3-dmg laser at Milky Way Federation Bomber #1 (hull: 10/10, shield: 10/10)
Milky Way Federation Bomber #1 (hull: 10/10, shield: 7/10) was hit

Andromeda Alliance Frigate #1 (hull: 30/30, shield: 13/30) firing 6-dmg missile at Milky Way Federation Fighter #2 (hull: 10/10, shield: 3/10)
Milky Way Federation Fighter #2 (hull: 10/10, shield: 3/10) dodged the missile

Milky Way Federation Fighter #2 (hull: 10/10, shield: 3/10) firing 3-dmg laser at Andromeda Alliance Bomber #1 (hull: 10/10, shield: 8/10)
Andromeda Alliance Bomber #1 (hull: 10/10, shield: 5/10) was hit

Andromeda Alliance Fighter #2 (hull: 10/10, shield: 6/10) firing 3-dmg laser at Milky Way Federation Fighter #1 (hull: 10/10, shield: 10/10)
Milky Way Federation Fighter #1 (hull: 10/10, shield: 7/10) was hit

Andromeda Alliance Bomber #1 (hull: 10/10, shield: 5/10) firing 6-dmg missile at Milky Way Federation Bomber #1 (hull: 10/10, shield: 7/10)
Milky Way Federation Bomber #1 (hull: 10/10, shield: 7/10) dodged the missile

Andromeda Alliance Frigate #1 (hull: 30/30, shield: 13/30) firing 3-dmg laser at Milky Way Federation Fighter #1 (hull: 10/10, shield: 7/10)
Milky Way Federation Fighter #1 (hull: 10/10, shield: 7/10) dodged the laser


=== round 4 ===

Milky Way Federation Bomber #1 (hull: 10/10, shield: 8/10) firing 6-dmg missile at Andromeda Alliance Frigate #1 (hull: 30/30, shield: 15/30)
Andromeda Alliance Frigate #1 (hull: 30/30, shield: 9/30) was hit

Milky Way Federation Fighter #1 (hull: 10/10, shield: 8/10) firing 3-dmg laser at Andromeda Alliance Bomber #1 (hull: 10/10, shield: 6/10)
Andromeda Alliance Bomber #1 (hull: 10/10, shield: 3/10) was hit

Andromeda Alliance Bomber #1 (hull: 10/10, shield: 3/10) firing 6-dmg missile at Milky Way Federation Fighter #2 (hull: 10/10, shield: 4/10)
Milky Way Federation Fighter #2 (hull: 8/10, shield: 0/10) was hit

Andromeda Alliance Frigate #1 (hull: 30/30, shield: 9/30) firing 3-dmg laser at Milky Way Federation Bomber #1 (hull: 10/10, shield: 8/10)
Milky Way Federation Bomber #1 (hull: 10/10, shield: 5/10) was hit

Milky Way Federation Fighter #2 (hull: 8/10, shield: 0/10) firing 3-dmg laser at Andromeda Alliance Bomber #1 (hull: 10/10, shield: 3/10)
Andromeda Alliance Bomber #1 (hull: 10/10, shield: 0/10) was hit

Andromeda Alliance Fighter #2 (hull: 10/10, shield: 7/10) firing 3-dmg laser at Milky Way Federation Bomber #1 (hull: 10/10, shield: 5/10)
Milky Way Federation Bomber #1 (hull: 10/10, shield: 2/10) was hit

Andromeda Alliance Frigate #1 (hull: 30/30, shield: 9/30) firing 6-dmg missile at Milky Way Federation Frigate #1 (hull: 30/30, shield: 12/30)
Milky Way Federation Frigate #1 (hull: 30/30, shield: 6/30) was hit

Milky Way Federation Frigate #1 (hull: 30/30, shield: 6/30) firing 6-dmg missile at Andromeda Alliance Fighter #1 (hull: 7/10, shield: 1/10)
Andromeda Alliance Fighter #1 (hull: 7/10, shield: 1/10) dodged the missile

Milky Way Federation Frigate #1 (hull: 30/30, shield: 6/30) firing 3-dmg laser at Andromeda Alliance Fighter #2 (hull: 10/10, shield: 7/10)
Andromeda Alliance Fighter #2 (hull: 10/10, shield: 7/10) dodged the laser

Andromeda Alliance Fighter #1 (hull: 7/10, shield: 1/10) firing 3-dmg laser at Milky Way Federation Fighter #2 (hull: 8/10, shield: 0/10)
Milky Way Federation Fighter #2 (hull: 8/10, shield: 0/10) dodged the laser


=== round 5 ===

Milky Way Federation Fighter #1 (hull: 10/10, shield: 9/10) firing 3-dmg laser at Andromeda Alliance Fighter #1 (hull: 7/10, shield: 2/10)
Andromeda Alliance Fighter #1 (hull: 6/10, shield: 0/10) was hit

Milky Way Federation Frigate #1 (hull: 30/30, shield: 8/30) firing 6-dmg missile at Andromeda Alliance Fighter #1 (hull: 6/10, shield: 0/10)
Andromeda Alliance Fighter #1 (hull: 0/10, shield: 0/10) was hit

Milky Way Federation Fighter #2 (hull: 8/10, shield: 1/10) firing 3-dmg laser at Andromeda Alliance Frigate #1 (hull: 30/30, shield: 11/30)
Andromeda Alliance Frigate #1 (hull: 30/30, shield: 8/30) was hit

Andromeda Alliance Bomber #1 (hull: 10/10, shield: 1/10) firing 6-dmg missile at Milky Way Federation Fighter #1 (hull: 10/10, shield: 9/10)
Milky Way Federation Fighter #1 (hull: 10/10, shield: 9/10) dodged the missile

Milky Way Federation Bomber #1 (hull: 10/10, shield: 3/10) firing 6-dmg missile at Andromeda Alliance Frigate #1 (hull: 30/30, shield: 8/30)
Andromeda Alliance Frigate #1 (hull: 30/30, shield: 2/30) was hit

Milky Way Federation Frigate #1 (hull: 30/30, shield: 8/30) firing 3-dmg laser at Andromeda Alliance Fighter #1 (hull: 0/10, shield: 0/10)
Andromeda Alliance Fighter #1 (hull: -3/10, shield: 0/10) was hit

Andromeda Alliance Fighter #1 (hull: -3/10, shield: 0/10) firing 3-dmg laser at Milky Way Federation Fighter #2 (hull: 8/10, shield: 1/10)
Milky Way Federation Fighter #2 (hull: 8/10, shield: 1/10) dodged the laser

Andromeda Alliance Fighter #2 (hull: 10/10, shield: 8/10) firing 3-dmg laser at Milky Way Federation Frigate #1 (hull: 30/30, shield: 8/30)
Milky Way Federation Frigate #1 (hull: 30/30, shield: 5/30) was hit

Andromeda Alliance Frigate #1 (hull: 30/30, shield: 2/30) firing 3-dmg laser at Milky Way Federation Fighter #1 (hull: 10/10, shield: 9/10)
Milky Way Federation Fighter #1 (hull: 10/10, shield: 6/10) was hit

Andromeda Alliance Frigate #1 (hull: 30/30, shield: 2/30) firing 6-dmg missile at Milky Way Federation Frigate #1 (hull: 30/30, shield: 5/30)
Milky Way Federation Frigate #1 (hull: 29/30, shield: 0/30) was hit


=== round 6 ===

Milky Way Federation Fighter #1 (hull: 10/10, shield: 7/10) firing 3-dmg laser at Andromeda Alliance Bomber #1 (hull: 10/10, shield: 2/10)
Andromeda Alliance Bomber #1 (hull: 10/10, shield: 2/10) dodged the laser

Andromeda Alliance Frigate #1 (hull: 30/30, shield: 4/30) firing 6-dmg missile at Milky Way Federation Fighter #1 (hull: 10/10, shield: 7/10)
Milky Way Federation Fighter #1 (hull: 10/10, shield: 7/10) dodged the missile

Milky Way Federation Fighter #2 (hull: 8/10, shield: 2/10) firing 3-dmg laser at Andromeda Alliance Frigate #1 (hull: 30/30, shield: 4/30)
Andromeda Alliance Frigate #1 (hull: 30/30, shield: 1/30) was hit

Milky Way Federation Frigate #1 (hull: 29/30, shield: 2/30) firing 6-dmg missile at Andromeda Alliance Bomber #1 (hull: 10/10, shield: 2/10)
Andromeda Alliance Bomber #1 (hull: 10/10, shield: 2/10) dodged the missile

Milky Way Federation Frigate #1 (hull: 29/30, shield: 2/30) firing 3-dmg laser at Andromeda Alliance Fighter #2 (hull: 10/10, shield: 9/10)
Andromeda Alliance Fighter #2 (hull: 10/10, shield: 6/10) was hit

Milky Way Federation Bomber #1 (hull: 10/10, shield: 4/10) firing 6-dmg missile at Andromeda Alliance Bomber #1 (hull: 10/10, shield: 2/10)
Andromeda Alliance Bomber #1 (hull: 10/10, shield: 2/10) dodged the missile

Andromeda Alliance Frigate #1 (hull: 30/30, shield: 1/30) firing 3-dmg laser at Milky Way Federation Fighter #2 (hull: 8/10, shield: 2/10)
Milky Way Federation Fighter #2 (hull: 8/10, shield: 2/10) dodged the laser

Andromeda Alliance Bomber #1 (hull: 10/10, shield: 2/10) firing 6-dmg missile at Milky Way Federation Fighter #1 (hull: 10/10, shield: 7/10)
Milky Way Federation Fighter #1 (hull: 10/10, shield: 7/10) dodged the missile

Andromeda Alliance Fighter #2 (hull: 10/10, shield: 6/10) firing 3-dmg laser at Milky Way Federation Fighter #1 (hull: 10/10, shield: 7/10)
Milky Way Federation Fighter #1 (hull: 10/10, shield: 4/10) was hit


=== round 7 ===

Milky Way Federation Fighter #2 (hull: 8/10, shield: 3/10) firing 3-dmg laser at Andromeda Alliance Frigate #1 (hull: 30/30, shield: 3/30)
Andromeda Alliance Frigate #1 (hull: 30/30, shield: 0/30) was hit

Milky Way Federation Frigate #1 (hull: 29/30, shield: 4/30) firing 6-dmg missile at Andromeda Alliance Frigate #1 (hull: 30/30, shield: 0/30)
Andromeda Alliance Frigate #1 (hull: 24/30, shield: 0/30) was hit

Milky Way Federation Bomber #1 (hull: 10/10, shield: 5/10) firing 6-dmg missile at Andromeda Alliance Fighter #2 (hull: 10/10, shield: 7/10)
Andromeda Alliance Fighter #2 (hull: 10/10, shield: 7/10) dodged the missile

Andromeda Alliance Frigate #1 (hull: 24/30, shield: 0/30) firing 3-dmg laser at Milky Way Federation Fighter #1 (hull: 10/10, shield: 5/10)
Milky Way Federation Fighter #1 (hull: 10/10, shield: 2/10) was hit

Andromeda Alliance Bomber #1 (hull: 10/10, shield: 3/10) firing 6-dmg missile at Milky Way Federation Fighter #1 (hull: 10/10, shield: 2/10)
Milky Way Federation Fighter #1 (hull: 6/10, shield: 0/10) was hit

Andromeda Alliance Fighter #2 (hull: 10/10, shield: 7/10) firing 3-dmg laser at Milky Way Federation Fighter #2 (hull: 8/10, shield: 3/10)
Milky Way Federation Fighter #2 (hull: 8/10, shield: 3/10) dodged the laser

Andromeda Alliance Frigate #1 (hull: 24/30, shield: 0/30) firing 6-dmg missile at Milky Way Federation Fighter #2 (hull: 8/10, shield: 3/10)
Milky Way Federation Fighter #2 (hull: 8/10, shield: 3/10) dodged the missile

Milky Way Federation Fighter #1 (hull: 6/10, shield: 0/10) firing 3-dmg laser at Andromeda Alliance Frigate #1 (hull: 24/30, shield: 0/30)
Andromeda Alliance Frigate #1 (hull: 21/30, shield: 0/30) was hit

Milky Way Federation Frigate #1 (hull: 29/30, shield: 4/30) firing 3-dmg laser at Andromeda Alliance Fighter #2 (hull: 10/10, shield: 7/10)
Andromeda Alliance Fighter #2 (hull: 10/10, shield: 4/10) was hit


=== round 8 ===

Andromeda Alliance Fighter #2 (hull: 10/10, shield: 5/10) firing 3-dmg laser at Milky Way Federation Bomber #1 (hull: 10/10, shield: 6/10)
Milky Way Federation Bomber #1 (hull: 10/10, shield: 3/10) was hit

Milky Way Federation Frigate #1 (hull: 29/30, shield: 6/30) firing 3-dmg laser at Andromeda Alliance Frigate #1 (hull: 21/30, shield: 2/30)
Andromeda Alliance Frigate #1 (hull: 20/30, shield: 0/30) was hit

Andromeda Alliance Frigate #1 (hull: 20/30, shield: 0/30) firing 3-dmg laser at Milky Way Federation Fighter #2 (hull: 8/10, shield: 4/10)
Milky Way Federation Fighter #2 (hull: 8/10, shield: 4/10) dodged the laser

Andromeda Alliance Bomber #1 (hull: 10/10, shield: 4/10) firing 6-dmg missile at Milky Way Federation Bomber #1 (hull: 10/10, shield: 3/10)
Milky Way Federation Bomber #1 (hull: 7/10, shield: 0/10) was hit

Milky Way Federation Bomber #1 (hull: 7/10, shield: 0/10) firing 6-dmg missile at Andromeda Alliance Fighter #2 (hull: 10/10, shield: 5/10)
Andromeda Alliance Fighter #2 (hull: 10/10, shield: 5/10) dodged the missile

Milky Way Federation Fighter #2 (hull: 8/10, shield: 4/10) firing 3-dmg laser at Andromeda Alliance Fighter #2 (hull: 10/10, shield: 5/10)
Andromeda Alliance Fighter #2 (hull: 10/10, shield: 2/10) was hit

Milky Way Federation Fighter #1 (hull: 6/10, shield: 1/10) firing 3-dmg laser at Andromeda Alliance Bomber #1 (hull: 10/10, shield: 4/10)
Andromeda Alliance Bomber #1 (hull: 10/10, shield: 1/10) was hit

Andromeda Alliance Frigate #1 (hull: 20/30, shield: 0/30) firing 6-dmg missile at Milky Way Federation Fighter #2 (hull: 8/10, shield: 4/10)
Milky Way Federation Fighter #2 (hull: 8/10, shield: 4/10) dodged the missile

Milky Way Federation Frigate #1 (hull: 29/30, shield: 6/30) firing 6-dmg missile at Andromeda Alliance Bomber #1 (hull: 10/10, shield: 1/10)
Andromeda Alliance Bomber #1 (hull: 10/10, shield: 1/10) dodged the missile


=== round 9 ===

Andromeda Alliance Fighter #2 (hull: 10/10, shield: 3/10) firing 3-dmg laser at Milky Way Federation Fighter #2 (hull: 8/10, shield: 5/10)
Milky Way Federation Fighter #2 (hull: 8/10, shield: 5/10) dodged the laser

Milky Way Federation Fighter #2 (hull: 8/10, shield: 5/10) firing 3-dmg laser at Andromeda Alliance Fighter #2 (hull: 10/10, shield: 3/10)
Andromeda Alliance Fighter #2 (hull: 10/10, shield: 0/10) was hit

Andromeda Alliance Bomber #1 (hull: 10/10, shield: 2/10) firing 6-dmg missile at Milky Way Federation Fighter #1 (hull: 6/10, shield: 2/10)
Milky Way Federation Fighter #1 (hull: 6/10, shield: 2/10) dodged the missile

Andromeda Alliance Frigate #1 (hull: 20/30, shield: 2/30) firing 6-dmg missile at Milky Way Federation Fighter #1 (hull: 6/10, shield: 2/10)
Milky Way Federation Fighter #1 (hull: 6/10, shield: 2/10) dodged the missile

Milky Way Federation Frigate #1 (hull: 29/30, shield: 8/30) firing 3-dmg laser at Andromeda Alliance Fighter #2 (hull: 10/10, shield: 0/10)
Andromeda Alliance Fighter #2 (hull: 7/10, shield: 0/10) was hit

Milky Way Federation Bomber #1 (hull: 7/10, shield: 1/10) firing 6-dmg missile at Andromeda Alliance Bomber #1 (hull: 10/10, shield: 2/10)
Andromeda Alliance Bomber #1 (hull: 6/10, shield: 0/10) was hit

Milky Way Federation Frigate #1 (hull: 29/30, shield: 8/30) firing 6-dmg missile at Andromeda Alliance Bomber #1 (hull: 6/10, shield: 0/10)
Andromeda Alliance Bomber #1 (hull: 6/10, shield: 0/10) dodged the missile

Milky Way Federation Fighter #1 (hull: 6/10, shield: 2/10) firing 3-dmg laser at Andromeda Alliance Fighter #2 (hull: 7/10, shield: 0/10)
Andromeda Alliance Fighter #2 (hull: 4/10, shield: 0/10) was hit

Andromeda Alliance Frigate #1 (hull: 20/30, shield: 2/30) firing 3-dmg laser at Milky Way Federation Fighter #2 (hull: 8/10, shield: 5/10)
Milky Way Federation Fighter #2 (hull: 8/10, shield: 2/10) was hit


=== round 10 ===

Andromeda Alliance Frigate #1 (hull: 20/30, shield: 4/30) firing 3-dmg laser at Milky Way Federation Frigate #1 (hull: 29/30, shield: 10/30)
Milky Way Federation Frigate #1 (hull: 29/30, shield: 7/30) was hit

Milky Way Federation Frigate #1 (hull: 29/30, shield: 7/30) firing 3-dmg laser at Andromeda Alliance Bomber #1 (hull: 6/10, shield: 1/10)
Andromeda Alliance Bomber #1 (hull: 4/10, shield: 0/10) was hit

Andromeda Alliance Frigate #1 (hull: 20/30, shield: 4/30) firing 6-dmg missile at Milky Way Federation Frigate #1 (hull: 29/30, shield: 7/30)
Milky Way Federation Frigate #1 (hull: 29/30, shield: 1/30) was hit

Andromeda Alliance Bomber #1 (hull: 4/10, shield: 0/10) firing 6-dmg missile at Milky Way Federation Frigate #1 (hull: 29/30, shield: 1/30)
Milky Way Federation Frigate #1 (hull: 24/30, shield: 0/30) was hit

Milky Way Federation Fighter #2 (hull: 8/10, shield: 3/10) firing 3-dmg laser at Andromeda Alliance Fighter #2 (hull: 4/10, shield: 1/10)
Andromeda Alliance Fighter #2 (hull: 2/10, shield: 0/10) was hit

Milky Way Federation Frigate #1 (hull: 24/30, shield: 0/30) firing 6-dmg missile at Andromeda Alliance Frigate #1 (hull: 20/30, shield: 4/30)
Andromeda Alliance Frigate #1 (hull: 18/30, shield: 0/30) was hit

Milky Way Federation Fighter #1 (hull: 6/10, shield: 3/10) firing 3-dmg laser at Andromeda Alliance Fighter #2 (hull: 2/10, shield: 0/10)
Andromeda Alliance Fighter #2 (hull: -1/10, shield: 0/10) was hit

Milky Way Federation Bomber #1 (hull: 7/10, shield: 2/10) firing 6-dmg missile at Andromeda Alliance Frigate #1 (hull: 18/30, shield: 0/30)
Andromeda Alliance Frigate #1 (hull: 12/30, shield: 0/30) was hit

Andromeda Alliance Fighter #2 (hull: -1/10, shield: 0/10) firing 3-dmg laser at Milky Way Federation Bomber #1 (hull: 7/10, shield: 2/10)
Milky Way Federation Bomber #1 (hull: 6/10, shield: 0/10) was hit


=== round 11 ===

Milky Way Federation Frigate #1 (hull: 24/30, shield: 2/30) firing 6-dmg missile at Andromeda Alliance Frigate #1 (hull: 12/30, shield: 2/30)
Andromeda Alliance Frigate #1 (hull: 8/30, shield: 0/30) was hit

Andromeda Alliance Frigate #1 (hull: 8/30, shield: 0/30) firing 3-dmg laser at Milky Way Federation Fighter #2 (hull: 8/10, shield: 4/10)
Milky Way Federation Fighter #2 (hull: 8/10, shield: 1/10) was hit

Milky Way Federation Fighter #2 (hull: 8/10, shield: 1/10) firing 3-dmg laser at Andromeda Alliance Bomber #1 (hull: 4/10, shield: 1/10)
Andromeda Alliance Bomber #1 (hull: 2/10, shield: 0/10) was hit

Milky Way Federation Frigate #1 (hull: 24/30, shield: 2/30) firing 3-dmg laser at Andromeda Alliance Frigate #1 (hull: 8/30, shield: 0/30)
Andromeda Alliance Frigate #1 (hull: 5/30, shield: 0/30) was hit

Andromeda Alliance Frigate #1 (hull: 5/30, shield: 0/30) firing 6-dmg missile at Milky Way Federation Frigate #1 (hull: 24/30, shield: 2/30)
Milky Way Federation Frigate #1 (hull: 20/30, shield: 0/30) was hit

Milky Way Federation Fighter #1 (hull: 6/10, shield: 4/10) firing 3-dmg laser at Andromeda Alliance Frigate #1 (hull: 5/30, shield: 0/30)
Andromeda Alliance Frigate #1 (hull: 2/30, shield: 0/30) was hit

Milky Way Federation Bomber #1 (hull: 6/10, shield: 1/10) firing 6-dmg missile at Andromeda Alliance Frigate #1 (hull: 2/30, shield: 0/30)
Andromeda Alliance Frigate #1 (hull: -4/30, shield: 0/30) was hit

Andromeda Alliance Bomber #1 (hull: 2/10, shield: 0/10) firing 6-dmg missile at Milky Way Federation Bomber #1 (hull: 6/10, shield: 1/10)
Milky Way Federation Bomber #1 (hull: 1/10, shield: 0/10) was hit


=== round 12 ===

Milky Way Federation Bomber #1 (hull: 1/10, shield: 1/10) firing 6-dmg missile at Andromeda Alliance Bomber #1 (hull: 2/10, shield: 1/10)
Andromeda Alliance Bomber #1 (hull: 2/10, shield: 1/10) dodged the missile

Milky Way Federation Fighter #2 (hull: 8/10, shield: 2/10) firing 3-dmg laser at Andromeda Alliance Bomber #1 (hull: 2/10, shield: 1/10)
Andromeda Alliance Bomber #1 (hull: 0/10, shield: 0/10) was hit

Milky Way Federation Frigate #1 (hull: 20/30, shield: 2/30) firing 6-dmg missile at Andromeda Alliance Bomber #1 (hull: 0/10, shield: 0/10)
Andromeda Alliance Bomber #1 (hull: 0/10, shield: 0/10) dodged the missile

Milky Way Federation Fighter #1 (hull: 6/10, shield: 5/10) firing 3-dmg laser at Andromeda Alliance Bomber #1 (hull: 0/10, shield: 0/10)
Andromeda Alliance Bomber #1 (hull: -3/10, shield: 0/10) was hit

Milky Way Federation Frigate #1 (hull: 20/30, shield: 2/30) firing 3-dmg laser at Andromeda Alliance Bomber #1 (hull: -3/10, shield: 0/10)
Andromeda Alliance Bomber #1 (hull: -6/10, shield: 0/10) was hit

Andromeda Alliance Bomber #1 (hull: -6/10, shield: 0/10) firing 6-dmg missile at Milky Way Federation Fighter #1 (hull: 6/10, shield: 5/10)
Milky Way Federation Fighter #1 (hull: 6/10, shield: 5/10) dodged the missile



Milky Way Federation wins!
Ships remaining:
Milky Way Federation Fighter #1 (hull: 6/10, shield: 5/10)
Milky Way Federation Fighter #2 (hull: 8/10, shield: 2/10)
Milky Way Federation Bomber #1 (hull: 1/10, shield: 1/10)
Milky Way Federation Frigate #1 (hull: 20/30, shield: 2/30)

Бедный альянс Андромеда! Не один убийство!

Там просто пара, другая вещь, которую вы должны знать о классах, прежде чем пытаться осуществить это. Во-первых, вы можете увидеть, какой класс что-то с Тип Функция – Тип (5) , так далее. Во-вторых, каждый класс хранит свое имя в __name__ атрибуция на сам класс. Прямоугольник .__ Имя__ будет «Прямоугольник» Отказ Я использую оба из них в моей реализации.

<Решение опущено>

И как только вы сделали это, это тривиально добавлять новые виды кораблей или новых типов атак! Вы также можете сделать что-то вроде Добавить Smartfighter который знает, чтобы сосредоточить свои атаки на вражеские бомбардировщики и стрелять на самых поврежденных, или SmartBomber который не знает, чтобы не нацелить небольшие корабли, если есть большие. Может быть, а РемонтProbe Это восстанавливает корпус поврежденных союзных кораблей? А Фабрика который производит истребитель или бомбардировщик каждый поворот? Может быть, тип атаки ионов, который имеет дополнительный ущерб щитам? Возможности бесконечны, и с гибкостью классов, их легко исследуйте.

Оригинал: “https://dev.to/yujiri8/the-concise-python-tutorial-part-7-classes-3b8a”