Melhoramento do código

6 respostas
J

Oi.

Estou a fazer um trabalho em que tenho de criar uma série de bases para um jogo de cartas.

Para o naipe das cartas tenho um enumerado
public enum Naipe {QUALQUER, COPAS, ESPADAS, PAUS, OUROS}
e para o valor das cartas tenho outro enumerado
public enum Valor {QUALQUER, NULO, DOIS, TRES, QUATRO, CINCO, SEIS, SETE, OITO, NOVE, DEZ, J, Q, K, AS}

Tenho ainda uma classe Carta onde tenho que fazer uma série de construtores e de comparações entre cartas.

Um dos construtores tem que construir uma carta apartir de uma string (por exemplo: "CK") para um Rei de Copas.
public class Carta {
	
	private Naipe Naipe;
	private Valor Valor;

  public Carta (String teste){
		char[] teste2 = teste.toCharArray();
		
		switch(teste2[0]){
		case 'C' : this.Naipe = Naipe.COPAS;
		case 'E' : this.Naipe = Naipe.ESPADAS;
		case 'O' : this.Naipe = Naipe.OUROS;
		case 'P' : this.Naipe = Naipe.PAUS;}
		
		switch(teste2[1]){
		case '2' : this.Valor = Valor.DOIS;
		case '3' : this.Valor = Valor.TRES;
		case '4' : this.Valor = Valor.QUATRO;
		case '5' : this.Valor = Valor.CINCO;
		case '6' : this.Valor = Valor.SEIS;
		case '7' : this.Valor = Valor.SETE;
		case '8' : this.Valor = Valor.OITO;
		case '9' : this.Valor = Valor.NOVE;
		case '1' : this.Valor = Valor.DEZ;
		case 'J' : this.Valor = Valor.J;
		case 'Q' : this.Valor = Valor.Q;
		case 'K' : this.Valor = Valor.K;
		case 'A' : this.Valor = Valor.AS;}
		
	}

Isto foi o que eu me lembrei de fazer, mas o código fica horrível e não suporta possíveis erros de entrada. Imaginando que eu fazia

new Carta("P10")
Para criar uma carta dez de paus, ele só ia ver o P para paus e o 1 para 10. mas se eu fizesse
new Carta("P11")
ele ia criar na mesma um 10 de Paus.

Alguém me ajuda a melhorar este código? Preciso de uma alternativa para cortar a string em duas partes e melhorar o reconhecimento e atribuição de cada atributo.

6 Respostas

Roger75

Faz um construtor com dois argumentos:

public Carta(Naipe,Valor)

Ou então, se quiser passar apenas uma String, terá que usar o método substring() da classe String (acho que o método é esse, dê uma olhada na API)

J

Roger75:
Faz um construtor com dois argumentos:

public Carta(Naipe,Valor)

Ou então, se quiser passar apenas uma String, terá que usar o método substring() da classe String (acho que o método é esse, dê uma olhada na API)

Esse foi um dos construtores que eu fiz. E este também está a trabalhar, mas de uma maneira um bocado má.

ViniGodoy

Guarde a propriedade e a letra no seu enum. Depois, crie um método chamado ValueOf para obter o enum a partir da letra.

Por exemplo:
public enum Naipe 
{
     COPAS('C'),
     ESPADAS('E'),
     OUROS('O'),
     PAUS('P');

    private char letra;

    private Naipe(char letra) {
       this.letra = letra;
    }

   public static void valueOf(char letra) {
        for (Naipe naipe : values()) 
           if (naipe.letra == letra)
               return naipe;
        throw new IllegalArgumentException("Letra inválida '" + letra + "'!");
   }
}

Isso pode simplificar sua classe carta, já que você passa a poder usar, por exemplo:

Naipe n = Naipe.valueOf('C');

Também elimina o switch e deixa a lógica de identificar a letra do Naipe onde deveria: na classe Naipe.
A tendência, se você não fizer assim, é encher de switchs como aquele pelo código.

Dieval_Guizelini

Algo bastante similar que tem no site da SUN:

[url]http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html[/url]

Outro link interessante sobre o tema:
[url]http://java.sun.com/docs/books/tutorial/java/javaOO/enum.html[/url]

import java.util.*;

public class Card {
    public enum Rank { DEUCE, THREE, FOUR, FIVE, SIX,
        SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE }

    public enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES }

    private final Rank rank;
    private final Suit suit;
    private Card(Rank rank, Suit suit) {
        this.rank = rank;
        this.suit = suit;
    }

    public Rank rank() { return rank; }
    public Suit suit() { return suit; }
    public String toString() { return rank + " of " + suit; }

    private static final List<Card> protoDeck = new ArrayList<Card>();

    // Initialize prototype deck
    static {
        for (Suit suit : Suit.values())
            for (Rank rank : Rank.values())
                protoDeck.add(new Card(rank, suit));
    }

    public static ArrayList<Card> newDeck() {
        return new ArrayList<Card>(protoDeck); // Return copy of prototype deck
    }
}
E lembre-se do método ordinal(), exemplo:
public class Teste {
    static enum Interno {
        UM("1"),
        DOIS("2"),
        TRES("3");
        private String rotuloAmigavel;
        private Interno(String s) {
            rotuloAmigavel = s;
        }
        @Override
        public String toString() {
            return rotuloAmigavel;
        }
    };    
    public static void main(String[] args) {
        for(Interno i : Interno.values() ) {
            System.out.println("=> " + i.toString() + " : "+i.ordinal() );
        }
    }
}

fw

J

Obrigado pelas dicas pessoal. Melhorou muito o meu código!

peczenyj

Naipe “Qualquer”?

Outra coisa, seu switch precisaria de 4557436594387 breaks, polimorfismo é a solução.

Criado 24 de fevereiro de 2008
Ultima resposta 24 de fev. de 2008
Respostas 6
Participantes 5