Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 15

Discussione: Finta ereditarietà

  1. #1

    Finta ereditarietà

    Ciao, sto creando un giochino sul poker, ma essendo all'inizio dello studio Java mi accontento di far si che il programma mi crei le carte in mano e quelle a terra. Per chi non conoscesse il texas holdem, il gioco prevede la consegna di 2 carte a ogni giocatore e poi il posizionamento di 3 carte a terra scoperte, seguita da un'altra e poi un'altra ancora. Sto cercando di usare la programmazione ad oggetti quindi ho deciso di creare delle classi. Il fatto è che non si tratta di ereditarietà in quanto le classi non rispondono mai "si" alla domanda "is a?". Posto tutto il codice, chi ha 5 minuti da perdere mi dirà se non c'ho capito niente finora.
    codice:
    import java.util.*;
    
    public class Carta {
        private String carta, seme, cartaCompleta;
        private Random caso=new Random();
        private String [] arrayCarte = new String[13];
        private String [] arraySemi = new String[4];
        
        public Carta()
        {
            for (byte i=0;i<13;i++)
            {
                if (i+1==11)
                    arrayCarte[i]="J";
                else if (i+1==12)
                        arrayCarte[i]="Q";
                else if (i+1==13)
                    arrayCarte[i]="K";
                else if (i+1==1)
                    arrayCarte[i]="A";
                else if (i+1==10)
                    arrayCarte[i]="T";
                else
                    arrayCarte[i]=String.valueOf(i+1);
            }
            arraySemi[0]="h";
            arraySemi[1]="d";
            arraySemi[2]="s";
            arraySemi[3]="c";
        }
        
        public void generaCartaCasuale()
        {
            int caso=this.caso.nextInt(7);
            this.carta=arrayCarte[caso];
            
            caso=this.caso.nextInt(1);
            this.seme=arraySemi[caso];
            cartaCompleta=carta+seme;
        }
        
        public String getCartaCompleta()
        {    return cartaCompleta;    }
    }
    Con questo ho creato la singola carta, tipo Ac per Asso di fiori (c sta per clubs).
    codice:
    public class HoleCards extends Carta{    
        private Carta carta1=new Carta();
        private Carta carta2=new Carta();
        static String carta1Static, carta2Static;
        
        public HoleCards()
        {
            carta1.generaCartaCasuale();
                    
                    while (0<1)
                    {
                        carta2.generaCartaCasuale();
                        
                        if (!carta2.getCartaCompleta().equals(carta1.getCartaCompleta()))
                            break;
                    }
                    carta1Static=carta1.getCartaCompleta();
                    carta2Static=carta2.getCartaCompleta();
        }
        
        public String getCarta1Static()
        {    return carta1Static;    }
        
        public String getCarta2Static()
        {    return carta2Static;    }
        
        public String getCarta1()
        {    return carta1.getCartaCompleta();    }
        
        public String getCarta2()
        {    return carta2.getCartaCompleta();    }
        
        public String getHoleCards()
        {    return carta1.getCartaCompleta()+" "+carta2.getCartaCompleta();    }
        
        public void stampaCarte()
        {    System.out.print(carta1.getCartaCompleta()+" "+carta2.getCartaCompleta());    }
    }
    Adesso ho creato 2 oggetti di tipo Carta per avere 2 carte diverse tra loro.
    codice:
    public class Flop extends HoleCards{
        private Carta carta1Flop=new Carta();
        private Carta carta2Flop=new Carta();
        private Carta carta3Flop=new Carta();
        static String carta1FlopStatic, carta2FlopStatic, carta3FlopStatic;
        
        public Flop()
        {
            while (0<1)
            {
                carta1Flop.generaCartaCasuale();
                if((!carta1Flop.getCartaCompleta().equals(carta1Static))&&(!carta1Flop.getCartaCompleta().equals(carta2Static)))
                        break;
            }
            while (0<1)
            {    
                carta2Flop.generaCartaCasuale();
                    if((!carta2Flop.getCartaCompleta().equals(carta1Static))&&(!carta2Flop.getCartaCompleta().equals(carta2Static))&&
                            (!carta2Flop.getCartaCompleta().equals(carta1Flop.getCartaCompleta())))
                            break;
            }
            while (0<1)
            {
                carta3Flop.generaCartaCasuale();
                    if((!carta3Flop.getCartaCompleta().equals(carta1Static))&&(!carta3Flop.getCartaCompleta().equals(carta2Static))&&
                            (!carta3Flop.getCartaCompleta().equals(carta1Flop.getCartaCompleta()))&&(!carta3Flop.getCartaCompleta().equals(carta2Flop.getCartaCompleta())))
                            break;
            }
            carta1FlopStatic=carta1Flop.getCartaCompleta();
            carta2FlopStatic=carta2Flop.getCartaCompleta();
            carta3FlopStatic=carta3Flop.getCartaCompleta();
        }
        
        public void stampaCarte()
        {
            super.stampaCarte();
            System.out.print(" --- "+carta1Flop.getCartaCompleta()+" "+carta2Flop.getCartaCompleta()+" "+carta3Flop.getCartaCompleta());
        }
    }
    Con questa creo le 3 carte a terra e per far si che siano diverse dalle carte in mano ho usato le variabili statiche in cui ci sono segnate le carte create prima (anche se non serviva farle static visto che non vengono più modificate).

    Ho fatto poi altre 2 classi, Turn e River che fanno in pratica quello che fa Flop.

    Alcune domande:
    è giusto forzare così l'ereditarietà per poter avere un ordine? in pratica sto ricreando la programmazione strutturata, ogni classe ne eredita un'altra.
    Ho notato che mi basta creare solo un oggetto della classe nata per ultima per avere tutto. Qua abbiamo, super classe, poi figlia, nipote, e così via, quindi se creo un oggetto dell'ultima automaticamente sto creando l'istanza di tutte le altre? Ho pensato che dipende semplicemente dal fatto che automaticamente eredito il costruttore vuoto (l'unico che ho) della classe madre, giusto?
    Ultima modifica di gennysennin; 18-03-2016 a 22:03

  2. #2
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Ciao, finché aspetti la risposta di un utente più esperto di me provo a risponderti io

    Quote Originariamente inviata da gennysennin Visualizza il messaggio
    ...quindi se creo un oggetto dell'ultima automaticamente sto creando l'istanza di tutte le altre? Ho pensato che dipende semplicemente dal fatto che automaticamente eredito il costruttore vuoto (l'unico che ho) della classe madre, giusto?
    Sì,creando un oggetto di una classe figlia viene automaticamente richiamato il costruttore della classe madre, se il costruttore della madre è vuoto puoi anche evitare di richiamarlo (con l'istruzione "super();") , ma se ad esempio la classe Carta avesse come unico costruttore un Carta(char seme,char valore) riceveresti un errore in compilazione nel costruttore di HoleCards, perché a quel punto si aspetta una chiamata a un super(char,char) che non può essere fatta in automatico.

    Però ti faccio una considerazione più generale sul design delle classi che hai scelto: perché ti stai complicando la vita in questo modo?

    Quote Originariamente inviata da gennysennin Visualizza il messaggio

    Con questa creo le 3 carte a terra e per far si che siano diverse dalle carte in mano ho usato le variabili statiche in cui ci sono segnate le carte create prima (anche se non serviva farle static visto che non vengono più modificate).
    Una considerazione di questo tipo non ha alcun senso! Se il mazzo è di 52 carte ti basta creare 52 oggetti di tipo Carta, in un ciclo creato appositamente per alternare i 13 valori e i 4 semi per non avere duplicati (tra l'altro la cosa è davvero banale).

    Quando ti sei memorizzato le 52 carte, anche in un banale array, sei a posto, non c'è bisogno di creare Carte sul momento e controllare che non siano uguali a quelle precedenti (tra l'altro gli if all'interno della classe Flop, con quelle variabili statiche sono davvero orripilanti)

    La classe Carta dovrebbe essere la tua entità di base, e avere solo le variabili relative alla singola carta, come il seme e il valore, dell'array di semi e di valori, e soprattutto del Random, non se ne fa davvero nulla.
    Prova quindi a creare le varie carte all'esterno, poi il Random lo utilizzerai per pescare casualmente le varie carte, ma in una classe esterna, che abbia le varie carte salvate !

  3. #3
    mi sto complicando la vita perchè ancora non ho ben chiaro come usare le classi, ho capito come funzionano nella teoria, ma non so come sfruttarle nella pratica, e tutte queste classi che partono dal trisavolo e arrivano ai pronipoti non piaceva neanche a me, ma sinceramente sono ancora nella fase "che ci faccio con queste classi"?

  4. #4
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Tranquillo, all'inizio è normale non avere ben chiaro quante e quali classi creare, farai esperienza programmando

    Nel tuo caso la catena di classi ereditarie che hai creato non ha senso dal punto di vista logico, a partire dal fatto che un insieme di carte come il Flop o HoleCards non possono essere un'estensione di una singola carta!

    Quello che potresti fare ad esempio è avere una classe FlopCard che estende Carta, ereditando correttamente le variabili come carta e seme (che pero' non vengono ereditate se dichiarate private in Carta) e i metodi, e aggiungendo ad esempio una variabile che indica la posizione della carta nelle tre possibili all'interno del flop.

    Ma è veramente utile? Io direi che serve a ben poco in realtà...Se il tuo non era un esercizio per provare l'ereditarietà per ora lascerei perdere.

    Anche avere una classe che modelli Flop, Turn e River non lo vedo di una grande utilità, sono solo insiemi di carte o una singola carta in fin dei conti, mentre ha senso creare una classe Giocatore che abbia come variabili due oggetti di tipo Carta (o un array di due carte o simili) e altre informazioni che aggiungerai in seguito come lo stack (quantità di fiches), il nome o quello che vuoi.
    Potresti creare una classe Mazzo, ma questo dipende dal design che vuoi adottare : potresti decidere di considerarlo solo un array di Carte, o invece una vera e propria classe con anche metodi tipo mescolaMazzo() etc.

    Intanto potresti mantenere solo la classe Carta (togliendo le informazioni non relative alla singola carta come ti dicevo prima) e avere una classe di prova dove crei le 52 carte, le salvi in un array chiamato mazzo o in oggetto di tipo Mazzo, le mescoli in modo casuale...

  5. #5
    ciao, in effetti dopo i consigli che mi hai dato prima ho cercato di ricreare il tutto e in effetti mi ritrovo con quello che mi hai scritto dopo, ecco cosa ho fatto:
    codice:
    public class Carta {    public char [] arrayCarte = new char[13];
        public char [] arraySemi = new char[4];
        public char valore, seme;
        
        public Carta()
        {
            for (byte i=0;i<13;i++)
            {
                if (i+1==11)
                    arrayCarte[i]='J';
                else if (i+1==12)
                        arrayCarte[i]='Q';
                else if (i+1==13)
                    arrayCarte[i]='K';
                else if (i+1==1)
                    arrayCarte[i]='A';
                else if (i+1==10)
                    arrayCarte[i]='T';
                else
                {
                    String temp=Integer.toString(i+1);
                    arrayCarte[i]=temp.charAt(0);
                }
            }
            arraySemi[0]='h';
            arraySemi[1]='d';
            arraySemi[2]='s';
            arraySemi[3]='c';
        }
    }
    Qua ho creato gli array e con la classe dopo creo il mazzo di carte
    codice:
    public class MazzoCarte extends Carta{    public Carta[] mazzo=new Carta[52];
        
        public MazzoCarte()
        {
            for (byte i=0;i<52;i++)
            {
                mazzo[i]=new Carta();
                if (i<13)
                {
                    mazzo[i].valore=arrayCarte[i];
                    mazzo[i].seme=arraySemi[0];
                }
                else if (i>=13 && i<26)
                {
                    mazzo[i].valore=arrayCarte[i-13];
                    mazzo[i].seme=arraySemi[1];
                }
                else if (i>=26 && i<39)
                {
                    mazzo[i].valore=arrayCarte[i-26];
                    mazzo[i].seme=arraySemi[2];
                }
                else
                {
                    mazzo[i].valore=arrayCarte[i-39];
                    mazzo[i].seme=arraySemi[3];
                }
            }
        }
    Ho trovato però 2 problemi:
    1. sono stato costretto a creare array pubblici perchè non sono riuscito a capire come usare il get con essi (ho provato con il ciclo ma non ci sono riuscito)
    2. con "String temp=Integer.toString(i+1); arrayCarte[i]=temp.charAt(0);"
    non sono riuscito ad avere lo stesso risultato lavorando con il char, ho dovuto trasformare l'intero in Stringa e poi estrarlo da essa per avere il char che preferisco perchè occupa meno memoria, ieri con il codice orrendo che avevo scritto eclipse si stava succhiando 700 mb di ram, una cosa del genere in un telefono sarebbe da brividi.
    Ultima modifica di gennysennin; 19-03-2016 a 15:50

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da gennysennin Visualizza il messaggio
    mi sto complicando la vita perchè ancora non ho ben chiaro come usare le classi, ho capito come funzionano nella teoria [...] sono ancora nella fase "che ci faccio con queste classi"?
    Se i dubbi sono ancora a questo livello, personalmente ti suggerisco di accantonare per un pochino i giochi (che siano carte o altro) e di fare qualche "esercizio" in più che metta bene in evidenza i concetti di ereditarietà/polimorfismo, override e quant'altro.

    Ce ne sono tanti che puoi fare, uno utile e abbastanza "classico": gerarchia di classi per rappresentare oggetti solidi, quindi classe base Solido e sottoclassi es. Sfera, Cubo, ecc.. con la possibilità di determinare in modo "polimorfico" superficie e volume. Magari gli oggetti possono essere "tirati su" da un file anche testuale.
    Ma ce ne sono decine di altri fattibili.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Se i dubbi sono ancora a questo livello, personalmente ti suggerisco di accantonare per un pochino i giochi (che siano carte o altro) e di fare qualche "esercizio" in più che metta bene in evidenza i concetti di ereditarietà/polimorfismo, override e quant'altro.

    Ce ne sono tanti che puoi fare, uno utile e abbastanza "classico": gerarchia di classi per rappresentare oggetti solidi, quindi classe base Solido e sottoclassi es. Sfera, Cubo, ecc.. con la possibilità di determinare in modo "polimorfico" superficie e volume. Magari gli oggetti possono essere "tirati su" da un file anche testuale.
    Ma ce ne sono decine di altri fattibili.
    In realtà questi esercizi li sto facendo, tipo quello delle figure, oppure Persona -> Dipendente e così via, se li trovo so risolverli, il problema è quando devo essere io a decidere come iniziare a usare le classi per un qualcosa che voglio fare, tipo questo gioco, con c# (senza però usare le classi, feci tutto nel main) l'ho fatto, è l'utilizzo delle classi che mi dà problemi. Tpo ora, so benissimo che la classe MazzoCarte non è in realtà giusta come sottoclasse in quanto un MazzoDiCarte NON è una Carta, però mi ritroverei a fare tutto in una sola classe poi.
    Ultima modifica di gennysennin; 19-03-2016 a 16:27

  8. #8
    Per la lettura da file ancora non ci sono arrivato.

  9. #9
    Utente di HTML.it
    Registrato dal
    Oct 2014
    residenza
    Padova
    Messaggi
    361
    Prima di tutto devo dire che concordo con andbin sul fatto che un gioco potrebbe essere un po' troppo complicato per ora (fra l'altro tra i vari giochi di carte il poker non è certo il più semplice), se vuoi continuare su questa strada è facile che ti bloccherai spesso per dubbi più elementari ...


    Quote Originariamente inviata da gennysennin Visualizza il messaggio
    Tpo ora, so benissimo che la classe MazzoCarte non è in realtà giusta come sottoclasse in quanto un MazzoDiCarte NON è una Carta, però mi ritroverei a fare tutto in una sola classe poi.

    Bene che hai capito che MazzoCarte NON deve estendere Carta, ma non è assolutamente vero che poi devi fare tutto in una sola classe !
    Puoi usare tutte le classi che vuoi, non c'è alcun bisogno di usare l'ereditarietà per collegare le classi tra di loro, lo puoi/dovresti fare solo in alcune circostanze, e per ora non ce n'è alcun bisogno!


    Per quanto riguarda la classe Carta: ok, hai tolto alcune cose inutili, ma ce ne sono ancora tante altre! Ricorda che una classe dovrebbe rappresentare il più fedelmente possibile ciò che vuoi modellare, nel tuo caso per ora una carta è solo un oggetto con un certo seme e un certo valore (poi aggiungerai altro magari). Quindi non deve assolutamente conoscere il valore di tutte le carte (arrayCarte) e di tutti i semi (arraySemi), queste informazioni le userai in una classe a parte !


    Il costruttore della classe Carta non deve avere quel ciclo all'interno, è opportuno passare alla carta solo il proprio seme e il proprio valore, quindi un buon modo per scrivere la classe Carta per ora potrebbe essere questo:


    codice:
    public class Carta
    {  
        private char valore,seme;
        public Carta(char s,char v)
        {
            seme=s;
            valore=v;
        }
        public char getSeme()
        {
            return seme;
        }
        public char getValore()
        {
            return valore;
        }
        // Override del metodo toString
        public String toString()
        {
            return valore+seme;
        }
    }

    Va benissimo mantenere valore e seme campi privati e accedervi con i metodi get, semplicemente dovrai ripensare la cosa qualora volessi estendere la classe Carta, cosa che per ora NON devi fare


    Poi crei una classe esterna, lascia stare per ora una classe per il Mazzo (ci ripenserai in seguito se serve), crei ad esempio una classe TestMazzo e all'interno inizializzi e riempi un array di 52 carte in questo modo:


    codice:
    public class TestMazzo
    {
        char[] arrayCarte=new char[13],arraySemi=new char[4];
        Carta[] mazzo=new Carta[52];
        public TestMazzo()
        {
            arrayCarte=new char[]{'2','3','4','5','6','7','8','9','T','J','Q','K','A'};
            arraySemi=new char[]{'h','d','s','c'};
            // Una semplice riga per creare il mazzo
            for(int i=0;i<13;i++)for(int j=0;j<4;j++)mazzo[4*i+j]=new Carta(arrayCarte[i],arraySemi[j]);
            // Stampi a video il mazzo
            for(int i=0;i<52;i++)System.out.print(mazzo[i]+" ");
        }
        public static void main(String[] a)
        {
            new TestMazzo();
        }
    }

    Prova a compilare ed eseguire TestMazzo e vedrai che così crei le 52 carte richieste.
    Non è molto più semplice di quanto stavi provando a fare?
    Ultima modifica di Ansharja; 19-03-2016 a 17:41

  10. #10
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da gennysennin Visualizza il messaggio
    Tpo ora, so benissimo che la classe MazzoCarte non è in realtà giusta come sottoclasse in quanto un MazzoDiCarte NON è una Carta
    Appunto, la ereditarietà serve per definire una relazione di generalizzazione-specializzazione tra due classi. Cioè la sottoclasse deve rappresentare una entità che è un "caso particolare" rispetto alla entità rappresentata dalla superclasse ma può comunque sempre essere vista anche come la entità superiore (un String è anche un Object). Devi quindi sempre valutare e verificare che a livello concettuale rispetti il principio "è-un" (IS-A).

    Casi che sono sensati ed appropriati e vanno bene:
    - un Gatto è-un Animale (ed es. GattoPersiano è-un Gatto)
    - una Sfera è-un Solido
    - una Auto è-un Veicolo (ed es. una Ferrari è-una Auto)

    Mentre invece:
    - un MazzoDiCarte NON è una Carta
    - un Punto3D NON è un Punto2D
    - un ContoCorrente NON è una Banca e nemmeno il contrario (ti sembrerà strano ma c'è stata gente che ha tentato questo!)
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.