5import java.util.Queue;
6import java.util.Stack;
7
8public class Deck { 9 private final Queue<Card> draw; 10 private final Stack<Card> discard; 11 12 public Deck() { 13 draw = new ArrayDeque<>(); 14 discard = new Stack<>(); 15 16 addCards(0, 9, Card.Color.RED); 17 addCards(1, 9, Card.Color.RED); 18 addCards(0, 9, Card.Color.BLUE); 19 addCards(1, 9, Card.Color.BLUE); 20 addCards(0, 9, Card.Color.GREEN); 21 addCards(1, 9, Card.Color.GREEN); 22 addCards(0, 9, Card.Color.YELLOW); 23 addCards(1, 9, Card.Color.YELLOW); 24 25 draw.add(new DrawTwoCard(Card.Color.RED)); 26 draw.add(new DrawTwoCard(Card.Color.RED)); 27 draw.add(new DrawTwoCard(Card.Color.BLUE)); 28 draw.add(new DrawTwoCard(Card.Color.BLUE)); 29 draw.add(new DrawTwoCard(Card.Color.YELLOW)); 30 draw.add(new DrawTwoCard(Card.Color.YELLOW)); 31 draw.add(new DrawTwoCard(Card.Color.GREEN)); 32 draw.add(new DrawTwoCard(Card.Color.GREEN)); 33 34 draw.add(new SkipCard(Card.Color.RED)); 35 draw.add(new SkipCard(Card.Color.RED)); 36 draw.add(new SkipCard(Card.Color.BLUE)); 37 draw.add(new SkipCard(Card.Color.BLUE)); 38 draw.add(new SkipCard(Card.Color.YELLOW)); 39 draw.add(new SkipCard(Card.Color.YELLOW)); 40 draw.add(new SkipCard(Card.Color.GREEN)); 41 draw.add(new SkipCard(Card.Color.GREEN)); 42 43 draw.add(new ReverseCard(Card.Color.RED)); 44 draw.add(new ReverseCard(Card.Color.RED)); 45 draw.add(new ReverseCard(Card.Color.BLUE)); 46 draw.add(new ReverseCard(Card.Color.BLUE)); 47 draw.add(new ReverseCard(Card.Color.YELLOW)); 48 draw.add(new ReverseCard(Card.Color.YELLOW)); 49 draw.add(new ReverseCard(Card.Color.GREEN)); 50 draw.add(new ReverseCard(Card.Color.GREEN)); 51 52 draw.add(new WildCard()); 53 draw.add(new WildCard()); 54 draw.add(new WildCard()); 55 draw.add(new WildCard()); 56 57 draw.add(new WildDrawFourCard()); 58 draw.add(new WildDrawFourCard()); 59 draw.add(new WildDrawFourCard()); 60 draw.add(new WildDrawFourCard()); 61 62 discard.addAll(draw); 63 draw.clear(); 64 65 shuffle(); 66 draw.add(discard.pop()); 67 68 } 69 70 private void addCards(int start, int end, Card.Color color) { 71 for (int i = start; i <= end; i++) { 72 draw.add(new Card(color, i)); 73 } 74 } 75 76 private void shuffle() { 77 while (discard.size() > 1) { 78 int index = (int) (Math.random() * discard.size()); 79 draw.add(discard.remove(index)); 80 } 81 } 82 83 public Card drawCard() { 84 if (draw.size() == 0) { 85 shuffle(); 86 } 87 return draw.poll(); 88 } 89 90 public void discard(Card card) { 91 discard.add(card); 92 } 93 94 public Card currentCard() { 95 if (discard.isEmpty()) { 96 return null; 97 } 98 return discard.peek(); 99 }100101 public Queue<Card> getDraw() {102 return draw;103 }104105 public List<Card> getDiscard() {106 return discard;107 }108}
1package de.wroracer.uno.engine.card;
2
3public class Card implements Comparable<Card> { 4 protected Color color; 5 protected int number; 6 protected Type type; 7 8 public Card(Color color, int number) { 9 this.color = color; 10 this.number = number; 11 this.type = Type.byName(number + ""); 12 } 13 14 protected Card(Color color, Type type) { 15 this.number = -1; 16 this.color = color; 17 this.type = type; 18 } 19 20 public static Card of(Type type, Color color) { 21 return switch (type) { 22 case SKIP -> new SkipCard(color); 23 case WILDE -> new WildCard(); 24 case REVERSE -> new ReverseCard(color); 25 case DRAW_TWO -> new DrawTwoCard(color); 26 case WILDE_DRAW_FOUR -> new WildDrawFourCard(); 27 default -> new Card(color, Integer.parseInt(type.name)); 28 }; 29 } 30 31 public boolean canPlayedOn(Card card) { 32 if (!(card.number < 0 || this.number < 0)) { 33 if (this.number == card.number) { 34 return true; 35 } 36 } 37 return card.color == this.color; 38 } 39 40 @Override 41 public String toString() { 42 return color + type.name; 43 } 44 45 @Override 46 public int compareTo(Card o) { 47 return 0; 48 } 49 50 public Type getType() { 51 return type; 52 } 53 54 public Color getColor() { 55 return color; 56 } 57 58 public enum Color { 59 RED, GREEN, BLUE, YELLOW, BLACK; 60 61 @Override 62 public String toString() { 63 switch (this) { 64 case RED -> { 65 return "R"; 66 } 67 case BLUE -> { 68 return "B"; 69 } 70 case BLACK -> { 71 return "Black"; 72 } 73 case GREEN -> { 74 return "G"; 75 } 76 case YELLOW -> { 77 return "Y"; 78 } 79 default -> { 80 return ""; 81 } 82 } 83 } 84 } 85 86 public enum Type { 87 ZERO("0"), ONE("1"), TWO("2"), THREE("3"), FOUR("4"), FIVE("5"), SIX("6"), SEVEN("7"), 88 EIGHT("8"), NINE("9"), DRAW_TWO("D2"), REVERSE("R"), SKIP("S"), WILDE("W"), 89 WILDE_DRAW_FOUR("WD4"); 90 private final String name; 91 92 Type(String name) { 93 this.name = name; 94 } 95 96 public static Type byName(String name) { 97 for (Type value : values()) { 98 if (value.name.equals(name)) { 99 return value;100 }101 }102 return null;103 }104105 public String getName() {106 return name;107 }108 }109}
3import de.wroracer.uno.engine.Player;
4import de.wroracer.uno.engine.card.Card;
5
6public class WildeEvent extends UnoEvent { 7 private final Player next; 8 private final Card.Color color; 910 public WildeEvent(Player next, Card.Color color) {11 super("Wild");12 this.next = next;13 this.color = color;14 }1516 public Player getNext() {17 return next;18 }1920 public Card.Color getColor() {21 return color;22 }23}
3import de.wroracer.uno.engine.Player;
4import de.wroracer.uno.engine.card.Card;
5
6public class WildeDrawFourEvent extends UnoEvent { 7 8 private final Card.Color color; 9 private final Player drawer;10 private final Player next;1112 public WildeDrawFourEvent(Player next, Player drawer, Card.Color color) {13 super("wilde draw four");14 this.next = next;15 this.drawer = drawer;16 this.color = color;17 }1819 public Player getNext() {20 return next;21 }2223 public Player getDrawer() {24 return drawer;25 }2627 public Card.Color getColor() {28 return color;29 }3031}
1package de.wroracer.uno.engine.event;
2
3public interface UnoEventListender<T extends UnoEvent> {45 void on(T event);6}
This class does not have any documentation.
Consider adding a documentation comment to explain its use.
While it may seem like the functionality of a class is perfectly obvious, any consumers of your API may not be able to pick up on certain details.
Consider a case where the class given below can be instantiated and provides certain functionalities within each instance in a thread-safe manner, perhaps it is a rest API client.
If there is no documentation comment on the class, it is not immediately obvious that the class is thread safe. Thus, multiple instances of the class may be created to perform operations concurrently, using up both memory as well as OS resources like sockets. If it were known from the beginning that the class were thread safe, the user would not need to create unnecessary extra instances of SomeClass
.
class SomeClass {
// ...
}
Make sure to add useful information regarding the usage or implementation of a particular declaration, so that anything about it which can't be understood from the name or some other cue is correctly conveyed.
/**
* Instances of this class are used to perform xyz action.
*
* This class is thread safe and the same instance can be used over multiple threads.
*/
class SomeClass {
// ...
}
This issue will not be reported for model entity classes. If there is any non-obvious behavior associated with a particular class however, do consider documenting it.