diff --git a/saga/Archer.cs b/saga/Archer.cs new file mode 100644 index 0000000..b771bbc --- /dev/null +++ b/saga/Archer.cs @@ -0,0 +1,17 @@ +namespace CourseApp +{ + using System; + + public class Archer : Player + { + public Archer(int health, int strength, string name) + : base(health, strength, name, "Огненная стрела", 1) + { + } + + public override string ToString() + { + return "(Лучник) " + Name; + } + } +} \ No newline at end of file diff --git a/saga/Game.cs b/saga/Game.cs new file mode 100644 index 0000000..4a59efb --- /dev/null +++ b/saga/Game.cs @@ -0,0 +1,186 @@ +namespace CourseApp +{ + using System; + using System.Collections.Generic; + + public class Game + { + public static void Start() + { + int count = CountOfPlayers(); // спрашиваем у пользователя число игроков + List participant = GetPlayersList(count); // генерируем лист игроков + Tourney(participant); // запускаем турнир + } + + private static void Tourney(List participant) + { + // играем до тех пор, пока не останется 1 игрок + for (int i = 1; participant.Count != 1; i++) + { + Logger.WriteRound(i); // передаем в логгер номер раунда + Randomize(participant); // в начале каждого раунда случайным образом перемешиваем игроков + Match(participant); // запускаем раунд + } + + Logger.WriteWinner(participant[0]); // передаем в логгер последнего оставщегося игрока + } + + private static void Match(List participant) + { + // так как сражения происходят в парах, то обрабатывать будем до половины листа + for (int i = 0; i < participant.Count / 2; i++) + { + Player[] opponents = { participant[i * 2], participant[(i * 2) + 1] }; // записываем в массив пару бойцов + Logger.WriteFight(opponents); // передаем в логгер созданный массив + participant[i * 2] = Duel(opponents); // записываем в первое место пары победителя + } + + // увеличиваем i на единицу, так как при удалении элемента массив сокращается и новый победитель оказывается на только что обработанном месте листа + for (int i = 1; i < participant.Count; i++) + { + participant.RemoveAt(i); // удаляем всех проигравших + } + } + + private static Player Duel(Player[] opponents) + { + // используем for а не while из-за удобства наличия счетчика + for (int i = 0; true; i++) + { + string dbf_status = opponents[i % 2].DebaffStatus(); // проверяем какой дебаф действует на игрока + Logger.WriteAction(opponents[i % 2], dbf_status); // передаем этот дебаф и игрока в логгер + + // если дебаф был с периодическим уроном, то передаем его + if (dbf_status == "Огненная стрела") + { + opponents[i % 2].GetDamage(2); + } + + bool checkDeath = opponents[i % 2].CheckDeath(); // проверяем не умер ли первый игрок от периодического урона + if (checkDeath) + { + Logger.WriteDeath(opponents[i % 2]); // передаем в логер умершего игрока + opponents[(i + 1) % 2].Refresh(); // восстанавливаем второго игрока + return opponents[(i + 1) % 2]; // передаем его как победителя + } + + // если дебаф на пропуск хода, соответсвенно пропускаем его + if (dbf_status == "Заворожение") + { + continue; + } + + string playerAction = GetAction(opponents[i % 2]); // выбираем действие игрока + + // если действие не атакующие, передаем в логер игрока, совершившего действие, игрока, над которым соверешенно действие, и название действия + if ((playerAction != "Атака") && (playerAction != "Удар возмездия")) + { + Logger.WriteAction(opponents[i % 2], opponents[(i + 1) % 2], playerAction); + opponents[(i + 1) % 2].SetDebaff(playerAction); // записываем его в дебаф + } + + // если действие атакующие, получаем значение урона и передаем в логер игрока, совершившего действие, игрока, над которым соверешенно действие, и урон + else + { + float damage = opponents[i % 2].Attack(); + Logger.WriteAction(opponents[i % 2], opponents[(i + 1) % 2], playerAction, damage); + opponents[(i + 1) % 2].GetDamage(damage); // наносим урон + } + + bool death = opponents[(i + 1) % 2].CheckDeath(); // проверяем не умер ли игрок после получения урона + if (checkDeath) + { + Logger.WriteDeath(opponents[(i + 1) % 2]); // передаем умершего игрока + opponents[i % 2].Refresh(); // восстанавливаем победителя и возвращаем его + return opponents[i % 2]; + } + } + } + + private static string GetAction(Player inputP) + { + Random rnd = new Random(); + int chosen = rnd.Next(0, 4); // случайным образом генерируем дейтсвие игрока + switch (chosen) + { + case 0: + // если игрок может совершить специальное действие возвращаем его название, иначе передаем команду об обычной атаке + if (inputP.CheckAbility()) + { + return inputP.Ability(); + } + + return "Атака"; + default: + return "Атака"; + } + } + + private static int CountOfPlayers() + { + // до тех пор, пока не введется корректное число, не возвращаем значение + while (true) + { + Console.WriteLine("Введите число игроков:"); + int count = Convert.ToInt32(Console.ReadLine()); + if (count <= 0) + { + Console.WriteLine("Введите число больше 0"); + } + else if (count % 2 != 0) + { + Console.WriteLine("Введите четное число"); + } + else + { + return count; + } + } + } + + private static void Randomize(List input) + { + // переставляем элементы листа начиная с 0-го + Random rnd = new Random(); + for (int i = 0; i < input.Count; i++) + { + int chosen = rnd.Next(i, input.Count); + (input[i], input[chosen]) = (input[chosen], input[i]); // перестановка элементов местами + } + } + + private static List GetPlayersList(int count) + { + // создаем лист и возрващаем его заполненный вариант + List playerList = new List(); + for (int i = 0; i < count; i++) + { + playerList.Add(GenPlayer()); // добавляем игрока в лист + } + + return playerList; + } + + private static Player GenPlayer() + { + string[] names = { "Рюрик", "Вещий Олег", "Игорь Старый", "Ольга", "Святослав", "Владимир I", "Ярослав Мудрый", "Всеволод Переяславский", "Владимир Мономах", "Юрий Долгорукий", "Андрей Боголюбский", "Всеволод Большое Гнездо", "Ярослав Всеволодович", "Александр Невский", "Даниил Московский", "Иван Калита" }; + Random random = new Random(); + + // рандомно выбираем здоровье, силу, класс и имя, затем возрващаем полученного игрока + int hlth = (int)random.NextInt64(20, 101); + int str = (int)random.NextInt64(5, 21); + int player_class = (int)random.NextInt64(0, 3); + switch (player_class) + { + case 0: + return new Knight(hlth, str, names[random.Next(names.Length)]); // передаем в конструктор класса здоровье, силу и элемент массива имен со случайного места + case 1: + return new Mage(hlth, str, names[random.Next(names.Length)]); + case 2: + return new Archer(hlth, str, names[random.Next(names.Length)]); + default: + return new Knight(hlth, str, names[random.Next(names.Length)]); + } + } + } +} \ No newline at end of file diff --git a/saga/Knight.cs b/saga/Knight.cs new file mode 100644 index 0000000..f3c4e73 --- /dev/null +++ b/saga/Knight.cs @@ -0,0 +1,40 @@ +namespace CourseApp +{ + using System; + + public class Knight : Player + { + private bool powerup; + + public Knight(int health, int strength, string name) + : base(health, strength, name, "Удар возмездия", 1) + { + powerup = false; + } + + public override string ToString() + { + return "(Рыцарь) " + Name; + } + + public override float Attack() // если была применена способность сильного удара, то возвращаем усиленный урон + { + if (powerup) + { + powerup = false; + return (float)Math.Round(Strength * 1.3); + } + else + { + return Strength; + } + } + + public override string Ability() // если была применена способность возвращаем название способности и устанавливаем флаг в "истина" + { + AbilityLeft--; + powerup = true; + return AbilityName; + } + } +} \ No newline at end of file diff --git a/saga/Logger.cs b/saga/Logger.cs new file mode 100644 index 0000000..35c492d --- /dev/null +++ b/saga/Logger.cs @@ -0,0 +1,60 @@ +namespace CourseApp +{ + using System; + + public static class Logger + { + public static void WriteWinner(Player winner) + { + Console.WriteLine($"{winner.ToString()} ПОБЕДИЛ!"); + } + + public static void WriteRound(int round) + { + Console.WriteLine($"Раунд {round}."); + } + + public static void WriteFight(Player[] opponents) + { + Console.WriteLine($"{opponents[0].ToString()} VS {opponents[1].ToString()}"); + } + + // у метода следующие перегрузки: применение способности по противнику, применение атакующей способности, действующие на игрока дебафы + public static void WriteAction(Player firstP, Player secondP, string action) + { + Console.WriteLine($"{firstP.ToString()} применяет ({action}) по противнику {secondP.ToString()}"); + } + + public static void WriteAction(Player firstP, Player secondP, string action, float damage) + { + switch (action) + { + case "Атака": + Console.WriteLine($"{firstP.ToString()} наносит урон {damage} противнику {secondP.ToString()}"); + break; + case "Удар возмездия": + Console.WriteLine($"{firstP.ToString()} применяет ({action}) и наносит урон {damage} противнику {secondP.ToString()}"); + break; + } + } + + public static void WriteAction(Player inputP, string action) + { + switch (action) + { + case "Огненная стрела": + Console.WriteLine($"{inputP.ToString()} получает периодический урон {2} от ({action})"); + break; + case "Заворожение": + Console.WriteLine($"{inputP.ToString()} пропускает ход из-за ({action})"); + break; + } + } + + public static void WriteDeath(Player inputP) + { + Console.WriteLine($"{inputP.ToString()} погибает"); + Console.WriteLine(); + } + } +} \ No newline at end of file diff --git a/saga/Mage.cs b/saga/Mage.cs new file mode 100644 index 0000000..7efc8e3 --- /dev/null +++ b/saga/Mage.cs @@ -0,0 +1,17 @@ +namespace CourseApp +{ + using System; + + public class Mage : Player + { + public Mage(int health, int strength, string name) + : base(health, strength, name, "Заворожение", 1) + { + } + + public override string ToString() + { + return "(Маг) " + Name; + } + } +} \ No newline at end of file diff --git a/saga/Player.cs b/saga/Player.cs new file mode 100644 index 0000000..05efdfd --- /dev/null +++ b/saga/Player.cs @@ -0,0 +1,100 @@ +namespace CourseApp +{ + using System; + using System.Collections.Generic; + + public abstract class Player + { + private string debaff; + + public Player(int maxHealth, int strength, string name, string abilityName, int maxAbilityUsages) + { + this.MaxHealth = maxHealth; + this.CurrentHealth = maxHealth; + this.Strength = strength; + this.Name = name; + this.AbilityName = abilityName; + this.MaxAbilityUsages = maxAbilityUsages; + this.AbilityLeft = maxAbilityUsages; + } + + public float MaxHealth { get; protected set; } + + public float CurrentHealth { get; protected set; } + + public float Strength { get; protected set; } + + public string Name { get; protected set; } + + public int MaxAbilityUsages { get; protected set; } + + public int AbilityLeft { get; protected set; } + + public string AbilityName { get; protected set; } + + public bool CheckAbility() // проверка на возможность применения способности + { + if (AbilityLeft > 0) + { + return true; + } + else + { + return false; + } + } + + public virtual string Ability() // применение способности + { + AbilityLeft--; + return AbilityName; + } + + public virtual float Attack() // атака + { + return Strength; + } + + public void GetDamage(float damage) // получение урона + { + CurrentHealth -= damage; + } + + public void SetDebaff(string dName) // установка дебаффов + { + debaff = dName; + } + + public string DebaffStatus() // проверка действующих дебаффов + { + string buffer = debaff; + switch (debaff) + { + case "Огненная стрела": + break; + case "Заворожение": + debaff = string.Empty; + break; + } + + return buffer; + } + + public bool CheckDeath() // проверка на смерть + { + if (CurrentHealth <= 0) + { + return true; + } + + return false; + } + + public void Refresh() // востановление показателей + { + AbilityLeft = MaxAbilityUsages; + CurrentHealth = MaxHealth; + debaff = string.Empty; + } + } +} \ No newline at end of file diff --git a/saga/Program.cs b/saga/Program.cs new file mode 100644 index 0000000..9cc1070 --- /dev/null +++ b/saga/Program.cs @@ -0,0 +1,10 @@ +namespace CourseApp +{ + public class Program + { + public static void Main(string[] args) + { + Game.Start(); + } + } +} diff --git a/saga/gitkeep b/saga/gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/saga/gitkeep @@ -0,0 +1 @@ +