Here I created a Card class that gives a value of suit and rank to a card I also created a Deck class that gives 52 cards, one of the standard playing cards, a shuffle method, deal method, report method( to report number left in deck) and toString method. My problem is in my Deck class when i try to make a new deck of cards. I receive this error from the Deck class:
Deck.java:12: error: cannot find symbol
for (int suit = Card.DIAMONDS; suit <= Card.SPADES; suit++)
symbol: variable DIAMONDS
location: class Card
Deck.java:12: error: cannot find symbol
for (int suit = Card.DIAMONDS; suit <= Card.SPADES; suit++)
symbol: variable SPADES
I've tried changing Card.DIAMONDS to Suit.DIAMONDS and that gave me another error. Any help as to what method my problem is in would be appreciate. This is a learning experience for me so Id like guidance not exact solutions.
enum Suit {
HEARTS, DIAMONDS, CLUBS, SPADES
};
enum Rank {
ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING
};
public class Card {
private Rank aRank;
private Suit aSuit;
public Card(Suit aSuit, Rank aRank) {
this.aSuit = aSuit;
this.aRank = aRank;
}
public Rank getRank() {
return aRank;
}
public Suit getSuit() {
return aSuit;
}
public String toString() {
String cardValue = "";
String rank = "";
String suit = "";
switch (aSuit) {
case HEARTS:
suit = "hearts";
break;
case DIAMONDS:
suit = "diamonds";
break;
case CLUBS:
suit = "clubs";
break;
case SPADES:
suit = "spades";
break;
}
switch (aRank) {
case ACE:
rank = "Ace";
break;
case TWO:
rank = "2";
break;
case THREE:
rank = "3";
break;
case FOUR:
rank = "4";
break;
case FIVE:
rank = "5";
break;
case SIX:
rank = "6";
break;
case SEVEN:
rank = "7";
break;
case EIGHT:
rank = "8";
break;
case NINE:
rank = "9";
break;
case TEN:
rank = "10";
break;
case JACK:
rank = "Jack";
break;
case QUEEN:
rank = "Queen";
break;
case KING:
rank = "King";
break;
}
cardValue += rank + " of " + suit;
return cardValue;
}
public int compareTo(Card other) {
int rankComparison = aRank.compareTo(other.aRank);
return rankComparison != 0 ? rankComparison : aSuit.compareTo(other.aSuit);
}
public boolean equals(Card other) {
if (aRank == other.aRank)
return true;
if (aSuit == other.aSuit)
return true;
return false;
}
// Main method to test.
public static void main(String[] args) {
Card c1 = new Card(Suit.SPADES, Rank.FIVE);
Card c2 = new Card(Suit.HEARTS, Rank.TWO);
Card c3 = new Card(Suit.CLUBS, Rank.EIGHT);
Card c4 = new Card(Suit.DIAMONDS, Rank.FIVE);
Card r1 = new Card(Suit.CLUBS, Rank.ACE);
Card r2 = new Card(Suit.DIAMONDS, Rank.JACK);
Card r3 = new Card(Suit.HEARTS, Rank.QUEEN);
Card r4 = new Card(Suit.SPADES, Rank.KING);
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
if (c1.compareTo(c2) < 0)
System.out.println(c2 + " outranks " + c1);
else if (c1.compareTo(c2) > 0)
System.out.println(c1 + " outranks " + c2);
if (c1.compareTo(c3) < 0)
System.out.println(c3 + " outranks " + c1);
else if (c1.compareTo(c3) > 0)
System.out.println(c1 + " outranks " + c3);
if (c1.compareTo(c1) == 0)
System.out.println(c1 + " is equal to " + c1);
else
System.out.println(c1 + " is NOT equal to " + c1);
if (c1.equals(c4))
System.out.println(c1 + " is equal to " + c4);
else
System.out.println(c1 + " is NOT equal to " + c4);
if (r1.compareTo(r2) < 0)
System.out.println(r1 + " comes before " + r2);
else if (r1.compareTo(r2) > 0)
System.out.println(r1 + " comes after " + r2);
else
System.out.println(r1 + " is equal to " + r2);
if (r4.compareTo(r3) < 0)
System.out.println(r4 + " comes before " + r3);
else if (r4.compareTo(r3) > 0)
System.out.println(r4 + " comes after " + r3);
else
System.out.println(r4 + " is equal to " + r3);
}
}
My deck class:
import java.lang.reflect.Array;
import java.util.*;
public class Deck{
public static final int NEWCARDS = 52;
private Card[] deckOfCards;
private int currentCard;
public void Deck( ) {
deckOfCards = new Card[ NEWCARDS ];
int i = 0;
for (int suit = Card.DIAMONDS; suit <= Card.SPADES; suit++)
for ( int rank = 1; rank <= 13; rank++ )
deckOfCards[i++] = new Card(suit, rank);
currentCard = 0;
}
public void shuffle(int n) {
int i, j, k;
for ( k = 0; k < n; k++ ){
i = (int) ( NEWCARDS * Math.random() );
j = (int) ( NEWCARDS * Math.random() );
Card temp = deckOfCards[i];
deckOfCards[i] = deckOfCards[j];
deckOfCards[j] = temp;
}
currentCard = 0;
}
public Card deal() {
if (currentCard < NEWCARDS) {
return ( deckOfCards[currentCard++] );
}
else{
System.out.println("Out of cards error");
return ( null );
}
}
public String toString() {
String s = "";
int k;
k = 0;
for ( int i = 0; i < 4; i++ ) {
for ( int j = 1; j <= 13; j++ )
s += (deckOfCards[k++] + " ");
s += "\n";
}
return (s);
}
}
The enum is not part of the class. It's also not an int. Change
for (int suit = Card.DIAMONDS; suit <= Card.SPADES; suit++)
to access Suit, and you need ordinal() to assign to an int. Something like
for (int suit = Suit.DIAMONDS.ordinal(); suit <= Suit.SPADES.ordinal(); suit++) {
Suit s = Suit.values()[suit];
// ...
}
Related
I am building a war card game for an assignment I have the game built and it is working but I am running into the issue such as card 10 jack of spades is less in value as say card 23 the jack of hearts. Looking for advice about the best way to be able to compare the cards to see if they are equal.
Below is the code I have so far:
import java.util.Random;
import java.util.Scanner;
public class WarGame {
public static void main(String a[]) {
DeckOfCards d = new DeckOfCards();
int input = 0;
int computer = 0;
int you = 0;
Scanner sc = new Scanner(System.in);
System.out.print("\n1.To play\n2.Exit\nEnter the choice:");
input = sc.nextInt();
while (input != 2) {
if (input == 1) {
System.out.print("\n\nEnter the value of the card:");
int card = sc.nextInt();
if (card >= 0 && card <= 51) {
int systemCard = d.computerTurn(card);
System.out.println("Your card - " + d.inputCard(card));
System.out.println("Computer card - " + d.inputCard(systemCard));
if(systemCard > card)
++computer;
else
++you;
System.out.println("The winner is " + (systemCard > card ? "Computer" : "You"));
} else {
System.out.println("Invalid card");
}
}
else {
System.out.println("That is an invalid selection please choose 1 or 2.");
}
System.out.print("\n1.To play\n2.Exit\nEnter the choice:");
input = sc.nextInt();
}
System.out.println("Total Wins by Computer: "+ computer);
System.out.println("Total Wins by You: "+ you);
if (computer > you)
System.out.println("Computer is the champion");
else if (computer == you)
System.out.println("Its a Tie");
else
System.out.println("You are the champion");
}
}
class DeckOfCards {
String suits[] = {"Spades", "Hearts", "Diamonds", "Clubs"};
Random ran = new Random();
int systemWin = 0;
int playerWin = 0;
String inputCard(int card) {
int suit = card / 13; //assigning suit to your card
int rank = card % 13; //Assigning rank to your card
String out = "";
switch (rank) { //Setting up face cards for the cases
case 0:
out = "Ace of " + suits[suit];
break;
case 10:
out = "Jack of " + suits[suit];
break;
case 11:
out = "Queen of " + suits[suit];
break;
case 12:
out = "King of " + suits[suit];
break;
default:
out = rank + 1 + " of " + suits[suit]; //Adding one to remainder so it will go from 2-10 instead of 1-9
break;
}
return out;
}
int computerTurn(int playerRank) { //Keeping track of the wins for computer and player
int systemRank = this.ran.nextInt(51);
if (systemRank > playerRank)
systemWin++;
else
playerWin++;
return systemRank;
}
}
I think you're comparing the index to your deck rather than the card values themselves. If I'm understanding, you want to compare d.inputCard(card) with d.inputCard(systemCard) instead of card with systemCard. But of course, that's a String. Having a hard time following the code :-).
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Hi there I am trying to get this to calculate the winner from 4 players (The game is the classic card game war) but I can only get it to do two. the first bit of the code is my Card class and the second bit is the main program where there are more if statements for working out the winner. the issue i'm having is with the method "getWinner". I have included the deck class also if that is needed (at the bottom).
package warcard;
public class Card
{
private int value, suit;
private String result, suitStr;
/**
* #param num represents value of card
* #param type represents the suit of card
*/
public Card(int num, int type)
{
/**
* Class constructor.
*/
value = num;
suit = type;
switch(value)
{
case 1: result = "Ace";
break;
case 2: result = "Two";
break;
case 3: result = "Three";
break;
case 4: result = "Four";
break;
case 5: result = "Five";
break;
case 6: result = "Six";
break;
case 7: result = "Seven";
break;
case 8: result = "Eight";
break;
case 9: result = "Nine";
break;
case 10: result = "Ten";
break;
case 11: result = "Jack";
break;
case 12: result = "Queen";
break;
case 13: result = "King";
break;
default: result = "";
break;
}
switch(suit)
{
case 1: suitStr = "Clubs";
break;
case 2: suitStr = "Diamonds";
break;
case 3: suitStr = "Hearts";
break;
case 4: suitStr = "Spades";
break;
}
}
/**
* getters
*/
public int getNum()
{
return value;
}
public int getSuit()
{
return suit;
}
/**
* setters
*/
public void setVal(int choice)
{
value = choice;
}
public void setSuit(int choice)
{
suit = choice;
}
/**
* #param play represents Cards object
* #return flag the String result of the game
*/
public String getWinner(Card play)
{
String flag = "";
if(value == play.getNum())
{
if(suit > play.getSuit())
flag = "win";
else if (suit == play.getSuit())
flag = "tie";
else
flag = "lose";
}
else if (value > play.getNum())
flag = "win";
else
flag = "lose";
return flag;
}
/**
* toString method
*/
public String toString()
{
String info = "";
info = info + result + " of " + suitStr;
return info;
}
} /** end Cards class */
main program
package warcard;
public class Warcard
{
public static void main(String[] args)
{
// instantiation of 2 decks
Deck hand1, hand2, hand3, hand4;
hand1 = new Deck();
hand2 = new Deck();
hand3 = new Deck();
hand4 = new Deck();
String result = "";
// shuffle the decks
hand1.shuffle();
hand2.shuffle();
hand3.shuffle();
hand4.shuffle();
/** tracker variables
* wins1 tracks user's wins
* wins2 tracks computer's wins
*/
int count = 0;
int wins1 = 0;
int wins2 = 0;
int wins3 = 0;
int wins4 = 0;
int ties = 0;
for (int i= 0; i < 52; i++)
{
Card tester = hand1.getCard(count);
Card tester2 = hand2.getCard(count);
Card tester3 = hand3.getCard(count);
Card tester4 = hand4.getCard(count);
count++;
System.out.println("Player 1's hand: " + tester);
System.out.println("Player 2's hand: " + tester2);
System.out.println("Player 3's hand: " + tester3);
System.out.println("Player 4's hand: " + tester4);
result = tester.getWinner(tester2);
if(result == "win")
{
System.out.println("Win!");
wins1++;
}
else if(result == "tie")
{
System.out.println("Tie!");
ties++;
}
else
{
System.out.println("Lose!");
wins2++;
}
} // end for loop
System.out.println();
System.out.println("Total score:");
System.out.println();
System.out.println("Player 1's wins: " + wins1 + "\n" + "Player 2's wins: " + wins2 + "\n" + "Player 3's wins: " + wins3 + "\n" + "Player 4's wins: " + wins4 + "\n" + "Ties: " + ties);
if (wins1 > wins2 && wins1 > wins3 && wins1 > wins4)
System.out.println("Player 1 won the game!");
else if(wins2 > wins1 && wins2 > wins3 && wins2 > wins4)
System.out.println("Player 2 wins!");
else if(wins3 > wins1 && wins3 > wins2 && wins3 > wins4)
System.out.println("Player 3 wins!");
else if(wins4 > wins1 && wins4 > wins2 && wins4 > wins3)
System.out.println("Player 4 wins!");
else if(wins1 == wins2 && wins1 == wins3 && wins1 == wins4)
System.out.println("It's a tie!");
} // end main
} // end class
Deck class
package warcard;
import java.util.Random;
public class Deck
{
private Card[] deck;
private int[] suit = {1, 2, 3, 4};
private int[] numbers = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
private int count;
public Deck()
{
deck = new Card[52];
count = 0;
for(int i = 0; i <= 3; i++)
{
for(int k = 2; k <= 14; k++)
{
deck[count] = new Card(k, suit[i]);
count++;
}
} /**
* end outer loop
*/
}
/**
* end constructor
*/
public Card getCard(int index)
{
return deck[index];
}
public void shuffle()
{
int rand;
Random mix = new Random();
for (int i = 0; i < deck.length; i++)
{
/**
* shuffles deck
*/
rand = mix.nextInt(deck.length);
Card temp = deck[i];
deck[i] = deck[rand];
deck[rand] = temp;
} /**
* end for loop
*/
}
} /** end DeckCards class */
Currently, you are only comparing the values of 2 cards; you're comparing tester against tester2, but do not include player 3 or player 4's cards. Not only that, you don't return which player has won. Instead, you only specify whether p1 has won or lost.
Your String getWinner(Card) method needs more parameters, so you can pass more cards into it. Compare against all the cards. It should also return which player has won:
public String getWinner(Card p2, Card p3, Card p4) {
//compare against ALL cards
//return which player won
}
You would then call this, passing in all opposing cards, not just tester2:
result = tester.getWinner(tester2, tester3, tester4);
Finally, you have to fix up your score keeper. Instead of checking for "win" or "lose", check for which player won:
/* could use a switch statement */
if(result == "p1") {
System.out.println("Player 1 wins!");
wins1++;
} else if(result == "p2") {
System.out.println("Player 2 wins!");
wins2++;
} else if(result == "p3") {
//...
}
If I were on a computer, I'd suggest a LOT more, such as encapsulating the "battle" somewhere else rather than within the first player's Card; I recommend posting to CodeReview once you are done. If you have any problems, let me know.
As far as I can see, only the tester-deck is playing against the tester2-deck. If thats not intended, the reason, only 2 of your 4 decks are "competitive" ist that only 2 of them do play, right?
First time posting on here. I've heard many good things about the community. I'm an amateur programmer and have dabbled in C++ and Java so far. Anywhoo, I've been cracking my head open with this BlackJack game in java I've sort of haphazardly put together over the last few days. Basically, I am having an issue with the creating of my deck. I am using an ArrayList to hold the cards, but I cant figure out a way to correctly add a value to each card. As you can see by my code, I am using parseint to get the value from the String and add it to the card sum but the problem is, when values such as "Ace" and "Jack" "King" "Queen" come up, clearly no int can be parsed from there so when the program runs, everything works fine, unless of course one of the previously mentioned cards are pulled. Then I get an error that reads:
(""Exception in thread "main" java.lang.NumberFormatException: For input string: "Queen"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at blackjack.Blackjack.getHumanValue(Blackjack.java:110)
at blackjack.Blackjack.main(Blackjack.java:27)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)"") .
I've tried looking it up online to see if I can spark some inspiration but all I can find is to use Enums or Switch to build my deck, but the problem is I don't fully understand those techniques yet. Any advice will be greatly appreciated.
Thanks!
public class Blackjack{
ArrayList<card> buildDeck = new ArrayList<card>();
public static void main(String[] args)
{
Blackjack b = new Blackjack();
// Compares both scores. The largest score wins.
if(b.getHumanValue() < b.getRobotValue())
{
System.out.println("ROBOT WINS!!!");
}
else if(b.getRobotValue() > 21 && b.getHumanValue() <=21 )
{
System.out.println("YOU WIN!!!");
}
}
public ArrayList<card> buildDeck(ArrayList<card> buildDeck)
{
String [] suit = {"Spade", "Hearts", "Clubs", "Diamonds"};
String [] cardValue = {"Ace","2","3","4","5","6",
"7","8","9","10","Jack","Queen","King"};
for(int i = 0; i < suit.length; i++)
{
for(int j = 0; j < cardValue.length; j++)
{
card card = new card(suit[i], cardValue[j]);
buildDeck.add(card);
}
}
return buildDeck;
}
// This returns the human score
public int getHumanValue()
{
buildDeck(buildDeck);
Scanner s = new Scanner(System.in);
card value;
int ranCard = 0;
int i = 0;
int aceValue = 0;
int totalValue = 0;
String drawAgain = "";
System.out.println("[[Dealer gives you two cards.]]");
System.out.println("");
while(i < 2)
{
ranCard = 0+(int)(Math.random()*52);
System.out.println("Card " + (i+1) + ":");
System.out.println(buildDeck.get(ranCard));
value = buildDeck.get(ranCard);
while(value.cardValue.equalsIgnoreCase("Ace")) // Ace value; either 1 or 11
{
System.out.println("");
System.out.println("This is an ace.");
System.out.println("It is equal to 1 or 11");
System.out.println("Which number do you prefer?");
System.out.println("");
aceValue = s.nextInt();
s.nextLine();
if(aceValue == 11)
{
totalValue += 11;
totalValue -= 1; // Subtracted 1; was off by one
break;
}
else if(aceValue == 1)
{
totalValue += 1;
totalValue -= 1; // Subtracted 1; was off by one
break;
}
}
totalValue += Integer.parseInt(value.cardValue);
System.out.println("Total Score: " + totalValue);
System.out.println("");
i++;
}
System.out.println("[[Would you like to draw another card? Yes/No]]");
System.out.println("");
drawAgain = s.nextLine();
System.out.println("");
if(drawAgain.equalsIgnoreCase("YES"))
{
ranCard = 0+(int)(Math.random()*52);
System.out.println("Card 3:");
System.out.println(buildDeck.get(ranCard));
value = buildDeck.get(ranCard);
totalValue += Integer.parseInt(value.cardValue);
System.out.println("Total Score: " + totalValue);
System.out.println("");
}
else
{
}
return totalValue;
}
// This returns the robot's score
// Mostly copied from gethumanValue method but more automated
public int getRobotValue()
{
buildDeck(buildDeck);
card value;
int ranCard = 0;
int i = 0;
int totalValue2 = 0;
System.out.println("[[Dealer gives Robot two cards.]]");
System.out.println("");
while(i < 2)
{
ranCard = 0+(int)(Math.random()*52);
System.out.println("Card " + (i+1) + ":");
System.out.println(buildDeck.get(ranCard));
value = buildDeck.get(ranCard);
while(value.cardValue.equalsIgnoreCase("Ace")) // Ace value; either 1 or 11
{
if(totalValue2 < 11)
{
totalValue2 += 11;
totalValue2 -= 1; // Subtracted 1; was off by one
break;
}
else if(totalValue2 > 10)
{
totalValue2 += 1;
totalValue2 -= 1; // Subtracted 1; was off by one
break;
}
}
totalValue2 += Integer.parseInt(value.cardValue);
System.out.println("Total Score: " + totalValue2);
System.out.println("");
i++;
}
if(totalValue2 < 17)
{
ranCard = 0+(int)(Math.random()*52);
System.out.println("Card 3:");
System.out.println(buildDeck.get(ranCard));
value = buildDeck.get(ranCard);
while(value.cardValue.equalsIgnoreCase("Ace")) // Ace value; either 1 or 11
{
if(totalValue2 < 11)
{
totalValue2 += 11;
totalValue2 -= 1; // Subtracted 1; was off by one
break;
}
else if(totalValue2 > 10)
{
totalValue2 += 1;
totalValue2 -= 1; // Subtracted 1; was off by one
break;
}
}
totalValue2 += Integer.parseInt(value.cardValue);
System.out.println("Total Score: " + totalValue2);
System.out.println("");
}
else
{
}
return totalValue2;
}
}
EDIT Sorry, Forgot to include my card class!!!
public class card {
String suit;
String cardValue;
#Override
public String toString() {
return cardValue + " of " + suit;
}
public card(String suit, String cardValue) {
this.suit = suit;
this.cardValue = cardValue;
}
public card(String cardValue) {
this.cardValue = cardValue;
}
public String getSuit() {
return suit;
}
public void setSuit(String suit) {
this.suit = suit;
}
Pay close attention to this call.
totalValue2 += Integer.parseInt(value.cardValue);
It's innocuous enough since it works for any of the integer values you have in cardValue. But, you don't just have integral values there either - you have words, too.
You can't change the word "Queen" to a number. Java doesn't have that capability, since it has no numerical meaning*.
It'd be better to store the value of the card and the name of the card as separate parts of data, since the name of the card would also include the suit information.
You haven't shown us your Card class implementation, but what you can do without changing your external contract is to do a bit of parsing on the inside when you get the String, and return an int instead of a String when you retrieve the cardValue. In the case of an "Ace" type, then depending on the total value of the hand, you should pick the most appropriate value (either 1 or 11). This part I leave as an exercise for the reader.
public Card(String suit, String value) {
this.suit = suit;
switch(value) {
case "Ace":
isAce = true; // conditional logic req'd since Ace can be 1 or 11.
break;
case "Jack":
case "Queen":
case "King":
this.value = 10;
break;
}
this.cardName = value;
}
*: "Queen" does have a value in base 31: 24919187. But that's probably not what you were going for.
Whenever I run the code, if any of the players gets an ace, king, queen, or jack, I get the following error :
Exception in thread "main" java.lang.NumberFormatException: For input string: "Ace"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at Card.getCard(Card.java:19)
at Card.main(Card.java:37)
this is the code I have so far :
public class Card
{
String suit;
String rank;
int getCard;
int a;
int b;
int getSuit;
public Card(){
String [] xSuit = {"Clubs","Diamonds","Hearts","Spades"};
String [] xRank = {"Ace","2","3","4","5","6","7","8","9","10","Jack","Queen","King"};
a = ((int)(Math.random() * 4));
b = ((int)(Math.random() * 13));
suit = xSuit[a];
rank = xRank[b];
}
int getCard(){
getCard = Integer.parseInt (rank);
return getCard;
}
int getSuit(){
getSuit = Integer.parseInt (suit);
return getSuit;
}
public static void main(String[] args)
{
Card player = new Card();
Card player2 = new Card();
System.out.println("WAR");
System.out.println("--------------");
System.out.println("You played the " + player.rank + " of " + player.suit);
System.out.println("Player 2 played the " + player2.rank + " of " + player2.suit);
if (player.getCard() > player2.getCard()){
System.out.println("You win!");
}
else if (player.getCard() < player2.getCard()){
System.out.println("Player 2 wins!");
}
else if (player.getCard() == player2.getCard()){
if(player.getSuit() > player2.getSuit()){
System.out.println("You win!");
}
else if(player.getSuit() < player2.getSuit()){
System.out.println("Player 2 wins!");
}
else{
System.out.println("There was a draw.");
}
}
}
}
Is there a way I could make it so it will say "Jack" and "Queen" without getting an error?
You're not able to pass non-numeric text into a parseInt() method call because it's not actually a number. Another way you could do it would be to try this instead:
String suit;
String rank;
int a;
int b;
int getCard;
int getSuit;
public Card(){
String [] xSuit = {"Clubs","Diamonds","Hearts","Spades"};
// xRank array removed because I don't think you need it anymore.
a = ((int)(Math.random() * 4));
b = ((int)(Math.random() * 13) + 1);
suit = xSuit[a];
switch(b) {
case 1:
rank = "Ace";
break;
case 11:
rank = "Jack";
break;
case 12:
rank = "Queen";
break;
case 13:
rank = "King";
break;
default:
rank = Integer.toString(a);
break;
}
}
int getCard(){
return b; // this will probably be unnecessary now, you'd probably also want a better name for this numeric card value...
}
Hey everyone so I am stuck on the last part of this program that I have been doing for an assignment. So generally I am given a large list of names and numbers that represent popularity ranks for names in certain decades. This is what the file looks like <----- this is a link to see the names.txt
So I created a method that sorts the list in a certain decade which is the getIndexOfSmallest and interchange. Every decade has two names that are ranked the same so between the years of 1900-1909 there are two names that are ranked 1, two names that are ranked 2, two names that are ranked 3 and so on. The last part of the program and the one I need help with is suppose to sort through the object array and find any decades where there is only one name for one rank or no names for a certain rank. The output will be sent to a file and it will look like this. <------ this is another link to see the expected output
This is what my code looks like. This is my Name code that creates the objects:
public class Name{
private String givenName;
private int[] ranks = new int[12];
public Name(String name, int[] popularityRanks){
givenName = name;
for (int i = 0; i < 11; i++){
ranks[i] = popularityRanks[i];
}
}
public String getName(){
return givenName;
}
public int getPop(int decade){
if (decade >= 0 && decade <= 10){
return ranks[decade];
}
else{
return -1;
}
}
public String getHistoLine(int decade){
String histoLine = ranks[decade] + ": ";
double popularity = (1000 - ranks[decade]) / 11.7;
int histo = (int)popularity;
if(popularity != 0){
for (int i = 0; i < histo; i++){
histoLine += "*";
}
}
return histoLine;
}
public String getHistogram(){
String histogram = "";
for (int i = 0; i < 11; i++){
histogram += this.getHistoLine(i) + "\n";
}
return histogram;
}
}
This is my NameApp which is where my main is at:
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class NameApp{
private static boolean validInput;
private static boolean stillWorking = true;
private static boolean validDecade;
private static boolean validName;
static Scanner keyboard = new Scanner(System.in);
// Main method
public static void main(String[] args) throws FileNotFoundException{
String[] nameArray = readNamesFile();
Name[] list = new Name[nameArray.length];
loadNames(list, nameArray);
char choice;
do {
do {
displayMenu();
choice = getUserInput();
} while (!validInput);
switch (choice){
case 'A':
displayHistogram(list);
break;
case 'B':
compareTwoNames(list);
break;
case 'C':
displayTopTenNames(list);
break;
case 'D':
writeAnomaliesToFile(list);
stillWorking = false;
break;
default:
break;
}
} while (stillWorking);
}
/*
* This method will read the file name names.txt and load the names and populations into a string array.
*/
private static String[] readNamesFile() throws FileNotFoundException{
String[] nameArray = new String[4429];
Scanner inputStream = null;
String fileName = "names.txt";
inputStream = new Scanner (new File(fileName));
int i = 0;
while (inputStream.hasNextLine()){
nameArray[i] = inputStream.nextLine();
i++;
}
inputStream.close();
return nameArray;
}
/*
* load names method will take a Name array and the string array from the readNamesFile method. This method will split the names and the population ranks and send them to the constructor in Name.java.
*/
private static void loadNames(Name[] list, String[] nameArray){
int length;
int spacePos;
int[] popRanks = new int[11];
String name;
String linePop;
for (int i = 0; i < nameArray.length; i++){
length = nameArray[i].length();
spacePos = nameArray[i].indexOf(" ");
name = nameArray[i].substring(0,spacePos);
linePop = nameArray[i].substring(spacePos + 1, length);
for (int j = 0; j < 11; j++){
popRanks[j] = Integer.parseInt(linePop.split(" ")[j]);
}
list[i] = new Name(name, popRanks);
}
}
/*
* displayMenu method will display the menu that the user will select their program function.
*/
private static void displayMenu(){
System.out.println("Enter the character corresponding to your selection:");
System.out.println("\ta - Print histogram for a name");
System.out.println("\tb - Compare two names in a decade");
System.out.println("\tc - Print top ten names for a decade");
System.out.println("\td - Quit (display file anomalies)");
}
/*
* getUserInput is a method that will accept a string input from the user it will send this string to two different helper methods.
*/
private static char getUserInput(){
String selection = keyboard.nextLine();
System.out.println(" Your selection: " + selection);
checkUserInput(selection);
char choice = stringToChar(selection);
return choice;
}
/*
* helper method: checkUserInput will accept the user input from getUserInput and test the input to see if the input is a valid input from the user. If it is not set the instance boolean variable to false if it is set it to true.
*/
private static boolean checkUserInput(String selection){
if (!selection.equalsIgnoreCase("a") && !selection.equalsIgnoreCase("b") && !selection.equalsIgnoreCase("c") && !selection.equalsIgnoreCase("d")){
System.out.println("Invalid input. Try again...");
return validInput = false;
}
else {
return validInput = true;
}
}
/*
* helper method: stringToChar method will take the input that the user entered after it has been tested to see if it is valid and this method will change the input to a character value. This will also make the character to an upper case letter.
*/
private static char stringToChar(String selection){
char choice = selection.charAt(0);
choice = Character.toUpperCase(choice);
return choice;
}
/*
* Menu option: A. This method will take a user input for the name they want and display the histogram for the selected name.
*/
private static void displayHistogram(Name[] list){
String nameInput;
String histogram;
int nameLocation;
do {
nameInput = nameEntry();
nameLocation = checkListArray(nameInput, list);
if (!validName){
System.out.println("The name, " + nameInput + ", was not found!");
}
} while (!validName);
histogram = list[nameLocation].getHistogram();
System.out.println("Histogram for name, " + list[nameLocation].getName() + ":");
System.out.println(histogram);
}
private static void compareTwoNames(Name[] list){
String nameOne;
String nameTwo;
String oneHistoLine;
String twoHistoLine;
int oneLocation;
int twoLocation;
int decade;
do {
nameOne = nameEntry();
oneLocation = checkListArray(nameOne, list);
if (!validName){
System.out.println("The first name, " + nameOne + ", was not found!");
}
} while (!validName);
do {
nameTwo = nameEntry();
twoLocation = checkListArray(nameTwo, list);
if (!validName){
System.out.println("The second name, " + nameTwo + ", was not found!");
}
} while(!validName);
decadeMenu();
decade = decadeSelection();
oneHistoLine = list[oneLocation].getHistoLine(decade);
twoHistoLine = list[twoLocation].getHistoLine(decade);
System.out.println("Data for " + list[oneLocation].getName());
System.out.println(" " + oneHistoLine);
System.out.println("Data for " + list[twoLocation].getName());
System.out.println(" " + twoHistoLine);
}
private static void displayTopTenNames(Name[] list){
int decade;
int count = 0;
int l = 0;
String[] decadeName = new String[20];
Name[] temp = new Name[list.length];
decadeMenu();
decade = decadeSelection();
for (int i = 0; i < list.length; i++){
temp[i] = list[i];
}
for (int index = 0; index < temp.length; index++){
int smallestIndex = getIndexOfSmallest(decade, index, temp);
interchange(decade, index, smallestIndex, temp);
}
do {
if (temp[l].getPop(decade) == 0){
l++;
}
else {
decadeName[count] = temp[l].getName() + " " + "(" + temp[l].getPop(decade) + ")";
count++;
l++;
}
} while (count < 20);
writeTopTen(decadeName, decade);
}
private static void writeAnomaliesToFile(Name[] list){
System.out.println("Terminating... but first the anomalies in the data file:");
checkAnomalies(list);
System.out.println("Anomalies written to anomalies.txt.");
}
private static String nameEntry(){
String nameInput = "";
System.out.println("Enter a name: ");
nameInput = keyboard.nextLine();
return nameInput;
}
private static int checkListArray(String nameInput, Name[] list){
int nameLocation = -1;
int listLength = list.length;
for (int i = 0; i < listLength; i++){
if (nameInput.equalsIgnoreCase(list[i].getName())){
validName = true;
return nameLocation = i;
}
}
if (nameLocation == -1){
validName = false;
return nameLocation;
}
return nameLocation;
}
private static void decadeMenu(){
System.out.println("Enter number correpsonding to your decade:");
System.out.println(" 1 - 1900-1909");
System.out.println(" 2 - 1910-1919");
System.out.println(" 3 - 1920-1929");
System.out.println(" 4 - 1930-1939");
System.out.println(" 5 - 1940-1949");
System.out.println(" 6 - 1950-1959");
System.out.println(" 7 - 1960-1969");
System.out.println(" 8 - 1970-1979");
System.out.println(" 9 - 1980-1989");
System.out.println(" 10 - 1990-1999");
System.out.println(" 11 - 2000-2005");
}
private static int decadeSelection(){
String decadeChoice;
int decade;
do {
System.out.println("Enter a decade: ");
decadeChoice = keyboard.nextLine();
decade = checkDecade(decadeChoice);
} while (!validDecade);
return decade;
}
private static int checkDecade(String decadeChoice){
int decade = 0;
try {
decade = Integer.parseInt(decadeChoice);
}
catch (Exception e){
System.out.println("That is not an integer. Please try again.");
validDecade = false;
return decade;
}
if (decade < 1 || decade > 11){
System.out.println("Enter an integer between 1 and 11");
validDecade = false;
return decade;
}
else {
validDecade = true;
decade = changeDecade(decade);
return decade;
}
}
private static int changeDecade(int decade){
int newDecade = 0;
switch (decade){
case 1:
newDecade = 0;
break;
case 2:
newDecade = 1;
break;
case 3:
newDecade = 2;
break;
case 4:
newDecade = 3;
break;
case 5:
newDecade = 4;
break;
case 6:
newDecade = 5;
break;
case 7:
newDecade = 6;
break;
case 8:
newDecade = 7;
break;
case 9:
newDecade = 8;
break;
case 10:
newDecade = 9;
break;
case 11:
newDecade = 10;
break;
default:
break;
}
return newDecade;
}
private static int getIndexOfSmallest(int decade, int startIndex, Name[] temp){
int min = temp[startIndex].getPop(decade);
int indexOfMin = startIndex;
for (int index = startIndex + 1; index < temp.length; index++){
if (temp[index].getPop(decade) < min){
min = temp[index].getPop(decade);
indexOfMin = index;
}
}
return indexOfMin;
}
private static void interchange(int decade, int i, int j, Name[] temp){
Name tempInt = temp[i];
temp[i] = temp[j];
temp[j] = tempInt;
}
private static String decadeYears(int decade){
String decadeYear = "";
switch (decade){
case 0:
decadeYear = "1900 - 1909";
break;
case 1:
decadeYear = "1910 - 1919";
break;
case 2:
decadeYear = "1920 - 1929";
break;
case 3:
decadeYear = "1930 - 1939";
break;
case 4:
decadeYear = "1940 - 1949";
break;
case 5:
decadeYear = "1950 - 1959";
break;
case 6:
decadeYear = "1960 - 1969";
break;
case 7:
decadeYear = "1970 - 1979";
break;
case 8:
decadeYear = "1980 - 1989";
break;
case 9:
decadeYear = "1990 - 1999";
break;
case 10:
decadeYear = "2000 - 2005";
break;
default:
break;
}
return decadeYear;
}
private static void writeTopTen(String[] decadeName, int decade){
String years;
years = decadeYears(decade);
System.out.println("Ten most popular names (male and female) during the decade " + years + " were:");
for (int i = 0; i < 20; i += 2){
System.out.printf("%20s\t%20s\n", decadeName[i],decadeName[i + 1]);
}
}
private static void checkAnomalies(Name[] list){
Name[] temp = new Name[list.length];
int anomalyCount = 0;
int popTwo = 0;
int popOne = 0;
String[] anomalies = new String[list.length];
for (int i = 0; i < list.length; i++){
temp[i] = list[i];
}
for (int decade = 0; decade < 11; decade++){
for (int index = 0; index < temp.length; index++){
int smallestIndex = getIndexOfSmallest(decade, index, temp);
interchange(decade, index, smallestIndex, temp);
}
int rank = 0;
for (int i = 1; i < temp.length - 1; i += 2){
popOne = temp[i].getPop(decade);
popTwo = temp[i+1].getPop(decade);
if (popOne != 0){
rank++;
}
if (popOne == rank && popTwo != rank){
String decadeYear = decadeYears(decade);
anomalies[anomalyCount] = "One name (" + temp[i].getName() + ") for " + decadeYear + ", rank " + temp[i].getPop(decade) + ".";
anomalyCount++;
}
else if (popOne != rank && popTwo == rank){
String decadeYear = decadeYears(decade);
anomalies[anomalyCount] = "One name (" + temp[i+1].getName() + ") for " + decadeYear + ", rank " + temp[i+1].getPop(decade) + ".";
anomalyCount++;
}
else if (popOne != rank && popTwo != rank){
String decadeYear = decadeYears(decade);
anomalies[anomalyCount] = "No names for " + decadeYear + ", rank " + temp[i].getPop(decade) + ".";
anomalyCount++;
}
}
}
}
}
This is the information provided by my professor:
There are 1,065 anomalies: in some cases, only one name with a particular rank in a decade or in other cases, no names in a decade with a particular rank. With 11 decades and 999 ranks to check, 1065 is only about 9.7% of the name-pairs that are broken or anomalous. There should be a pair of names for each rank (999) in each decade (11): this gives 10,989 name-pairs. Your code to do this will need to check each name in each decade for each rank in order to find all 1065 anomalies.
When I was debugging my program I saw that the ranks end on odd numbers. which is why I started my loop in checkAnomalies at 1 instead of 0 (considering that at 0 the names rank will be 0 and that is considered to be a name that was picked 1000 or less). When I run the program with:
String[] anomalies = new String[1065];
I get this error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1065
at NameApp.checkAnomalies(NameApp.java:512)
at NameApp.writeAnomaliesToFile(NameApp.java:259)
at NameApp.main(NameApp.java:43)
and when I change my code to be:
String[] anomalies = new String[temp.length];
I get this error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4429
at NameApp.checkAnomalies(NameApp.java:502)
at NameApp.writeAnomaliesToFile(NameApp.java:259)
at NameApp.main(NameApp.java:43)
I figure my error is in my loops but I can't figure out where.. I figured my loops are finding way more errors then their really is.. Just wondering if anyone can help me out with this.. It is really the only part that I need left. Thanks in advance
EDIT:
This is the relevant code for what I need help with:
private static void writeAnomaliesToFile(Name[] list){
System.out.println("Terminating... but first the anomalies in the data file:");
checkAnomalies(list);
System.out.println("Anomalies written to anomalies.txt.");
}
method that is called:
private static void checkAnomalies(Name[] list){
Name[] temp = new Name[list.length];
int anomalyCount = 0;
int popTwo = 0;
int popOne = 0;
String[] anomalies = new String[list.length];
for (int i = 0; i < list.length; i++){
temp[i] = list[i];
}
for (int decade = 0; decade < 11; decade++){
for (int index = 0; index < temp.length; index++){
int smallestIndex = getIndexOfSmallest(decade, index, temp);
interchange(decade, index, smallestIndex, temp);
}
int rank = 0;
for (int i = 1; i < temp.length - 1; i += 2){
popOne = temp[i].getPop(decade);
popTwo = temp[i+1].getPop(decade);
if (popOne != 0){
rank++;
}
if (popOne == rank && popTwo != rank){
String decadeYear = decadeYears(decade);
anomalies[anomalyCount] = "One name (" + temp[i].getName() + ") for " + decadeYear + ", rank " + temp[i].getPop(decade) + ".";
anomalyCount++;
}
else if (popOne != rank && popTwo == rank){
String decadeYear = decadeYears(decade);
anomalies[anomalyCount] = "One name (" + temp[i+1].getName() + ") for " + decadeYear + ", rank " + temp[i+1].getPop(decade) + ".";
anomalyCount++;
}
else if (popOne != rank && popTwo != rank){
String decadeYear = decadeYears(decade);
anomalies[anomalyCount] = "No names for " + decadeYear + ", rank " + temp[i].getPop(decade) + ".";
anomalyCount++;
}
}
}
}
Solved myself just had to sleep on it:
private static void checkAnomalies(Name[] list)
throws FileNotFoundException{
Name[] temp = new Name[list.length];
String[] anomalies = new String[1065];
int anomalyCount = 0;
for (int i = 0; i < list.length; i++){
temp[i] = list[i];
}
for (int decade = 0; decade < 11; decade++){
for (int ranks = 1; ranks < 1000; ranks++){
int found = 0;
String tempName = "";
String decadeYear = decadeYears(decade);
for (int i = 0; i < temp.length; i++){
if (temp[i].getPop(decade) == ranks){
found++;
}
if (found == 1 &&
temp[i].getPop(decade) == ranks){
tempName = temp[i].getName();
}
}
if (found == 0){
anomalies[anomalyCount] = "No names "
+ "for " + decadeYear + ", rank "
+ ranks + ".";
anomalyCount++;
}
else if (found == 1){
anomalies[anomalyCount] = "One "
+ "Name (" + tempName + ") for "
+ decadeYear + ", rank "
+ ranks + ".";
anomalyCount++;
}
}
}
writeAnomaliesFile(anomalies);
}
/*
* Helper method: this method will create and write
* each anomalies to a text document called
* anomalies.txt.
*/
private static void
writeAnomaliesFile(String[] anomalies)
throws FileNotFoundException{
String fileName = "anomolies.txt";
PrintWriter outputStream = null;
outputStream = new PrintWriter(fileName);
for (int i = 0; i < anomalies.length; i++){
outputStream.println(anomalies[i]);
}
outputStream.close();
}