Loading...
indieza avatar indieza 46 Точки

[LABProblems] OOP - Problem{1} - Mass Effect

Някой би ли ми казал как се практикува при този тип задачи, някакви съвети и от къде мога да намеря решение на задачата ако зацикля някъдеsmiley

 

Благодаря предварителноlaugh

Тагове:
1
C# OOP Basics
RoYaL avatar RoYaL Trainer 6849 Точки

Здравей,

Авторското решение можеш да намериш тук: http://svn.softuni.org/admin/svn/oop/January-2015/OOP-Retake-Exam-1-June-2015.zip

Ако ти иска username/password - student/student

В инстанцията на курса има упътване за Лаба, където има 15 страници walkthrough.

Това е тип задача, която те поставя малко повече в реална среда. Тези задачи тестват два основни компонента (считайки, че вече е тестван компонента 'четене на условие'), а именно: Бързо изучаване на чужд код и принципи на обектно ориентираното програмиране.

Започвайки от четенето на условието, трябва да придобием представа какво трябва да представлява проекта. Той е съвкупност от две неща - това, което има до момента и това, което се иска от нас.

Прочитайки условието си изясняваме предмета на проекта: игра с галактически битки с корабчета. След изчитането на условието докрай става ясно какво трябва да има в проекта и какво трябва да се случва при определени потребителски действия.

Изяснява се идеята, че потребителските действия ще са вход в конзолата, който ще се състои от определени стрингове, които в условието са наречени команди. Корабче можеш да бъде създадено чрез команда за създаване. Можеш да се сбият две корабчета с команда за атакуване. Кораб може да пътува, че команда за пътуване. И кораб дава информация за състоянието си при команда за статус.

От тук трябва да направим една мини-схема на проекта в главата си/на лист хартия.

Излиза, че като за начало чакаме за потребителски вход. В един момент идва потребителския вход под формата на стринг. Четем този стринг и според написаното в него трябва да извършим съответното действие. Трябва да вършим тези действия спазвайки приниципите на обектно ориентираното програмиране.

С уменията да четем условията и да си представяме нещата като в реалния свят, стигнахме до заключението какви обекти имаме в проекта. Беше написано, че "Има няколко СЛЪНЧЕВИ СИСТЕМИ в ГАЛАКТИКАТА. КОСМИЧЕСКИ КОРАБ може да пътува между системите и да напада други кораби. Корабите стрелят СНАРЯД с определен демидж и имат колекция от ПОДОБРЕНИЯ".

От уголемените съществителни имена в текста по-горе разбираме и какви са основните ни обекти в играта: Слънчева система (StarSystem), Галактика (Galaxy), Космически кораб (StarShip), Снаряд (Projectile), Подобрение (Enhancement).

В условието беше засегната и частта, че има няколко вида космически кораби и няколко вида снаряди, всеки един от които се държи по различен начин. Корабите имат различни статистики, а снарядите се бият по различен начин. Тук горе-долу си правим една лека схема, че ще имаме няколко подвида на един вид - т.е. наследяване на Космическия кораб и наследяване на Снаряда.

Написано ни е и какво има един кораб - живот, щитове, щета, разход, локация и подобрения (полета), както и какво може да прави - да произвежда снаряд, да реагира на атака и да добавя подобрения (методи).

Казано ни е същото и за галактика - има няколко слънчеви системи (поле) и TravelTo метод.

Сега е време да видим какво от това ни е дадено. Отваряме проекта и започваме от входната точка. Там забелязваме, че ни е дадена Галактиката, Слънчевата система както и нещата около тях - галактика да съдържа сълнчеви системи и слънчева система да съдържа съседните си слънчеви системи. Виждаме, че ни е даден клас CommandManager, също и клас Engine. Отваряме Engine и виждаме, че в него са ни дадени още неща - фабрика за кораби и подобрения. Колекция от кораби и галактиката от която стартираме (тази направената в мейн метода). Както и метод, в който има while цикъл. Отваряме CommandManager. Виждаме, че в него има речник. Лявата част на речника е стринг, а дясната част инстанция на клас наследяващ Command. Обратно в Engine виждаме, че се извиква метод, който пълни този речник и после се извиква някакъв друг метод ProcessCommand. Отваряме този метод и виждаме, че той получава потребителския вход като цял стринг. Сплитва го по спейс (create Frigate Pesho Artemis-Tau) и проверява нулевия елемент (create) дали съществува като ключ в речника. Ако съществува му взима стойността, която е обект от тип Command и извиква метода му Execute().

До тук разбираме, че нулевия елемент "create" ще се вземе от речника (dictionary["create"]), което ще върне CreateCommand клас и ще му извика Execute. Навигираме с F12 до CreateCommand и виждаме, че там няма почти нищо. Навигираме до неговия базов клас и виждаме, че там има метод Execute().

И горе долу така завърши нашето пътешествие в кода. До момента имаме ясната представа нашият възложител какъв проект има и ясната представа каква до момента функционалност имаме. В условието беше написано, че има интерфейси, така че вече можем да навигираме по тях. Имаме интерфейс за корабче, който ни задължава да имаме пропъртита за полетата, които установихме, че ще имаме. Както и да имаме няколко метода.

След като направим хамалската част - boilerplate кодът, който се получава при създаването на класове, започваме вече да мислим малко по-абстрактно. Взаимовръзките между обектите, базови класове и т.н. и т.н.

Направили сме по условие трите вида кораби и един базов клас за тях. Оглеждаме на какъв принцип потребителя може да взаимодейства с нашите обекти. Излиза, че потребител може да направи корабче, но самото то според вида си има статсове. Така, че оставяме това което потребителят ще вкара като входни данни, а останалото го взимаме като константи и го предаваме на конструктора на базовия клас. Така излиза, че едно конкретно корабче има само Локация и Име, а предава освен локацията  името и останалите си статсове на базовия конструктор.

Оглеждаме дали потребител може да прави другия тип обекти - Снаряди. Излиза, че не - всъщност кораб произвежда снаряд и го произвежда с някакъв демидж. Тогава правим различните типове снаряди да приемат в конструктора си демидж.

Като сме направили тези два типа обекти, които имат някаква връзка между себе си е време да почнем да я градим. Казано ни е, че Един кораб произвежда Един снаряд с определен демидж, посредством ProduceAttack(); Започваме да обикаляме по типовете и да следваме условието. Минаваме през Фрегатата и виждаме, че тя произвежда ShieldRiever с демидж, колкото и демиджа на фрегатата. Така, че създаваме нов обект от тип ShieldRiever, подаваме му нашия демидж и го връщаме на останалия свят в ProduceAttack().

Отиваме в другия обект. Казано ни е, че всеки Снаряд когато стигне целта, се държи по определен начин посредством метода Hit(). Отиваме в ShieldReaver-а, който току-що произведохме с Фрегатата. Виждаме, че метода Hit приема като параметър кораба, който ще бием. Т.е. това което ще ни се подаде ще бъде нашата мишена. По условие от нашата мишена трябва ShieldReaver-а да свали толкова живот, колкото демидж има Снаряда, също така да свали и два пъти повече Щитове от мишената. Правим аритметиката и се връщаме обратно във Фрегатата.

Корабът освен, че произвежда определен снаряд, може и да реагира по някакъв начин на удар от снаряд. Виждаме, че Фрегата няма нищо специфично. Снарядът просто я удря и тя не реагира по никакъв допълнителен начин. Същото се отнася за крузера. Само Дредноута реагира по някакъв начин. До момента имаме метод "Реагира при атака", на който се подава съответната атака. И очевидно при два от три случая той прави едно и също. При третият прави същото + още нещо. Идеален пример да изнесем поведението на този метод в виртуален метод на базовия клас.

Отиваме в базовия клас и казваме, че реакцията при атака по подразбиране ще е - снарядът да ни удари. Т.е. параметърът, който получаваме (attack) да извика метода си Hit() и да му се подаде нашия кораб (мишената). Демек "attack.Hit(this)".

На подобна схема на изучаване на взаимовръзката между обектите се дописват и останалите неща. После се пренасяме и в командите. Там общо взето поведението на описаните ни до момента обекти и методи ще трябва да се навърже, за да работи приложението по условие.

Например Атакуващата команда приема име на атакуващия и име на защитника. Видяхме, че за всеки обект от тип команда се извиква Execute(), но този метод далеч не позволява да бъде използван в наследниците си. За щастие не ни е забранено да пипаме по класа Command и дописваме, че методът е виртуален, за да можем да го презаписваме в наследниците.

Виждаме, и че командата приема в конструктора си Engine-а. Engine-ът пък от своя страна имаше пропърти с колекцията от до момента създадените кораби в галактиката.

Въртим по тази колекция и намираме този кораб, който има името подадено на командата като атакуващ кораб. Това връща един обект от тип Космически кораб.

Въртим по същия начин през колекцията за да намерим и защитника по име.

Вече имаме двата обекта - атакуващ и защитник. Време е да кажем на атакуващия да произведе снаряд (ProduceAttack()). Произведенията снаряд да го пратим на защитника да реагира на него (RespondToAttack()) и според зависи от какво се е случи после да принтираме резултат. Например ако след атаката защитникът е унищожен, да напишем, че е унищожен.

На подобен принцип отиграваме и останалите подобни действия, в случая команди. Като гледаме да се придържаме до кодът, който ни е даден до момента и да не пренаписваме поведение, което вече е написано по някакъв начин. Например бяха ни даден две фабрики. Едната искаше да допишем код (ShipFactory). След като сме направили отделните типове кораби можем спокойно да допишем фабриката да връща обект от тип Фрегата при подаден тип Фрегата и т.н. за останалите кораби.

След като имаме тази фабрика, спокойно можем да я използваме да ни създаде кораб, когато се изпълни Create командата. И вместо да си пишем нова колекция с кораби, които сме създали, просто да добавим новосъздадения кораб в колекцията от кораби, която Engine-ът има.

Разбира се, задачата може да няма engine, или engine-ът да няма всичките нужни колекция написани от начало или персистването на данните да трябва да става по друг начин. Важно е да се направи оценката на проекта - какво трябва да направи човек, ако ще пише проекта от самото начало. След тази оценка на проекта да се погледне кода и да се види какво ни е дадено. Да се съобрази с даденото и задължителното (интерфейсите). И да допише кода спрямо изискванията плюс задълженията.

 

25
indieza avatar indieza 46 Точки

Благодаря за отделеното време а само да те попитам как мога да си тествам решението в Judge smiley

0
D.Kostadinov avatar D.Kostadinov 30 Точки

За да тестваш решението си, oтваряш на съответния изпит в Judge, който е OOP Retake Exam - 1 June 2015. Когато искаш да провериш решението си, отиваш в папката на solution-a си (т.е, тази която си свалил, а именно Skeleton) и zip-ваш всичко. Както при домашните е. За да ти се намали размера на файла можеш да изтриеш папките bin и obj, защото така или иначе системата ти ги генерира отново. Там където принципно избираме на какъв език искаме да качим кода си, от падащото поле ще видиш опцията C# project/solution. Избираш него и след това Select file, и избираш zip-a. 

2
11/06/2015 11:26:14
nikola.m.nikolov avatar nikola.m.nikolov 830 Точки

Това е задачата от поправката по ООП на 1 Юни. Може да се види в Judge системата, както и който иска да си тества решението. Понеже в лаб-а ви условието е по-описателно нямам представа дали са променили нещо в него спрямо задачата от поправката.

0
ivailo.pankow avatar ivailo.pankow 11 Точки

Условието на задачата от "OOP Retake Exam - 1 June 2015" в "Judge" е сбъркано. При корабите на Фрегата е посочено, че innitialDammage = 30, а по - късно при нулевите тестове си вижда, че е 80. Иначе няма как dreadnought да се унищожи от три атаки на фегатата.

0
aanguelov avatar aanguelov 219 Точки

Не е сбъркано, прочети си пак условието малко по-внимателно. 

Hint: Наблегни на енхансментите...

1
ivailo.pankow avatar ivailo.pankow 11 Точки

Ох..да много ти благодаря. Аз съм си включил ъпгрейдите, само че вместо dammageBonus да ми подобрява dammage  му бях дал health.. :)

0
i.yotov avatar i.yotov 0 Точки

Може ли да направите тестове №1-9 в judge публични?

0
Filkolev avatar Filkolev 4482 Точки

Може да ги изтеглиш от тук.

0
i.yotov avatar i.yotov 0 Точки

Authorization Required, може ли да направиш mirror в dox?

0
Filkolev avatar Filkolev 4482 Точки

student / student

1
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.