I was just trying to get NumberWizard to work on java and I couldn't quite get it. Or can you just not do it in java? I'm pretty stuck because I can only get it to guess one time.
I'm using Processing 3 and my code looks like this:
int max = 1000, min = 1, guess = 500;
void setup() {
size(400, 400);
background(0);
println("welcome to NumberGuesser ");
println("In this game you're gonna think of a ");
println("number and im gonna guess it as fast as possible ");
println(" \n ");
println("Now pick of a number between " + min + "and" + max);
println("Great! now that you have picked a number ");
println("Press the up-arrow if its more");
println("and the down-arrow if it's less ");
println("is it less or more than "+ guess + "? \nif more press up-arrow, if less press down-arrow");
}
void draw() {
if (key == CODED) {
if (keyCode == 38) { // up-arrow
min = guess;
nextGuess();
} else if (keyCode == 40) { //down-arrow
max = guess;
nextGuess();
} else if (keyCode == 13) { //return
win();
}
}
}
void nextGuess() {
frameRate(1);
guess = (max + min) /2;
println("Is it less or more than "+ guess + "? \nif more press up-arrow, if less press down-arrow ");
}
void win() {
println("that was'nt hard at all, ezz pezz! ");
noLoop();
}
Please note that the draw() function fires 60 times per second. Even after you call frameRate(1), the draw() function fires once per second. Further note that all of your logic is inside your draw() function. So the guessing will happen on an interval.
You're also not checking whether the key is currently pressed. Note that the key and keyCode variables contain the most recently pressed key. You still need to check whether the key is currently pressed. You can use the keyPressed variable or the keyPressed() function for this.
If I were you, I'd modify my program to use the keyPressed() function to detect user input instead of polling for it in the draw() function.
Also, you need to get in the habit of debugging your code. Try to isolate the problem to a specific line of code that's behaving differently from what you expected, instead of posting your full program and saying it's not working.
Related
I am trying to create a simple number guessing GUI game. I am using 'Integer.parseInt' to get the user's input as an integer instead of string so it can be compared. The program still executes as expected but it gives me the following error in the console:
Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:678)
at java.base/java.lang.Integer.parseInt(Integer.java:784)
at Window.takeGuess(Window.java:58)
at Window$2.actionPerformed(Window.java:32)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
line 58 is where the Integer.parseInt command is used and line 32 is where the takeGuess() function is called. My code is shown below:
public void takeGuess() {
while (playing) {
// retrieve input and convert to integer for comparison
int guess = Integer.parseInt(txtGuess.getText());
txtGuess.setText(null);
// decide outcome of guess
if (guess > number) {
txtDescription.setText("Too high!");
} else if (guess < number) {
txtDescription.setText("Too low!");
} else {
win = true;
txtDescription.setText("You win!");
playing = false;
}
// increment guess counter then repeat if needed
guessCount++;
currentScore.setText("" + guessCount);
System.out.println("received guess\n");
}
}
I originally had txtGuess.setText(null) set to txtGuess.setText("") and it gave the same error. As I said, the program still functions despite this error but I'd obviously like to get it fixed anyway. Can anyone help?
This comment helped solve the problem:
Well, you're trying to parse an empty string as if it's an integer.
It's not clear how you're calling takeGuess(), but it should probably
only be in response to the user clicking a button or something like
that - and it shouldn't be in a loop, otherwise you're not giving them
a chance to change their guess before trying again. – Jon Skeet
I introduced a new boolean called 'lose' which is set to true if they give up. Also changed the while loop to an if statement so function only does something when both win = false and lose = false, i.e. they're still playing.
public void takeGuess() {
// cannot make a guess if won the game or given up
if (!win && !lose) {
// retrieve input and convert to integer for comparison
int guess = Integer.parseInt(txtGuess.getText());
txtGuess.setText(null);
// decide outcome of guess
if (guess > number) {
txtDescription.setText("Too high!");
} else if (guess < number) {
txtDescription.setText("Too low!");
} else {
win = true;
lose = false;
txtDescription.setText("You win!");
}
// increment guess counter then repeat if needed
guessCount++;
currentScore.setText("" + guessCount);
System.out.println("received guess\n");
}
}
It no longer loops back around to be met with an empty string to be parsed, which gave the error.
I am trying to build a copy cat of the game risk. I have a while loop which says while the attack isn't finished do something. Then I ask the user to type in either 'end turn' to end turn or 'continue' to recursively call the attack function again. The problem is after the user types in attack a few times and then 'end turn' the turn doesn't end rather it starts from the beginning or the function again. I would greatly appreciate an expert eye to look at my code and see what I am missing, thanks in advance.
public void attackOrSkip(Player player,Player[] playerArray, int playerId) {
boolean attackFinished = false;
int numUnitsAttackWith = 0;
int defenceArmiesNumber =0;
displayString(makeLongName(player) + ": Type 'attack' to attack or 'skip' to skip your turn...");
String command = commandPanel.getCommand();
displayString(PROMPT + command);
if(command.equals("skip") ||command.equals("skip ") ||command.equals("s")) {
return;
}else if (command.equals("attack") ||command.equals("attack ")){
displayString(PROMPT + command);
//while the attack isn't finished
while(attackFinished == false) {
//get the country the user is attacking
int countryAttackingFrom=countryFromCheck(playerId,player);
//get the country to attack
int countryToAttack = countryToCheck(player);
//get the player who we are attacking
int occupierPlayer =board.getOccupier(countryToAttack);
if ((board.getNumUnits(countryAttackingFrom)) < 2) {
displayString("You dont have enough units on this country to make an attack!");
attackOrSkip(player, playerArray, playerId);
break;
}
//if the country is adjacent to another one then you can attack else no
else if(isAdjacent(countryAttackingFrom,countryToAttack)) {
//check the number of unit to attack with
numUnitsAttackWith =numUnitsCheckerAttack(player,countryAttackingFrom);
//check the number of unit to defend with
defenceArmiesNumber = numUnitsCheckerDefence(player,countryToAttack);
//roll the dice
player.rollDice(numUnitsAttackWith);
playerArray[occupierPlayer].rollDice(defenceArmiesNumber);
//display the roll results
displayString(makeLongName(player) + "Rolled: "+printDie(player));
displayString(makeLongName(playerArray[occupierPlayer]) + "Rolled: "+printDie(playerArray[occupierPlayer]));
}
displayString(makeLongName(player) + ": 'end turn' or 'continue'");
command = commandPanel.getCommand();
displayString(PROMPT + command);
if(command.equals("end turn")||command.equals("end turn ") ||command.equals("endturn")||command.equals("endturn ") ||command.equals("end")) {
attackFinished = true;
return;
}else if(command.equals("attack") ||command.equals("attack ")){
// break;
}else if(command.equals("continue") ||command.equals("continue ") ||command.equals("con")){
attackOrSkip(player,playerArray,playerId);
}else {
return;
}
}else {
displayString(makeLongName(player) + ": ERROR, not adjacent countries");
}
}
}
}
Okay - as currently written - every time you call attackOrSkip within the method - you end up 1 level lower in the stack - with a new set of variables -
attackFinished, numUnitsAttackWith, defenceArmiesNumber
When you leave the recursion (i.e. via a return) you end up with simple variables as they were before you enter the recursive call - remember Java is Call By Value (even though you can pass in references to objects, you get a value (the current value of the variable reference when called ... and changing the reference to point at a different object doesn't change the callers reference).
SO, without looking to see whether you have done the correct algorithm - I would guess that if you made the method return type a boolean and returned the status instead of nothing, you could update attackFinished and the right thing might happen..
e.g. change all the
return;
to
return attackFinished;
AND change all the places where you call
attackOrSkip(....)
to set attack finished based on what the method return
attackFinished = attackOrSkip(....)
OR - you can pass in an extra parameter - attackFinished - in a Holder (an example of the concept) object - again the reference can't change, but you can go attackFinished.value = true (and it will then be the same the whole way out the stack as you drop out of the recursion).
Here's my code. I want to make sure that randomNumber remains the same until the user chooses the right number, so I'm trying to display that number via Log.i. However, whenever my button is clicked, nothing is printed to the android monitor.
int randomNumber = (int) (Math.random() * 50) + 1;
public void checkNumber(View view) {
Log.i("Number", Integer.toString(randomNumber));
EditText numberEntered = (EditText) findViewById(R.id.numberEntered);
int numberEnteredInt = Integer.parseInt(numberEntered.getText().toString());
if(!(numberEnteredInt <= 50 && numberEnteredInt >= 1)) {
//some code
} else if(numberEnteredInt < randomNumber) {
//some code
} else if(numberEnteredInt > randomNumber) {
//some code
} else {
//some code
randomNumber = (int) (Math.random() * 50) + 1;
}
}
Just by running this app multiple times, it seems that the rest of my code is working properly (so I don't actually need Log to work in this case), but I am curious why nothing is being displayed to the monitor. Thanks.
Update:
Ok, now it's working perfectly; I don't know what was happening before. I noticed a couple of you recommended using "" + randomNumber instead of Integer.toString(randomNumber). Is the former more efficient? Thanks again.
I don't believe you even need to use the Integer.toString() at all. You can just replace that whole line with:
Log.i("NUMBER", "" + randomNumber);
If you are calling the checkNumber() method as the onClick for the button, it should absolutely be printing to the console. Make sure your console is set to DEBUG mode, and that the line above the printouts doesn't read "No debuggable applications", but instead says the name of your app.
Are you sure checkNumber() is called in your onClickListener? If so, try adding \n to the Log message.
Log.i("Number", "\n" + randomNumber);
I have a question that may be very basic, but I cant seem to find it on stack (and what I do find is very complicated) so I'm very sorry if it's already out there somewhere.
I'm writing a card game in java, and I want to move the piece of code that draws a new card into a separate method, so that I may call on it whenever, instead of having the same piece of code appear again and again whenever I need it.
The only problem is I don't know what type of method to use or how to call on it, since it's not going to return anything, just do a bunch of code.
Here is the piece of my code that draws a card, if that helps to show what I'm aiming to do.
if (event.getSource() == hit && endOfRound == false) {
Continue = true;
while (Continue == true) //If the random number has been drawn before, loop the random number generator again
{
cardID = (int) RandomNumber.GetRandomNumber(52);
if (cardsLeft[cardID] == true) //If a new card is drawn, continue normally
{
Continue = false; //Stop the loop that draws a new card
cardsLeft[cardID] = false; //save that the card was drawn
stay.setBackground(Color.green);
plyrSum += BlackJack.value(cardID); //add value to sum
plyrSumLabel.setText("Your sum: " + plyrSum); //display new sum
cardLabel[plyrCardCounter].setIcon(cardImage[cardID]); //Display card
plyrCardCounter++;
if (cardID >= 48) //record how many aces are in the hand so the program knows how many times it can reduce the sum.
plyrAceCounter++;
while (plyrSum > 21 && plyrAceCounter > 0) //If bust, reduce the value of an ace by 10 (from 11 to 1).
{
plyrSum -= 10;
plyrSumLabel.setText("Your sum: " + plyrSum);
plyrAceCounter--;
}
if (plyrSum > 21) //Automatically end the round if someone busts (player)
{
stay.doClick();
}
}
}
}
Declare a method drawCard() that returns void. Now copy the block inside if and paste it inside the method.
Then rewrite the if part:
if (event.getSource() == hit && endOfRound == false) drawCard();
This feed method is supposed to first increase the energy state and decrease hungry state, use a dumplings meal (which can be purchased in the shop) then see that the item purchased from the shop, is a positive number or greater than 0. Then ensure that hungry and energy states do not go out of bounds (if it does print warning statements).
If it reaches the border of 100 then start increment overfeed, every time method is executed, if overfeed is greater than 4 then execute die method().
If it meets criteria running feed method will print Eating... and I have ate enough(...) statements.
#Override
protected void feed() {
decHungry(10);
incEnergy(10);
shop.useDumplingsMEAL();
do {
if (shop.dumplingsMEAL <= 0) {
JOptionPane.showMessageDialog(null, "You cannot eat right now, You need to purchase item in the shop");
}
else if (hungry <= 0 && energy >= 100) {
System.out.print("\nI have ate enough! My hungry state is " + hungry +
" and my energy state is " + energy + "." );
overfeed++;
while (overfeed>4)
{
die();
System.out.println("You have overfed me.");
}
}
else {
System.out.println("\nEating...");
System.out.println("I've just ate dumplings, my current energy state is " + energy
+" and hungry state is " + hungry + ".");
overfeed = 0;
}
}
You are calling a method called feed. This method looks like it should feed once if it can when it's called. Get rid of all the loops. If you want to keep it, read on do..while loop.
if(no food){
// nothing to feed
} else if (hunger level 0 or below & energy 100 or more){ // by the way hunger level should never go below 0 and energy should never go over 100
// increment overfeed
if(overfeed more than 4) {
// die
}
} else {
// feed
}
Just like the error message says, the syntax for do while is:
do {
// Do stuff
} while(some condition);
Also you seem to have some conditions that won't do what you want.
You are either having problem with your braces {} and indentation or don't understand properly how to use do-while loop.
Do-while should look like following:
do{
//making stuff
}
while(condition of loop);
At the moment your code looks like following:
do{
if(){
}
else{
while{
}
}
}