The following block of code is supposed to check if the coordinates that the user entered are the coordinates of the ship. The ship is located on a two dimensional array at (1,1) and (1,2).
The problem started when I surrounded the getUserGuess method implementation with a while loop. The loop checks if the ship is still alive and will keep asking for the user to enter coordinates until the ship is sunk. However, as soon as the user enters either pair of the correct coordinates, the entire ship is sunk.
I have no idea why this keeps happening. As soon as I comment out the loop, the problem stops, but the loop is necessary.
Here is the method:
public void checkResult(String userGuess) {
while (frigateIsAlive == true) {
if (userGuess.equalsIgnoreCase(board[1][1])){
System.out.println("hit!");
numOfHitsOnFrigate++;
board[1][1] = " *";
createBoard();
}
if (userGuess.equalsIgnoreCase(board[1][2])) {
System.out.println("hit!");
numOfHitsOnFrigate++;
board[1][2] = " *";
createBoard();
}
else if (numOfHitsOnFrigate == 2) {
System.out.println("Enemy frigate has been sunk!");
frigateIsAlive = false;
break;
}
else {
System.out.println("miss!");
// try again
}
}
}
public String getUserGuess()
{ // takes the users guess
System.out.println("Choose a coordinate on the board to fire at");
int x = input.nextInt();
int y = input.nextInt();
String userGuess = board[x][y];
return userGuess;
}
Let me know if you need to see any other part of the code in order to better assist me.
This method is flawed :
If userGuess matches board[1][1], the loop will make you increment numOfHitsOnFrigate twice, and then you'll change frigateIsAlive to false and exit.
If userGuess matches board[1][2], the loop will make you increment numOfHitsOnFrigate infinite times and you'll never exit.
If userGuess doesn't match, the loop will never terminate, and keep printing miss! without getting new input.
You need to remove the loop, since this method checks a single userGuess, and change the conditions :
public void checkResult(String userGuess) {
if (userGuess.equalsIgnoreCase(board[1][1])){
System.out.println("hit!");
numOfHitsOnFrigate++;
board[1][1] = " *";
createBoard();
} else if (userGuess.equalsIgnoreCase(board[1][2])) {
System.out.println("hit!");
numOfHitsOnFrigate++;
board[1][2] = " *";
createBoard();
} else {
System.out.println("miss!");
// try again
}
if (numOfHitsOnFrigate == 2) {
System.out.println("Enemy frigate has been sunk!");
frigateIsAlive = false;
}
}
Based on what you wrote - I surrounded the getUserGuess method implementation with a while loop. - you have another loop which keeps getting input from the user. That other loop, whose code you haven't shown us, is necessary, since without it the game won't progress.
What you probably want (pseudo-code):
start (of a loop)
ask user for a guess
check result for the guess
sunk => stop / not sunk => continue to start
(i.e. you misplaced your while loop)
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've a little problem.
Myself and a few friends were playing poker yesterday but we didn't have chips so I decided to start writing a program for that [Without Cards, just Chips].
In my code I have two main variables in the Game Object.
private int id;
private long bank;
I have a different file called Aside in which I can do different calculations.
In the code below I am trying to compare all instance bank variables to see if all the banks matched [In this case this will mean a new card can be drawn, otherwise users will have to keep to either raise or fold].
Is there a way of writing this in an easier term:
package poker;
import java.util.ArrayList;
public class Aside
{
public boolean compareBanks(ArrayList<Game> x)
{
ArrayList<Game> players = new ArrayList(x);
if(players.get(0).getBank() == players.get(1).getBank() && players.get(0).getBank() == players.get(2).getBank()
&& players.get(1).getBank() == players.get(2).getBank())
{
return true;
}
return false;
}
}
Later I use this here:
while(aside.compareBanks(players))
But the loop keeps going.
I'm fairly intermediate in programming so go easy on me with mistakes.
Thank you for your time.
P.S: This is NOT a code dump.
while(aside.compareBanks(players))
{
for(Game x : players)
{
if(x.hasPayedBid() == true)
{
System.out.println("Player : " + x.getName() + " [Call, Raise, Fold]:");
action = in.nextLine();
if(action.equalsIgnoreCase("call"))
{
break;
}else if(action.equalsIgnoreCase("raise"))
{
System.out.println("How much are you raising? $");
int raise = in.nextInt();
table += raise;
x.raise(raise);
}else
{
x.fold();
}
}
}
in.nextLine();
for(Game x : players)
{
System.out.println(x.toString() + "\n");
}
}//End While
You can do it using java-8 Stream API something like this
return players.stream().allMatch(p -> p.getBlank().equals( players.get(0).getBalnk()))
However if you will use while(aside.compareBanks(players)) and all elements of the list have equal blank value, your while loop will never stop. It is the same as while(true). So in this case you probably need to use if(aside.compareBanks(players)) or in case of equal blank values change them.
Try this
long bankValue=0;
For(Game player: players){
bankValue+=player.getBank();
}
if(bankValue==(players.get(0).getBank()*players.size)){
return true;}
else return false;
I'm trying to make a very basic game where you guess a number between 1-1000 using a do loop. Everything works, except when I finally make the correct guess, I am still prompted to make another guess, and when I enter the same correct guess again, the program terminates like it's suppose to.
Why do I have to make that extra guess to finally get my program to work? Am I looping around an extra time? Also, if I make a correct guess (the compiler will say I am correct then still prompt me), then a wrong guess (the compiler will tell me I'm wrong), then the correct guess again, the program will only terminate after I make the correct guess a second time.
The second do loop at the bottom is what I put in my main method. Everything above is in a method I wrote called play.
public static boolean play()
{
boolean c;
int n = 0;
do {
String input = JOptionPane.showInputDialog("Enter a number between 1-1000");
n = Integer.parseInt(input);
if (n == guess)
{
System.out.println("Correct");
c = true;
}
else if (n < guess)
{
System.out.println("Not Right");
c = false;
}
else
{
System.out.println("Not Right");
c = false;
}
guess++;
} while (c == false);
return c;
}
In main method:
do {
game1.play();
} while (game1.play() != true);
This loop runs the play method twice in each iteration of the loop :
do {
game1.play(); // first call
} while (game1.play()!=true); // second call
You are not testing the value returned by the first call, so even if it returns true, you would still call game1.play() again, which will display "Enter a number between 1-1000" again.
Replace it with:
boolean done = false;
do {
done = game1.play();
} while (!done);
This would only call play() one time in each iteration of the loop.
That said, I'm not sure why you need the outer loop.
You can just replace in with one call to game1.play(), since game1.play() will loop until the correct number is entered.
Lets say if the last level of a game is beaten then you dont show a dialog box asking if the player wants to go on to the next level, but rather to the mainmenu. SO basically if something happens the things that are supposed to happen afterward dont.
private void submitButtonActionPerformed(java.awt.event.ActionEvent evt) {
final ImageIcon pokeballIcon = new ImageIcon("C:\\Users\\bacojul15\\Pictures\\pokeball5.gif");
final ImageIcon pokemoneggIcon = new ImageIcon("C:\\Users\\bacojul15\\Pictures\\nidoking.gif");
final ImageIcon pokemonredIcon = new ImageIcon("C:\\Users\\bacojul15\\Pictures\\red.gif");
String userAnswer = answertextArea.getText().trim();
if (userAnswer.equalsIgnoreCase(answers.get(questionNumber))) {
answerLabel.setText("Correct");
levelScore ++;
triviagui.totalScore ++;
} else {
answerLabel.setText("Incorrect");
}
answertextArea.setText("");
questionNumber++;
if(questionNumber == questions.size()){
JOptionPane.showMessageDialog(null, "Your score for this level was : " + levelScore + " out of 10. \n Your total score is " + triviagui.totalScore, "Scores",JOptionPane.INFORMATION_MESSAGE, pokeballIcon );
if(difficulty == 3){
JOptionPane.showMessageDialog(null, "Good job you beat the game! \n Your total score was " + triviagui.totalScore + " out of 30.", "Thanks for playing!", JOptionPane.INFORMATION_MESSAGE, pokemonredIcon);
triviagui.questionFrame.setVisible(false);
triviagui.mainFrame.setVisible(true);
}
int leveloptionPane = JOptionPane.showConfirmDialog(null,"Would you like to go on to the next level?" , "Next Level?", JOptionPane.YES_NO_OPTION, levelScore, pokemoneggIcon);
if(leveloptionPane == JOptionPane.YES_OPTION){
difficulty++;
triviagui.questionFrame.setVisible(false);
triviagui.questionFrame=new QuestionFrame(difficulty);
triviagui.questionFrame.setVisible(true);
}
if(leveloptionPane == JOptionPane.NO_OPTION){
triviagui.questionFrame.setVisible(false);
triviagui.mainFrame.setVisible(true);
}
return;
}
updateQuestionScore();
}
You simply want to do:
if(something happens) {
return;
}
If you want to jump out from method use
return;
example of something like that:
public void myMethod(){
if(mynumber==5){
doThis();
}else{
return;
}
/*
*do something else <- this wont be executed if number doesnt equal 5
*cause we are already out of method.
*/
}
If you dont want to jump out from whole method bud only form part of it for instance loop.
break;
example of that:
public void myMethod(String[] stringArr){
for(String s:stringArr){
if(s.equals("hello")){
break; //get me out of this loop now !
}else{
s+="alriight";
}
}
}
doSomethingElse();//this will be executed even if you go thru break; you are still inside method dont forget.You are just out of loop
}
There are better uses for that maybe examples aint best bud you will understand how to use it form this:).
When you use break or return.In eclipse for instance you will be shown Where you actually exit. it will highlight "}"
There are several ways to do this:
You can return from a method.
You can break to exit a loop or continue to start the next iteration of the loop.
You can use an 'else' to only execute other code if the first section did not execute.
You can set a boolean flag variable and then check for that elsewhere in your code.
Depending on what you are trying to do each of these is sometimes the best way, sometimes not the best way.
So I'm making a TicTacToe-program, and I made a method for checking if there are 3 pieces in a row, to check if the game is over or not.
public boolean hasWon() {
if (tictac[0][0].equals(tictac[1][0]) && tictac[0][0].equals(tictac[2][0]) && tictac[1][0].equals(tictac[2][0])) { //Vertical
return false;
} else if (tictac[0][1].equals(tictac[1][1]) && tictac[0][1].equals(tictac[2][1]) && tictac[1][1].equals(tictac[2][1])) { //Vertical
return false;
} else if (tictac[0][2].equals(tictac[1][2]) && tictac[0][2].equals(tictac[2][2]) && tictac[1][2].equals(tictac[2][2])) { //Vertical
return false;
} else if (tictac[0][0].equals(tictac[0][1]) && tictac[0][0].equals(tictac[0][2]) && tictac[0][1].equals(tictac[0][2])) { //Horizontal
return false;
} else if (tictac[1][0].equals(tictac[1][1]) && tictac[1][0].equals(tictac[1][2]) && tictac[1][1].equals(tictac[1][2])) { //Horizontal
return false;
} else if (tictac[2][0].equals(tictac[2][1]) && tictac[2][0].equals(tictac[2][2]) && tictac[2][1].equals(tictac[2][2])) { //Horizontal
return false;
} else if (tictac[0][0].equals(tictac[1][1]) && tictac[0][0].equals(tictac[2][2]) && tictac[1][1].equals(tictac[2][2])) { //Diagonal
return false;
} else if (tictac[0][2].equals(tictac[1][1]) && tictac[0][2].equals(tictac[2][0]) && tictac[1][1].equals(tictac[2][0])) { //Diagonal
return false;
} else {
return true;
}
}
The problem here is, with these conditions I figured if, say, all of the indexes "in a row" where f.ex. X, " X X X " it would be a win for the player X. However, my program calls for a winner if any kind of piece fill 3 in a row, f.ex. " X O X " would end the game, which obviously is wrong.
Have I misunderstood .equals?
EDIT: after the wonderful feedback, is there a way that I can make the if-statements to ignore blank spaces (" ")?
You should consider creating a class, Board. Have this class provide an interface that includes getLines. This should return a List<Line>. There are eight lines in a tic tac toe board: three horizontal, three vertical, two diagonal. Create a method isWin(String player, Line line). Return true or false based on whether the count of the player's marker in the cells of the line is three.
I would guess you can write the whole thing in the same amount of space as the horrible nested if with all its inscrutable && clauses, and the functioning will be obvious. (This is also good practice for encapsulation.)
Your prog returns true if all three values on some line are the same. So, it won't return true on XOX. But would on OOO, XXX and SpaceSpaceSpace.
The first two are both OK, for if you check after a move, only the last mover could have three in a line and win. But three spaces are a problem. In every if you should check the first cell for not having space.
It is longer, but if you use the advice of #ajb, you'll even shorten the prog.
As for structuring, I would advice more simple way than that of #syrion. Make an array lines[5,3,2]. It has 5 lines, 3 cells for every line and 2 coords for every cell. And you can do the check in two inserted loops. It is not a Java way to do things, but you can take it as a first step. Or you could move immediately to a more readable structure - a list of 5 x lines= array of Cell = pair of coordinates. I don't know which one is more simple for you.