Diskuze: Co dělám špatně??

C# .NET .NET (C# a Visual Basic) Co dělám špatně?? American English version English version

Avatar
Kafac
Člen
Avatar
Kafac:

Ahoj,zkouším udělat hru je sice jenom na začátku vývoje,ale mám tam chybu ve výstupu,píše mi to že hráč Baltazar zaútočil na protivníka..... a takhle pořád dokola,to mám kvůli cyklu,ale druhého bojovníka mi to nevypíše.Bez cyklu mi to vypíše i druhého bojovníka.Něco tam mám určitě špatně a určitě vím,že tam bude dost asi začátečnických chyb,tak budu i rád,když mě klidně zkritizujete pomluvíte atd.Budu jen rád.Programuju rok,ale toto je múj největši OOP program co jsem dělal,tak se rád poučím a vyvaruju,některým chybám : class Program :

class Program
{
    static void Main(string[] args)
    {
        Warrior orc = new Warrior("Baltazar",100,25,50);
        Mage elf = new Mage("Blood",50,150,20);

        orc.Attack(elf);
        elf.Attack(orc);

        Console.ReadKey();
    }
}

class Warrior :

class Warrior
   {
       protected string name;
       protected int live;
       protected int damage;
       protected int defense;

       public Warrior(string name,int live,int damage,int defense)
       {
           this.name = name;
           this.live = live;
           this.damage = damage;
       }
       public bool Alive()
       {
           if (live > 0)
               return true;
           else
               return false;
       }
       public  void Attack(Warrior rival)
       {
           while (live > 0)
           {
               damage = damage - rival.defense;

               damage = rival.live - this.damage - rival.defense;

               Console.WriteLine("Hráč {0}, zaútočil na protivníka {1} a způsobil mu škodu za  {2} hp", this.name, rival.name, damage);
           }
           if ((live == 0) || (live < 0))
           {
             Console.WriteLine("Nemůžete provádět dál útok,máte příliš málo života");

           }

           }
       }

class Mage:

class Mage:Warrior
   {


       public Mage(string jmeno,int zivot,int damage,int obrana):base (jmeno,zivot,damage,obrana)
       {

       }

   }
Odpovědět 3.2.2015 21:34
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na Kafac
Jan Vargovský:

Davas dmg a neubiras hp.

 
Nahoru Odpovědět 3.2.2015 22:27
Avatar
Ziki
Redaktor
Avatar
Odpovídá na Kafac
Ziki:

Ono celej ten způsob vyřešení útoku se mi zdá špatnej, ty při každým volání funkce Attack() snížíš jeho damage (takže po několika voláních může být i záporný :D). a ten další řádek pod tím mi taky nepřijde správně a jak už pako poznamenal, nikde se nesnižuje hp.

druhého bojovníka ti to nevypíše, protože celej ten while cyklus (ten s live > 0) se provede v rámci jednoho volání orc.Attack(elf). a protože se hodnota proměnné live nemění tak se ti to nekonečně zacyklí.

Nahoru Odpovědět 4.2.2015 0:10
Ve vědění je síla.
Avatar
Kafac
Člen
Avatar
Odpovídá na Ziki
Kafac:

Teď jsem si toho taky trochu všiml, dělal jsem to narychlo večer, ten útok zkusím dneska po škole upravit. Je tam ještě něco co se někomu nelíbí, nechci si navyknout na špatný návyky.

Nahoru Odpovědět 4.2.2015 7:55
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Odpovídá na Kafac
sadlomaslox25:

mel by sis udelat zakladni abstraktni tridy pro objekty, o kterych vis ze maji stejny zaklad ale lisi se zpusobem jak budou pracovat.

napr. mas ruzne druhy nepratel, kteri maji ruzne aury a ruzne druhy utoku, tak is udelas CreepBase a od toho budou dedit ostatni nepratele. To same treba pro pro hrace. Udelas PlayerBase a toho odvodis Warrior,Mage .... Vyhoda je ze pak v kodu misto:
public void Attack(Warrior rival)
public void Attack(Mage rival)
public void Attack(Paladin rival)

mas jednotnou metodu
public void Attack(PlayerBase rival) nebo public void Attack(CreepBase rival)

(zalezi jak slozita ta hra bude)

 
Nahoru Odpovědět 4.2.2015 10:59
Avatar
Kafac
Člen
Avatar
Odpovídá na sadlomaslox25
Kafac:

Přesně nad tím jsem taky přemýšlel,jestli udělat abstraktní třídu a z toho zdědit Mága a Bojovníka.Nakonec jsem to udělal takhle,jelikož jsem si říkal,že mágovi nebudu dávat manu a nepotřeboval by nic navíc oproti válečníkovi,kdyby jo,tak bych to kdyžtak udělal s polymorfismem a v mágovi bych to přepsal ten Attack,ale asi s tou abstraktní třídou to bude lepší.Určitě to zkusím :).

Nahoru Odpovědět 4.2.2015 16:04
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Kafac
Člen
Avatar
Odpovídá na sadlomaslox25
Kafac:

abstraktní třída:

class PlayerBase
    {
        protected string name;
        protected int life;
        protected int damage;
        protected int defense;

        public PlayerBase(string name,int life,int damage,int defense)
        {
            this.name = name;
            this.life = life;
            this.damage = damage;
            this.defense = defense;
        }
        public void Attack(PlayerBase rival)
        {
            rival.life = rival.life + rival.defense;
            damage = rival.life - this.damage;

            Console.WriteLine("Hráč {0} zaútočil na hráče {1} a sebral mu životy za {2} hp",this.name,rival.name,damage);
        }
    }

Warrior :

class Warrior:PlayerBase
    {
        public Warrior(string name,int life,int damage,int defense):base (name,life,damage,defense)
        {

        }
    }

Mage :

class Mage:PlayerBase
    {
        public Mage(string name,int life,int damage,int defense):base (name,life,damage,defense)
        {

        }
    }

a Program :

{
    Warrior orc = new Warrior("Baltazar",100,25,50);
    Mage shadow = new Mage("Blood",50,80,10);

    orc.Attack(shadow);
    shadow.Attack(orc);

    Console.ReadKey();
}

už to v pohodě útočí,bere i druhý hráč,zkusím tam dát ještě ten cyklus,+ při 0 hp se přestane bojovat :)

Nahoru Odpovědět 4.2.2015 22:15
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Odpovídá na Kafac
sadlomaslox25:

no tak zrovna v tomhle pripade by mela byt metoda bud metoda Attack virtualni a z podedenych tridach by se mela upravit protoze warrior asi utoci jinak nez mage :). pripadne udelat par protected metod jako OnAttack a CalculateDamage a Attack bych prepsal na neco jako

public void Attack(PlayerBase rival)
{
if(rival.OnAt­tack(this))
{ int damage=Calcula­teDamage(); rival.TakeDama­ge(damage); this.DoDamage(da­mage); }

else
//nemuze utocit, (miss,dodge,pa­rry,aura...)

 
Nahoru Odpovědět  +1 5.2.2015 7:48
Avatar
Kafac
Člen
Avatar
Odpovídá na sadlomaslox25
Kafac:

Samozřejmě to udělám,taky,ale zatím mi stačí to mít u mága a bojovníka stejný.Časem tam chci přidat i věci,tak potom tam použiju ten polymorfismus a zkusím to nějak vylepšit.Ale díky za radu,až se dostanu ze školy domů,kdyžtak to zkusím napsat a ukázat ti to jestli to dělám správně.

Nahoru Odpovědět 5.2.2015 13:22
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Kafac
Člen
Avatar
Kafac:

Promiň,že píšu asi tak špatný kód,ale jak říkám je to můj první projekt.Byl bych rád,kdyby si měl někdy náhodou čas a chtěl mi pomoci jestli by si mi ten kód upravit,tak aby byl správně.Chtěl bych se podívat co jsem udělal špatně a porovnat to.Ono se i říká,že z těhle prográmku se naučíš nejvíc a já bych rád příště neopakoval chyby:
Program.cs :

class Program
    {
        static void Main(string[] args)
        {
            Warrior orc = new Warrior("Strong",500,100,150,50);
            Mage elf = new Mage("Shadow",500,150,100,80);

            orc.Attack(elf);
            elf.Attack(orc);

            Console.ReadKey();
        }

PlayerBase :

class PlayerBase
   {
       protected string name;
       protected int life;
       protected int damage;
       protected int defense;
       protected int writeDMG;

       public PlayerBase(string name,int life,int damage,int defense)
       {
           this.name = name;
           this.life = life;
           this.damage = damage;
           this.defense = defense;
       }
       public virtual void Attack(PlayerBase rival)
       {
           rival.life = rival.life + rival.defense;
           damage = rival.life - this.damage;
           Console.WriteLine("Hráč {0} zaútočil na hráče {1} a sebral mu životy za {2} hp", this.name, rival.name, damage);

       }

Mage:

class Mage:PlayerBase
   {
       private int magicStrike;
       Staff staff;

       public Mage(string name,int life,int damage,int defense,int magicStrike):base (name,life,damage,defense)
       {
           this.magicStrike = magicStrike;
       }
       public override void Attack(PlayerBase rival)
       {
           magicStrike = this.magicStrike + staff.magicAT + this.damage;
           writeDMG = life - this.magicStrike;

           Console.WriteLine("Hráč {0} zaútočil na hráče {1} a sebral mu životy za {2} hp", this.name, name, writeDMG);

       }

Warrior:

class Warrior:PlayerBase
   {
       private int strike;

       public Warrior(string name,int life,int damage,int defense,int strike):base (name,life,damage,defense)
       {
           this.strike = strike;
       }
       public override void Attack(PlayerBase rival)
       {
           strike = this.strike + this.damage;
            writeDMG = life - this.strike;

           Console.WriteLine("Hráč {0} zaútočil na hráče {1} a sebral mu životy za {2} hp",this.name,name,writeDMG);
       }

Staff :

public class Staff
   {
       public int magicAT;

       public Staff(int magicAT)
       {
           this.magicAT = magicAT;
       }
Nahoru Odpovědět 9.2.2015 19:21
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Kafac
Člen
Avatar
Odpovídá na Kafac
Kafac:

Nedělal jsem tam item pro warriora,takže to tam chybí.

Nahoru Odpovědět 9.2.2015 19:58
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
hanpari
Redaktor
Avatar
Odpovídá na Kafac
hanpari:

První věc, kterou bych na tvém místě nedělal, je toto:

Console.WriteLine("Hráč {0} zaútočil na hráče {1} a sebral mu životy za {2} hp",this.name,name,writeDMG)

Místo toho vrať hodnotu(ideální varianta) nebo si alespon udelej jednoduchou třídu render, přes kterou budeš vypisovat. To má tu výhodu, že ti stačí změnit kód na jednom místě, kdežto teď musíš vyeditovat všechna místa v kódu, kde máš Console.WriteLine. Což je opravdu špatně :)

Zkus zauvažovat nad tím, že bys svou hru dodělal a pak chtěl místo textového výstupu grafický. Anebo jen jiné formátování. Kolik změn by to pro tebe znamenalo?

Další věc, kterou bych ti doporučil, je konsistentní řádkování. A hlavně maximálně cca 60-70 znaků na řádek. Řádky přes celý monitor opravdu nejsou pravé ořechové, nehledě na známou skutečnost, že dlouhé řádky se špatně čtou.

 
Nahoru Odpovědět  +1 9.2.2015 20:00
Avatar
Kafac
Člen
Avatar
Odpovídá na hanpari
Kafac:

Ty myslíš to s tím

public override string ToString()

jo a když se snažím spustit program vypíše mi to : NullReference­Exception was unhandled a zastaví se mi u jednoho řádku taková šipka u tohoto řádku :

magicStrike = this.magicStrike + staff.magicAT + this.damage;
Nahoru Odpovědět 9.2.2015 20:06
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Kafac
Člen
Avatar
Odpovídá na hanpari
Kafac:

Ale jinak jsem rád,že si mi poradil,aspoň to příště neudělám.

Nahoru Odpovědět 9.2.2015 20:08
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na Kafac
Jan Vargovský:

staff nikde neinicializuješ, takže je defaultně null.

 
Nahoru Odpovědět 9.2.2015 20:08
Avatar
Kafac
Člen
Avatar
Odpovídá na hanpari
Kafac:

Jo a jak mám abstraktní třídu PlayerBase a pak metodu Attack přepišuju u Mage a Warrior,tak jak to mám udělat,aby to vypsalo jméno druhého bojovníka.Mohl jsem tam dát třeba rival.name jen když jsem měl

public void Attack(Warrior rival

,ale já tam mám

public void Attack(PlayerBase rival)

a to mi jde jen name,nemůžu dát třeba rival.name.

Možná,že ti přijdou tyto moje chyby takový začátečnický,nebo divný,ale zatím jsem to moc nepoužíval jen u nějakých lehkých prográmků.

Nahoru Odpovědět 9.2.2015 20:12
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Kafac
Člen
Avatar
Odpovídá na Jan Vargovský
Kafac:

A jo teď jsem si toho všiml :-).Ale i když jsem to tam dal,tak mi to stejně vypisuje to stejný.

Nahoru Odpovědět 9.2.2015 20:14
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na Kafac
Jan Vargovský:

Tak se to chce zamyslet nad modifikátorem přístupu (např. udělat getter).

 
Nahoru Odpovědět 9.2.2015 20:14
Avatar
Kafac
Člen
Avatar
Odpovídá na Jan Vargovský
Kafac:

Ty gettery a settery se budu učit teprv teď,teď jsem akorát u statiky (toje kapitola před tím) :D.Ale podívám se teda na to.

Nahoru Odpovědět 9.2.2015 20:16
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
hanpari
Redaktor
Avatar
Odpovídá na Kafac
hanpari:

Ne, to nemyslím. To je něco jiného.

 
Nahoru Odpovědět 9.2.2015 20:26
Avatar
Kafac
Člen
Avatar
Nahoru Odpovědět 9.2.2015 20:37
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Kafac
Člen
Avatar
Kafac:

Rád bych někoho požádal,jestli by přepsal aspoň 1 třídu,abych viděl jak to vypadá normálně,aby to bylo aspoň trochu k světu.A já podle toho mohl psát dál a dobře si navykl.

Nahoru Odpovědět 9.2.2015 20:39
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Odpovídá na Kafac
sadlomaslox25:

toho rival.name muzes dosahnout treba tak jak sem psal ve svem poslednim prispevku. obecne se tento postup jmenuje NVI (non virtual interface, nebo take zname jako template method). funguje tak ze ze napr. metoda attack NENI virtualni a nejde overidovat. avsak v jejim tele nekde volas metodu attackCore a ta attack core se overiduje a v ni se pocita/dela to dulezite.

 
Nahoru Odpovědět 9.2.2015 20:46
Avatar
Odpovídá na Kafac
sadlomaslox25:

"Rád bych někoho požádal,jestli by přepsal aspoň 1 třídu"
no ty chyby se musi pochopit a nejlip je pochopis tak ze je udelas abys pak vedel proc je nemas delat :D

 
Nahoru Odpovědět 9.2.2015 20:48
Avatar
hanpari
Redaktor
Avatar
Odpovídá na Kafac
hanpari:

Já bych ti doporučil, aby ses nebál dělat chyby.
Protože z vlastních chyb se člověk učí nejlíp.
Když budeš kopírovat cizí věci, nikdy nepochopíš, oč skutečně jde.
Žádný perfektní kód neexistuje.
Nepoužívej vlastnost jazyka jen proto, že ji použil někdo jiný. Použij ji až tehdy, kdy pochopíš, že přináší výhodu. Popřípadě ji nepoužívej vůbec, pokud ji nepotřebuješ.

Programátoři jsou tlupa výjimečných. Proto si vymysleli výraz refaktorovat. Všichni ostatní ovšem svá díla předělávají nebo přepisují. Ale ty se neboj refaktorovat, budeš výjimečný.

 
Nahoru Odpovědět  +1 9.2.2015 20:56
Avatar
Kafac
Člen
Avatar
Odpovídá na hanpari
Kafac:

Tak jo pokusím se o to to opravit a najít ještě nějaký chyby :).Až to dodělám budu mít i lepší pocit,že jsem to zvládl sám ;).

Nahoru Odpovědět  +1 9.2.2015 21:12
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Kafac
Člen
Avatar
Odpovídá na hanpari
Kafac:

Zatím jsem nic neupravoval,ale zkusil jsem to takhle a útok proběhl bez chyby: PlayerBase:

public class PlayerBase
    {
        public string name;
        public int life;
        public int damage;
        public int defense;

        public PlayerBase(string name,int life,int damage,int defense)
        {
            this.name = name;
            this.life = life;
            this.damage = damage;
            this.defense = defense;
        }
        public void Attack(PlayerBase rival)
        {
            rival.life = rival.life + rival.defense;
            damage = rival.life - this.damage;

            Console.WriteLine("Hráč {0} zaútočil na hráče {1} a sebral mu životy za {2} hp",this.name,rival.name,damage);
        }

Warrior:

class Warrior:PlayerBase
    {

        public Warrior(string name,int life,int damage,int defense):base (name,life,damage,defense)
        {

        }

Mage :

class Mage:PlayerBase
    {
        public Mage(string name,int life,int damage,int defense):base (name,life,damage,defense)
        {

        }

IronArmor :

class IronArmor
   {
       public bool Iarmor;
       private int defense = 25;

       public void IArmorWearing(PlayerBase user)
       {
           if (Iarmor == true)
           {
               user.defense = user.defense + this.defense;
           }
           else
           {
               defense = user.defense;
           }
       }

Program.cs :

class Program
    {
        static void Main(string[] args)
        {
            Warrior orc = new Warrior("Star",250,80,120);
            Mage elf = new Mage("Shadow",150,130,70);
            IronArmor iron = new IronArmor();

            iron.IArmorWearing(orc);

            orc.Attack(elf);
            elf.Attack(orc);

            Console.ReadKey();

        }

Budu rád za všechnu kritiku :-).

Nahoru Odpovědět 10.2.2015 20:53
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na Kafac
Jan Vargovský:

Tvoje zděděné třídy jsou momentálně k ničemu. Kdyby tohle mělo být finále, tak bych radši udělal něco takového:

public class Player
{
    public string name;
    public int life;
    public int damage;
    public int defense;
    public void Attack(Player rival)
    {
        rival.life = rival.life + rival.defense;
        damage = rival.life - this.damage;

        Console.WriteLine("Hráč {0} zaútočil na hráče {1} a sebral mu životy za {2} hp", this.name, rival.name, damage);
    }
}

a pak můžeš vytvářet instanci takto:

Player warrior = new Player { damage = 20, life = 100, defense = 10, name = "Garrosh"};

Jednotlivé třídy, které reprezentují zbraně, různé výzbroje apod. bych si nechal jako instance uvnitř třídy. pak by měla dědičnost nějaký smysl, protože warrior bude asi nosit jiné věci než mage.

 
Nahoru Odpovědět 10.2.2015 21:05
Avatar
Kafac
Člen
Avatar
Odpovídá na Jan Vargovský
Kafac:

Děkuji,tohle ještě určitě není finální,taky jsem si všiml,že to je k ničemu,ale jestli tam ještě něco přidám (chci tam přidat mágovi magickou útok a manu a válečníkovi něco s útokem),tak se to bude hodit.Ale zatím to můžu takhle předělat,jelikož teď asi nebudu mít moc času,tak aby to tam zbytečně nebylo.

Ještě nějaká kritika nebo rada? :)

Nahoru Odpovědět 10.2.2015 21:12
"Lepší, než předpovídat budoucnost, je vytvořit ji." Bill Gates
Avatar
hanpari
Redaktor
Avatar
Odpovídá na Kafac
hanpari:

Pisu z mobilu takze se omlouvam. zajimalo by mne jak bys udelal tridu Monstrum, aniz bys dedil z base player. Dale jak bys poresil ruzne druhy brneni. A posledni IArmorWearing - to mel byt pokus o interface?

 
Nahoru Odpovědět 11.2.2015 7:44
Avatar
Jiří Gracík
Redaktor
Avatar
Odpovídá na hanpari
Jiří Gracík:

To bude asi od IronArmor.

Nahoru Odpovědět  +1 11.2.2015 7:50
Creating websites is awesome till you see the result in another browser ...
Avatar
hanpari
Redaktor
Avatar
Avatar
Jiří Gracík
Redaktor
Avatar
Odpovídá na hanpari
Jiří Gracík:

Taky jsem si ale nejdřív říkal, že takhle interface nefunguje :D

Nahoru Odpovědět  +1 11.2.2015 9:38
Creating websites is awesome till you see the result in another browser ...
Avatar
hanpari
Redaktor
Avatar
Odpovídá na Kafac
hanpari:

Mimochodem takhle muzes prepisovat do nekonecna. Co si napred ujasnit, ceho chces dosahnout.

 
Nahoru Odpovědět 11.2.2015 16:55
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 34 zpráv z 34.