From 2f7e74979453354878a2329d8617b02d15195e48 Mon Sep 17 00:00:00 2001 From: Kirill Karamysh Date: Sun, 15 Jan 2023 14:23:24 +0300 Subject: [PATCH] Make RPG-Saga --- CourseApp.Tests/DemoTest.cs | 39 ++++++++++++++- CourseApp/Ability.cs | 36 ++++++++++++++ CourseApp/Archer.cs | 12 +++++ CourseApp/Attack.cs | 10 ++++ CourseApp/BattleManager.cs | 80 ++++++++++++++++++++++++++++++ CourseApp/Blind.cs | 10 ++++ CourseApp/EntitiesFactory.cs | 41 ++++++++++++++++ CourseApp/Entity.cs | 90 ++++++++++++++++++++++++++++++++++ CourseApp/FireArrows.cs | 16 ++++++ CourseApp/ILogger.cs | 7 +++ CourseApp/Knight.cs | 12 +++++ CourseApp/Logger.cs | 10 ++++ CourseApp/Program.cs | 15 +++++- CourseApp/RetaliationStrike.cs | 10 ++++ CourseApp/StepSkip.cs | 10 ++++ CourseApp/Wizard.cs | 12 +++++ 16 files changed, 408 insertions(+), 2 deletions(-) create mode 100644 CourseApp/Ability.cs create mode 100644 CourseApp/Archer.cs create mode 100644 CourseApp/Attack.cs create mode 100644 CourseApp/BattleManager.cs create mode 100644 CourseApp/Blind.cs create mode 100644 CourseApp/EntitiesFactory.cs create mode 100644 CourseApp/Entity.cs create mode 100644 CourseApp/FireArrows.cs create mode 100644 CourseApp/ILogger.cs create mode 100644 CourseApp/Knight.cs create mode 100644 CourseApp/Logger.cs create mode 100644 CourseApp/RetaliationStrike.cs create mode 100644 CourseApp/StepSkip.cs create mode 100644 CourseApp/Wizard.cs diff --git a/CourseApp.Tests/DemoTest.cs b/CourseApp.Tests/DemoTest.cs index cf7cbb1..d8750eb 100644 --- a/CourseApp.Tests/DemoTest.cs +++ b/CourseApp.Tests/DemoTest.cs @@ -1,13 +1,50 @@ namespace CourseApp.Tests { + using CourseApp; using Xunit; public class DemoTest { + private Knight k; + private Blind b; + private Attack a; + + public DemoTest() + { + k = new Knight(20, 20, "knight"); + b = new Blind(); + a = new Attack(5); + } + [Fact] public void Test1() { - Assert.True(true); + Assert.Equal(20, k.Health); + Assert.Equal(20, k.Damage); + Assert.Equal("knight", k.Name); + Assert.Equal(new Attack(20).Damage, k.ActiveAbility.Damage); + } + + [Fact] + public void Test2() + { + k.AddEffect(b); + Assert.Equal(0, k.CheckState()); + Assert.Equal(new StepSkip().Damage, k.MakeStep().Damage); + } + + [Fact] + public void Test3() + { + k.AddEffect(a); + Assert.Equal(5, k.CheckState()); + } + + [Fact] + public void Test3() + { + k.Refresh(); + Assert.Equal(0, k.CheckState()); } } } diff --git a/CourseApp/Ability.cs b/CourseApp/Ability.cs new file mode 100644 index 0000000..7854d50 --- /dev/null +++ b/CourseApp/Ability.cs @@ -0,0 +1,36 @@ +namespace CourseApp +{ + public enum AbilityTypes + { + Skip, + Attack, + Blind, + } + + public abstract class Ability + { + public Ability(string abilityName, int damage, int steps, AbilityTypes type) + { + AbilityName = abilityName; + Damage = damage; + StepsDuration = steps; + CanUse = true; + Type = type; + } + + public AbilityTypes Type { get; } + + public string AbilityName { get; } + + public int Damage { get; } + + public int StepsDuration { get; set; } + + public bool CanUse { get; set; } + + public virtual Ability UseAbility() + { + return this; + } + } +} \ No newline at end of file diff --git a/CourseApp/Archer.cs b/CourseApp/Archer.cs new file mode 100644 index 0000000..b4256b1 --- /dev/null +++ b/CourseApp/Archer.cs @@ -0,0 +1,12 @@ +namespace CourseApp +{ + using System.Collections.Generic; + + public class Archer : Entity + { + public Archer(int health, int damage, string name) + : base(health, damage, name, new FireArrows()) + { + } + } +} \ No newline at end of file diff --git a/CourseApp/Attack.cs b/CourseApp/Attack.cs new file mode 100644 index 0000000..0ae51bc --- /dev/null +++ b/CourseApp/Attack.cs @@ -0,0 +1,10 @@ +namespace CourseApp +{ + public class Attack : Ability + { + public Attack(int damage) + : base("Атака", damage, 1, AbilityTypes.Attack) + { + } + } +} \ No newline at end of file diff --git a/CourseApp/BattleManager.cs b/CourseApp/BattleManager.cs new file mode 100644 index 0000000..65ec9bc --- /dev/null +++ b/CourseApp/BattleManager.cs @@ -0,0 +1,80 @@ +namespace CourseApp +{ + using System.Collections.Generic; + + public class BattleManager + { + private List players; + + private EntitiesFactory entitiesFactory; + + private ILogger logger; + + public BattleManager(int playerCount, ILogger logger) + { + players = new List(); + entitiesFactory = new EntitiesFactory(); + this.logger = logger; + InitPlayers(playerCount); + } + + public void Battle() + { + for (int round = 1; players.Count > 1; round++) + { + logger.Log($"Round {round}"); + for (int i = 1; i < players.Count; i++) + { + Duel(players[i - 1], players[i]); + logger.Log($"---------"); + } + + RefreshPlayers(); + } + } + + public void Duel(Entity e1, Entity e2) + { + while (e1.Health > 0 && e2.Health > 0) + { + DoEntityAction(e1, e2); + DoEntityAction(e2, e1); + } + } + + public void DoEntityAction(Entity src, Entity dest) + { + if (src.Health <= 0) + { + return; + } + + dest.AddEffect(src.MakeStep()); + int damage = dest.CheckState(); + logger.Log($"{src.Name} использует {src.ActiveAbility.AbilityName} и наносит {damage} ед. урона"); + if (dest.Health <= 0) + { + logger.Log($"{dest.Name} погибает"); + players.Remove(dest); + } + } + + public void InitPlayers(int count) + { + while (count > 0) + { + Entity e = entitiesFactory.CreateEntity(); + players.Add(e); + count--; + } + } + + public void RefreshPlayers() + { + foreach (var p in players) + { + p.Refresh(); + } + } + } +} \ No newline at end of file diff --git a/CourseApp/Blind.cs b/CourseApp/Blind.cs new file mode 100644 index 0000000..937fb72 --- /dev/null +++ b/CourseApp/Blind.cs @@ -0,0 +1,10 @@ +namespace CourseApp +{ + public class Blind : Ability + { + public Blind() + : base("Ослепление", 0, 1, AbilityTypes.Blind) + { + } + } +} \ No newline at end of file diff --git a/CourseApp/EntitiesFactory.cs b/CourseApp/EntitiesFactory.cs new file mode 100644 index 0000000..101c003 --- /dev/null +++ b/CourseApp/EntitiesFactory.cs @@ -0,0 +1,41 @@ +namespace CourseApp +{ + public class EntitiesFactory + { + private string[] names = + { + "Олег", + "Владилен", + "Борислав", + "Всеволод", + "Гаврила", + "Казимир", + }; + + public enum Classes + { + Archer = 0, + Knight, + Wizard, + ClassesLength, + } + + public Entity CreateEntity() + { + System.Random random = new System.Random(); + int classIndex = random.Next((int)Classes.ClassesLength); + int nameIndex = random.Next(names.Length); + switch (classIndex) + { + case (int)Classes.Archer: + return new Archer(random.Next(1, 50), random.Next(1, 20), names[nameIndex]); + case (int)Classes.Knight: + return new Knight(random.Next(1, 50), random.Next(1, 20), names[nameIndex]); + case (int)Classes.Wizard: + return new Wizard(random.Next(1, 50), random.Next(1, 20), names[nameIndex]); + default: + return new Knight(random.Next(1, 50), random.Next(1, 20), names[nameIndex]); + } + } + } +} \ No newline at end of file diff --git a/CourseApp/Entity.cs b/CourseApp/Entity.cs new file mode 100644 index 0000000..0c15d2d --- /dev/null +++ b/CourseApp/Entity.cs @@ -0,0 +1,90 @@ +namespace CourseApp +{ + using System.Collections.Generic; + + public class Entity + { + private List abilities; + private List effects; + + public Entity(int health, int damage, string name, Ability ability) + { + abilities = new List + { + new Attack(damage), + ability, + }; + effects = new List(); + ActiveAbility = abilities[0]; + Health = health; + Damage = damage; + Name = name; + CanAttack = true; + } + + public int Health { get; private set; } + + public int Damage { get; private set; } + + public string Name { get; } + + public bool CanAttack { get; protected set; } + + public Ability ActiveAbility { get; private set; } + + public Ability MakeStep() + { + if (Health <= 0 || !CanAttack) + { + CanAttack = true; + ActiveAbility = new StepSkip(); + return ActiveAbility.UseAbility(); + } + + System.Random random = new System.Random(); + int abilityIndex = random.Next(abilities.Count); + ActiveAbility = abilities[abilityIndex]; + if (!ActiveAbility.CanUse) + { + ActiveAbility = abilities[0]; + } + + return ActiveAbility.UseAbility(); + } + + public int CheckState() + { + int totalDamage = 0; + foreach (var e in effects) + { + totalDamage += e.Damage; + if (e.Type == AbilityTypes.Blind) + { + CanAttack = false; + } + + e.StepsDuration--; + } + + Health -= totalDamage; + effects.RemoveAll(e => e.StepsDuration <= 0); + return totalDamage; + } + + public void Refresh() + { + foreach (var a in abilities) + { + a.CanUse = true; + } + + CanAttack = true; + effects = new List(); + } + + public void AddEffect(Ability ability) + { + effects.Add(ability); + } + } +} \ No newline at end of file diff --git a/CourseApp/FireArrows.cs b/CourseApp/FireArrows.cs new file mode 100644 index 0000000..0dc02da --- /dev/null +++ b/CourseApp/FireArrows.cs @@ -0,0 +1,16 @@ +namespace CourseApp +{ + public class FireArrows : Ability + { + public FireArrows() + : base("Огненные стрелы", 2, 9999, AbilityTypes.Attack) + { + } + + public override Ability UseAbility() + { + CanUse = false; + return this; + } + } +} \ No newline at end of file diff --git a/CourseApp/ILogger.cs b/CourseApp/ILogger.cs new file mode 100644 index 0000000..5da3ca8 --- /dev/null +++ b/CourseApp/ILogger.cs @@ -0,0 +1,7 @@ +namespace CourseApp +{ + public interface ILogger + { + void Log(string str); + } +} \ No newline at end of file diff --git a/CourseApp/Knight.cs b/CourseApp/Knight.cs new file mode 100644 index 0000000..63ac141 --- /dev/null +++ b/CourseApp/Knight.cs @@ -0,0 +1,12 @@ +namespace CourseApp +{ + using System.Collections.Generic; + + public class Knight : Entity + { + public Knight(int health, int damage, string name) + : base(health, damage, name, new RetaliationStrike((int)(damage + ((damage / 10) * 3)))) + { + } + } +} \ No newline at end of file diff --git a/CourseApp/Logger.cs b/CourseApp/Logger.cs new file mode 100644 index 0000000..e54699c --- /dev/null +++ b/CourseApp/Logger.cs @@ -0,0 +1,10 @@ +namespace CourseApp +{ + public class Logger : ILogger + { + public void Log(string str) + { + System.Console.WriteLine(str); + } + } +} \ No newline at end of file diff --git a/CourseApp/Program.cs b/CourseApp/Program.cs index d6d2c87..005adfd 100644 --- a/CourseApp/Program.cs +++ b/CourseApp/Program.cs @@ -4,9 +4,22 @@ public class Program { + private static ILogger logger; + public static void Main(string[] args) { - Console.WriteLine("Hello World"); + logger = new Logger(); + int playersCount; + logger.Log("Введите число игроков:"); + int.TryParse(Console.ReadLine(), out playersCount); + if (playersCount % 2 != 0) + { + logger.Log("Число игроков должно быть четным"); + return; + } + + BattleManager bm = new BattleManager(playersCount, logger); + bm.Battle(); } } } diff --git a/CourseApp/RetaliationStrike.cs b/CourseApp/RetaliationStrike.cs new file mode 100644 index 0000000..a09832b --- /dev/null +++ b/CourseApp/RetaliationStrike.cs @@ -0,0 +1,10 @@ +namespace CourseApp +{ + public class RetaliationStrike : Ability + { + public RetaliationStrike(int damage) + : base("Удар возмездия", damage, 1, AbilityTypes.Attack) + { + } + } +} \ No newline at end of file diff --git a/CourseApp/StepSkip.cs b/CourseApp/StepSkip.cs new file mode 100644 index 0000000..7dfd39b --- /dev/null +++ b/CourseApp/StepSkip.cs @@ -0,0 +1,10 @@ +namespace CourseApp +{ + public class StepSkip : Ability + { + public StepSkip() + : base("Пропуск хода", 0, 1, AbilityTypes.Skip) + { + } + } +} \ No newline at end of file diff --git a/CourseApp/Wizard.cs b/CourseApp/Wizard.cs new file mode 100644 index 0000000..3538edd --- /dev/null +++ b/CourseApp/Wizard.cs @@ -0,0 +1,12 @@ +namespace CourseApp +{ + using System.Collections.Generic; + + public class Wizard : Entity + { + public Wizard(int health, int damage, string name) + : base(health, damage, name, new Blind()) + { + } + } +} \ No newline at end of file