lundi 21 novembre 2022

design pattern and best practice card game yugioh

I started to develop a card game based on yugioh! I want to know how to optimize it before going further. So after searching for design patterns, I am thinking of two choices, but I do not know what is the best one. Before that, to explain the game :

 We have different type of cards : 
      ->  1.SPELL
      -> 1.Trap 
      -> 3.Monster 
           3.1->->monster from the main deck
           3.2-> -> mosters from extra deck 
               3.2.1>->->Link
               3.2.2>->->Pendulum
                           ....

I also have three type of deck when playing : -> Main deck (accepts spells, traps and mainMonsters) -> Extra deck (accepts monsters that are link, pendulum...) -> Side (accepts everything, it is used if you want to change some cards from your main / extra between matchs)

So the other issue, is to find the best way to make a link between the card and its belonging deck in order to know if I accept to add the card to the deck or not

OPTION one : use the design pattern decorator : The thing is I will create a lot of classes for sometimes nothing. For example, a link monster have 1 more attribute and does't have def points. A pendulum can change to a spell card...

OPTION 2 : Create only one class with all attributes.

I hope that my issue is clear, thank you all for your help

public class Card extends javafx.scene.image.ImageView implements Serializable {
    private int id;
    private String name;
    private String type; //SpellCard, TrapCard, FusionMonster, SynchroMonster, Tuner monster, Pendulum monster
    private String desc; 
    private String race;
    private String image;
    private String imageSmall;
    private Player owner;
    private Limit limit = Limit.NO_LIMITED; 
    private Face face = Face.UP; 
    
    /**
     * This constructor is used to generate a card from data formatted as JSon
     * @param card  its type is JsonNode
     */
    public Card(JsonNode card, Player owner)
    {
        id = card.path("id").asInt();
        name = card.path("name").asText();
        type = card.path("type").asText();
        desc = card.path("desc").asText();
        race = card.path("race").asText();
        image = card.path("card_images").get(0).path("image_url").asText();
        imageSmall = card.path("card_images").get(0).path("image_url_small").asText();      
        this.owner = owner;

        setCardImage();
    }
    
    /**
     * This constructor is used to generate a card from data exported from database 
     * @param cardInfo its type is ResultSet
     */
    public Card(ResultSet cardInfos, Player owner)
    {
        try {
            id = cardInfos.getInt("id");
            name = cardInfos.getString("name");
            type = cardInfos.getString("type");
            desc = cardInfos.getString("desc");
            race = cardInfos.getString("race");
            image = cardInfos.getString("image");
            imageSmall = cardInfos.getString("imageSmall");
            this.owner = owner;
            
            setCardImage();
        } 
        catch (SQLException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    /**
     * This constructor is used to generate a card manually
     * @param id  card id
     * @param name card name
     * @param desc card description
     * @param race card race 
     * @param image card images list formatted as csv (;)
     */
    public Card(int id, String name, String type, String desc, String race, String image, String imageSmall, Player owner) 
    {
        this.id =  id;
        this.name = name;
        this.type = type;
        this.desc = desc;
        this.race = race;
        this.image = image;
        this.imageSmall = imageSmall;
        this.owner = owner;
        setCardImage();
    }

    //setters and getters 
}
public class MonsterCard extends Card {
    private int atk;
    private int def;
    private int level;
    private String attribute;
    private Position mode;
    
    /**
     * This constructor is used to generate a monster card from data formated as Json
     * @param card its type is JsonNode
     * @param owner player 
     */
    public MonsterCard(JsonNode card, Player owner) {
        super(card, owner);
    
        this.atk =  card.path("atk").asInt();
        this.def = card.path("def").asInt();
        this.level = card.path("level").asInt();
        this.attribute = card.path("attribute").asText();
    }
    
    /**
     * This constructor is used to generate a monster card from data exported from database 
     * @param cardInfos its type is ResultSet
     */
    public MonsterCard(ResultSet cardInfos, Player owner) {
        super(cardInfos, owner);
        
        try {
            this.atk = cardInfos.getInt("atk");
            this.def = cardInfos.getInt("def");
            this.level = cardInfos.getInt("level");
            this.attribute = cardInfos.getString("attribute");  
        }
        catch (SQLException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    /**
     * @param id
     * @param name
     * @param type
     * @param desc
     * @param race
     * @param image
     * @param imageSmall
     * @param owner
     */
    public MonsterCard(int id, String name, String type, String desc, String race, String image, String imageSmall,
            Player owner) {
        super(id, name, type, desc, race, image, imageSmall, owner);
        
    }
        //getter and setter
[/code]

[code=java]
public  class SpellCard extends Card{

    public SpellCard(int id, String name, String type, String desc, String race, String image, String imageSmall, Player owner) {
        super(id, name, type, desc, race, image, image, owner);
    }

    public SpellCard(JsonNode card, Player owner) {
        super(card, owner);
    }

    public SpellCard(ResultSet cardInfos, Player owner) {
        super(cardInfos, owner);
    }

        //getter and setter
}
public class TrapCard extends Card{

    /**
     * @param id
     * @param name
     * @param type
     * @param desc
     * @param race
     * @param image
     * @param owner
     */
    public TrapCard(int id, String name, String type, String desc, String race, String image, String imageSmall, Player owner) {
        super(id, name, type, desc, race, image, imageSmall, owner);
        // TODO Auto-generated constructor stub
    }

         //getter and setter
}
public class Deck implements Serializable{
    
    private List<Card> cardList ;   
    
    private DeckType type;
    
    public Deck(DeckType type)
    {
        cardList = new ArrayList<Card>(type.getMinCard());
        
        this.type = type;
    }
    
    
    public boolean checkNbCard()
    {

        //size of the deck 
        int size = cardList.size() ;
        
        return (size >= getMinCard()&& size <= getMaxCard());
    }
    
    public boolean checkCardCopies()
    {
        //count each card occurrences
         Map<String,Long> occurrenceMap = cardList.stream().collect(Collectors.groupingBy(card -> card.getName(),Collectors.counting()));
         
         return (cardList.stream().filter(card -> card.getLIMIT().getNbCopies()< occurrenceMap.get(card.getName())).count() > 0);
    }
    
    public boolean isValid()
    {
        return (checkNbCard() && checkCardCopies());
    }

    public void addCard(Card card)
    {
        cardList.add(card);
    }
    
    public void removeCard(Card card)
    {
        cardList.remove(card);
    }
    
    public void clearDeck()
    {
        cardList.clear();   
    }
    //getter and setter
}

Aucun commentaire:

Enregistrer un commentaire