I'm trying to write a black jack program in Eclipse and I'm having an issue when the program deals an Ace. I asked the user if they want the Ace to be worth 1 or 11. It does that, but when I type in a value, it gives an error message
"Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.lang.String.charAt(Unknown Source)
at PlayBlackJack.main(PlayBlackJack.java:72)"
Could someone help with that? I have a separate class that if the random card generated is an ace, it returns the value of 11. Here's that part of the code
Update: It adds the value of the Ace to the user's total. But after an Ace is dealt and the user chooses a value, no matter what the total is, it stops the users turn and goes to the dealer. How can I correct this? Also another issues I am having is After the user says 'no' to wanting another card, it goes to the dealer and works fine, but then when asking the user if they want to play again, it goes into an infinite loop and starts throwing out random cards. How can I correct this issue also?
import java.util.Scanner;
public class PlayBlackJack {
public final static int MAXCARDS=52;
//declaring the constant maxcards to be 52
//since there are 52 cards in the deck
public static void main(String[] args) {
Scanner kbd=new Scanner (System.in);
String printRules;
//check to see if the user wants to see the rules or not
String more;
//variable used to see if the user would like to play the game
String next;
//variable used to see if the user would like another card
int dealerTotal, userTotal;
//keeps track of the user's total and the dealer's total
int wins=0, losses=0;
//variables used to keep track of the user's wins and losses
int card = 0;
System.out.println(" Welcome to Black Jack!");
System.out.println("Would you like to see the rules? Type yes or no");
//If yes, rules printed, if no, rules not printed
printRules=kbd.nextLine();
printRules=printRules.toUpperCase();
if (printRules.charAt(0)=='Y')
{
(print rules)
System.out.println("Now lets play!\n\n\n");
}
System.out.println("Would you like to play a game of Black Jack?");
more=kbd.nextLine();
more=more.toUpperCase();
next="Yes";
while (!more.isEmpty() && more.charAt(0)=='Y')
{
System.out.println("The game begins with this your first card:");
userTotal=0;
dealerTotal=0;
while (!next.isEmpty() && next.charAt(0)=='Y')
{
card=PickACard.findCardValue();
if (card==11)
{
System.out.println("Would you like the Ace to be a 1 or 11?");
int aceValue=kbd.nextInt();
while (aceValue!=1 && aceValue!=11)
{
System.out.println("You did not enter a 1 or 11");
aceValue=kbd.nextInt();
}
card=aceValue;
}
userTotal=userTotal+card;
System.out.println("You're total is " +userTotal);
if (userTotal>21)
{
System.out.println("Sorry, You lose");
losses++;
System.out.println("Would you like to play again?");
next="No";
more=kbd.nextLine();
more=more.toUpperCase();
}
else
{
System.out.println("Would you like another card?");
next=kbd.nextLine();
next=next.toUpperCase();
}
}
while (dealerTotal<=userTotal && userTotal<21)
{
System.out.println("Now it's the dealer's turn");
int card1=0;
card1=PickACard.findCardValue();
if (card1==11)
{
int aceValue1;
if (dealerTotal+11>21)
{
aceValue1=1;
}
else
{
aceValue1=11;
}
card1=aceValue1;
}
dealerTotal=dealerTotal+card1;
System.out.println("The dealer's total is "+dealerTotal);
if (dealerTotal==userTotal && userTotal<21)
{
losses++;
System.out.println("Sorry, you lose. Would you like to play again?");
more=kbd.nextLine();
more=more.toUpperCase();
}
if (dealerTotal>21)
{
wins++;
System.out.println("You Win! Would you like to play again?");
more=kbd.nextLine();
more=more.toUpperCase();
}
/*else
{
losses++;
System.out.println("You lose. Would you like to play again?");
more=kbd.nextLine();
more=more.toUpperCase();
}*/
}
}
System.out.println("You won "+wins+" game(s) and lost "+losses+" game(s)");
kbd.close();
}
}
I think that because you are using kbd.nextInt() to get the Ace value there is a new line character is left in the buffer so when the loop goes around kbd.nextLine() returns new line character and not Y that might be causing an issue with more.charAt(0) You might have to add an extra kbd.nextLine(); to get rid the new line character. Also as Elliot Frisch pointed out you should check if the string is empty in the while control statement.
while(!more.isEmpty() && more.charAt(0) == 'y')
{
}
I guess next.charAt(0) is showing the error. You can try to do kbd.nextLine(); right before you ask would you like another game and also check if next is not empty.
while(!next.isEmpty() && more.charAt(0) == 'y')
{
}
Try this
System.out.println("Sorry, You lose");
losses++;
System.out.println("Would you like to play again?");
next="No";
kbd.nextLine(); // to flush out new line character
more=kbd.nextLine();
more=more.toUpperCase();
You can also use nextLine() and parse it to int that will avoid the new line character issue.
aceValue = Integer.parseInt(kbd.nextLine());
I can't tell which line is line 72 of your code, but I can tell you that it's pretty likely based on what you've given us that somehow either your more or next variables are becoming empty strings (i.e. ""). If you try and call charAt(0) for a 0-length String, you'll get a StringIndexOutOfBoundsException.
Related
I'm struggling with dealing of inventory scan for my game, it basically search for the user inventory if "Flying Broom" if present(it was collected in another method and upload the code is too long), if not it will run the method challengedragon() again; else, it will proceed to the next challenge if the item is present.I was think of inserting method as parameter but it is not possible. This is what I have now. :
public class Main {
String Flyingbroom = "Flying broom";
public static void main(String[] args) {
Player_inventory p = new Player_inventory();
challengedragon();
}
public void challengedragon() {
System.out.println("a Hungarian Horntail dragon! Let's start the battle! You have four options to beat the dragon: ");
System.out.println("1: Fly away with your broom");
System.out.println("2: Fight the dragon");
System.out.println("3: Just run to the egg and get it");
System.out.println("4: Hide behind a rock");
System.out.println("5: Go back to Hogwart");
System.out.println("Your choice is: ");
Scanner in = new Scanner(System.in);
int dragonfightchoice = in .nextInt();
if (dragonfightchoice == 1) {
{
p.Scanitem(Flyingbroom,
"Good choice! You managed to kill the Hungarian Horntail dragon and to get the golden egg",
"You dont have the broom. Try to search for the broom",
playerHP);
proceedtonextchallengelake();
} else if (dragonfightchoice == 2) {
System.out.println("The Hungarian Horntail dragon fired you. - 70HP. ");
playerHP -= 70;
challengedragon();
} else if (dragonfightchoice == 3) {
System.out.println("Bad idea... You lose 100 HP");
playerHP -= 100;
challengedragon();
} else if (dragonfightchoice == 4) {
System.out.println("The dragon found you. You lose 30 HP");
playerHP -= 30;
challengedragon();
} else if (dragonfightchoice == 5) {
Hogwart();
} else {
invalid();
challengedragon();
}
}
For my inventory class:
public void Scanitem(String item, String trueouputext, String textifconditionisnotmet) {
if (inv.contains(item) == true) {
System.out.println(trueouputext);
} else if (inv.contains(item) == false) {
System.out.println(textifconditionisnotmet);
}
public static ArrayList<String> inv = new ArrayList<String>();
Do you guys have any recommendation?
Are there additional steps to populate the inventory (variable inv)?
Also, wouldn't you want ScanItem to answer true or false, depending on whether the item was found? Then you would have something like this:
public boolean scanitem(String item) {
return ( inv.contains(item) );
}
if ( p.scanItem(flyingBroom) ) {
System.out.println("Good choice! You managed to kill the Hungarian Horntail dragon and to get the golden egg");
} else {
System.out.println("You dont have the broom. Try to search for the broom");
}
That will get you closer to what you want. However, there are two other issues which you'll need to put into your code:
You will need a loop of some sort, instead of calling challengeDragon from inside of itself.
Somehow, the return value from scanItem must be used to decide whether to loop.
Currently, you do a nested call of a method each time the player does something, this means that sooner or later you'll run out of the stack. A better idea for the framework for your text-based adventure is to have some kind of a description of the current game's state. The state could be represented as an object that contains the following information:
where's the player currently at (on which step, at which "crossing" etc.)
the player's stats (HP, available skills etc.)
the contents of the player's inventory
some previously made choices affecting the game
Then, the code could be written as a simple loop that does the following:
process player's input
change the state according to the player's input
present the player with available options according to the new state
wait for the next input
repeat
I'm really scratching my heard on this one. I'm new at java, and I'm having the strangest thing happen.
It's homework and I'm taking it one step at a time. My issue is the loop just keeps going and stops asking for input, just keeps looping until it terminates. My comments are largely for myself. I tried to extract what was causing my problem and post it here.
Look at the "hatColor" switch, you'll notice the way I'm making sure the user enter only from the options I have allotted. Should I be using a exception handler or something?
Anyway, in short, the problem is that if I enter something with spaces, the loop skips asking for my next input. Like, if I entered "y y y y y " to the scanner when first prompted, the program will terminate and not give me the chance to enter something else.
Please, anyone that understands this, I would really appreciate your help.
import java.util.Scanner;
public class Testing
{
static String hatColor;
public static void main(String[] args) {
gameStart();
}
public static void gameStart()
{
Scanner userInput = new Scanner(System.in);
boolean keepLooping = true;
int loopCounter = 0;
System.out.println("The game begins. You must choose between 3 different colored hats."
+ " You can type white, black, or gray.");
while (keepLooping == true)
{
hatColor = userInput.next();
switch(hatColor)
{
case "white":
System.out.println("You have chosen the path of well intentioned decisions.");
walletDrop();
//the two items below are only there in case the wallet drop somehow completes without calling another method
keepLooping = false; // stops the while loop from looping again.
break; // breaks out of the switch
case "gray":
System.out.println("You have chosen the path of free will.");
walletDrop();
keepLooping = false;
break;
case "black" :
System.out.println("You have chosen the path of personal gain.");
walletDrop();
keepLooping = false;
break;
default : //we could just copy this default chunk for later switch statements
if (loopCounter >= 3)//end program on them
{
System.exit(0);
}
System.out.println("You didn't enter a usable answer. Try again");
loopCounter++;
if (loopCounter == 3)
{
System.out.println("This program will self destruct if you enter another invalid response.");
}
}//end of switch
}//end of while
}//end of game start method
public static void walletDrop()
{
System.out.println("wallet drop successful");
}
}
So I have actually solved this right after posting. In case someone else needs to look here for help:
The issue I was experiencing was due to using the scanner method
variableToAssign = scannerName.next();
instead of
variableToAssign = scannerName.nextLine();
I have a project for my computer science class and we're making battleship. Part of the program is that we have make sure that the piece the player puts down does not go off of the board.
I've made a method to check to see whether it goes off the board:
private static boolean test(String s, int row, int column,int spaces)
{
if(s.equals("right")&&column+5<=10)
{
return true;
}
if(s.equals("up")&&row-spaces>=0)
{
return true;
}
if(s.equals("left")&&column-spaces>=0)
{
return true;
}
if(s.equals("Down")&&row+spaces<=10)
{
return true;
}
return false;
}
But once I've gotten it to print out an error message, I'm not sure how to make it so that the program can re-recieve the new position for the piece, without putting an if statement in and if statement in an if statement (and on and on), because you need to check the new position to make sure it doesn't go off of the board.
Here is the part where I get the position of the playing piece (although I don't think you need it)
Scanner sonic= new Scanner(System.in);
System.out.println("Please input the row where you want the aircraft carrier (5 spaces) to begin: ");
int beginrow = sonic.nextInt();
System.out.println("Please input the column where you want the aircraft carrier (5 spaces) to begin: ");
int begincolumn = sonic.nextInt();
System.out.print("Please input what direction (up, down, left, right) \nyou want your battle ship to face, making sure it doesn't go off of the board.");
String direction = sonic.next();
And here's one of the if statements that I use to check/place the pieces
if(direction.equals("left")&&test("left",beginrow,begincolumn,5))
{
for(int i = beginrow; i>beginrow-5; i--)
{
battleship[begincolumn-1][i-1] = ('a');
}
}
else if(!test("left",beginrow,begincolumn,5))
{
System.out.println(" ");
System.out.println("*****ERROR: your piece goes off the board, please re-enter your position and direction*****");
}
This may be a duplicate, but I didn't know how to reword my search to find what I wanted. (So if anyone could direct me to the right article, that'd be nice as well)
What you should do is split your code appropriately into methods and call that methods repeatedly until your program is satisfied with the outcome.
For example:
create a method startGame() which has the job call methods getting user input until satisfied
make a method to request the user to input all the different ships and other required data
That might look something like
public void startGame() {
// do some setup
while(!requestShipInput()) { // request ship data until the data is valid
System.out.println(" ");
System.out.println("*****ERROR: your piece goes off the board, please re-enter your position and direction*****");
}
// do some more ship setup
// get the actual playing started
}
public boolean requestShipInput() {
Scanner sonic= new Scanner(System.in);
System.out.println("Please input the row where you want the aircraft carrier (5 spaces) to begin: ");
int beginrow = sonic.nextInt();
System.out.println("Please input the column where you want the aircraft carrier (5 spaces) to begin: ");
int begincolumn = sonic.nextInt();
System.out.print("Please input what direction (up, down, left, right) \nyou want your battle ship to face, making sure it doesn't go off of the board.");
String direction = sonic.next();
if(direction.equals("left")&&test("left",beginrow,begincolumn,5)) {
for(int i = beginrow; i>beginrow-5; i--) {
battleship[begincolumn-1][i-1] = ('a');
}
return true; // valid ship data
}
return false; // invalid ship data
}
As a first step, separate input validation from taking the action based on that input - you already have the validation logic in a separate function, so this is easy. Then figure out what needs to be done in case of invalid input - in your case, you need to ask for new input until you get a valid position:
do {
System.out.println("Please input the row where you want the aircraft carrier (5 spaces) to begin: ");
beginrow = sonic.nextInt();
System.out.println("Please input the column where you want the aircraft carrier (5 spaces) to begin: ");
begincolumn = sonic.nextInt();
System.out.print("Please input what direction (up, down, left, right) \nyou want your battle ship to face, making sure it doesn't go off of the board.");
direction = sonic.next();
} while (!test(direction, beginrow, begincolumn, 5))
After that, you know you've got a valid position.
My next step would probably be to group the information required to describe a ship on the board (i.e. beginrow,begincolumn,direction, probably also size) in a separate Object - possibly named Ship.
I think you could pretty naturally use recursion here:
public void getInput() {
// scanner code to get input
if (!test("left",beginrow,begincolumn,5)) { // test failed
getInput()
return
}
// test succeeded, continue
}
You already have something to the limits of you board? If you execute the check first, you don't need to execute a cascade of if-else
if(!test(direction,beginrow,begincolumn,size))
{
System.out.println(" ");
System.out.println("*****ERROR: your piece goes off the board, please re-enter your position and direction*****");
} else {
// check for collision with already placed ships
}
Keep in mind that there is a chance to combine up/down and left/right. The calculation rules are nearly the same and you only have to decide if you have to look to the one or the other direction.
The problem I seem to be having is that I am unsure on how to make the program recognize if the player is in one of the "MVP" positions (C,SS,CF) before moving forward with my program logic.
These three positions qualify for "MVP" status only if their OPS is above 800 for everyone else, it has to be 900 or above to be considered for "MVP".
Once again, I am having trouble with the "if" and "if else" statement.
Again, This IS school given problem and I don't want the answer. Only insight into what I am doing wrong. I want to learn this not have it done for me. Thank you in advance.
import java.util.Scanner;
public class baseBall {
public static void main(String[] args) {
/* A good part of a baseball player's offensive value is captured by the
statistic OPS - the sum of the player's on base percentage and slugging
percentage. An MVP candidate will typically have an OPS above 900,
however if they play a difficult defensive position (catcher, shortstop, or center field)
then they are an MVP candidate if their OPS is above 800. Write a program that will prompt the user for
a player's name, their on base percentage, slugging percentage, and defensive position and report whether the player is an MVP candidate*/
Scanner input = new Scanner(System.in);
System.out.println("Please enter players name: ");
String name = input.next();
System.out.println("Please enter On Base Percentage: ");
double Obp = input.nextDouble();
System.out.println("Please enter slugging Percentage: ");
double Slg = input.nextDouble();
System.out
.println("Please enter position (P,C,1B,2B,3B,SS,LF,CF,RF): ");
String ball = input.next();
String position;
double Ops = Obp + Slg;
if ( position.equalsIgnoreCase("ss")){
if (position.equalsIgnoreCase("cf")){
if (position.equalsIgnoreCase("c")){
System.out.println("MVP Candidate!");
else
System.out.println("NOT an MVP Candidate!);
}
}
}
}
}
Try doing it without nested IFs. Instead, try using Boolean operators like AND and OR.
As previously stated try using a paper first. Try drawing a decision tree to see what and where it might be going wrong.
Your code is checking if the player position is c AND ss AND cf. But the player will be only in one position, it can't be in all the three, so your code will always print "Not an MVP Candidate!".
To make it simple your code is checking if the position is c AND ss AND CF, instead you want to check if the position is c OR ss OR cf.
So you have to use the conditional operator OR -> ||:
if(position.equalsIgnoreCase("ss") || position.equalsIgnoreCase("cf") || position.equalsIgnoreCase("c") {
System.out.println("MVP Candidate!");
} else {
System.out.println("NOT an MVP Candidate!);
}
Your nested ifs will never be true. Think about this logically and on paper.
If position equals ss how can it equal cf and c at the same time? Always ask yourself: "does this make sense?" -- do this before committing code to screen and you'll be golden.
As a side recommendation, please get rid of those distracting // from your question text. They serve no purpose other than to annoy.
I'm creating a game for homework, and I'm very stuck in the beginning stages. The game takes inputs from two players. The player class controls the guesses by each player. I've been able to correctly set up the player class so that it only accepts the allowed range of inputs.
However, I'm having difficulty calling the guess variable for two player objects. I've tried to determine how to call the value of each guess variable for each object, but it keeps giving me errors. Am I calling the variable correctly? Or is my logic of having two different guesses values for each player object correct? Or is there another way that I need to write the code to have a guess variable for each player?
player class code:
import java.util.Scanner;
public class player {
//handles the input from the player
public player() {
while (true) {
// Prompt the user to guess the number
System.out.println("Enter your guess: ");
Scanner input = new Scanner(System.in);
int guess = input.nextInt();
System.out.println(guess);
if (guess < 0) {
System.out.println("You entered a negative number.
+ "The number you enter must be between 0 and 4. " +
"Please try again. ");
}
else if (guess >= 5){
System.out.println("You entered is greater than 4. "
+ "The number you enter must be between 0 and 4. " +
"Please try again. ");
}
else{
break;
}
} // End of while loop
}//end of player method
}//End of player class
Main code:
public class HW2 {
public static void main(String[] args) {
System.out.println("It's Player A's turn to guess!");
player playerA = new player();
System.out.println(playerA.guess);
System.out.println("It's Player B's turn to guess!");
player playerB = new player();
System.out.println(playerB.guess);
}//end of main
} // end of HW2 class
Thank you in advance for any help!
Declare your guess variable as an instance field instead of a method variable. It's simply a matter of scope
public class player {
int guess;
.....
and instead of int guess = input.nextInt();in the method simply write guess = input.nextInt();
This should solve the call issue
You are trying to access the guess variable outside of its scope (this variable is only accesible in the player method).
In order to fix it, define a public field in the Player class and assign the guess value to it (better use setter and getter). Then you will be able to access it in your main method.
With regards to your initial question, about accessing the "guess" variable for each player:
The guess variable for each player is a local variable declared within the constructor. As such, it can't be seen outside the constructor scope and so when your main method tries to access playerB.guess, the compiler can see that there is no variable called guess in the player class. It doesn't, and can't, realize that you're actually trying to access a local variable inside the constructor. So, to solve this particular problem - you could make the guess variable a field in the player class. e.g.
//handles the input from the player
public player() {
public int guess = 0;
while (true) {
// Prompt the user to guess the number
System.out.println("Enter your guess: ");
Scanner input = new Scanner(System.in);
guess = input.nextInt();
System.out.println(guess);
if (guess < 0) {
System.out.println("You entered a negative number.
+ "The number you enter must be between 0 and 4. " +
"Please try again. ");
}
else if (guess >= 5){
System.out.println("You entered is greater than 4. "
+ "The number you enter must be between 0 and 4. " +
"Please try again. ");
}
else{
break;
}
} // End of while loop
}//end of player method
}//End of player class
This will resolve the particular compile problem - but one thing to note, because the logic for making a guess is in the constructor of the player object, this means it will only be called once, when the class is created.