Picking cards at random, then excluding those from further picking.

edited November 2015 in How To...

Hello, I'm reading a csv file which looks roughly like the following:

Each row is a different playing card.

  • Number, value, suit, image,
  • 1, Ace, Clubs, 1c.jpg,
  • 2, Two, Clubs, 2c.jpg,
  • 3, Three, Clubs, 3c.jpg, ... etc

My question is this: I'd like to pick a few rows at random (ace of hearts, five of diamonds, three of spades) and load their respective fields into my program but I need to make sure that no duplicate cards show up.

How do I limit the choices of a random table entry so that it only chooses entries that haven't been chosen before?

The way I'm doing it just now is finding a random row in my table, setting an int to that random row number called randcard, Then, say I wanted to find the jpg name of randcard, I'd do:

String s = table.getString(3,randcard)

But the problem is how to then pull another random card (row) from the deck, ignoring the ones that can't still be in there.

I hope this makes sense, thanks for your time. James

Answers

  • There are several ways. One of them is to store the cards you have drawn in a list. Then when you draw another card, you check if it is already in the list, and redraw if it is there. Not the most efficient way, but simple enough.

    Another way is to make a copy of the list of cards. When you draw one, you just remove it from the list.

  • edited January 2016 Answer ✓

    Made a Card class to represent a Table structured loaded from a ".csv" file. ;)

    Since I don't have your original file (and images), I've made a sketch to create a similar 1.
    If your original ".csv" file doesn't work w/ my program, you gotta generate a new 1 too:


    /** 
     * Table CSV Card Pack Creation (v1.01)
     * by GoToLoop (2014/Feb)
     *
     * forum.Processing.org/two/discussion/2801/
     * picking-cards-at-random-then-excluding-those-from-further-picking-
     */
    
    final String[] ranks = {
      "Ace", "Two", "Three", "Four", "Five", 
      "Six", "Seven", "Eight", "Nine", "Ten", 
      "Jack", "Queen", "King"
    };
    
    final String[] suits = {
      "Clubs", "Diamonds", "Hearts", "Spades"
    };
    
    final Table table = new Table();
    
    table.addColumn("Number", Table.INT);
    table.addColumn("Rank");
    table.addColumn("Suit");
    table.addColumn("Image");
    
    for (int r = 0, s = 0; s != suits.length; ++s, r = 0)
      while (r != ranks.length) {
        final TableRow newRow = table.addRow();
    
        newRow.setString("Rank", ranks[r]);
        newRow.setString("Suit", suits[s]);
    
        newRow.setInt("Number", ++r);
    
        newRow.setString("Image", str(r) + 
          Character.toLowerCase(suits[s].charAt(0)));
      }
    
    saveTable(table, dataPath("Cardpack.csv"));
    
    exit();
    

    And finally my model solution: :bz


    /** 
     * Table CSV Card Pack Loading (v1.2)
     * by GoToLoop (2014/Feb)
     *
     * forum.Processing.org/two/discussion/2801/
     * picking-cards-at-random-then-excluding-those-from-further-picking-
     */
    
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
    
    static final String ARCHIVE = "Cardpack.csv", EXT = ".jpg";
    static final int NUM = 5, GAP = 040, FPS = 60;
    
    Card[] cards;
    final List<Card> myHand = new ArrayList<Card>(NUM);
    
    void setup() {
      size(800, 600);
      frameRate(FPS);
      noLoop();
      smooth(4);
    
      fill(0200);
      textSize(GAP);
      textAlign(CENTER);
    
      cards = loadCards(ARCHIVE, EXT, true);
    
      showDeckContent(true, cards);
      println(ENTER);
    
      mousePressed();
    }
    
    void draw() {
      clear();
    
      for (int i = myHand.size(); i-- != 0; 
        myHand.get(i).displayAt(width>>1, i*GAP + GAP));
    }
    
    void mousePressed() {
      final int btn = mouseButton;
      final int len = myHand.size();
    
      if (btn == RIGHT & len > 0)  myHand.remove(len - 1);
      else if (btn == LEFT)        pickCard();
      else                         PickNewRandomHand(NUM);
    
      println(myHand);
      println();
    
      redraw();
    }
    
    Card[] loadCards(String name, String ext, boolean gotHeader) {
      final Table table = loadTable(name, gotHeader? "header":"");
      final Card[] deck = new Card[table.getRowCount()];
    
      table.setColumnType(0, Table.INT);
    
      for (int i = 0; i != deck.length; ++i) {
        final TableRow row = table.getRow(i);
    
        final int num = row.getInt(0);
        final String rank = row.getString(1), suit = row.getString(2);
        final PImage img = loadImage(row.getString(3) + ext);
    
        deck[i] = new Card(num, rank, suit, img);
      }
    
      return deck;
    }
    
    static final void showDeckContent(boolean toSort, Card... cards) {
      println();
      println(cards);
      println();
    
      if (toSort) {
        Arrays.sort(cards);
        println(cards);
        println();
      }
    
      for (Card c : cards) {
        final int  rank = c.hash & 0xFF;
        final char suit = (char) (c.hash >> 020);
        print(" - " + rank + suit);
      }
    }
    
    void pickCard() {
      if (myHand.size() >= cards.length)  return;
    
      Card c;
    
      do c = cards[(int) random(cards.length)];
      while (myHand.contains(c));
    
      myHand.add(c);
      Collections.sort(myHand);
    }
    
    void PickNewRandomHand(int qty) {
      if ((qty = min(abs(qty), cards.length))
        == (cards.length | myHand.size()))  return;
    
      myHand.clear();
    
      if (qty == cards.length) {
        myHand.addAll(Arrays.asList(cards));
        return;
      }
    
      while (qty != 0) {
        final Card c = cards[(int) random(cards.length)];
    
        if (!myHand.contains(c)) {
          myHand.add(c);
          --qty;
        }
      }
    
      Collections.sort(myHand);
    }
    
    final class Card implements Comparable<Card> {
      short x, y;
      final byte w, h;
      final byte value, group;
      final int hash;
      final String rank, suit, info;
      final PImage img;
    
      Card(int val, String r, String s, PImage pic) {
        value = (byte) abs(val);
        rank = r;
        suit = s;
        img = pic;
    
        group = (byte) suit.charAt(0);
        hash = group<<020 | value;
    
        w = (byte) (img == null? 0 : img.width);
        h = (byte) (img == null? 0 : img.height);
    
        info = rank + " of " + suit;
      }
    
      Card setPos(int x, int y) {
        x = (short) x;
        y = (short) y;
    
        return this;
      }
    
      Card display() {
        return displayAt(x, y);
      }
    
      Card displayAt(int xx, int yy) {
        if (img != null)  set(xx, yy, img);
        else text(info, xx, yy);
    
        return this;
      }
    
      String toString() {
        return info;
      }
    
      int hashCode() {
        return hash;
      }
    
      boolean equals(Object o) {
        return o instanceof Card? 
          ((Card) o).hash == hash : false;
      }
    
      int compareTo(Card o) {
        return value != o.value? 
          Integer.signum(value - o.value) :
          Integer.signum(group - o.group);
      }
    }
    

  • edited February 2014 Answer ✓

    A fast array based approach:

    String[] cardStack = { "Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" };
    int stackSize = cardStack.length;
    
    void setup() {
        String card;
        for(int n = 0; n < 100; n++) {
            card = getRandomCard();
            if(card != null)
                println("Card " + n + " is: " + card);
            else
                break;
        }
    }
    
    String getRandomCard() {
        if(stackSize <= 0)
            return null;
        int index = (int)random(stackSize);
        stackSize--;
        String card = cardStack[index];
        cardStack[index] = cardStack[stackSize];
        cardStack[stackSize] = card;
        return card;
    }
    
    void resetStack() { // Just to show how to reset the stack
        stackSize = cardStack.length;
    }
    
Sign In or Register to comment.