Rechnen mit enums



  • Um die neuen Sprachfeatures von Java 1.5 mal auszuprobieren, hab ich mal angefangen, mein nie fertiggestelltes Poker-Projekt zu portieren. Das erste, was rausgeflogen ist, sind die Konstanten für die Werte der Karten:

    public static final int TWO = 0;
        public static final int THREE = 0;
    [...]
    

    Statt dessen hab ich jetzt

    public enum Suite { DIAMONDS, HEARTS, SPADES, CLUBS }
        public enum Rank { TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE }
    

    Problem: Wenn ich jetzt prüfen will, ob ein Spieler eine Strasse besitzt, brauch ich ja irgendwie den nächsthöheren Wert. Irgendwie erhalte ich den Eindruck, das geht mit enums nicht vernünftig - oder doch? Aktuelle Idee ist, den Wert mit einem Iterator zu suchen, und dann noch einen Schritt weiter zu gehen - aber das ist ja unschön hoch drei. Andere Vorschläge?



  • http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html

    Lies mal ab: "Suppose you want to add data and behavior"

    Bye, TGGC (Pipe my World.)



  • LOL. Da mach ich mir die ganze Arbeit und die Leute von Sun benutzen genau das als Beispiel... Aber: Mein Problem lösen tut das ganze leider nicht :(. Klar kann ich sowas machen:

    public enum Rank {
      TWO (THREE),
      THREE (FOUR),
    [...]
      private final Rank next;
      Rank(Rank next) {this.next = next;}
      Rank getNext() {return next;}
    }
    

    Nur: dann muss ich ja alle Karten doppelt aufzählen. Irgendwie auch nicht so schön...

    <edit>Code-Tags repariert...</edit>



  • a) das würde dein Problem ja doch lesen.
    b) Du kannst auch wie früher wieder Zahlen hinschreiben

    Bye, TGGC (Pipe my World.)



  • TGGC schrieb:

    a) das würde dein Problem ja doch lesen.

    Nein, das Problem ist "schöner Code". Beide Implementierungen sind nicht wirklich schön, IMHO (aber natürlich um Längen besser als die alten Integer-Konstanten...)



  • Wenn wir schon von schönen Code reden: Mit enums zu rechnen ist nicht schön. Es ist sogar komplett hässlich. Idealerweise benutzt man den numerischen Wert von enums gar nicht.
    Und enum-Werte TWO, THREE, FOUR, FIVE, ... ist (sorry) das affigste was ich jemals gesehen habe. Wenns nicht so mies wäre, müsste man das an The daily WTF schicken. :p

    Vielleicht solltest du dir nochmal die Frage stellen, ob ein enum wirklich das ist, was du willst.



  • Optimizer schrieb:

    Und enum-Werte TWO, THREE, FOUR, FIVE, ... ist (sorry) das affigste was ich jemals gesehen habe.

    Naja, nicht alle Karten haben numerischen Wert.



  • Und diese Werte solltest du wie oben gezeigt zuordnen.

    Bye, TGGC (Pipe my World.)



  • TGGC schrieb:

    Und diese Werte solltest du wie oben gezeigt zuordnen.

    Und wie löst das das Problem des redundanten Codes?



  • Optimizer schrieb:

    Vielleicht solltest du dir nochmal die Frage stellen, ob ein enum wirklich das ist, was du willst.

    Eigentlich schon. Ich brauche:
    - einen Typ mit kleinem, endlichen Wertebereich
    - Singletons
    - Vergleich auf Gleichheit
    - eine totale Ordnung
    - den Nachfolger bezüglich dieser totalen Ordnung

    Die ersten 4 Punkte sind bei enums implizit mit drin, nur der fünfte nicht. Gibt es da wirklich keine schöne Lösung für?



  • Der fünfte Punkt ist jedenfalls nicht das typische Anwendungsgebiet von enums. Ne Lösung gibt es natürlich schon

    enum Test
    {
    	a(2), b(3), c(5);
    
    	private Test(int i)	{this.value = i;}
    	public final int value;
    }
    


  • Ich seh keinen redundanten Code.

    Bye, TGGC (Pipe my World.)



  • Dann kauf Dir 'ne Brille. Die Ordnung auf den Elementen ist durch die Reihenfolge definiert, damit ist auch die Nachfolgerrelation eigentlich schon gegeben. Du willst sie aber explizit angeben.



  • Wieso sollte ich das wollen?

    Bye, TGGC (Pipe my World.)



  • @SG1: Du verstehst die Enums nicht wirklich. Das ist nur ein Konstruktoraufruf und gibt nicht die Reihenfolge der Aufzählung wieder. Du kannst noch weitere beliebige Datenelemente zu diesen Singleton-Objekten jeweils hinzufügen. Lies dir jetzt einfach nochmal das Tutorial von Sun durch. 😉



  • Optimizer schrieb:

    @SG1: Du verstehst die Enums nicht wirklich.

    Wenn Du meinst, enums wären so unpassend, mach doch mal 'nen Gegenvorschlag. Integer-Konstanten zählen nicht, die saugen.

    Das ist nur ein Konstruktoraufruf und gibt nicht die Reihenfolge der Aufzählung wieder.

    Ach. Nur zur Erinnerung: Es geht um folgende Konstruktion:

    public enum Rank {
      TWO (THREE),
      THREE (FOUR),
      FOUR (FIVE),
      FIVE (SIX),
      SIX (SEVEN),
    [...]
      private final Rank next;
      Rank(Rank next) {this.next = next;}
      Rank getNext() {return next;}
    }
    

    Also wird da nicht jeweils der Nachfolger übergeben? Was dann?

    Du kannst noch weitere beliebige Datenelemente zu diesen Singleton-Objekten jeweils hinzufügen. Lies dir jetzt einfach nochmal das Tutorial von Sun durch. 😉

    Danke. Verarschen kann ich mich selber. 👎



  • Es geht auch anders. Zwar auch mit Iterator aber ich denke ein klein wenig anders als hier schon besprochen wurde. Dazu ist es vielleicht hilfreich zu wissen dass jeder Aufzählungstyp implizit von java.lang.Enum erbt.

    import java.util.EnumSet;
    import java.util.Iterator;
    
    public class EnumTest {
    	public static void main (String args[]) {
    		System.out.println(Rank.NINE);
    		EnumTool<Rank> tool = new EnumTool<Rank>();
    		System.out.println(tool.successorOf(Rank.NINE));
    		System.out.println(tool.successorOf(tool.successorOf(Rank.NINE)));
    		System.out.println(tool.successorOf(tool.successorOf(tool.successorOf(Rank.NINE))));
    		System.out.println(tool.successorOf(tool.successorOf(tool.successorOf(tool.successorOf(Rank.NINE)))));
    		System.out.println(tool.successorOf(tool.successorOf(tool.successorOf(tool.successorOf(tool.successorOf(Rank.NINE))))));
    	}
    }
    
    class EnumTool<E extends Enum<E>> {
    	public E successorOf(E e) {
    		E next = null;
    		int index = -1;
    		EnumSet<E> enums = null;
    		if (e!=null) {
    			enums = EnumSet.allOf((Class<E>)e.getClass());
    			for (Iterator<E> i = enums.iterator(); i.hasNext() ;) {
    				E testRank = i.next();
    				if (index==e.ordinal()) {
    					next = testRank;
    					break;
    				}
    				index++;
    			}
    		}
    		return next;
    	}
    }
    
    enum Rank { 
    	TWO, 
    	THREE, 
    	FOUR, 
    	FIVE, 
    	SIX, 
    	SEVEN, 
    	EIGHT, 
    	NINE, 
    	TEN, 
    	JACK, 
    	QUEEN, 
    	KING, 
    	ACE 
    }
    

    Hoffe dass man damit weiterkommt. Wo ich mir noch nicht sicher bin ist der Iterator ... ob der immer die Definitionsreihenfolge beachet? Müsste mal getestet werden. Ansonsten wird man obige Implementation wohl abändern müssen.

    Edit: Bessere Implementation eingefügt.


Anmelden zum Antworten