如何在 Java 中打印组合的开关值而不重复?



我如何让控制台打印出 1 套花色和 1 个数字,而不打印出完全相同的组合?

这是我正在创造的扑克游戏的开始。

import java.util.Scanner;
public class Poker {
public static void main(String[] args) {
int Cards_Per_Player= 5;
int Num_Cards = 5;
int Num_Players = 5;
int Num_Attempts = 0;
String suit = "deck";
String value = "Ace";
Scanner input = new Scanner(System.in);
System.out.println("welcome to the den");
System.out.println("only 2 to 5 players are allowed in here.");
System.out.println("How many of you are there?");
Num_Players = input.nextInt();
Num_Attempts = 1;
while(Num_Players < 2 |  Num_Players > 5) {
if(Num_Players < 2 | Num_Players > 5)
System.out.println("That is wrong try again.");
Num_Players = input.nextInt();
Num_Attempts++;
}
System.out.println("alright, we got "+ Num_Players + " Here");
for(int i=1; i <= Num_Players; i++) {
System.out.println("Player" + i);
for (int card = 1; card <= Num_Cards; card++) {
double s1 = Math.random();
double v1 = Math.random();
int Suit = (int)(s1 * 4) + 1;
int Cards = (int)(v1 * 13);
switch (Suit)
{
case 1: suit = "Hearts"; break;
case 2: suit = "Clubs"; break;
case 3: suit = "Spades"; break;
case 4: suit = "Diamond"; break;
}
switch (Cards)
{
case 1: value = "Ace"; break;
case 2: value = "2"; break;
case 3: value = "3"; break;
case 4: value = "4"; break; 
case 5: value = "5"; break;
case 6: value = "6"; break;
case 7: value = "7"; break;
case 8: value = "8"; break;
case 9: value = "9"; break;
case 10: value = "10"; break;
case 11: value = "Jack"; break;
case 12: value = "Queen"; break;
case 13: value = "King"; break;
}
System.out.println(" " + value + " of " + suit + ",");
}
System.out.println();
}
}
}

您的问题不在于打印,而在于打印前的值选择,因为该值是当您将程序扩展到真实游戏时将继续使用的值。

您根本不应该在此处使用switch语句。使用合法值的集合。例如,当您有一个列表时

喜欢

List<String> list = Arrays.asList("foo", "bar", "baz");

您可以选择一个随机值,例如

Random r = new Random(); // reusable
String value = list.get(r.nextInt(list.size()));

但为了避免重复,您不应该选择一个随机值并在事后检查冲突。选择的值越多,发生冲突的可能性就越大,选择非重复值的过程就越长。

相反,像真正的发卡商一样做。只需洗牌整个套牌,然后按结果顺序分配牌。当列表包含不同的值时,打乱它不会改变它,并且按顺序获取元素永远不会选择元素两次。

例如

// invariants; starting with Java 9, you can use List.of(...)
List<String> suits = Arrays.asList("Hearts", "Clubs", "Spades", "Diamond");
List<String> ranks = Arrays.asList(
"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King");
// create a deck
List<List<String>> allCards = new ArrayList<>(suits.size() * ranks.size());
for(String suit: suits) for(String rank: ranks) allCards.add(Arrays.asList(rank, suit));
Collections.shuffle(allCards); // shuffle in one operation
System.out.println("alright, we got "+ Num_Players + " here");
for(int i = 1, pos = 0; i <= Num_Players; i++, pos += Num_Cards) {
System.out.println("Player " + i);
// split the deck into sublist of Num_Card size
List<List<String>> hand = allCards.subList(pos, pos + Num_Cards);
for(List<String> card: hand) {
System.out.println(" " + card.get(0) + " of " + card.get(1) + ",");
}
System.out.println();
}

这使用两个字符串的列表,一个等级和一个花色来表示一张牌。但更好的是使用专用类型,例如enum花色和等级的类型以及表示等级和花色组合的不可变Card类型。原则上,您也可以为卡片设置enum类型,但声明所有可能的卡片并不是正确的方法。不可变的Card类型仍然允许在内部为所有可能的组合维护不同的对象。

这可能看起来像:

enum Suit {
Hearts, Clubs, Spades, Diamond
}
enum Rank {
Ace, _2, _3, _4, _5, _6, _7, _8, _9, _10, Jack, Queen, King;
String userName = name().startsWith("_")? name().substring(1): name();
@Override
public String toString() {
return userName;
}
}
final class Card {
public static Card of(Suit suit, Rank rank) {
return LOOKUP.get(suit).get(rank);
}
public static List<Card> newDeck() {
return new ArrayList<>(ALL);
}
public static List<Card> newShuffledDeck() {
final List<Card> deck = newDeck();
Collections.shuffle(deck);
return deck;
}
public static Map<String, List<Card>> deal(int numberOfPlayers, int cardsPerPlayer) {
if(numberOfPlayers < 1 || cardsPerPlayer < 1
|| numberOfPlayers*cardsPerPlayer > ALL.size()) {
throw new IllegalArgumentException();
}
Map<String, List<Card>> allHands = new LinkedHashMap<>();
List<Card> deck = newShuffledDeck();
for(int player = 1, pos = 0;
player <= numberOfPlayers; player++, pos += cardsPerPlayer) {
allHands.put("Player "+player,
Collections.unmodifiableList(deck.subList(pos, pos + cardsPerPlayer)));
}
return allHands;
}
public final Suit suit;
public final Rank rank;
private Card(Suit suit, Rank rank) {
this.suit = suit;
this.rank = rank;
}
@Override
public String toString() {
return rank+" of "+suit;
}
private static final Map<Suit,Map<Rank,Card>> LOOKUP;
private static final List<Card> ALL;
static {
Map<Suit,Map<Rank,Card>> all = new EnumMap<>(Suit.class);
List<Card> list = new ArrayList<>();
for(Suit suit: Suit.values()) {
Map<Rank,Card> byRank = new EnumMap<>(Rank.class);
all.put(suit, Collections.unmodifiableMap(byRank));
for(Rank rank: Rank.values()) {
byRank.put(rank, new Card(suit, rank));
}
list.addAll(byRank.values());
}
LOOKUP = Collections.unmodifiableMap(all);
ALL = Collections.unmodifiableList(list);
}
}

您可以将其集成到现有代码中,例如

Map<String, List<Card>> hands = Card.deal(Num_Players, Cards_Per_Player);
for(Map.Entry<String, List<Card>> hand: hands.entrySet()) {
System.out.println(hand.getKey());
for(Card card: hand.getValue()) {
System.out.println(" "+card);
}
}

如果你想确保输出不会重复,我建议使用java.util.ArrayList.例如,如果在切换后,suit == "Hearts"value == "10",那么您可以执行java.util.List <Integer> suitList = new ArrayList<>(),并且每次在打印卡片之前,都可以调用suitList.add(suit)。(当然,您也必须对值执行此操作,最好创建包含两个变量的自己的类,而不是创建 2 个数组列表(

潜在实施:

System.out.println(" "+value+" of "+suit+",");之前

调用suitList.add(suit),值也是如此。

和一个 for 循环,用于遍历 ArrayList 以检查是否已经打印了相同的卡。

您有一些选择,但我会使用Set跟踪已经看到的卡片。您可以使用"花色数"格式或Set<Card> cards进行Set<String> cards,然后调用cards.contains(card)以查看是否找到了生成的卡。

作为旁白/提醒,Java 中的约定是以小写字母开头命名所有变量,因为像这些这样的名称传统上是为类保留的。

最新更新