javaarraysarraylistprintingplaying-cards

Need help on printing an Array of ArrayLists (of different sizes)


I'm making my own solitaire program I can run on my computer (for leisure and practice) and I am trying to display my 'ArrayList<Card>[] playspace' like it shows in Solitaire. More specifically I'm trying to display the card order downward instead of to the right side like it currently is. Following is my entire program (necessary classes needed to run).

This seemed to be a solution when I checked, but their issue was the bounds of the array and I don't think they included the printing function, it is also not a 2D Array of ArrayLists... so it might be a solution but it looks just off enough to not be what I need.

Card:

package Playspace;

import java.util.Arrays;
import java.util.List;

/**
 * A card object with value, suit, and faceUp identification.
 * 
 * @author Austin M
 * @param numValue
 * @param faceValue
 * @param suit
 * @param faceUp
 */
public class Card {

    private int numValue;
    private String faceValue;
    private String suit;
    private String shortSuit;
    public boolean faceUp;
    public String[] values = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", " " };
    public String[] suits = { "Clubs", "Diamonds", "Hearts", "Spades", " " };

    /**
     * Public constructor for generating a card with value face & suit
     * 
     * @param value
     * @param suit
     */
    Card(String faceValue, String suit, boolean faceUp) {
        for (String v : values) {
            if (v.equals(faceValue)) {
                this.faceValue = faceValue;
                setNumValue(faceValue);
            }
        }
        for (String s : suits) {
            if (s.equals(suit)) {
                this.suit = suit;

                shortSuit = suit.substring(0, 1);
            }
        }
        this.faceUp = faceUp;
    }

    /**
     * Private method, returns a list of valid card values
     * 
     * @returns Arrays.asList()
     */
    private static List<String> getValues() {
        return Arrays.asList("A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", " ");
    }

    /**
     * Private method, returns a list of valid suit values
     * 
     * @return Arrays.asList()
     */
    @SuppressWarnings("unused")
    private static List<String> getSuits() {
        return Arrays.asList("clubs", "diamonds", "hearts", "spades", " ");
    }

    /**
     * Gets string value of face
     * 
     * @return String faceValue
     */
    public String getFaceValue() {
        return faceValue;
    }

    @SuppressWarnings("unused")
    private void setFaceValue(String faceValue) {
        this.faceValue = faceValue;
    }

    /**
     * Gets suit value of card
     * 
     * @return String suit
     */
    public String getSuit() {
        return suit;
    }

    /**
     * Gets faceUp value of card
     * 
     * @return Boolean faceUp
     */
    public boolean isFaceUp() {
        return faceUp;
    }

    /**
     * Sets the card face up
     */
    public void setFaceUp() {
        this.faceUp = true;
    }

    /**
     * Sets the card face down
     */
    public void setFaceDown() {
        this.faceUp = false;
    }

    /**
     * Gets numerical value of card
     * 
     * @return int numValue
     */
    public int getNumValue() {
        return numValue;
    }

    /**
     * Sets numerical value with the index + 1 of the corresponding face value
     * 
     * @param faceValue
     */
    private void setNumValue(String faceValue) {
        numValue = getValues().indexOf(faceValue) + 1;
    }

    /**
     * Generates a string with faceValue and Suit, if card is face down, it does not
     * display card value
     * 
     * @return String concat
     */
    @Override
    public String toString() {
        String concat;
        if (faceUp) {
            concat = extValue() + " of " + suit;
        } else {
            concat = " --- --- --- --- ";
        }

        return concat;
    }

    public String shortHand() {
        String shortHand = "";
        if (faceUp) {
            shortHand = "[" + String.format("%-3s", faceValue) + shortSuit + "]";
        } else {
            shortHand = "[ -- ]";
        }

        return shortHand;
    }

    /**
     * Returns the Extended value of the card name (if it's Jack-Ace)
     * 
     * @return String faceValue
     */
    private String extValue() {

        faceValue = faceValue.toUpperCase();
        if (faceValue.equals("A")) {
            return "Ace";
        } else if (faceValue.equals("J")) {
            return "Jack";
        } else if (faceValue.equals("Q")) {
            return "Queen";
        } else if (faceValue.equals("K")) {
            return "King";
        }
        return faceValue;
    }

}

Deck:

package Playspace;

import java.util.ArrayList;
import java.util.Collections;

/**
 * A collection of Card objects where the order can be manipulated
 * 
 * @author Austin M
 * @param deck
 */
public class Deck {

    public ArrayList<Card> deck = new ArrayList<Card>();

    Deck() {
        generateCards();
    }

    /**
     * Shuffles the deck randomly using Collections.shuffle() method
     */
    public void shuffleDeck() {
        Collections.shuffle(deck);
    }

    /**
     * Generates 52 card objects in a collection
     */
    void generateCards() {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 13; j++) {
                addCard(i, j);
            }
        }

    }

    /**
     * Gets the top card (first in deck)
     * 
     * @return Card
     */
    public Card getTop() {
        return deck.get(0);
    }

    /**
     * Gets the card in given value of the deck (0-51)
     * 
     * @param int pos
     * @return Card
     */
    public Card getPos(int pos) {
        return deck.get(pos);
    }

    /**
     * Combines the contents of the deck list and prints out the deck in a right
     * aligned column (%18s\n)
     * @return String concat
     */
    @Override
    public String toString() {
//      String concat = "";
//
//      for (Card card : deck) {
//          concat += card.toString() + " ";
//      }
        String concat = "";
        for (Card card : deck) {
            concat += String.format("[%17s]\n", card.toString());
        }

        return concat;
    }

    /**
     * Combines the contents of the deck list and prints out the deck in a right
     * aligned column (%5s\n)
     */
    public String shortHand() {
        String concat = "";
        for (Card card : deck) {
            concat += String.format("%5s\n", card.shortHand());
        }
        return concat;
    }

    /**
     * Adds a card to ArrayList<Card> deck given suit (i) and faceValue (j)
     * 
     * @param i
     * @param j
     */
    private void addCard(int i, int j) {
        String suit, faceValue;
        switch (i) {
        case 0: {
            suit = "Clubs";
            break;
        }
        case 1: {
            suit = "Diamonds";
            break;
        }
        case 2: {
            suit = "Hearts";
            break;
        }
        case 3: {
            suit = "Spades";
            break;
        }
        default:
            suit = "clubs";
            System.err.println("Unexpected suit: " + i);
        }

        switch (j) {
        case 0: {
            faceValue = "A";
            break;
        }
        case 1: {
            faceValue = "2";
            break;
        }
        case 2: {
            faceValue = "3";
            break;
        }
        case 3: {
            faceValue = "4";
            break;
        }
        case 4: {
            faceValue = "5";
            break;
        }
        case 5: {
            faceValue = "6";
            break;
        }
        case 6: {
            faceValue = "7";
            break;
        }
        case 7: {
            faceValue = "8";
            break;
        }
        case 8: {
            faceValue = "9";
            break;
        }
        case 9: {
            faceValue = "10";
            break;
        }
        case 10: {
            faceValue = "J";
            break;
        }
        case 11: {
            faceValue = "Q";
            break;
        }
        case 12: {
            faceValue = "K";
            break;
        }
        default:
            faceValue = "A";
            System.err.println("Unexpected value: " + j);
        }
        deck.add(new Card(faceValue, suit, false));

    }
}

Wasp:

package Playspace;

import java.util.ArrayList;
import java.util.Arrays;

public class Wasp extends Playspace {

    Wasp() {
        setUp();
    }

    @Override
    public void setUp() {
        initialize();

//      deck.shuffleDeck();
        setFaceUp();

        for (int i = 0; i < 49; i += 7) {
            playSpace[0].add(deck.getPos(i));
            playSpace[1].add(deck.getPos(i + 1));
            playSpace[2].add(deck.getPos(i + 2));
            playSpace[3].add(deck.getPos(i + 3));
            playSpace[4].add(deck.getPos(i + 4));
            playSpace[5].add(deck.getPos(i + 5));
            playSpace[6].add(deck.getPos(i + 6));
        }
//      System.out.println(deck.shortHand());
        displayBoard();
    }

    /**
     * 
     */
    public void setFaceUp() {
        int[] faceDownPos = { 0, 1, 2, 3, 7, 8, 9, 10, 14, 15, 16, 17 };
        for (int i = 0; i < 49; i++) {
            int res = Arrays.binarySearch(faceDownPos, i);
            boolean test = res >= 0 ? true : false;

            if (!test) {
                deck.getPos(i).setFaceUp();
            }
        }
    }
    
    /**
     * Displays the playSpace as shorthand card values (testing)
     */
    public void displayBoard() {
        playSpace[0].add(new Card(" ", " ", true)); //Used in testing, not necessary to include in final
//      playSpace[0].remove(6); //Used in testing, not necessary to include in final
        playSpace[3].add(new Card(" ", " ", true)); //Used in testing, not necessary to include in final
        for (ArrayList<Card> ac : playSpace) {
            for (Card c : ac) {
                System.out.print(c.shortHand());
            }
            System.out.println();
        }
        
        
    }
    
//  /**
//   * Displays playSpace as shorthand card values (defunct)
//   * @param column
//   * @return String concat
//   */
//  public String shortHand(int column) {
//      String concat = "";
//      for (Card card : playSpace[column]) {
//          concat += String.format("%5s\n", card.shortHand());
//      }
//      return concat;
//  }
}

Playspace:

package Playspace;

import java.util.ArrayList;

/**
 * A game board class for utilizing Card and Decks
 * 
 * @author Austin M
 * 
 * @param ArrayList<Card>[] playSpace
 * @param ArrayList<Card>[] buffer
 * @param Deck deck
 * @param Card[] offHand
 */
public abstract class Playspace {

    @SuppressWarnings("unchecked")
    public ArrayList<Card>[] playSpace = new ArrayList[7];
    public ArrayList<Card> buffer = new ArrayList<Card>();
    public Deck deck = new Deck();
    public Card[] offHand = new Card[3];

    public abstract void setUp();

    public abstract void setFaceUp();

    public abstract void displayBoard();

    public void initialize() {
        for (int i = 0; i < 7; i++) {
            playSpace[i] = new ArrayList<Card>();
        }
    }
}

Main:

package Playspace;

/**
 * 
 * @author Austin M
 *
 */
public class Main {

    public static void main(String[] args) {
//      Deck deck1 = new Deck();
//      Deck deck2 = new Deck();
//      pointCount(deck1, deck2);
        
        @SuppressWarnings("unused")
        Wasp wasp = new Wasp();

    }

    @SuppressWarnings("unused")
    private static void pointCount(Deck deck1, Deck deck2) {
        deck1.shuffleDeck();
        System.out.println(deck1);

        deck2.shuffleDeck();
        System.out.println(deck2);
        
        int points = 0;
        for (int i = 0; i < 52; i++) {
            if (deck1.getPos(i).toString().equals(deck2.getPos(i).toString())) {
                System.out.println("At position: " + (i + 1) + "\n" + deck1.getPos(i).toString());
                points++;
            }
        }
        System.out.println(points + " points.\n");
    }

    @SuppressWarnings("unused")
    private static void compare(Deck deck) {
        int pos = 0;
        for (int i = 0; i < 10; i++) {
            System.out.println("Iteration: " + (i + 1));

            if (deck.getPos(pos).getNumValue() > deck.getPos(pos + 1).getNumValue()) {
                System.out.println("The card: " + deck.getPos(pos).toString().toUpperCase()
                        + " is \nhigher in value than " + deck.getPos(pos + 1).toString().toUpperCase());
            } else if (deck.getPos(pos).getNumValue() == deck.getPos(pos + 1).getNumValue()) {
                System.out.println("The card: " + deck.getPos(pos).toString().toUpperCase() + " is \nequal in value to "
                        + deck.getPos(pos + 1).toString().toUpperCase());
            } else {
                System.out.println("The card: " + deck.getPos(pos).toString().toUpperCase()
                        + " is \nlower in value than " + deck.getPos(pos + 1).toString().toUpperCase());
            }
            System.out.println();
            pos++;
        }
    }
}

As it stands it prints like:

[ -- ][ -- ][ -- ][9  D][3  H][10 H][4  S][    ]
[ -- ][ -- ][ -- ][10 D][4  H][J  H][5  S]
[ -- ][ -- ][ -- ][J  D][5  H][Q  H][6  S]
[ -- ][ -- ][ -- ][Q  D][6  H][K  H][7  S][    ]
[5  C][Q  C][6  D][K  D][7  H][A  S][8  S]
[6  C][K  C][7  D][A  H][8  H][2  S][9  S]
[7  C][A  D][8  D][2  H][9  H][3  S][10 S]

but I want it to print like: (Flipped along the line X = -Y)

[ -- ][ -- ][ -- ][ -- ][5  C][6  C][7  C]
[ -- ][ -- ][ -- ][ -- ][Q  C][K  C][A  D]
[ -- ][ -- ][ -- ][ -- ][6  D][7  D][8  D]
[9  D][10 D][J  D][Q  D][K  D][A  H][2  H]
[3  H][4  H][5  H][6  H][7  H][8  H][9  H]
[10 H][J  H][Q  H][K  H][A  S][2  S][9  S]
[4  S][5  S][6  S][7  S][8  S][9  S][10 S]
[    ]            [    ]                  

Where each ArrayList is a column in an Array of 7. In the future (if I get a functional display, I would be removing the brackets around blank cards, simply having them in line with the columns as spaces, but one bridge at a time.


Solution

  • This isn't super pretty, but it does the trick. I created a queue for each column and scanned through popping one element off of each to make a row. I had to put a spacer for the columns that had already run out of elements.

    List<Deque<Card>> deques = Arrays.stream(playSpace)
        .map(ArrayDeque::new)
        .collect(Collectors.toList());
    
    while(deques.stream().anyMatch(dq -> !dq.isEmpty())) {
        System.out.println(deques.stream()
            .map(dq -> dq.isEmpty()?"      ":dq.pop().shortHand())
            .collect(Collectors.joining()));
    }