Itemliste



  • Hallo!

    Im Zuge des Lernens von C# dachte ich mir heute ich programmiere mir ein kleines Konsolenspiel. Damit das ganze nicht zu kompliziert wird, soll es einfach nur einen Spieler geben und einen Gegner, welche abwechselnd an der Reihe sind. Für Spieler wie Gegner sind folgende Attribute relevant: Armor, HP, DmgMin, DmgMax.

    Nun würde ich aber gern eine Palette mit Fähigkeiten für Spieler wie auch Gegner machen. Für den Gegner sollen diese Fähigkeiten dann zufällig ausgewählt und ausgeführt werden. Meine Frage aber: wie speichere ich diese Fähigkeiten am schönsten? Die Fähigkeiten selbst bestehen aus einer Reihe von noch nicht so ganz klaren Eigenschaften (Basis-Schaden, ...). Schnell gegoogelt habe ich mal das Wort "Dictionary" gefunden - klingt ja gar nicht mal so unbrauchbar. Ist es aber das richtige?

    Quellcode zu posten wäre bislang sinnlos, da es nur 2 Klassen sind, wovon 1 "Enemy" heißt und ein paar Member-Variablen hat (eben die relevanten Attribute für den Gegner). Mehr gibts noch nicht :>...

    Danke schonmal



  • Meinst du mit "Speichern" wie du es persistent speicherst oder wie du es lokal in deiner Anwendung speicherst?



  • Versuche diese Fähigkeiten zu unterteilen, z.B. in passive und offensive fähigkeiten. Überlege dir dann was für Eigenschaften welche Gruppe haben müsste und erstel dann für jede Gruppe eine Klasse.
    Die fertigen Fertigkeiten kannst du dann z.B. in einer weiteren Klasse speichern, welche sie als statische Liste speichert.
    Das hätte den Vorteil, dass du keine Instanz von der speicherklasse erstellen müstest, sondern direkt darauf zugreifen könntest. Zudem könntest du mehrere Listen für verschiedene Kampfklassen machen (Magier, Krieger, etc.).

    Ich hoffe, dass ich die Frage richtig verstanden und richtig beantwortet habe, wenn nicht, einfach fragen.
    Das Ganze ist auch nur eine Möglichkeit von vielen, ich behaupte nicht, dass meine am besten ist. 😉

    Grüsse
    Chiller



  • Erstmal danke 🙂

    Ich meine mit Speichern einfach schön im Quellcode verarbeiten 🙂

    Und Chiller:
    Wie sieht denn so eine "statische Liste" aus? Ich möchte ungern einfach nur eine Klasse erstellen, wo die ganzen Fähigkeiten als Methoden drin sind (zudem das Zufallsprinzip dann ziemlich hässlich werden würde, wenn ich "zufällige Methoden" aufrufe :/).



  • Ein schöneres Beispiel für mein Anliegen wäre:

    Ich habe nun eine Fähigkeit, nennen wir sie einfach mal "draufhauen". Diese Fähigkeit hat einen Basis-Schaden von 1.5, als Beischreibung "Mitten in die Fresse!" und einen zusätzlichen Schaden von 30. Das heißt, ich will im Quellcode irgendwo ein Archiv dieser Fähigkeiten anfertigen. Da es 4 Elemente sind, die einer Fähigkeit gelten (Name, Basis-Schaden, Beschreibung, zusätzl. Schaden) inkl. einer etwaigen ID (für den Aufruf), finde ich einfach keine passende Möglichkeit wie ich das schön integriere. Am ehesten würde ich zum assoziativen Array greifen, aber damit wäre ich wieder bei "Dictionary".



  • Okay, ich hab es vorerst mal ohne "Skill-Liste" gelöst. Evtl. will mal irgendwer was zum Code sagen :>

    Program.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace GameTest
    {
        class Game
        {
            static void Main(string[] args)
            {
                Enemy Bob = new Enemy();
                Player Me = new Player();
                char Turn = 'P';
                int Round = 0;
    
                Console.Write("Ein wilder {0} erscheint! Er will dein Geld, dein Haus und deine Frau. ", Bob.m_Name);
                Console.WriteLine("Abgesehen von letzterem bist du dagegen. Verteidige dich!\n");
                while ((Bob.HP > 0) && (Me.HP > 0))
                {
                    // show information
                    Console.Write("Deine HP: {0,7}", Me.HP);
                    Console.Write(" - ");
                    Console.Write("{0}s HP: {1,7}", Bob.m_Name, Bob.HP);
                    Console.WriteLine("\n");
    
                    if (Turn == 'P')
                    {
                        Console.WriteLine("Du bist an der Reihe! Was willst du tun...?");
                        Me.showCastList();
                        Console.Write("\nIch will folgendes tun: ");
                        try {
                            int CastID = Convert.ToInt32(Console.ReadLine());
                            Console.WriteLine("\n");
                            Me.cast(CastID);
    
                            Bob.takeDamage(Me.getCastDmg(CastID));
                        } catch(FormatException) {
                            Console.WriteLine("Du Trottel! Das kannst du doch überhaupt nicht!");
                        }
                        Console.WriteLine("==========================================================");
                        Turn = 'E';
                    }
                    else if(Turn == 'E')
                    {
                        Random rnd = new Random();
                        int castID = rnd.Next(1, 3);
                        Bob.rndCast(castID);
                        Me.takeDamage(Bob.getCastDmg(castID));
    
                        Console.WriteLine("==========================================================");
                        Turn = 'P';
                    }
    
                    Console.Read();
                }
            }
        }
    }
    

    Enemey.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace GameTest
    {
        class Enemy
        {
            public string m_Name = "Bob";
    
            private int m_HP = 25000;
            private int m_DmgMin = 500;
            private int m_DmgMax = 1000;
    
            public int HP
            {
                get
                {
                    return m_HP;
                }
            }
    
            public int Damage
            {
                get
                {
                    Random rnd = new Random();
                    return rnd.Next(m_DmgMin, m_DmgMax);
                }
            }
    
            public void takeDamage(int n)
            {
                m_HP -= n;
            }
    
            public int getCastDmg(int castID)
            {
                switch (castID)
                {
                    case 1:
                        return Damage * 2;
                    case 2:
                        return Damage * 3;
                    case 3:
                        return Damage * 5;
                }
    
                return 0;
            }
    
            public void rndCast(int castID)
            {
                switch (castID)
                {
                    case 1:
                        Console.WriteLine("{0} beißt dir ein Bein ab!", m_Name);
                        Console.WriteLine("Du nimmst {0} Schaden!\n", getCastDmg(castID));
                        break;
                    case 2:
                        Console.WriteLine("{0} macht einen Deine-Mutter-Witz!", m_Name);
                        Console.WriteLine("Du nimmst {0} Schaden!\n", getCastDmg(castID));
                        break;
                    case 3:
                        Console.WriteLine("{0} bittet dich darum zu sterben.");
                        Console.WriteLine("Du nimmst {0} Schaden!\n", getCastDmg(castID));
                        break;
                }
            }
        }
    }
    

    Player.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace GameTest
    {
        class Player
        {
            private int m_HP = 20000;
            private int m_Armor = 100;
            private int m_DmgMin = 100;
            private int m_DmgMax = 300;
    
            public int HP
            {
                get
                {
                    return m_HP;
                }
            }
    
            public int Armor
            {
                get
                {
                    return m_Armor / 100;
                }
            }
    
            public int Damage
            {
                get
                {
                    Random rnd = new Random();
                    return rnd.Next(m_DmgMin, m_DmgMax);
                }
            }
    
            private bool missed(double chance)
            {
                Random rnd = new Random();
                double miss = rnd.NextDouble();
                if (miss <= chance)
                    return true;
                else
                    return false;
            }
    
            public void takeDamage(int n)
            {
                m_HP -= n;
            }
    
            private int realCastDmg(int baseDmg)
            {
                return (baseDmg * Damage) - Armor;
            }
    
            public int getCastDmg(int spellID)
            {
                int baseDmg;
                double chanceToMiss;
                switch (spellID)
                {
                    case 1:
                        baseDmg = 2;
                        chanceToMiss = 0.1d;
    
                        if (!missed(chanceToMiss))
                            return realCastDmg(baseDmg);
                        else
                            return 0;
    
                    case 2:
                        baseDmg = 4;
                        chanceToMiss = 0.25d;
    
                        if (!missed(chanceToMiss))
                            return realCastDmg(baseDmg);
                        else
                            return 0;
    
                    case 3:
                        baseDmg = 10;
                        chanceToMiss = 0.5d;
    
                        if (!missed(chanceToMiss))
                            return realCastDmg(baseDmg);
                        else
                            return 0;
    
                    default:
                        return 0;
                }
            }
    
            public void cast(int spellID)
            {
                int castDmg = getCastDmg(spellID);
                bool miss = false;
    
                switch (spellID)
                {
                    case 1:
                        if (castDmg != 0)
                        {
                            Console.WriteLine("Du hast deinem Gegner ins Gesicht geschlagen. Sah heftig aus!");
                            Console.WriteLine("Dein Gegner erlitt {0} Schaden!\n", castDmg);
                        }
                        else miss = true;
                        break;
    
                    case 2:
                        if (castDmg != 0)
                        {
                            Console.WriteLine("BOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOM!");
                            Console.WriteLine("Dein Gegner erlitt {0} Schaden!\n", castDmg);
                        }
                        else miss = true;
                        break;
    
                    case 3:
                        if (castDmg != 0)
                        {
                            Console.WriteLine("Du hast deinen Gegner mit einem Nudelholz geschlagen. Lol!");
                            Console.WriteLine("Dein Gegner erlitt {0} Schaden!\n", castDmg);
                        }
                        else miss = true;
                        break;
                }
    
                if (miss)
                    Console.WriteLine("Du scheinst etwas betrunken zu sein... VERFEHLT!");
            }
    
            public void showCastList()
            {
                Console.WriteLine("1.   Draufhauen (Mitten in die Fresse!)");
                Console.WriteLine("2.   Doom (Boooom!)");
                Console.WriteLine("3.   Nudelholz der Verdamnis.");
            }
        }
    }
    

    Paar Dinge die ich selbst noch gern ändern würde:
    - Skill-Liste eben integrieren. Diese Switcherei ist nicht schön.
    - Ein paar Dinge muss ich noch schöner umbauen, scheint mir teilweise noch etwas zu "chaotisch" zu sein (paar Dinge auslagern, ...)

    Sonst gilt: mein erstes C#-Programm. *stolz* :p



  • Glückwunsch!

    Zum Code:
    Enemy.cs Zeile 66: Der Parameter 1 (m_Name) fehlt.

    Generell würde ich anstatt zweier Klassen "Player" und "Enemy" lieber eine Klasse "Character" sehen. Davon erstellst Du in Main.cs zwei Instanzen, denen Du unterschiedliche Namen, Hitpoints, etc. gibst.



  • Zu der statischen Liste:
    Da kommen Daten rein, welche zur runtime nicht mehr geändert werden.

    Die statische Liste

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace GameTest
    {
        public class SkillList
        {
            public static List<PassiveFertigkeit> PassiveFertigkeiten = new List<Fertigkeit>
            {
                new PassiveFertigkeit 
                {
                    FertigkeitsName = "GibRüstung",
                    FertigkeitsBeschreibung = "Diese Fertigkeit gibt Rüstung!",
                    RuestungBonus = 50,
                    LebensBonus = 0
                },
                new PassiveFertigkeit 
                {
                    FertigkeitsName = "GibLeben",
                    FertigkeitsBeschreibung = "Diese Fertigkeit gibt Leben!",
                    RuestungBonus = 0,
                    LebensBonus = 50
                }
            }
        }
    }
    

    Die Klasse PassiveFertigkeit

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace GameTest
    {
        public class PassiveFertigkeit
        {
            public string FertigkeitsName {get; set;}
    
            public string FertigkeitsBeschreibung {get; set;}
    
            public int RuestungBonus {get; set;}
    
            public int LebensBonus {get; set;}
    
            public PassiveFertigkeit ()
            {
                FertigkeitsName = string.Empty;
                Fertigkeitsbeschreibung = string.Empty;
                RuestungBonus = 0;
                LebensBonus = 0;
            }
        }
    }
    

    Das Ganze erzeugt eine statische Liste, welche mit zwei Fertigkeiten gefüllt ist. Jetzt kannst du diese Liste direkt abrufen, aber nicht zur laufzeit verändern.

    PassiveFertigkeit fertigkeit = SkillList.PassiveFertigkeiten[0];
    

    So kannst du dann auf die Liste zugreifen.
    Wenn du mehrere verschiedene Fertigkeitstypen haben willst, mach einfach mehrere Listen 😉

    Übrigens habe ich den code direkt hier geschrieben, wenn ich Fehler habe, dann einfach sagen oder ignorieren, ich übernehme keine Garantie :p

    Grüsse
    Chiller



  • Vielen Dank erstmal!
    Genau so eine Möglichkeit habe ich gesucht für die Fähigkeiten, danke. Werde ich die Tage direkt mal testen. 🙂

    Enemy.cs Zeile 66: Der Parameter 1 (m_Name) fehlt.

    Upps 🤡

    Generell würde ich anstatt zweier Klassen "Player" und "Enemy" lieber eine Klasse "Character" sehen. Davon erstellst Du in Main.cs zwei Instanzen, denen Du unterschiedliche Namen, Hitpoints, etc. gibst.

    Das hatte ich ursprünglich auch geplant, nur wusste ich nicht wie ich es lösen kann, dass man einen Spieler steuern kann und der andere "vom PC gesteuert wird" (wenn man es überhaupt so sagen kann :p). Prinzipiell aber würde mir spontan ein Parameter einfallen der einfach bestimmt wer den Spieler steuert, dann hätte ich auch die Möglichkeit mehrere Spieler einzubauen... klingt interessant, werde ich testen!



  • Was mir gerade noch aufgefallen ist: wie kann ich denn diese gesamte Liste durchgehen (oder auch rausfinden wieviele Einträge darin gespeichert sind)? Da ich jetzt eine Character-Klasse gebaut habe, will ich differenzieren zwischen "für den Spieler" und "nicht für Spieler" - sprich bei der Ausgabe der Fähigkeiten für den Spieler sollten nur Fähigkeiten gelistet werden, die nur für den Spieler sind - und umgekehrt natürlich.



  • Hast du schon mal mit der Klasse List<T> gearbeitet?
    Wenn nicht, schau dir mal die Klasse an.
    Es gibt hier auch ein gutes Beispiel wie du diese List verwenden kannst.

    Eine List ist Ähnlich wie ein Array, nur nicht so statisch und hat viel mehr Möglichkeiten. Technisch gesehen kannst du aber für dein Beispiel auch ein Array benutzen, da du es eh statisch machst.
    Ich würde dir aber empfehlen, dass du dennoch die List verwendest, da sie viel mächtiger ist.

    Grüsse
    Chiller


Anmelden zum Antworten