Skip to content

Instantly share code, notes, and snippets.

@Natetnosova
Last active February 7, 2025 04:50
Show Gist options
  • Save Natetnosova/621674b06ba9a02a4ec57c4c532ab837 to your computer and use it in GitHub Desktop.
Save Natetnosova/621674b06ba9a02a4ec57c4c532ab837 to your computer and use it in GitHub Desktop.
ДЗ: Гладиаторские бои
using System;
using System.Collections.Generic;
namespace Colosseum
{
class Program
{
static void Main(string[] args)
{
ColosseumGame game = new ColosseumGame();
game.Run();
}
}
public interface IDamageable
{
void TakeDamage(int damage);
bool IsAlive { get; }
}
public abstract class Fighter : IDamageable
{
public const int MinDamage = 0;
public const int MinHealth = 0;
private readonly string _name;
protected int _health;
private readonly int _damage;
private readonly int _defense;
protected Fighter(string name, int health, int damage, int defense)
{
_name = name;
_health = health;
_damage = damage;
_defense = defense;
}
public string Name => _name;
public int Health => _health;
public int Damage => _damage;
public int Defense => _defense;
public bool IsAlive => _health > MinHealth;
public virtual void Attack(IDamageable opponent)
{
Console.WriteLine($"{Name} атакует {opponent}.");
opponent.TakeDamage(Damage);
}
public virtual void TakeDamage(int damage)
{
int actualDamage = Math.Max(damage - Defense, MinDamage);
_health = Math.Max(_health - actualDamage, MinHealth);
Console.WriteLine($"{Name} получил {actualDamage} урона, здоровье: {Health}");
}
public abstract Fighter Clone();
public override string ToString()
{
return $"{Name} (Здоровье: {Health}, Урон: {Damage}, Защита: {Defense})";
}
}
public class Berserker : Fighter
{
private const int DamageMultiplier = 2;
private const int DoubleDamageChance = 20;
public Berserker(string name, int health, int damage, int defense)
: base(name, health, damage, defense) { }
public override void Attack(IDamageable opponent)
{
const int ChanceMin = 0;
const int ChanceMax = 100;
bool doubleDamage = RandomProvider.Next(ChanceMin, ChanceMax) < DoubleDamageChance;
int attackDamage = doubleDamage ? Damage * DamageMultiplier : Damage;
string attackMessage = doubleDamage
? $"{Name} наносит удвоенный урон!"
: $"{Name} атакует {opponent} и наносит {attackDamage} урона.";
Console.WriteLine(attackMessage);
opponent.TakeDamage(attackDamage);
}
public override Fighter Clone()
{
return new Berserker(Name, Health, Damage, Defense);
}
}
public class DualAttacker : Fighter
{
private const int AttackInterval = 3;
private const int DoubleAttackMultiplier = 2;
private int _attackCount = 0;
public DualAttacker(string name, int health, int damage, int defense)
: base(name, health, damage, defense) { }
public override void Attack(IDamageable opponent)
{
_attackCount++;
int attackDamage = Damage;
if (_attackCount % AttackInterval == 0)
{
attackDamage *= DoubleAttackMultiplier;
Console.WriteLine($"{Name} наносит двойную атаку!");
}
else
{
Console.WriteLine($"{Name} атакует {opponent} и наносит {attackDamage} урона.");
}
opponent.TakeDamage(attackDamage);
}
public override Fighter Clone()
{
return new DualAttacker(Name, Health, Damage, Defense);
}
}
public class RageFighter : Fighter
{
private const int MaxRage = 100;
private const int RageGain = 25;
private const int HealAmount = 20;
private int _rage = 0;
public RageFighter(string name, int health, int damage, int defense)
: base(name, health, damage, defense) { }
public override void TakeDamage(int damage)
{
base.TakeDamage(damage);
_rage += RageGain;
if (_rage >= MaxRage)
{
Heal(HealAmount);
_rage = 0;
}
}
private void Heal(int amount)
{
_health += amount;
Console.WriteLine($"{Name} исцеляется на {amount} здоровья, текущее здоровье: {Health}");
}
public override Fighter Clone()
{
return new RageFighter(Name, Health, Damage, Defense);
}
}
public class Mage : Fighter
{
private const int ManaCost = 30;
private const int SpellDamage = 40;
private int _mana = 100;
public Mage(string name, int health, int damage, int defense)
: base(name, health, damage, defense) { }
public override void Attack(IDamageable opponent)
{
if (_mana >= ManaCost)
{
_mana -= ManaCost;
Console.WriteLine($"{Name} применяет заклинание 'Огненный шар' и наносит {SpellDamage} урона.");
opponent.TakeDamage(SpellDamage);
}
else
{
Console.WriteLine($"{Name} не хватает маны для заклинания. Выполняется обычная атака.");
base.Attack(opponent);
}
}
public override Fighter Clone()
{
return new Mage(Name, Health, Damage, Defense);
}
}
public class Dodger : Fighter
{
private const int DodgeChance = 30;
private const int ChanceMin = 0;
private const int ChanceMax = 100;
public Dodger(string name, int health, int damage, int defense)
: base(name, health, damage, defense) { }
public override void TakeDamage(int damage)
{
if (RandomProvider.Next(ChanceMin, ChanceMax) < DodgeChance)
{
Console.WriteLine($"{Name} уклоняется от атаки!");
}
else
{
base.TakeDamage(damage);
}
}
public override Fighter Clone()
{
return new Dodger(Name, Health, Damage, Defense);
}
}
public static class RandomProvider
{
private static readonly Random _random = new Random();
public static int Next(int minValue, int maxValue) => _random.Next(minValue, maxValue);
}
public class ColosseumGame
{
private const string MenuOptionFight = "1";
private const string MenuOptionExit = "2";
private readonly List<Fighter> _fighters = new List<Fighter>();
public void Run()
{
Console.WriteLine("Добро пожаловать на арену Колизея!");
InitializeFighters();
ShowMainMenu();
}
private void InitializeFighters()
{
_fighters.Add(new Berserker("Берсерк", 100, 20, 5));
_fighters.Add(new DualAttacker("Двойной атакующий", 120, 15, 7));
_fighters.Add(new RageFighter("Разъярённый", 110, 18, 6));
_fighters.Add(new Mage("Маг", 90, 10, 3));
_fighters.Add(new Dodger("Уворотчик", 80, 12, 5));
}
private void ShowMainMenu()
{
bool isRunning = true;
while (isRunning)
{
Console.WriteLine("\nГлавное меню:");
Console.WriteLine($"{MenuOptionFight}. Посмотреть бой");
Console.WriteLine($"{MenuOptionExit}. Выйти из программы");
string choice = Console.ReadLine();
switch (choice)
{
case MenuOptionFight:
RunFight();
break;
case MenuOptionExit:
Console.WriteLine("Выход из программы...");
isRunning = false;
break;
default:
Console.WriteLine("Неверный ввод. Попробуйте снова.");
break;
}
}
}
private void RunFight()
{
Fighter fighter1 = ChooseFighter("Выберите первого бойца:", null)?.Clone();
Fighter fighter2 = ChooseFighter("Выберите второго бойца:", fighter1)?.Clone();
if (fighter1 == null || fighter2 == null)
{
Console.WriteLine("Бой не может начаться, один из бойцов не выбран.");
return;
}
Console.WriteLine($"\nБой начинается между {fighter1.Name} и {fighter2.Name}!");
while (fighter1.IsAlive && fighter2.IsAlive)
{
fighter1.Attack(fighter2);
if (fighter2.IsAlive)
{
fighter2.Attack(fighter1);
}
}
Console.WriteLine(fighter1.IsAlive ? $"{fighter1.Name} одержал победу!" : $"{fighter2.Name} одержал победу!");
}
private Fighter ChooseFighter(string message, Fighter excludeFighter)
{
Console.WriteLine(message);
for (int i = 0; i < _fighters.Count; i++)
{
Console.WriteLine($"{i + 1}. {_fighters[i]}");
}
int selectedIndex;
if (!int.TryParse(Console.ReadLine(), out selectedIndex) || selectedIndex < 1 || selectedIndex > _fighters.Count)
{
Console.WriteLine("Неверный выбор. Попробуйте снова.");
return ChooseFighter(message, excludeFighter);
}
Fighter chosenFighter = _fighters[selectedIndex - 1];
return chosenFighter == excludeFighter ? null : chosenFighter.Clone();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment