Reputation: 81
I'm coding a cards game, I have an ArrayList
holding cards (Object
) where
each one of them has its id.
Since I want to make this game to support multiplayer mode, I must in some way send/receive game progress between the 2 players.
Now, if I shuffled the cards on a side, I must do the same thing in the other but it will be a big packet to be sent since every card has an image.
What I thought is to send an integer array of the shuffled list, so it will be received on the other side and re-ordered following the integer array.
How can I send the shuffled order and apply it on the other side?
Upvotes: 3
Views: 7847
Reputation: 21
Although it is possible to initialize two java.util.Random instance with the same seed, and use these instances with Collections.shuffle()
as mentioned by Henrik. The only problem is that Collections.shuffle()
calls with these instances have to be called in the same sequence (i.e. synchronized). It may not be possible to guarantee this, for example if one player requests card shuffle more than one in very quick succession, and the other player falls out of sync (due to network issues).
One alternative is to do the sorting manually on both ends. An illustration is given below.
public class Card {
private final int id;
private final String imageURL;
public Card(int id, String imageURL) {
this.id = id;
this.imageURL = imageURL;
}
public int getId() {
return id;
}
public String getImageURL() {
return imageURL;
}
/**
* Getters and setters below
*/
}
public class Example {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
final int NUMBER_OF_CARDS = 6;
//
final List<Card> originalList = new ArrayList<>();
//
for (int i = 1; i <= NUMBER_OF_CARDS; i++) {
originalList.add(new Card(i, "image_url"));
}
//Create player card list
final List<Card> firstPlayerCardsList = new ArrayList<>(originalList);
final List<Card> secondPlayerCardsList = new ArrayList<>(originalList);
//
//1. Shuffle list on one side
Collections.shuffle(firstPlayerCardsList);
//
//2. Iterate over the list and add indices to array
final int[] indices = new int[NUMBER_OF_CARDS];
//note indices are zero based to allign with arrays
for (int i = 0; i < NUMBER_OF_CARDS; i++) {
indices[i] = firstPlayerCardsList.get(i).getId();
}
//
// 3. Send the shuffle indices array across to second player
// ********* omitted ******
//
// 4. Recreate the shuffle order at the second players end, based on the shuffle indices array
final List<Card> tempCardsList = new ArrayList<>(secondPlayerCardsList);
secondPlayerCardsList.clear();
IntStream.range(0, NUMBER_OF_CARDS).forEach((int index) -> {
final int id = indices[index];
for (final Card c : tempCardsList) {
if (c.getId() == id) {
secondPlayerCardsList.add(c);
}
}
// can also use in place of the above
//tempCardsList.stream().filter((c) -> (c.getId() == id)).forEachOrdered((c) -> {
// secondPlayerCardsList.add(c);
//});
});
// Show the results for this illustration
System.out.println(" Original" + " First" + " Second");
IntStream.range(0, NUMBER_OF_CARDS).forEach((int index) -> {
System.out.println("\t" + originalList.get(index).getId() +"\t" + firstPlayerCardsList.get(index).getId() + "\t" + secondPlayerCardsList.get(index).getId());
});
}
}
Upvotes: 2
Reputation: 6123
Yes, just initialise and store the cards in an read-only array of 52 Card objects at the start of both sides:
final Card[] allCards = new Card[52] {...};
Use this array exclusively in the whole application on both sides to refer to each card using just an int
index instead of a Card
instance.
Then you'll have a deck
object which is an int[52]
. Initially, it will contain all the numbers from 0 to 51. Then you shuffle the array. Then you send the array of ints to the other side, and the other side then has the same shuffled deck.
Upvotes: 0
Reputation: 7147
The Random
class can be used for this.
If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers. In order to guarantee this property, particular algorithms are specified for the class Random. Java implementations must use all the algorithms shown here for the class Random, for the sake of absolute portability of Java code.
This means that you can transmit only the seed value to the client, instantiate a new Random
instance using it and expect to receive the same sequence of random numbers as on the other player's machine.
Collections.shuffle
can be invoked with a Random
source.
Upvotes: 5