Verkliga Klasser och Objekt 🏗️

Nu bygger vi riktiga system med objektorienterad programmering! Från vardagsföremål till komplexa system - här lär du dig skapa klasser som löser verkliga problem! 🚀

🎯 Vad kommer du att bemästra?

  • Klasser med properties och metoder
  • Konstruktorer för objekt-initiering
  • Encapsulation för säker datahantering
  • Inheritance för kodåteranvändning
  • Polymorphism för flexibel design
  • Interfaces för clean architecture

🏦 Övning 2: Bank Account System (Inheritance & Encapsulation)

Problem: Skapa ett banksystem med olika typer av konton och säkerhetsfunktioner!


// Base class för alla bankkonton
public abstract class BankAccount
{
    protected double balance;
    protected string accountNumber;
    protected string accountHolder;
    protected DateTime createdDate;
    protected List<Transaction> transactions;

    // Properties
    public string AccountNumber { get { return accountNumber; } }
    public string AccountHolder { get { return accountHolder; } }
    public double Balance { get { return balance; } }
    public DateTime CreatedDate { get { return createdDate; } }

    // Constructor
    public BankAccount(string holder, double initialDeposit = 0)
    {
        accountHolder = holder;
        accountNumber = GenerateAccountNumber();
        balance = initialDeposit;
        createdDate = DateTime.Now;
        transactions = new List<Transaction>();

        if (initialDeposit > 0)
        {
            transactions.Add(new Transaction("Initial Deposit", initialDeposit, balance));
        }

        Console.WriteLine($"🏦 Nytt {GetType().Name} skapat för {accountHolder}");
        Console.WriteLine($"📋 Kontonummer: {accountNumber}");
    }

    // Abstract methods - måste implementeras av child classes
    public abstract bool Withdraw(double amount, string description = "Withdrawal");
    public abstract double GetInterestRate();
    public abstract string GetAccountType();

    // Virtual methods - kan overrides av child classes
    public virtual bool Deposit(double amount, string description = "Deposit")
    {
        if (amount <= 0)
        {
            Console.WriteLine("❌ Insättning måste vara större än 0!");
            return false;
        }

        balance += amount;
        transactions.Add(new Transaction(description, amount, balance));
        Console.WriteLine($"✅ Insättning: {amount:C} - Nytt saldo: {balance:C}");
        return true;
    }

    public void ShowTransactionHistory(int lastTransactions = 10)
    {
        Console.WriteLine($"\n📋 TRANSAKTIONSHISTORIK - {AccountHolder}");
        Console.WriteLine($"Kontonummer: {AccountNumber}");
        Console.WriteLine("".PadRight(60, '='));

        var recentTransactions = transactions.TakeLast(lastTransactions);

        foreach (var transaction in recentTransactions)
        {
            Console.WriteLine(transaction);
        }

        Console.WriteLine("".PadRight(60, '='));
        Console.WriteLine($"Aktuellt saldo: {balance:C}\n");
    }

    public void CalculateMonthlyInterest()
    {
        double interest = balance * (GetInterestRate() / 12 / 100);
        if (interest > 0)
        {
            Deposit(interest, "Monthly Interest");
        }
    }

    private string GenerateAccountNumber()
    {
        Random rand = new Random();
        return $"{rand.Next(1000, 9999)}-{rand.Next(1000000, 9999999)}";
    }
}

// Sparkonto - konservativt med ränta
public class SavingsAccount : BankAccount
{
    private double minimumBalance;
    private int freeWithdrawalsPerMonth;
    private int withdrawalsThisMonth;
    private DateTime lastWithdrawalReset;

    public SavingsAccount(string holder, double initialDeposit = 0, double minBalance = 100)
        : base(holder, initialDeposit)
    {
        minimumBalance = minBalance;
        freeWithdrawalsPerMonth = 5;
        withdrawalsThisMonth = 0;
        lastWithdrawalReset = DateTime.Now;
    }

    public override bool Withdraw(double amount, string description = "Withdrawal")
    {
        // Reset withdrawal count if new month
        if (DateTime.Now.Month != lastWithdrawalReset.Month)
        {
            withdrawalsThisMonth = 0;
            lastWithdrawalReset = DateTime.Now;
        }

        if (amount <= 0)
        {
            Console.WriteLine("❌ Uttag måste vara större än 0!");
            return false;
        }

        if (balance - amount < minimumBalance)
        {
            Console.WriteLine($"❌ Uttag nekas! Minimum saldo: {minimumBalance:C}");
            return false;
        }

        double fee = 0;
        if (withdrawalsThisMonth >= freeWithdrawalsPerMonth)
        {
            fee = 25; // Avgift för extra uttag
            Console.WriteLine($"⚠️ Avgift för extra uttag: {fee:C}");
        }

        balance -= (amount + fee);
        withdrawalsThisMonth++;

        transactions.Add(new Transaction(description, -(amount + fee), balance));
        Console.WriteLine($"✅ Uttag: {amount:C} - Nytt saldo: {balance:C}");

        if (withdrawalsThisMonth > freeWithdrawalsPerMonth)
        {
            Console.WriteLine($"💡 Du har {freeWithdrawalsPerMonth - withdrawalsThisMonth + freeWithdrawalsPerMonth} gratis uttag kvar denna månad");
        }

        return true;
    }

    public override double GetInterestRate() { return 1.2; } // 1.2% årlig ränta
    public override string GetAccountType() { return "Sparkonto"; }
}

// Lönekonto - flexibelt för dagligt bruk
public class CheckingAccount : BankAccount
{
    private double overdraftLimit;
    private double overdraftFee;

    public CheckingAccount(string holder, double initialDeposit = 0, double overdraft = 1000)
        : base(holder, initialDeposit)
    {
        overdraftLimit = overdraft;
        overdraftFee = 75;
    }

    public override bool Withdraw(double amount, string description = "Withdrawal")
    {
        if (amount <= 0)
        {
            Console.WriteLine("❌ Uttag måste vara större än 0!");
            return false;
        }

        bool willGoOverdrawn = (balance - amount) < 0;
        double newBalance = balance - amount;

        if (Math.Abs(newBalance) > overdraftLimit)
        {
            Console.WriteLine($"❌ Uttag nekas! Överdrag gräns: {overdraftLimit:C}");
            return false;
        }

        double totalFee = 0;
        if (willGoOverdrawn && balance >= 0)
        {
            totalFee = overdraftFee;
            Console.WriteLine($"⚠️ Överdrag-avgift: {totalFee:C}");
            newBalance -= totalFee;
        }

        balance = newBalance;
        transactions.Add(new Transaction(description, -(amount + totalFee), balance));

        if (balance < 0)
        {
            Console.WriteLine($"⚠️ Uttag: {amount:C} - ÖVERDRAG: {balance:C}");
        }
        else
        {
            Console.WriteLine($"✅ Uttag: {amount:C} - Nytt saldo: {balance:C}");
        }

        return true;
    }

    public override double GetInterestRate() { return 0.1; } // Minimal ränta
    public override string GetAccountType() { return "Lönekonto"; }
}

// Investment Account - för långsiktig förmögenhetsbyggande
public class InvestmentAccount : BankAccount
{
    private double minimumInvestment;
    private double managementFeePercent;
    private List<Investment> investments;

    public InvestmentAccount(string holder, double initialDeposit = 0)
        : base(holder, initialDeposit)
    {
        minimumInvestment = 10000;
        managementFeePercent = 0.5; // 0.5% management fee
        investments = new List<Investment>();
    }

    public override bool Withdraw(double amount, string description = "Investment Withdrawal")
    {
        if (amount <= 0)
        {
            Console.WriteLine("❌ Uttag måste vara större än 0!");
            return false;
        }

        if (balance < minimumInvestment + amount)
        {
            Console.WriteLine($"❌ Måste behålla minimum {minimumInvestment:C} för investeringar!");
            return false;
        }

        // Withdrawal fee för investeringskonto
        double fee = amount * 0.01; // 1% withdrawal fee
        balance -= (amount + fee);

        transactions.Add(new Transaction(description, -(amount + fee), balance));
        Console.WriteLine($"✅ Uttag: {amount:C} (Avgift: {fee:C}) - Nytt saldo: {balance:C}");
        return true;
    }

    public bool MakeInvestment(string investmentName, double amount)
    {
        if (balance < amount || amount < 1000)
        {
            Console.WriteLine($"❌ Otillräcklig balans eller för liten investering (min 1000kr)");
            return false;
        }

        balance -= amount;
        investments.Add(new Investment(investmentName, amount, DateTime.Now));
        transactions.Add(new Transaction($"Investment: {investmentName}", -amount, balance));

        Console.WriteLine($"📈 Investering i {investmentName}: {amount:C}");
        return true;
    }

    public void ShowInvestments()
    {
        Console.WriteLine($"\n📊 INVESTERINGAR - {AccountHolder}");
        double totalInvestmentValue = 0;

        foreach (var investment in investments)
        {
            // Simulera värdeförändringar
            Random rand = new Random();
            double performance = (rand.NextDouble() - 0.5) * 0.4; // -20% till +20%
            double currentValue = investment.Amount * (1 + performance);
            totalInvestmentValue += currentValue;

            Console.WriteLine($"• {investment.Name}: {investment.Amount:C}{currentValue:C} " +
                             $"({performance:P1})");
        }

        Console.WriteLine($"Total portföljvärde: {totalInvestmentValue:C}\n");
    }

    public override double GetInterestRate() { return 3.5; } // Högre potential avkastning
    public override string GetAccountType() { return "Investeringskonto"; }
}

// Helper classes
public class Transaction
{
    public DateTime Date { get; set; }
    public string Description { get; set; }
    public double Amount { get; set; }
    public double BalanceAfter { get; set; }

    public Transaction(string desc, double amount, double balance)
    {
        Date = DateTime.Now;
        Description = desc;
        Amount = amount;
        BalanceAfter = balance;
    }

    public override string ToString()
    {
        string amountStr = Amount >= 0 ? $"+{Amount:C}" : $"{Amount:C}";
        return $"{Date:yyyy-MM-dd HH:mm} | {Description.PadRight(20)} | {amountStr.PadLeft(10)} | Saldo: {BalanceAfter:C}";
    }
}

public class Investment
{
    public string Name { get; set; }
    public double Amount { get; set; }
    public DateTime DatePurchased { get; set; }

    public Investment(string name, double amount, DateTime date)
    {
        Name = name;
        Amount = amount;
        DatePurchased = date;
    }
}

// Demonstration av banksystemet
class BankDemo
{
    static void Main()
    {
        Console.WriteLine("🏦 VÄLKOMMEN TILL NORDIC BANK 🏦\n");

        // Skapa olika typer av konton
        var savings = new SavingsAccount("Anna Andersson", 5000, 500);
        var checking = new CheckingAccount("Erik Eriksson", 2000, 1500);
        var investment = new InvestmentAccount("Maria Millionär", 50000);

        Console.WriteLine("\n💰 TRANSAKTIONER:");

        // Sparkonto operationer
        savings.Deposit(1000, "Lön");
        savings.Withdraw(200, "Hyra");
        savings.Withdraw(100, "Mat");

        // Lönekonto operationer
        checking.Deposit(8000, "Månadslön");
        checking.Withdraw(4500, "Hyra");
        checking.Withdraw(2500, "Dagliga utgifter");
        checking.Withdraw(2000, "Extra utgifter"); // Detta går på överdrag

        // Investeringskonto operationer
        investment.MakeInvestment("OMXS30 Index", 15000);
        investment.MakeInvestment("Global Tech Fund", 20000);
        investment.Withdraw(5000, "Vinst-uttag");

        Console.WriteLine("\n📊 KONTOSTATUS:");
        savings.ShowTransactionHistory(5);
        checking.ShowTransactionHistory(5);
        investment.ShowTransactionHistory(5);
        investment.ShowInvestments();

        Console.WriteLine("💡 MÅNATLIG RÄNTA:");
        savings.CalculateMonthlyInterest();
        checking.CalculateMonthlyInterest();
        investment.CalculateMonthlyInterest();
    }
}

Din uppgift:

  1. Skapa en “CreditCardAccount” klass med kreditgräns
  2. Implementera en “BankManager” klass som hanterar flera konton
  3. Lägg till automatiska överföringar mellan konton

🎮 Övning 3: RPG Character System (Polymorphism & Interfaces)

Problem: Skapa ett flexibelt RPG-system med olika karaktärsklasser och förmågor!


// Interface för attackbara enheter
public interface ICombatant
{
    string Name { get; }
    double Health { get; }
    double MaxHealth { get; }
    bool IsAlive { get; }
    void TakeDamage(double damage, string source = "Unknown");
    double AttackTarget(ICombatant target);
}

// Interface för spellcasters
public interface ISpellCaster
{
    double Mana { get; }
    double MaxMana { get; }
    bool CanCastSpells { get; }
    bool CastSpell(string spellName, ICombatant target = null);
}

// Interface för healers
public interface IHealer
{
    bool CanHeal { get; }
    double HealTarget(ICombatant target, double amount);
    double HealSelf(double amount);
}

// Base character class
public abstract class Character : ICombatant
{
    protected double health;
    protected double maxHealth;
    protected double baseDamage;
    protected double armor;
    protected int level;
    protected double experience;

    public string Name { get; protected set; }
    public double Health { get { return health; } }
    public double MaxHealth { get { return maxHealth; } }
    public bool IsAlive { get { return health > 0; } }
    public int Level { get { return level; } }
    public double Experience { get { return experience; } }
    public abstract string CharacterClass { get; }

    public Character(string name)
    {
        Name = name;
        level = 1;
        experience = 0;
        SetBaseStats();
        health = maxHealth;
    }

    protected abstract void SetBaseStats();
    public abstract double AttackTarget(ICombatant target);
    public abstract void LevelUp();

    public virtual void TakeDamage(double damage, string source = "Unknown")
    {
        // Armor reducerar damage
        double actualDamage = Math.Max(1, damage - armor);
        health = Math.Max(0, health - actualDamage);

        Console.WriteLine($"💥 {Name} tar {actualDamage:F1} skada från {source}!");

        if (health <= 0)
        {
            Console.WriteLine($"💀 {Name} har besegrats!");
        }
        else if (health < maxHealth * 0.2)
        {
            Console.WriteLine($"⚠️ {Name} har kritiskt låg hälsa!");
        }
    }

    public void GainExperience(double exp)
    {
        experience += exp;
        Console.WriteLine($"⭐ {Name} fick {exp} XP! (Total: {experience})");

        // Check for level up
        double expNeededForNext = level * 100; // Simple formula
        if (experience >= expNeededForNext)
        {
            LevelUp();
        }
    }

    public void ShowStatus()
    {
        Console.WriteLine($"\n📊 {Name} ({CharacterClass}) - Level {level}");
        Console.WriteLine($"❤️ Health: {health:F0}/{maxHealth:F0}");
        Console.WriteLine($"⚔️ Base Damage: {baseDamage:F1}");
        Console.WriteLine($"🛡️ Armor: {armor:F1}");
        Console.WriteLine($"⭐ Experience: {experience:F0}");
    }
}

// Warrior class - tank som fokuserar på fysisk damage och defense
public class Warrior : Character
{
    private double rageMeter;
    private bool isRaging;

    public override string CharacterClass { get { return "Warrior"; } }

    public Warrior(string name) : base(name)
    {
        rageMeter = 0;
        isRaging = false;
    }

    protected override void SetBaseStats()
    {
        maxHealth = 120;
        baseDamage = 15;
        armor = 8;
    }

    public override double AttackTarget(ICombatant target)
    {
        double damage = baseDamage;

        // Rage bonus
        if (isRaging)
        {
            damage *= 1.5;
            Console.WriteLine($"🔥 {Name} attackerar med RAGE!");
        }

        // Random variation
        Random rand = new Random();
        damage *= (0.8 + rand.NextDouble() * 0.4); // 80% to 120% damage

        Console.WriteLine($"⚔️ {Name} attackerar {target.Name} för {damage:F1} skada!");
        target.TakeDamage(damage, Name);

        // Build rage meter
        rageMeter = Math.Min(100, rageMeter + 15);

        return damage;
    }

    public void ActivateRage()
    {
        if (rageMeter >= 50 && !isRaging)
        {
            isRaging = true;
            rageMeter = 0;
            Console.WriteLine($"💀 {Name} goes into BERSERKER RAGE!");

            // Rage lasts for a few turns (simplified)
            Task.Delay(3000).ContinueWith(_ => {
                isRaging = false;
                Console.WriteLine($"😤 {Name}'s rage subsides...");
            });
        }
        else if (rageMeter < 50)
        {
            Console.WriteLine($"⚠️ Not enough rage! ({rageMeter}/50)");
        }
    }

    public override void LevelUp()
    {
        level++;
        maxHealth += 20;
        health = maxHealth; // Full heal on level up
        baseDamage += 3;
        armor += 2;
        experience = 0;

        Console.WriteLine($"🎉 {Name} reached level {level}! Health and damage increased!");
    }
}

// Mage class - spellcaster med elemental magic
public class Mage : Character, ISpellCaster, IHealer
{
    private double mana;
    private double maxMana;
    private Dictionary<string, Spell> spells;

    public double Mana { get { return mana; } }
    public double MaxMana { get { return maxMana; } }
    public bool CanCastSpells { get { return mana > 0; } }
    public bool CanHeal { get { return mana >= 20; } }

    public override string CharacterClass { get { return "Mage"; } }

    public Mage(string name) : base(name)
    {
        InitializeSpells();
        mana = maxMana;
    }

    protected override void SetBaseStats()
    {
        maxHealth = 70;
        baseDamage = 8;
        armor = 2;
        maxMana = 100;
    }

    private void InitializeSpells()
    {
        spells = new Dictionary<string, Spell>
        {
            { "Fireball", new Spell("Fireball", 25, 35, "🔥") },
            { "Ice Shard", new Spell("Ice Shard", 15, 20, "❄️") },
            { "Lightning Bolt", new Spell("Lightning Bolt", 30, 45, "⚡") },
            { "Heal", new Spell("Heal", 20, 30, "✨") },
            { "Shield", new Spell("Shield", 15, 0, "🛡️") }
        };
    }

    public override double AttackTarget(ICombatant target)
    {
        // Basic staff attack
        double damage = baseDamage * (0.7 + new Random().NextDouble() * 0.6);
        Console.WriteLine($"🪄 {Name} attacks with staff for {damage:F1} damage!");
        target.TakeDamage(damage, Name);
        return damage;
    }

    public bool CastSpell(string spellName, ICombatant target = null)
    {
        if (!spells.ContainsKey(spellName))
        {
            Console.WriteLine($"❌ {Name} doesn't know the spell '{spellName}'!");
            return false;
        }

        Spell spell = spells[spellName];

        if (mana < spell.ManaCost)
        {
            Console.WriteLine($"❌ Not enough mana! Need {spell.ManaCost}, have {mana}");
            return false;
        }

        mana -= spell.ManaCost;

        if (spellName == "Heal")
        {
            if (target != null)
            {
                HealTarget(target, spell.Power);
            }
            else
            {
                HealSelf(spell.Power);
            }
        }
        else if (spellName == "Shield")
        {
            armor += 5; // Temporary armor boost
            Console.WriteLine($"{spell.Icon} {Name} casts Shield! Armor increased temporarily!");

            // Remove shield after some time
            Task.Delay(5000).ContinueWith(_ => {
                armor = Math.Max(2, armor - 5); // Back to base armor
                Console.WriteLine($"🛡️ {Name}'s shield fades...");
            });
        }
        else if (target != null)
        {
            // Attack spell
            double damage = spell.Power * (0.8 + new Random().NextDouble() * 0.4);
            Console.WriteLine($"{spell.Icon} {Name} casts {spellName} at {target.Name} for {damage:F1} damage!");
            target.TakeDamage(damage, $"{Name}'s {spellName}");
        }

        return true;
    }

    public double HealTarget(ICombatant target, double amount)
    {
        if (target is Character character)
        {
            double oldHealth = character.Health;
            // Using reflection to access protected health field (simplified)
            double newHealth = Math.Min(character.MaxHealth, oldHealth + amount);
            double actualHealing = newHealth - oldHealth;

            Console.WriteLine($"✨ {Name} heals {target.Name} for {actualHealing:F1} HP!");
            return actualHealing;
        }
        return 0;
    }

    public double HealSelf(double amount)
    {
        double oldHealth = health;
        health = Math.Min(maxHealth, health + amount);
        double actualHealing = health - oldHealth;

        Console.WriteLine($"✨ {Name} heals themselves for {actualHealing:F1} HP!");
        return actualHealing;
    }

    public void RestoreMana(double amount)
    {
        mana = Math.Min(maxMana, mana + amount);
        Console.WriteLine($"💙 {Name} restores {amount} mana! ({mana}/{maxMana})");
    }

    public override void LevelUp()
    {
        level++;
        maxHealth += 10;
        maxMana += 15;
        health = maxHealth;
        mana = maxMana;
        baseDamage += 2;
        armor += 1;
        experience = 0;

        Console.WriteLine($"🎉 {Name} reached level {level}! Mana and spell power increased!");

        // Learn new spell at certain levels
        if (level == 3 && !spells.ContainsKey("Meteor"))
        {
            spells.Add("Meteor", new Spell("Meteor", 50, 80, "☄️"));
            Console.WriteLine($"📚 {Name} learned new spell: Meteor!");
        }
    }
}

// Rogue class - sneak attacks och mobility
public class Rogue : Character
{
    private bool isStealthed;
    private double stealthMeter;

    public override string CharacterClass { get { return "Rogue"; } }

    public Rogue(string name) : base(name)
    {
        isStealthed = false;
        stealthMeter = 100;
    }

    protected override void SetBaseStats()
    {
        maxHealth = 85;
        baseDamage = 12;
        armor = 4;
    }

    public override double AttackTarget(ICombatant target)
    {
        double damage = baseDamage;

        // Sneak attack bonus
        if (isStealthed)
        {
            damage *= 2.5; // Massive sneak attack damage
            isStealthed = false;
            Console.WriteLine($"🗡️ {Name} delivers a SNEAK ATTACK!");
        }

        // Critical hit chance
        Random rand = new Random();
        if (rand.NextDouble() < 0.25) // 25% crit chance
        {
            damage *= 1.8;
            Console.WriteLine($"💀 CRITICAL HIT!");
        }

        damage *= (0.9 + rand.NextDouble() * 0.2); // 90% to 110%

        Console.WriteLine($"🗡️ {Name} strikes {target.Name} for {damage:F1} damage!");
        target.TakeDamage(damage, Name);

        return damage;
    }

    public void EnterStealth()
    {
        if (stealthMeter >= 30 && !isStealthed)
        {
            isStealthed = true;
            stealthMeter -= 30;
            Console.WriteLine($"🌫️ {Name} disappears into the shadows...");

            // Stealth breaks after some time or after attacking
            Task.Delay(4000).ContinueWith(_ => {
                if (isStealthed) // Only break if still stealthed
                {
                    isStealthed = false;
                    Console.WriteLine($"👁️ {Name} emerges from stealth");
                }
            });
        }
        else if (stealthMeter < 30)
        {
            Console.WriteLine($"⚠️ Not enough stealth energy! ({stealthMeter}/30)");
        }
    }

    public void RestoreStealthMeter(double amount = 20)
    {
        stealthMeter = Math.Min(100, stealthMeter + amount);
        Console.WriteLine($"🌙 Stealth energy restored: {stealthMeter}/100");
    }

    public override void LevelUp()
    {
        level++;
        maxHealth += 12;
        health = maxHealth;
        baseDamage += 4; // Rogues get more damage per level
        armor += 1;
        experience = 0;

        Console.WriteLine($"🎉 {Name} reached level {level}! Speed and stealth improved!");
    }
}

// Spell helper class
public class Spell
{
    public string Name { get; set; }
    public double ManaCost { get; set; }
    public double Power { get; set; }
    public string Icon { get; set; }

    public Spell(string name, double cost, double power, string icon)
    {
        Name = name;
        ManaCost = cost;
        Power = power;
        Icon = icon;
    }
}

// Combat simulator
public class Combat
{
    public static void StartBattle(ICombatant fighter1, ICombatant fighter2)
    {
        Console.WriteLine($"\n⚔️ COMBAT BEGINS: {fighter1.Name} vs {fighter2.Name}! ⚔️");

        int round = 1;

        while (fighter1.IsAlive && fighter2.IsAlive && round <= 20)
        {
            Console.WriteLine($"\n--- ROUND {round} ---");

            // Fighter 1's turn
            if (fighter1.IsAlive)
            {
                PerformTurn(fighter1, fighter2);
            }

            // Fighter 2's turn
            if (fighter2.IsAlive)
            {
                PerformTurn(fighter2, fighter1);
            }

            round++;
            System.Threading.Thread.Sleep(1000); // Dramatic pause
        }

        // Determine winner
        if (fighter1.IsAlive && !fighter2.IsAlive)
        {
            Console.WriteLine($"\n🏆 {fighter1.Name} WINS!");
            if (fighter1 is Character winner)
            {
                winner.GainExperience(50);
            }
        }
        else if (fighter2.IsAlive && !fighter1.IsAlive)
        {
            Console.WriteLine($"\n🏆 {fighter2.Name} WINS!");
            if (fighter2 is Character winner)
            {
                winner.GainExperience(50);
            }
        }
        else
        {
            Console.WriteLine($"\n🤝 It's a draw!");
        }
    }

    private static void PerformTurn(ICombatant attacker, ICombatant target)
    {
        Random rand = new Random();

        // AI decision making for different character types
        if (attacker is Warrior warrior)
        {
            if (rand.NextDouble() < 0.3) // 30% chance to try rage
            {
                warrior.ActivateRage();
            }
            warrior.AttackTarget(target);
        }
        else if (attacker is Mage mage)
        {
            if (mage.Health < mage.MaxHealth * 0.3 && mage.CanHeal && rand.NextDouble() < 0.7)
            {
                // Low health - heal
                mage.CastSpell("Heal");
            }
            else if (mage.CanCastSpells && rand.NextDouble() < 0.8)
            {
                // Cast offensive spell
                string[] spells = { "Fireball", "Ice Shard", "Lightning Bolt" };
                string chosenSpell = spells[rand.Next(spells.Length)];

                if (!mage.CastSpell(chosenSpell, target))
                {
                    mage.AttackTarget(target); // Fallback to basic attack
                }
            }
            else
            {
                mage.AttackTarget(target);
            }
        }
        else if (attacker is Rogue rogue)
        {
            if (rand.NextDouble() < 0.4) // 40% chance to stealth before attack
            {
                rogue.EnterStealth();
            }
            rogue.AttackTarget(target);
        }
        else
        {
            attacker.AttackTarget(target);
        }
    }
}

// Demo program
class RPGDemo
{
    static void Main()
    {
        Console.WriteLine("⚔️ VÄLKOMMEN TILL RPG WORLD! ⚔️\n");

        // Skapa karaktärer
        var warrior = new Warrior("Bjorn the Mighty");
        var mage = new Mage("Astrid the Wise");
        var rogue = new Rogue("Erik Shadowstep");

        // Visa initial stats
        warrior.ShowStatus();
        mage.ShowStatus();
        rogue.ShowStatus();

        // Test abilities
        Console.WriteLine("\n🧪 TESTING ABILITIES:");
        warrior.ActivateRage();
        mage.CastSpell("Shield");
        rogue.EnterStealth();

        // Battle 1: Warrior vs Mage
        Combat.StartBattle(warrior, mage);

        System.Threading.Thread.Sleep(2000);

        // Heal up for next battle (simplified)
        if (warrior.IsAlive) warrior.GainExperience(25);
        if (mage.IsAlive)
        {
            mage.GainExperience(25);
            if (mage is Mage healingMage)
            {
                healingMage.HealSelf(50);
                healingMage.RestoreMana(50);
            }
        }

        // Battle 2: Winner vs Rogue
        if (warrior.IsAlive)
        {
            Combat.StartBattle(warrior, rogue);
        }
        else if (mage.IsAlive)
        {
            Combat.StartBattle(mage, rogue);
        }

        Console.WriteLine("\n🎉 Demo completed!");
    }
}

Din uppgift:

  1. Skapa en “Paladin” klass som implementerar både ICombatant och IHealer
  2. Lägg till equipment system med vapen och armor
  3. Skapa en “Party” klass som hanterar grupper av karaktärer

🎯 Sammanfattning

Du behärskar nu OOP för verkliga problem! Du kan:

  • ✅ Skapa klasser med properties och metoder
  • ✅ Använda konstruktorer för objekt-initiering
  • ✅ Implementera encapsulation för säker data
  • ✅ Använda inheritance för kodåteranvändning
  • ✅ Implementera interfaces för clean contracts
  • ✅ Bygga komplexa system med polymorphism
  • ✅ Lösa verkliga problem med objektorienterad design

Nästa steg: Kombinera OOP med datastrukturer för ännu mer kraftfulla system!

🤣 Obligatorisk Dad Joke

Varför gillar programmerare objektorienterad programmering?

För att de äntligen kan organisera sitt kod-kaos… precis som de borde organisera sitt rum! 🏠📦


Upp

Upp


Licens: Apache 2.0 | © 2023 Marcus Medina, Campus Mölndal. Alla rättigheter förbehållna.
Du får använda och modifiera detta verk enligt villkoren i Apache License, Version 2.0. Du får inte använda detta verk för kommersiella ändamål utan tillstånd från upphovsmannen.