Syntax when looking for an arraylist element - java

Ok so, I have a fillhand method that is supposed to get cards from a shuffled deck and add the cards one by one through the top method while also sorting them by suits. The top method saves the card at shuffledDeck at index 0 to a variable, removes the index at 0, and then returns the card. So i added the first card, then its suppose to check if the next card that top returns is of a different suit, if it is then add it to the array list, if it is of the same suit then add it to the arraylist but, in order of ranks within that suit. As of now, where it is supposed to check if the handArray contains the upcoming card's suit == false is not working.
public ArrayList fillHand(ArrayList Array, int handSize)
{
ArrayList<Card> shuffledDeck = Array;
handArray.add(deck.top(shuffledDeck));
for (int i = 0; i < handSize + 1; i++)
{
if (handArray.contains(shuffledDeck.get(i).getSuit()) == false)
{
handArray.add(deck.top(shuffledDeck));
}
}
return handArray;
}

Since you didn't post any code, I'll assume that Deck is a class with two attributes(rank and suit).
You'll want to create a method for this class that makes it print itself(i.e. "Ace of Spades" or "Jack of Hearts")
You'll also need a method that returns the suit.
From there you iterate over your arraylist and call that method on each node that satisfies the required suit
Edit, since code was posted:
The logic itself seems flawed, you're iterating over the handSize, checking if the suit number is in the handArray. This is a major issue, as handArray is an array of Card, not an array of int.
There are multiple ways to fix this, the simpler ones are:
Simplest: iterate over the handArray manually, checking if the suit matches with any of the card's
Faster: creating an array of size 4, with all values initialized as false, representing whether or not a suit is in the handArray.
Now that the if statement is dealt with, we must fix it's code. As of now, you're checking if the i suit is in the Array, and adding the top card to it.
The best course of action here would be ditching the for loop, replacing it with something like this:
while(ArrayList.size()){
/* code */
}
This will loop the array due to the way that top works, since it removes the top card

Related

Creating objects in loops

I am creating a simplistic poker game in Java that will create a deck of cards, let you draw a hand and display what kind of suit you have. Here is what I have so far and have run into a problem.
I have 3 different Array Lists, one for the card values, one for the card suits, and one to hold the actual card objects once the card suit and value is applied. I created a loop that is supposed to add a suit to each value (13 values) and add them into the newCards ArrayList (it is of type CARD, a different class I have that allows the objects to have both an integer and a string). After I try to print out newCards to see if it works properly. I get quite a few exception errors.
I'm not sure how to efficiently create a loop like this so any help is appreciated.
import java.util.*;
public class pokerMain {
public static void main (String [] args){
ArrayList<String> suits = new ArrayList<String>();//array list for the card suits
ArrayList<Integer> val = new ArrayList<Integer>();//array list for card values
ArrayList<CARDS> newCards = new ArrayList<CARDS>();//array list for cards with assigned val/suits
suits.add("Clubs");//These are the suits, added to the suits ArrayList
suits.add("Hearts");
suits.add("Diamonds");
suits.add("Spades");
System.out.println("suits contains: " + suits );//Testing for suit
for(int i = 1; i <= 13; i ++){//loop that adds all 13 values to to the val ArrayList
val.add(i);
}
System.out.println("val contains " + val);//Testing for val
This is the loop
for(int i = 0; i <= val.size(); i ++){//This loop will be used to add a suit to every card value
newCards.add(new CARDS(suits.get(0), val.get(i)));//assigns hearts
newCards.add(new CARDS(suits.get(1), val.get(i)));//assigns hearts
newCards.add(new CARDS(suits.get(2), val.get(i)));//assigns diamonds
newCards.add(new CARDS(suits.get(3), val.get(i)));//assigns spades
}
-------------------------------------------------------------------------
System.out.println(newCards.toString());//prints newCards arrayList
//newCards.add(card);// puts card object into array list newCards
To prevent code duplication you could try two loops and use for each
for(String s : suits) {
for(Integer i : val) {
newCards.add(new CARDS(s, i));
}
}
Firstly, as John Mercier said, for:each is the way to go here.
Secondly, and this isn't causing your problem, but CARDS is not exactly a conventional class name. Something like Card or Cards (or wrap the Card in a Deck class...).
Thirdly, and most importantly, the main() doesn't seem to be your problem, as far as I can tell. Check your CARDS class.

Pulling and printing the first object from arraylist?

I'm trying to deal a card (the object) from my deck (the arraylist) and I'm having trouble trying to get the first object in the arraylist.
I've used a shuffle method (which is working and prints out the total number of cards in the newly shuffled pack) but I have no idea how to get the first object from the array (ie dealing a card from the top).
Can anyone point me in the right direction please?
Thanks.
Take a look at the ArrayList.get(int index) method. It'll return the object at the given position (index).
In your case, it'd be the yourList.get(0).
List#remove() will help:
List<String> cards = new ArrayList<>();
for (char suit : "♥♦♠♣".toCharArray())
for (char rank : "23456789TJQKA".toCharArray())
cards.add(String.valueOf(rank) + String.valueOf(suit));
Collections.shuffle(cards);
System.out.println(cards.remove(0)); // Q♥ //

Java - War Game - Getting an object from an array

I'm new to Java and I am having trouble wrapping my mind around one of the concepts.
The assignment I am currently working on is the card game War. The current instructions is for me to remove a random card from a a deck of cards.
I have created an array, but it is an array of class Card. The class creates the card by basically adding an int and a String together. I then created the array from that class. In my mind, I neither have an int or a String in my array, is that correct?
Now I need to remove one of the random cards from the deck and give it to a player. This is where I am getting lost. I would think I can just use Random to remove a random card, but I always seem to get an error.
I'm not asking for you to do the assignment for me, but if you would please point me in the right direction and possibly correct me if I am confused.
Current Class I am working on:
import java.util.Random;
import java.util.*;
public class War3
{
Random ran = new Random();
public FullDeck randomCard()
{
ArrayList <FullDeck> randCard = new ArrayList <FullDeck> (52);
int index = ran.nextInt(randCard.size());
FullDeck x = randCard.remove(index);
return x;
}
public void display()
{
System.out.println("Your card is" + randomCard());
}
}
Entire project for clarification Java - War Game - Gist
Many thanks in advance.
ArrayList <FullDeck> randCard = new ArrayList <FullDeck> (52);
This creates an ArrayList. You do not need to specify the number 52, since ArrayLists grow dynamically, as opposed to Arrays. The call is similar to
ArrayList <FullDeck> randCard = new ArrayList <FullDeck> ();, the difference being that the constructor you used sets the initial capacity of the ArrayList to 52. That in no way restricts the size of the ArrayList though.
Anyway, you are creating a new, empty ArrayList. Then you want the size, but since you didn't put anything into the list, it is still empty, to the size is zero. You then try to call ran.nextInt(0)... nextInt(int n) expects a number greater than zero. From the javadoc:
public int nextInt(int n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
Two issues that I see:
You're creating an ArrayList that can hold a reference to 52 instances of the FullDeck class, but you're not adding anything to it. You need to do something like randCard.add(new FullDeck()) 52 times/in a loop**. Then likely you'll want to "shuffle" the deck, see this question for how to do that.
You're naming is a little weird...the FullDeck class in actuality seems like it should be renamed to just Card, and the randCard variable should be renamed to something like fullDeck...after you've added 52 Cards.
**EDIT: actually, the generation of a deck of cards will be more complicated to make sure you don't have any duplicate cards.

Iterable/Multidimensional array next method issues

Disclaimer: This is for a homework assignment.
I am currently working on an assignment where I need to implement an iterable interface in order to pass each array from a square two-dimensional array. This array is supposed to represent a grid of numbers (so I will be referring to them as such [row][col]). My problem is that I want to use the same next method to iterate through the rows and the columns. First, is this possible? Second, any suggestions/hints?
My next method currently looks like this:
public Data[] next(){
Data [] holder = new Data[ray.length];
for (int i = 0; i <ray.length; i++)
holder[i]=ray[counter][i];
counter++;
return holder;}
EDIT: I am aware of being able to switch counter and i in ray[counter][i], but I'm not sure how to have it do both if that's possible.
ray is the multidimensional array and count is an attribute of the Iterator method I've created (It's initialized to 0 and this is the only method that changes it). I know I cannot return the "column" of ray this way, so how would I go about having next call columns and rows?? Thanks for any of the help. I'll be standing by if you have further questions.
My problem is that I want to use the same next method to iterate through the rows and the columns. First, is this possible?
Yes it is possible, assuming you mean what I think you mean. (The phrase "iterate through the rows and the columns" is horribly ambiguous.)
Since this is a homework exercise here are a couple of hints:
You need two counters not one.
When you get to the end of one row you need to go to the start of the next row. (Obviously!) Think about what that means if you've got two counters.
This should be enough to get you on the right track.
I want a row by row iteration and a column by column iteration.
This is also a horribly ambiguous description, but I'm going to interpret it as meaning that sometimes you want to iterate left to right and top to bottom, and other times you want to iterate top to bottom and left to right.
That is also possible:
One possibility is to use an extra state variable to tell the iterator which direction you are iterating; i.e. row within column, or column within row.
Another possibility is to implement two distinct Iterator classes for the two directions.
The problem is that the iterator class is only supposed to have one counter and returns an single-dimension array.
You've (finally) told us unambiguously that the iterator is supposed to return an array. (A good dentist could pull out a tooth quicker than that!)
So here's a hint:
Returning the ith row is easy, but returning the jth column requires you to create a new array to hold the values in that column.
My advice is: transform the 2d array to a list and iterate.
When initialize the Iterator, transform the list. Then you could iterate the list easily.
Following is p-code, you could enrich the implementation in your homework. Hope it helps you!
class TwoDimeIterator implements Iterator<Date> {
List transformedList = new ArrayList();
int cursor = 0;
/** transform to a list row by row.
So you could define your Iterator order.**/
TwoDimeIterator(){
for(int i=0; i < ray.length; i++)
for(int j=0; j < ray[0].length; j++)
transformedList.add(ray[i][j]);
}
public Date next() {
return transformedList.get(cursor++);
}
public boolean hasNext() {
return cursor != transformedList.size();
}
//...
}

Sorting a deck of cards by suit and then rank

I have this Java class:
class Card
{
private Suit suit;
private int rank;
}
(Suit is an enum)
There are four suits with ranks 1-9 each and four suits with a single possible rank 0. Each card exists in an unknown but constant among all cards number of copies. How would I sort a deck in a set order of suits, and by increasing rank in each suit?
You'll need to either
implement the Comparable interface on the card object: add a compareTo function that determines whether another card should be before or after this one in the sort order
implement a Comparator object that accepts two cards and indicates which order they should appear in
and then you can use Collections.sort on your list.
Have a look at implementing Comparable on the enum.
Make Rank an enum too and you can deal a sorted deck as such:
for (Suit suit : Suit.values())
for (Rank rank : Rank.values())
deck.add(new Card(rank, suit));
make it implement the Comparable interface. Theres only only one method you'll need to write. Then they can be compared to each other, and you have a number of existing sort options, such as static Arrays.sort if you have an array or Collections.sort if its any kind of Collection (List, Vector, etc)
Besides implementing on Card you might have to do the same for Suit depending on how its done.
Here would be an example of the Card Class. As the questions states the Suit would be of a specific class while the Rank would be an integer (in this example I didn't implement rank validation). Implementing the Comparable class allows a Card class to compare another Card Class. So that a List/Set of Cards can be sorted.
public class Card implements Comparable<Card>{
private SUIT cardSuit;
private int cardRank;
public enum SUIT {SPADE, CLUB, HEART, DIAMOND};
public Card(int cardRank, SUIT cardSuit) {
this.cardSuit = cardSuit;
this.cardRank = cardRank;
}
/**
* Generates a random card
*/
public Card(){
this((int) (Math.random() * 9) , SUIT.values()[(int) (Math.random() * SUIT.values().length)]);
}
public String getSuit() {
return cardSuit.toString();
}
public int getRank() {
return cardRank;
}
#Override
public int compareTo(Card2 o) {
if (this.cardRank == o.cardRank) {
return this.cardSuit.compareTo(o.cardSuit);
} else {
return o.cardRank - this.cardRank;
}
}
}
A fast way to accomplish this task is by Radix Sort. Set up an array of lists of card values, then walk through your deck, placing each card into the appropriate list as you encounter it. Then merge all the lists together into a partially sorted deck. Now do the same thing, only with an array of lists of suits. Merge all the lists together and you should have a sorted deck.
Although I don't see it posted now, I believe that the original poster was working with a representation of cards that is very similar to the one that I worked with. Specifically, I remember seeing cards in the original post similar to the following format:
[ 'As', 'Kd', '4c', '6h' . . ..], i.e., Ace of Spades, King of Diamonds, 4 of Clubs, and 6 of Hearts, etc.
In my case, I was working with a whole deck of cards represented as follows:
[AcQhJd8h9c9h6d3cTc3dQdKhJs6h3hThQc7d3sJc4h2h6c8d7c5c7s8cAd4dTd9sKs5h8s2c4c2d2s5sAhKd9dKcQs4s5dAs7hJhTs6s]
This deck is one of hundreds of thousands of decks found by Mathematician Jeremy Kun where a two player game of Texas Holdem always results in a win for Player #1 no matter where the deck is cut (but not shuffled). For more details, see, https://jeremykun.com/2012/04/09/optimal-stacking-hold-em/
I found that reading each card as text and trying to figure who won and who lost with what hole cards, burn cards, and community cards (flop, turn and river) was well nigh impossible. I wanted to see actual cards separated for each player's hole cards, the community cards, etc.
The format of the deck of cards is understandable, but it is not in the form of an actual array that would be recognized using JavaScript. So, I started by turning it into a string by replacing the square brackets with quote marks. From there, I could use string methods to take two characters at a time and translate them into visible cards. I could have done that any number of ways, but I chose to use Unicode card characters since they behave just like text and can be resized and be given different colors with CSS, just like text.
The format for displaying a Unicode card character within the inner html of an element, e.g., a span element, is to use the code pattern &#x1f0_ _ ; where the two blanks will be first a hex number for the suit and then a hex number for the rank of the card.
The possible hex numbers for the suits are 'a' = spades, 'b' = hearts, 'c' = diamonds, and 'd' = clubs.
The possible hex numbers for the rank of each card are:
'1' = ace, '2' = 2, . . . 'a' = 10, 'b' = Jack, 'c' = "Count" (not used in poker, as in Count Dracula never gets invited to poker games), 'd' = Queen, and 'e' = King.
When using the code pattern &#x1f0_ _; the length of the characters will be 9 characters when first coded, but after the card is displayed on an html page, the browser converts the code into two characters, which will change the length of your html element for each card. For example, a span element with no attributes and inner html code for a card would be 22 characters long, but after being displayed on an html page, the length would change to 7 less (i.e., 15).
My code for displaying the above deck as Unicode card characters is fairly short:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Display Deck</title>
<style type="text/css">
body {
font-size: 21pt;
}
span {
background-color: white;
}
.aspade {
color: black;
}
.bheart {
color: red;
}
.cdiams {
color: mediumvioletred;
}
.dclubs {
color: blue;
}
</style>
</head>
<body>
<p id="displayPoint"></p>
<script type="text/javascript">
let holdemWinDeck = 'AcQhJd8h9c9h6d3cTc3dQdKhJs6h3hThQc7d3sJc4h2h6c8d7c5c7s8cAd4dTd9sKs5h8s2c4c2d2s5sAhKd9dKcQs4s5dAs7hJhTs6s';
let displayDeck = [];
let rankTranslate = {'A':'1', '2':'2', '3':'3', '4':'4', '5':'5', '6':'6', '7':'7', '8':'8', '9':'9', 'T':'a', 'J':'b', 'Q':'d', 'K':'e'};
let suitTranslate = {'h':'b', 'c':'d', 'd':'c', 's':'a'};
for (let i = 0; i < holdemWinDeck.length; i += 2) {
let unicodeCardRank = rankTranslate[holdemWinDeck.slice(i, i + 1)];
let unicodeCardSuit = suitTranslate[holdemWinDeck.slice(i + 1, i + 2)];
let plainSuitNameTranslate = {'b':'bheart', 'd':'dclubs', 'c':'cdiams', 'a':'aspade'};
let className = plainSuitNameTranslate[unicodeCardSuit];
let card = (`<span onclick='cutCards(this.outerHTML);' class='${className}'>&#x1f0${unicodeCardSuit}${unicodeCardRank};</span>`);
displayDeck.push(card);
}
document.getElementById('displayPoint').innerHTML=displayDeck.join('');
</script>
</body>
</html>
When I first tried to use the string method, .slice(), to access the suit and rank number for each card, I hit a wall. The two characters are actually four characters each, which are known as the "surrogate pair" of Unicode codes that are used under the hood of the browser to display a card since the longer code first written has to be translated by the browser into two shorter codes to represent and display the card. Worse, when you query for the length of either surrogate pair of four characters, you will get back a length of one. You will not be allowed to use slice() among the four characters of either surrogate pair.
The first surrogate (called the "high surrogate") is always the same four characters for any Unicode card character, and the second surrogate (called the "low surrogate" has the same first two characters for any Unicode card character, but the last two characters are where the magic happens, they are the very same two characters for suit and rank as in the original code.
I knew that I would need to access those two codes so that I could ask questions about suit or rank in any given sequence of cards. For example, to determine whether a player's two hole cards and five community cards hold a Royal Flush, I would need to ask if there were five cards of the same suit and whether those cards were in a numerical sequence of one number apart with an ace at the top. (Ultimately, I did it differently, and plan to change it yet again, but I still need access to suit and rank information among the cards.)
I searched the Internet and found my solution in two methods that I had never really used or understood before:
for (let i = 0; i < arr7.length; i++) {
suit[i] = arr7[i].slice(57, 59).codePointAt(0).toString(16).slice(3, 4);
rank[i] = lowAcesAnd_C_Gap[arr7[i].slice(57, 59).codePointAt(0).toString(16).slice(4, 5)];
}
The variable arr7 is an array of a player's two hole cards concatenated with the community cards and then sorted (.sort() ), which puts the cards into suit order first and then into rank order within each suit. So, my new arrays of suit and rank will follow the same order as the original sorted arr7. I may then ask suit and rank questions in my JavaScript code, and, if satisfied, pull actual cards from the same positions in the original arr7.
I have found that I need to sort purely by rank but still have access to the card, so I have also created an array that puts the rank before the actual card so that I will still have access to the card after I sort purely by rank.

Categories