ООП вариант “Меню прокачки персонажа”

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

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

Решение:

using System;
using System.Collections.Generic;
using System.Linq;

namespace IMJunior
{
    class Program
    {
        static void Main(string[] args)
        {
            Player player = new Player(new Skill("Сила"), new Skill("Ловкость"), new Skill("Ум"));

            Console.WriteLine("Добро пожаловать в меню выбора создания персонажа!");
            Console.WriteLine("У вас есть 25 очков, которые вы можете распределить по умениям");
            Console.WriteLine("Нажмите любую клавишу чтобы продолжить...");
            Console.ReadKey();

            while (player.SkillPoints > 0)
            {
                Console.Clear();
                Console.WriteLine("Поинтов - {0}", player.SkillPoints);
                DrawCharacterData(player);

                Console.WriteLine("Какую характеристику вы хотите изменить?");
                string subject = Console.ReadLine();

                Console.WriteLine(@"Что вы хотите сделать? +\-");
                string operation = Console.ReadLine();

                Console.WriteLine(@"Колличество поинтов которые следует {0}", operation == "+" ? "прибавить" : "отнять");
                int operandPoints = ReadInt();


                foreach (var skill in player.Skills)
                    if (skill.Name.ToLower() == subject.ToLower())
                        player.DistributePoints(skill, operandPoints * (operation == "+" ? 1 : -1));
            }

            Console.WriteLine("Вы распределили все очки. Введите возраст персонажа:");

            player.Age = ReadInt();

            Console.Clear();
            DrawCharacterData(player);
        }

        private static void DrawCharacterData(Player player)
        {
            Console.WriteLine($"Возраст - {player.Age}");

            foreach (var skill in player.Skills)
                Console.WriteLine($"{skill.Name} - {skill.Value}");
        }

        private static string GetProgressLine(Skill skill)
        {
            return "".PadLeft(skill.Value, '#').PadRight(10, '_');
        }

        private static int ReadInt()
        {
            int result = 0;
            string raw = string.Empty;
            do
            {
                raw = Console.ReadLine();
            } while (int.TryParse(raw, out result) == false);

            return result;
        }
    }

    class Player
    {
        public IReadOnlyCollection<Skill> Skills { get; private set; }
        public int SkillPoints { get; private set; } = 25;
        public int Age { get; set; }

        public Player(params Skill[] skills)
        {
            Skills = skills.ToList().AsReadOnly();
        }

        public void DistributePoints(Skill skill, int points)
        {
            if (Skills.Contains(skill) == false)
                throw new InvalidOperationException();

            SkillPoints += skill.ApplyDelta(points);
        }
    }

    class Skill
    {
        public string Name { get; }
        public int Value { get; private set; }

        public Skill(string name)
        {
            Name = name;
        }

        public int ApplyDelta(int delta)
        {
            var oldValue = Value;
            Value = Mathi.Clamp(Value + delta, 0, 10);

            return oldValue - Value;
        }
    }

    static class Mathi
    {
        public static int Clamp(int value, int min, int max)
        {
            if (value < min)
                return min;
            else if (value > max)
                return max;

            return value;
        }
    }
}

Если вы нашли ошибку, пожалуйста выделите её и нажмите Ctrl+Enter.


Leave a Reply

Your email address will not be published. Required fields are marked *