Ми створюємо консольну гру, де герої можуть атакувати по-різному. Щоб не дублювати код та легко змінювати поведінку персонажів, застосовуємо патерн «Стратегія».
У проекті є такі класи:
Герой (Context) використовує вибрану стратегію атаки (Strategy). Легко замінювати стратегію під час гри.
| Стратегія | Опис | Критичний ефект | Візуальні ефекти |
|---|---|---|---|
| Меч | Фізична атака ближнього бою | Подвійна шкода | Мерехтіння червоно-жовто-фіолетове, звук ⚔️ |
| Магія | Заклинання середньої шкоди | Подвійна шкода + вибух магії | Мерехтіння фіолетово-блакитно-жовте, звук ✨ |
| Лук | Дальнобійна атака | Подвійна шкода + точний постріл | Мерехтіння жовто-зелено-блакитне, звук 🏹 |

Пояснення: Context (персонаж) використовує інтерфейс Strategy для виконання дії. Реалізації Strategy визначають різні стилі атаки.
using System;
using System.Threading;
// Інтерфейс стратегії атаки
public interface IAttackStrategy
{
int Attack(string attackerName);
}
// Стратегія: меч
public class SwordAttack : IAttackStrategy
{
public int Attack(string attackerName)
{
int baseDamage = new Random().Next(15, 26);
bool critical = new Random().Next(1, 5) == 1;
int damage = critical ? baseDamage * 2 : baseDamage;
if (critical)
SuperAttackEffect($"{attackerName} ⚔️ КРИТИЧНИЙ МЕЧ! Завдано {damage} шкоди!");
else
NormalAttackEffect($"{attackerName} ⚔️ атакує мечем і завдає {damage} шкоди.");
return damage;
}
private void SuperAttackEffect(string message)
{
ConsoleColor[] colors = { ConsoleColor.Red, ConsoleColor.Yellow, ConsoleColor.Magenta };
for (int i = 0; i < 5; i++)
{
Console.BackgroundColor = colors[i % colors.Length];
Console.Clear();
Thread.Sleep(100);
}
Console.ResetColor();
foreach (char c in message)
{
Console.ForegroundColor = colors[new Random().Next(colors.Length)];
Console.Write(c);
Thread.Sleep(20);
}
Console.WriteLine();
Console.Beep(800, 150);
Console.Beep(1000, 150);
Console.Beep(1200, 150);
Console.BackgroundColor = ConsoleColor.Black;
Console.Clear();
Console.ResetColor();
}
private void NormalAttackEffect(string message)
{
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine(message);
Console.Beep(600, 100);
Console.ResetColor();
}
}
// Стратегія: магія
public class MagicAttack : IAttackStrategy
{
public int Attack(string attackerName)
{
int baseDamage = new Random().Next(10, 31);
bool critical = new Random().Next(1, 5) == 1;
int damage = critical ? baseDamage * 2 : baseDamage;
if (critical)
SuperAttackEffect($"{attackerName} ✨ КРИТИЧНА МАГІЯ! Завдано {damage} шкоди!");
else
NormalAttackEffect($"{attackerName} ✨ атакує магією і завдає {damage} шкоди.");
return damage;
}
private void SuperAttackEffect(string message)
{
ConsoleColor[] colors = { ConsoleColor.Magenta, ConsoleColor.Cyan, ConsoleColor.Yellow };
for (int i = 0; i < 5; i++)
{
Console.BackgroundColor = colors[i % colors.Length];
Console.Clear();
Thread.Sleep(100);
}
Console.ResetColor();
foreach (char c in message)
{
Console.ForegroundColor = colors[new Random().Next(colors.Length)];
Console.Write(c);
Thread.Sleep(20);
}
Console.WriteLine();
Console.Beep(900, 150);
Console.Beep(1200, 150);
Console.Beep(1500, 150);
Console.BackgroundColor = ConsoleColor.Black;
Console.Clear();
Console.ResetColor();
}
private void NormalAttackEffect(string message)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine(message);
Console.Beep(700, 100);
Console.ResetColor();
}
}
// Стратегія: лук
public class BowAttack : IAttackStrategy
{
public int Attack(string attackerName)
{
int baseDamage = new Random().Next(12, 28);
bool critical = new Random().Next(1, 5) == 1;
int damage = critical ? baseDamage * 2 : baseDamage;
if (critical)
SuperAttackEffect($"{attackerName} 🏹 КРИТИЧНИЙ УДАР ЛУКОМ! Завдано {damage} шкоди!");
else
NormalAttackEffect($"{attackerName} 🏹 стріляє з лука і завдає {damage} шкоди.");
return damage;
}
private void SuperAttackEffect(string message)
{
ConsoleColor[] colors = { ConsoleColor.Yellow, ConsoleColor.Green, ConsoleColor.Cyan };
for (int i = 0; i < 5; i++)
{
Console.BackgroundColor = colors[i % colors.Length];
Console.Clear();
Thread.Sleep(100);
}
Console.ResetColor();
foreach (char c in message)
{
Console.ForegroundColor = colors[new Random().Next(colors.Length)];
Console.Write(c);
Thread.Sleep(20);
}
Console.WriteLine();
Console.Beep(800, 120);
Console.Beep(1000, 120);
Console.Beep(1200, 120);
Console.BackgroundColor = ConsoleColor.Black;
Console.Clear();
Console.ResetColor();
}
private void NormalAttackEffect(string message)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(message);
Console.Beep(650, 100);
Console.ResetColor();
}
}
// Клас персонажа
public class GameCharacter
{
public string Name { get; set; }
public int HP { get; set; } = 100;
private IAttackStrategy attackStrategy;
public GameCharacter(string name, IAttackStrategy strategy)
{
Name = name;
attackStrategy = strategy;
}
public void SetStrategy(IAttackStrategy strategy)
{
attackStrategy = strategy;
Console.WriteLine($"\n{Name} змінив стиль атаки!\n");
}
public void Attack(GameCharacter target)
{
int damage = attackStrategy.Attack(Name);
target.HP -= damage;
if (target.HP <0) target.HP = 0;
AnimateHP(target);
CheckSpecial(target);
}
public bool IsAlive() => HP > 0;
private void AnimateHP(GameCharacter target)
{
int totalBars = 20;
int filledBars = (int)((target.HP / 100.0) * totalBars);
Console.Write($"{target.Name} HP: [");
for (int i = 0; i < totalBars; i++)
{
if (i < filledBars)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write("█");
}
else
{
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.Write("░");
}
}
Console.ResetColor();
Console.WriteLine($"] {target.HP}/100\n");
Thread.Sleep(300);
}
private void CheckSpecial(GameCharacter target)
{
if (target.HP > 0 && target.HP <= 20)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"⚠️ {target.Name} в небезпечному стані! ⚠️\n");
Console.ResetColor();
}
}
}
// Програма
class Program
{
static void Main()
{
GameCharacter hero = new GameCharacter("Герой", new SwordAttack());
GameCharacter enemy = new GameCharacter("Монстр", new MagicAttack());
Console.WriteLine("=== Інтерактивна RPG гра з суперефектами та звуком ===\n");
int round = 1;
while (hero.IsAlive() && enemy.IsAlive())
{
Console.WriteLine($"--- Раунд {round} ---\n");
// Вибір стратегії для Героя
Console.WriteLine("Виберіть стратегію для Героя: 1-Меч, 2-Магія, 3-Лук, 0-Вихід з гри");
string choiceHero = Console.ReadLine();
if (choiceHero == "0") break;
hero.SetStrategy(GetStrategy(choiceHero));
// Вибір стратегії для Монстра
Console.WriteLine("Виберіть стратегію для Монстра: 1-Меч, 2-Магія, 3-Лук");
string choiceEnemy = Console.ReadLine();
enemy.SetStrategy(GetStrategy(choiceEnemy));
// Атаки
hero.Attack(enemy);
if (!enemy.IsAlive()) break;
enemy.Attack(hero);
if (!hero.IsAlive()) break;
round++;
}
Console.ForegroundColor = ConsoleColor.Yellow;
if (hero.IsAlive() && enemy.IsAlive())
Console.WriteLine("\nГра завершена достроково!");
else if (hero.IsAlive())
Console.WriteLine("\n🎉 Герой переміг!");
else
Console.WriteLine("\n💀 Монстр переміг!");
Console.ResetColor();
Console.WriteLine("\nДякуємо за гру!");
}
static IAttackStrategy GetStrategy(string choice)
{
switch (choice)
{
case "1": return new SwordAttack();
case "2": return new MagicAttack();
case "3": return new BowAttack();
default: return new SwordAttack();
}
}
}
Обирайте стратегію для Героя 1 і Героя 2, щоб атакувати один одного: