Java: 如何用相同的算法打乱2个ArrayList?
Java: How to shuffle 2 ArrayList with same algorithm?
我想用算法洗牌 cardList 和 valueList,但是当我对每个使用洗牌集合时,它们使用不同的算法。因此,当我抽出一张牌时,它将是牌组中的一张随机牌,并且不会再次出现同一张牌。
public class BlackJack {
public static void main(String[] args) {
Random rand = new Random();
Scanner input =new Scanner(System.in);
ArrayList<String> cardList= new ArrayList<String>();
ArrayList<String> cardShuffle= new ArrayList<String>();
ArrayList<Integer> valueList= new ArrayList<Integer>();
ArrayList<String> valueShuffle= new ArrayList<String>();
cardList = card(cardList);
valueList = value(valueList);
Collections.shuffle(cardList);
Collections.shuffle(valueList);
System.out.println(cardList);
System.out.println(valueList);
}
private static ArrayList card(ArrayList<String> cardList){
String cards = null;
String suits = null;
int cardCount = 0;
for(int s = 1;s<5; s++){
switch (s){
case 1: suits = " of Heart"; break;
case 2: suits = " of Diamond"; break;
case 3: suits = " of Spades"; break;
case 4: suits = " of Clubs"; break;
}
for(int c = 1;c<14; c++){
switch (c){
case 1: cards = "2"; break;
case 2: cards = "3"; break;
case 3: cards = "4"; break;
case 4: cards = "5"; break;
case 5: cards = "6"; break;
case 6: cards = "7"; break;
case 7: cards = "8"; break;
case 8: cards = "9"; break;
case 9: cards = "10"; break;
case 10: cards = "Jack"; break;
case 11: cards = "Queen"; break;
case 12: cards = "King"; break;
case 13: cards = "Ace"; break;
}
cardList.add(cardCount, cards + suits);
cardCount++;
}
}
return cardList;
}
private static ArrayList<Integer> value(ArrayList<Integer> valueList){
int v = 2;
int counter = 1;
for(int c = 1;c<52; c++){
if(v > 10){
v = 10;
}
valueList.add(v);
v++;
counter++;
if(counter>13){
counter = 1;
v=2;
}
}
return valueList;
}
}
编辑:我按照@Cinnam 的建议做了第二个 class,然后使用 For int 随机数洗牌。
public class BlackJack {
public static void main(String[] args) {
Random rand = new Random();
Scanner input =new Scanner(System.in);
ArrayList<String> cardList= Cards.card();
ArrayList<Integer> valueList= Cards.value();
ArrayList<String> cardShuffle= new ArrayList<String>();
ArrayList<Integer> valueShuffle= new ArrayList<Integer>();
int r = 0;
for(int i = 0; i < 52; i++){
r = rand.nextInt(52);
cardShuffle.add(i,cardList.get(r));
valueShuffle.add(i,valueList.get(r));
}
System.out.println(cardShuffle);
}
我认为在你的情况下最好的解决方案是创建一个 class 来保存卡片和价值:
class ValuedCard {
private String card;
private int value;
// constructor, getters/setters...
}
那么你可以只有一个列表 ArrayList<ValuedCard>
并洗牌。
首先回答你的几个问题:
您可以使用地图将值映射到卡片上。这样你就可以通过发送卡来查询价值。
Map<String, Integer> cardsWithValues = new HashMap<>();
//Fill it by going cardsWithValue.put("2 of Dimonds", 2) for all cards. You can use a loop.
//Shuffle the cards array, then you can get the values by doing:
System.out.print(cardsWithValue.get(cards.get(i));
这可行,但并不是那么漂亮。另一种选择是创建一张卡片 class。
Public class Card{
Integer value;
String cardName;
public Card(Integer value, String cardName){
this.value = value;
this.cardName = cardName;
}
然后您可以将卡片存储在列表中,一切正常。这可能是最 Java 的方式。您甚至可以为 class 提供一些实用功能。也许您只想发送一套西装和一个数字,而不是完整的字符串。
最后一个选项是将种子发送到随机播放方法。
Long seed = 1234;
Random r = new Random(seed);
Collections.shuffle(cardsList, r);
r = new Random(seed);
Collections.shuffle(valueList, r);
现在开始其他事情:对您的代码的评论。
private static ArrayList card(ArrayList<String> cardList){
您向此方法发送一个您添加所有内容的列表,然后您 return 该列表。你真的不需要两者都做。你可以做
ArrayList<String> cardList= card();
private static ArrayList card(){
List<String> cardList = new ArrayList<String>
//Fill it with stuff
return cardList;
}
或者您可以只发送列表而不是 return。我更喜欢第一种方法,因为它更干净。
您可以使用 Collections.shuffle() that accepts a Random as a parameter, which you can initialized using the same seed via the setSeed() 方法的重载版本。
因此,在您的代码中,您需要 Random
每个牌组都使用相同的种子,例如:
Random rand1 = new Random();
rand1.setSeed(123);
Random rand2 = new Random();
rand2.setSeed(123);
//..and further below
Collections.shuffle(cardList, rand1);
Collections.shuffle(valueList, rand2);
只需确保将两者混在一起(您需要更好的 OO 设计来封装它)。
另外请注意,在 Collection.shuffle()
中,数组的大小正在被使用 因此在您的情况下,您的两个集合需要具有相同的大小。
在上面的代码示例中,情况并非如此,因为存在错误:
在您的静态 value()
方法中,for 循环需要包含 52,换句话说:
for(int c = 1;c<=52; c++){
在这种情况下,代码结果符合预期。
你的值和你的牌在 2 个单独的 ArrayList 中,所以当你洗牌时,它们会以不同的方式洗牌,并且它们将不再对应。我的建议是创建一个名为 Card 的新 class,有一个包含 Cards 的 ArrayList,然后将其洗牌。
这是一张可能的卡片 class:
public class Card {
public static enum Suit {SPADE,HEART,DIAMOND,CLUB};
public static enum Value {
//The integer parameter is the score. Adjust as needed.
ACE(1),DEUCE(2),THREE(3),FOUR(4),FIVE(5),SIX(6),SEVEN(7),
EIGHT(8),NINE(9),TEN(10),JACK(10),QUEEN(10),KING(10);
int score;
Value(int score) {
this.score = score;
}
}
private Suit suit;
private Value value;
public Card(Suit suit, Value value) {
this.suit = suit;
this.value = value;
}
public int getScore() {
return value.score;
}
}
您可以像这样创建一个包 (ArrayList):
ArrayList<Card> pack = new ArrayList<Card>();
for (Card.Value value : Card.Value.values()) {
for (Card.Suit suit : Card.Suit.values()) {
pack.add(new Card(suit, value));
}
}
//finally, shuffle it:
Collections.shuffle(pack);
我想用算法洗牌 cardList 和 valueList,但是当我对每个使用洗牌集合时,它们使用不同的算法。因此,当我抽出一张牌时,它将是牌组中的一张随机牌,并且不会再次出现同一张牌。
public class BlackJack {
public static void main(String[] args) {
Random rand = new Random();
Scanner input =new Scanner(System.in);
ArrayList<String> cardList= new ArrayList<String>();
ArrayList<String> cardShuffle= new ArrayList<String>();
ArrayList<Integer> valueList= new ArrayList<Integer>();
ArrayList<String> valueShuffle= new ArrayList<String>();
cardList = card(cardList);
valueList = value(valueList);
Collections.shuffle(cardList);
Collections.shuffle(valueList);
System.out.println(cardList);
System.out.println(valueList);
}
private static ArrayList card(ArrayList<String> cardList){
String cards = null;
String suits = null;
int cardCount = 0;
for(int s = 1;s<5; s++){
switch (s){
case 1: suits = " of Heart"; break;
case 2: suits = " of Diamond"; break;
case 3: suits = " of Spades"; break;
case 4: suits = " of Clubs"; break;
}
for(int c = 1;c<14; c++){
switch (c){
case 1: cards = "2"; break;
case 2: cards = "3"; break;
case 3: cards = "4"; break;
case 4: cards = "5"; break;
case 5: cards = "6"; break;
case 6: cards = "7"; break;
case 7: cards = "8"; break;
case 8: cards = "9"; break;
case 9: cards = "10"; break;
case 10: cards = "Jack"; break;
case 11: cards = "Queen"; break;
case 12: cards = "King"; break;
case 13: cards = "Ace"; break;
}
cardList.add(cardCount, cards + suits);
cardCount++;
}
}
return cardList;
}
private static ArrayList<Integer> value(ArrayList<Integer> valueList){
int v = 2;
int counter = 1;
for(int c = 1;c<52; c++){
if(v > 10){
v = 10;
}
valueList.add(v);
v++;
counter++;
if(counter>13){
counter = 1;
v=2;
}
}
return valueList;
}
}
编辑:我按照@Cinnam 的建议做了第二个 class,然后使用 For int 随机数洗牌。
public class BlackJack {
public static void main(String[] args) {
Random rand = new Random();
Scanner input =new Scanner(System.in);
ArrayList<String> cardList= Cards.card();
ArrayList<Integer> valueList= Cards.value();
ArrayList<String> cardShuffle= new ArrayList<String>();
ArrayList<Integer> valueShuffle= new ArrayList<Integer>();
int r = 0;
for(int i = 0; i < 52; i++){
r = rand.nextInt(52);
cardShuffle.add(i,cardList.get(r));
valueShuffle.add(i,valueList.get(r));
}
System.out.println(cardShuffle);
}
我认为在你的情况下最好的解决方案是创建一个 class 来保存卡片和价值:
class ValuedCard {
private String card;
private int value;
// constructor, getters/setters...
}
那么你可以只有一个列表 ArrayList<ValuedCard>
并洗牌。
首先回答你的几个问题:
您可以使用地图将值映射到卡片上。这样你就可以通过发送卡来查询价值。
Map<String, Integer> cardsWithValues = new HashMap<>();
//Fill it by going cardsWithValue.put("2 of Dimonds", 2) for all cards. You can use a loop.
//Shuffle the cards array, then you can get the values by doing:
System.out.print(cardsWithValue.get(cards.get(i));
这可行,但并不是那么漂亮。另一种选择是创建一张卡片 class。
Public class Card{
Integer value;
String cardName;
public Card(Integer value, String cardName){
this.value = value;
this.cardName = cardName;
}
然后您可以将卡片存储在列表中,一切正常。这可能是最 Java 的方式。您甚至可以为 class 提供一些实用功能。也许您只想发送一套西装和一个数字,而不是完整的字符串。
最后一个选项是将种子发送到随机播放方法。
Long seed = 1234;
Random r = new Random(seed);
Collections.shuffle(cardsList, r);
r = new Random(seed);
Collections.shuffle(valueList, r);
现在开始其他事情:对您的代码的评论。
private static ArrayList card(ArrayList<String> cardList){
您向此方法发送一个您添加所有内容的列表,然后您 return 该列表。你真的不需要两者都做。你可以做
ArrayList<String> cardList= card();
private static ArrayList card(){
List<String> cardList = new ArrayList<String>
//Fill it with stuff
return cardList;
}
或者您可以只发送列表而不是 return。我更喜欢第一种方法,因为它更干净。
您可以使用 Collections.shuffle() that accepts a Random as a parameter, which you can initialized using the same seed via the setSeed() 方法的重载版本。
因此,在您的代码中,您需要 Random
每个牌组都使用相同的种子,例如:
Random rand1 = new Random();
rand1.setSeed(123);
Random rand2 = new Random();
rand2.setSeed(123);
//..and further below
Collections.shuffle(cardList, rand1);
Collections.shuffle(valueList, rand2);
只需确保将两者混在一起(您需要更好的 OO 设计来封装它)。
另外请注意,在 Collection.shuffle()
中,数组的大小正在被使用 因此在您的情况下,您的两个集合需要具有相同的大小。
在上面的代码示例中,情况并非如此,因为存在错误:
在您的静态 value()
方法中,for 循环需要包含 52,换句话说:
for(int c = 1;c<=52; c++){
在这种情况下,代码结果符合预期。
你的值和你的牌在 2 个单独的 ArrayList 中,所以当你洗牌时,它们会以不同的方式洗牌,并且它们将不再对应。我的建议是创建一个名为 Card 的新 class,有一个包含 Cards 的 ArrayList,然后将其洗牌。
这是一张可能的卡片 class:
public class Card {
public static enum Suit {SPADE,HEART,DIAMOND,CLUB};
public static enum Value {
//The integer parameter is the score. Adjust as needed.
ACE(1),DEUCE(2),THREE(3),FOUR(4),FIVE(5),SIX(6),SEVEN(7),
EIGHT(8),NINE(9),TEN(10),JACK(10),QUEEN(10),KING(10);
int score;
Value(int score) {
this.score = score;
}
}
private Suit suit;
private Value value;
public Card(Suit suit, Value value) {
this.suit = suit;
this.value = value;
}
public int getScore() {
return value.score;
}
}
您可以像这样创建一个包 (ArrayList):
ArrayList<Card> pack = new ArrayList<Card>();
for (Card.Value value : Card.Value.values()) {
for (Card.Suit suit : Card.Suit.values()) {
pack.add(new Card(suit, value));
}
}
//finally, shuffle it:
Collections.shuffle(pack);