Reputation: 225
I have this card program that prints out all 52 cards in a swing window. It contains 4 rows of 14 cards with the first being grey empty spots.
I am trying to randomize how they are printed. So far each row prints in a random order Ace through king and of random suits. The error I am getting is once it has a random value like [Ace, Four, Jack, etc] it follows that same pattern in each row.
How can I randomize the different rows?
package project2;
import javax.swing.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.awt.*;
public class main
{
public static final int PERIMETER_BEVEL = 20; //space between panel border and perimeter cards
public static final int LEFT_PERIMETER_BEVEL = 98;
public static final int INTERIOR_BEVEL = 5; //space between cards
public static final int CARD_HEIGHT = 97;
public static final int CARD_WIDTH = 73;
public static final int PANEL_HEIGHT = (2*PERIMETER_BEVEL) + (4*CARD_HEIGHT) + (3*INTERIOR_BEVEL);
public static final int PANEL_WIDTH = (2*PERIMETER_BEVEL) + (14*CARD_WIDTH) + (13*INTERIOR_BEVEL);
public static final String BACKGROUND_COLOR = "#64C866"; //window background color [hex]
public static final String CARD_FOLDER = "cardImages"; //default folder containing images
public static final String[] RANKS = { "jack","three","four","five","six","seven",
"eight","nine","ten","two","queen","king","ace"
};
public static final String[] GRAY = {"gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray",
"gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray",
"gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray",
"gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray","gray"};
public static void main(String[] args)
{
JFrame window = new JFrame("deck");
JPanel panel = new JPanel() {
public void paintComponent(Graphics g) { //find each rank of card in increasing
super.paintComponent(g); //order as specified in the array. All
File[] files = new File(CARD_FOLDER).listFiles(); //ranks appear in the same suit order in
//This randomizes the order the suits are put in.
for(int i = 0; i < files.length; i++)
{
int r = (int)(Math.random()*(i+1));
File swap = files[r];
files[r] = files[i];
files[i] = swap;
}
int counter = 0;
//This displays the gray background cards. These cannot move but can be placed over with any other card.
int grayCounter = 0;
for(String rank : GRAY) {
for(File filename : files) {
if(filename.getName().contains(rank)) {
new ImageIcon(filename.getPath()).paintIcon(this, g,
PERIMETER_BEVEL + (grayCounter/4) * (CARD_WIDTH + INTERIOR_BEVEL),
PERIMETER_BEVEL + (3-(grayCounter%4)) * (CARD_HEIGHT + INTERIOR_BEVEL));
grayCounter++;
}
}
}
//This randomizes the ranks Ace through King.
for(int i = 0; i < RANKS.length; i++)
{
int r = (int)(Math.random()*(i+1));
String swap = RANKS[r];
RANKS[r] = RANKS[i];
RANKS[i] = swap;
}
//the filesystem so suits will automatically
for(String rank : RANKS) { //be in order when printing in groups of four
for(File filename : files) { //cards.
if(filename.getName().contains(rank)) {
new ImageIcon(filename.getPath()).paintIcon(this, g,
LEFT_PERIMETER_BEVEL + (counter/4) * (CARD_WIDTH + INTERIOR_BEVEL),
PERIMETER_BEVEL + (3-(counter%4)) * (CARD_HEIGHT + INTERIOR_BEVEL));
counter++;
} //counter/4 keeps track of the correct column
} //3-(counter%4) keeps track of the correct row
} //in which to print the card image
}
};
panel.setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
window.setBackground(Color.decode(BACKGROUND_COLOR));
window.add(panel);
window.setVisible(true);
window.pack();
}
}
Upvotes: 0
Views: 327
Reputation: 2534
I believe your problem is that you only randomize RANKS once, and then you use that for every row. Then the code here:
//This randomizes the ranks Ace through King.
for(int i = 0; i < RANKS.length; i++)
{
int r = (int)(Math.random()*(i+1));
String swap = RANKS[r];
RANKS[r] = RANKS[i];
RANKS[i] = swap;
}
//the filesystem so suits will automatically
for(String rank : RANKS) { //be in order when printing in groups of four
for(File filename : files) { //cards.
if(filename.getName().contains(rank)) {
new ImageIcon(filename.getPath()).paintIcon(this, g,
LEFT_PERIMETER_BEVEL + (counter/4) * (CARD_WIDTH + INTERIOR_BEVEL),
PERIMETER_BEVEL + (3-(counter%4)) * (CARD_HEIGHT + INTERIOR_BEVEL));
counter++;
} //counter/4 keeps track of the correct column
} //3-(counter%4) keeps track of the correct row
} //in which to print the card image
If I understand your code correctly, that second for-loop in the snippet above, will paint the cards for all the rows right? But for every row, you are using the same list of RANKS. You need to randomize RANKS in between each call to write the rows.
As I mentioned in the comments, it would probably be better to use an ArrayList of Strings for RANKS and use Collections.shuffle Then you can use the something like the following:
for (int row = 0; row < 4; row++)
{
Collections.shuffle(RANKS);
for(String rank : RANKS) {
for(File filename : files) {
if(filename.getName().contains(rank)) {
new ImageIcon(filename.getPath()).paintIcon(this, g,
LEFT_PERIMETER_BEVEL + (counter/4) * (CARD_WIDTH + INTERIOR_BEVEL),
PERIMETER_BEVEL + (row) * (CARD_HEIGHT + INTERIOR_BEVEL));
counter++;
}
}
}
}
Note: I didn't actually run that code, so you may need to make slight adjustments.
Also as @MadProgrammer pointed out, you shouldn't be loading all this in your paint method, but that is a different problem.
Upvotes: 2
Reputation: 2372
I would rethink your way of doing this, separating Deck from the Card and separating the controller from the renderer inside the render method. (Pseudo code only)
Something like this:
public class CardView{
String cardName, cardValue, [...];
public void render(int x, int y){
// Render this card, in the given (x,y) cordinates
}
}
public class DeckView{
ArrayList<CardView> cards;
public void renderAll(){
// Select random cars rows
// Shuffle cols
// For every card in array, call render inside the card with it's x and y
}
public ArrayList<CardView> getRandomCards(ArrayList<CardView> cards, int cardsToSelect){
// Returns n random cards from the given list
}
public ArrayList<CardView> shuffleCards(ArrayList<CardView> cards){
// Shuffle the given cards, in random order.
}
}
Upvotes: 1