Професионална програма
Loading...
+ Нов въпрос
Elena123456 avatar Elena123456 200 Точки

03. MOBA Challenger (Associative Arrays - More Exercise) - with class

Здравейте, задачата е от Fundamental, но тъй като в Advanced-Set and Dictionaries exercise няма допълнителни задачи реших, че ще е добре да пререша задачите от Fundamental- More Exercise: Associative Arrays, но вече с използването на класове. Отварям темата, тъй като все още навлизам в класовете и имам неясноти.

Моето решение, което е 100/100 - https://pastebin.com/s7yWyxNJ

Условие- https://softuni.bg/trainings/resources/officedocument/52618/associative-arrays-more-exercise-csharp-fundamentals-september-2020/3135

Judge- https://judge.softuni.bg/Contests/Practice/Index/1302#2

 

Имам клас Player, който си има име и речник, който от своя страна държи всички позиции на играча със съотвения скил. Отделно имам и един речник, който държи името на играча и обекта Player. Използвам речник за да улесня търсенето, защото в речниците търсенето е по HashCode, доста по-бърз seаrch в сравнение с List. Въпросите са ми следните:

Между линии 21-27 създавам нов обект Player с име, позиция и скил, и го добавям в речника dictNamePlayer. Възможно ли е да има по-съкратен вариант при създаването на обекта? И ака има, дали е възможно някой да ми го обясни?

Между линия 56 и 77 използвам два вложени foreach за да сравня дали двата Player имат поне една обща позиция- възможно ли е чрез LINQ да използвам по-оптимален вариант? Все още като стане въпрос за класове и LINQ в комбинация, не се ориентирам интуитивно.

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

 

0
C# Fundamentals
MartinBG avatar MartinBG 3828 Точки
Best Answer

Oсвен за съхраняване на някакво състояние, класовете може да имат и методи. Например класа Player може да има метод, който да добавя или ъпдейтва position + skill, или друг метод, който да връща общия skill на играча. Това ще разтовари main метода от специфичната за Player логика. 

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

Ето примерен вариант на Player класа:

private class Player
{
    public string Name { get; }

    private readonly Dictionary<string, int> _dictPositionSkill;

    public Player(string name)
    {
        Name = name;
        _dictPositionSkill = new Dictionary<string, int>();
    }

    public void AddOrUpdatePosition(string position, int skill)
    {
        if (!_dictPositionSkill.ContainsKey(position))
        {
            _dictPositionSkill.Add(position, skill);
        }
        else if (_dictPositionSkill[position] < skill)
        {
            _dictPositionSkill[position] = skill;
        }
    }

    public IEnumerable<string> GetPositions()
    {
        return _dictPositionSkill.Keys;
    }

    public ImmutableDictionary<string, int> GetPositionsAndSkillsDictionary()
    {
        return _dictPositionSkill.ToImmutableDictionary();
    }

    public int GetTotalSkillPoints()
    {
        return _dictPositionSkill.Values.Sum();
    }
}

След горните промени по Player класа, редове #21 - #41 може да бъдат заменени с:

if (!dictNamePlayer.ContainsKey(playerName))
{
    var newPlayer = new Player(playerName);
    dictNamePlayer.Add(playerName, newPlayer);
}

dictNamePlayer[playerName].AddOrUpdatePosition(position, skill);

 

А това е логиката за дуелите:

if (!dictNamePlayer.ContainsKey(firstPlayer) || !dictNamePlayer.ContainsKey(secondPlayer))
{
    continue;
}

var playerOne = dictNamePlayer[firstPlayer];
var playerTwo = dictNamePlayer[secondPlayer];

if (playerOne.GetTotalSkillPoints() == playerTwo.GetTotalSkillPoints())
{
    continue;
}

var duelsCount = playerOne.GetPositions()
    .Intersect(playerTwo.GetPositions())
    .Count();

if (duelsCount <= 0)
{
    continue;
}

dictNamePlayer.Remove(playerOne.GetTotalSkillPoints() > playerTwo.GetTotalSkillPoints()
    ? playerTwo.Name
    : playerOne.Name);

 

Това е цялото решение.

 

Можем да разроварим main метода от логиката за ъпдейтване на играчите и за дуелите, ако я изнесем в отделен клас - например PlayersPool, с два метода - решение.

 

Разбира се, може да се стигне и още по-далеч с абстракцията и дори да се прекали с нея, поне за просто задание като това.  smiley

1
Elena123456 avatar Elena123456 200 Точки

Благодаря много! smiley

Официално още не съм стигнала до темата  "Обекти и класове", а все още съм на "Речници и сетове", като след "Стриймове, файлове, директорий" и "Функционално програмиране" идва вече техния ред. Но много интересно нещо ми се струват "Енкапсулацията" и "Абстракцията". Още днес ще прочета за тях.  Виждам, че чрез "Енкапсулацията" може цялата логика, която е свързана с класа да  се "скрие" в него за по-добра четивост на мейна. А пък "Абстракцията" при първа среща с нея ми изглежда, като нещо, което може да даде пълна свобода на програмиста да интерпретира представянето на решението по свой начин. Ще отделя необходимото време и ще ги усвоя добре.

И като видях Вашите решения осъзнавам колко малко знам за класовете и обектите, но това ме мотивира, защото има още толкова много интересни неща, които ще разширят свободата ми на изразяване.

Благодаря още веднъж!

Поздрави!

Ели

1