I have been unable to find something related to this so far. I've heard that surrounding the majority of your program in a while loop like this makes the program inefficient, is there any better way to get the same effect?
while (1 == 1) {
//User Input
System.out.println("Do you wish to roll? (Y/N)");
if (kb.hasNext()) {
userContinue = kb.next();
}
if (userContinue.equalsIgnoreCase("n")) {
System.exit(0);
}
//Calculations
score = 0;
while (userContinue.equalsIgnoreCase("Y")) {
rollResult = user.rollTwoDie();
score = rollResult + score;
if (score > 21) {
System.out.println("You loose for going over 21.");
System.out.println("Your final score was: " + score);
score = 0;
System.out.println("Play again? (Y/N)");
if (kb.hasNext()) {
userContinue = kb.next();
}
if (userContinue.equalsIgnoreCase("n")) {
System.exit(0);
}
}
else if (score <= 21) {
System.out.println("Your score is: " + score);
System.out.println("Roll again? (Y/N)");
if (kb.hasNext()) {
userContinue = kb.next();
}
}
}
if (userContinue.equalsIgnoreCase("N")) {
while (computerScore <= score && computerScore < max) {
computerResult = computer.rollTwoDie();
computerScore = computerResult + computerScore;
}
userContinue = computer.checkComputerScore(computerScore, score);
}
}
I'm not Java guy, but in many languages 1==1 is usually optimized to true anyway.
So you can use while(true) or while(1==1) or even while (2==2).
It doesn't matter.
In your case it doesn't matter even more, because your while loop is not forcing CPU to work a lot. Your loop is waiting for user input for most of the time. Don't worry about this in this case.
While loops can be extremely inefficient in some cases. In these cases - it's better to use Events instead of loops.
Theoretical example of very incorrect inefficient while loop:
while(true)
{
if(textBox1.Text == "yes") x = 1;
if(textBox1.Text == "no") x = 2;
if (x == 1) doSomething();
if (x == 2) doSomethingElse();
}
It is very inefficient, because you "ask" interface about data in textbox again and again, and there is no reason to do this. There is no pause, CPU and memory are forced to do same thing again and again without pause. In this case - Event should be used.
Events exist in many programming languages. There are many sites, videos and tutorials explaining Events.
Take a look at this video about Events in Java:
Java Programming Tutorial - 52 - Event Handling on Youtube (by Bucky Roberts)
After watching this (and maybe few more Bucky or other tutorial videos) you should understand better why while loops are bad idea sometimes.
It's not necessarily inefficient. It will just run endlessly. If you want that then this isn't necessarily evil.
One thing you may consider is adding a stop boolean. That way you can ask the user if they want to quit, and set the variable to true/false.
boolean stop = false;
while(stop == false) {
//...
}
Also, stylistically I like doing infinite while loops like this:
while(true) {
//...
}
Instead of using "1==1"
Related
I am currently learning java script and attempting new things, for example I wish to see if I can set a boolean expression to end if it detects a starting number through an ending number.
Or in other terms what I'll want is 3 through 8.
I will make it clear I am using netbeans IDE.
Within my last else if statement, I want it to end the asking process. I am hoping it is a simple fix, but I can not think of anything that will accomplish this unless I create a lot more else if statements.
Scanner input = new Scanner(System.in);
int[][] table;
boolean stopasking = true;
while (stopasking = true){
System.out.println("Let's make a magic Square! How big should it be? ");
int size = input.nextInt();
if (size < 0)
{
System.out.println("That would violate the laws of mathematics!");
System.out.println("");
}
else if (size >= 9)
{
System.out.println("That's huge! Please enter a number less than 9.");
System.out.println("");
}
else if (size <= 2)
{
System.out.println("That would violate the laws of mathematics!");
System.out.println("");
}
else if (size == 3)
{
stopasking = false;
}
}
You have used the assignmnent operator =
you should use == instead
also the condition size<=2 holds when size<0 so you can use one if for both
while(stopasking){
if (size <= 2) {
System.out.println("That would violate the laws of mathematics!\n");
} else if (size >= 9){
System.out.println("That's huge! Please enter a number less than 9.\n");
} else if (size == 3){
stopasking = false;
}
}
you can use the boolean expression in this way, as condition to exit from a loop. Some would say it is a more elegant solution than break.
So I wrote a java code for a numbers guessing game. The entire thing is pretty much done. It works by choosing a random number then asking the user for console inputs and then saying whether that is higher or lower than the random number. Once you guess it, it then asks if you want to play again. When you finally say no to this (be it one game or several) it prints out your Overall results including total games, total guesses, avg guesses/game and your best game. I have everything worked out except I cant figure out how to make it print your overall best game.
import java.util.*; //so I can use scanner
public class GuessingGame {
public static void main(String[] args) {
Random rand = new Random ();
int max = 100;
Scanner input = new Scanner(System.in);
int guess;
boolean play = true;
int totalGames = 0;
int totalGuesses = 0;
System.out.println("Can you guess the word?");
System.out.println("I am sure you cannot guess!");
System.out.println("Go ahead and try!");
System.out.println();
while (play) {
System.out.println("I'm thinking of a number between 1 and " + max + "...");
int numberToGuess = rand.nextInt(max) + 1;
int numberOfTries = 0;
boolean win = false;
while (!win) {
System.out.print("Your guess? ");
guess = input.nextInt();
numberOfTries++;
if (guess == numberToGuess) {
win = true;
} else if (guess > numberToGuess) {
System.out.println("It's lower.");
} else if (guess < numberToGuess) {
System.out.println("It's higher.");
}
input.nextLine();
}
if (numberOfTries == 1) {
System.out.println("You got it right in " + numberOfTries + " guess!");
} else {
System.out.println("You got it right in " + numberOfTries + " guesses!");
}
totalGames++;
totalGuesses+= numberOfTries;
System.out.print("Do you want to play again? ");
String answer = input.nextLine();
char firstLetter = answer.charAt(0);
if (firstLetter == 'y' || firstLetter == 'Y') {
play = true;
} else {
play = false;
}
System.out.println();
}
System.out.println("Overall results:");
System.out.println("Total games = " + totalGames);
System.out.println("Total guesses = " + totalGuesses);
System.out.println("Guesses/game = " + totalGuesses/totalGames);
System.out.println("Best game = ");
}
}
In order to get the best game you need a keep track of the best best after each game, such as a variable that checks it there is a new best game after each game.
Keep track of the best score, which is the lowest number of guesses.
int bestGame = Integer.MAX_VALUE; // at the top
bestGame = Math.min(bestGame, numberOfTries); // at the end of your inner while loop
The worst possible score is the highest number of guesses, which is limited by Integer.MAX_VALUE, so you start there.
By the best game u mean minimum number of tries needed to answer is the best game.
/* int mintries,bestgame,gamenumber=0;
bestgamenumber=0;mintreies=Integer.MAX_VALUE:*/
Add the above lines above your while(play)
gamenumber++;
/*if(mintries>numberOfTries)
{
mintries=numberOfTries;//update mintries
betgame=gamenumber;
}*/
Add the if condition just before closing while(play).
So it will be like
int mintries;
mintreies=Integer.MAX_VALUE:
int gamenumber=0;
int bestgamenumber=0//if you want to print the which game is the best game(!st,2nd,3rd..) ;
while(play)
{
// do all your stuff
gamenumber++;
if(mintries>numberOfTries)
{
mintries=numberOfTries;//update mintries
bestgamenumber=gamenumber;
}
}
}
System.out.println("Game number +bestgamenumber+"was the best game with"+ mintries+"tries);
I am considering that you want to print which game (1st,2nd,3rd)is best and minimum tries made to guess the best game.Correct me if i am wrong.
To fit into the code you have already written, You could
Create a new 'global' variable, for example int bestGame = Integer.MAX_VALUE;.
Whenever the user is done with a game do a check if the current numberOfGuesses is smaller than the current bestGame, and if it is, then overwrite bestGame with the current numberOfGuesses.
At the end, you simply need to output bestGame.
i need to know where i should put a Scanner close in this code to stop resource leak.
public class guess_main {
public static void main(String[] args) {
Random numGenerated = new Random();
int numToGuess = numGenerated.nextInt(100);
int numTries =0;
int Guess;
boolean win = false;
Scanner inputNum = new Scanner(System.in);
while (win == false){
System.out.println("Please guess a number between 1 and 100");
Guess = inputNum.nextInt();
numTries++;
if (Guess == numToGuess){
win = true;
}
else if (Guess < numToGuess) {
System.out.println("Your guess is LOW!");
}
else if (Guess > numToGuess){
System.out.println("Your guess is HIGH!");
}
}//End of loop
System.out.println("You won in " + numTries + " goes. Well done!");
}
}
Add it at the end of the loop.
Things should be closed as soon as you are done using them.
If you do anything else with the scanner afterwords, you will need to move it. For example, if you rewrite it to offer the option for another game, you will need to place the closing statement after your confirm that they don't want to play.
You should put it after the end of your loop:
while (win == false) {
...Game logic...
}
inputNum.close();
What this does is close the input stream, so you don't have memory leaks.
In addition to that, please follow Java coding conventions. The only (non-indent related) breaches I saw was that Guess is capitalized, but it's an object, and guess_main should be GuessMain (Uppercase and using camelCase instead of underscores) but it's good to keep an eye out, just in case.
Addendum: As David Wallace pointed out, there is a method that might throw an exception. If you don't care, then the above solution will work, but if you do, this is better:
try (Scanner inputNum = new Scanner(System.in)) {
...Game logic...
} catch (InputMismatchException e) {
e.printStackTrace();
}
I am having some problems making a small game for myself. The piece of code I am having problems with is a timeout for user input. For example: The game will show a letter on the screen. The user has to enter that letter by a certain time; if they don't, they take damage. If someone could explain what I could use to fix this problem it would be great.
package weapons;
import java.util.Random;
import java.util.Scanner;
class wepons {
public static void main(String args[]){
int weapondamage =0 , health = 0 , hits = 0, potion = 0, beast = 0, beastdmg = 0, letter = 0;
String weapon;
;
Scanner in = new Scanner (System.in);
System.out.println ("please pick a wepon that will kill the boss \n");
weapon = in.nextLine().toLowerCase();
if (weapon.equals("sword")){
System.out.println("you have picked the sword");
weapondamage = (int) ((Math.random()*100));
health = weapondamage*3;
}
System.out.println("Sword damage is " + weapondamage);
System.out.println("Boss health is " + health);
System.out.println("Enter the amount of hits it will take to kill the boss.");
hits = in.nextInt();
if(hits == health/weapondamage) {
System.out.println("you have killed the boss.The boss had droped a potion.\nYou pick up the potion and drink it!\nYour health has now gone up to 350hp");
}
else {
System.out.print("You have failed to kill the boss");
}
potion = (int)350;
beastdmg = (int) ((Math.random()*60));
System.out.println("By killing the boss you have awoken the beast!");
System.out.println("The beast nocks you onto your back");
System.out.println("The beast will hit you for"+beastdmg+"damage");
System.out.println("You can block the beast damage by hitting the write key");
Random r = new Random();
int c = r.nextInt(26) + (byte)'a';
System.out.println((char)c);
letter = in.next().charAt(0);
if( letter == ((char)c)){
System.out.println("You blocked the beast damage");
}
else {
System.out.print("You took damage");
}
}
} // main
There are various ways to do this, I'm answering using the OP's style, in the simplest possible way, so measuring user time to press the letter. Here's a functioning snippet:
System.out.println("You can block the beast damage by hitting the write key");
long startTime = System.currentTimeMillis();
Random r = new Random();
int c = r.nextInt(26) + (byte) 'a';
System.out.println((char) c);
char letter = in.next().charAt(0);
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
if (letter == ((char) c) && elapsedTime <=5000) {
System.out.println("You blocked the beast damage");
} else {
System.out.print("You took damage");
}
Hope it helps.
You'd need to take a look at Threads.
With threads, you can execute several processes at once, rather than just linear coding line by line.
For example, you could say:
while(health > 0){
Thread.sleep(5000); //parameter for sleep is milliseconds, so this is 5 seconds
if(weapon == null){
health -= damage;
}else{ break; }
}
The problem with this is that you might need to create a separate class which extends Thread to invoke the damage loss... If the timed aspect is that necessary I would suggest reading up on threads. Don't take this code snipped literally, this is just a basic outline... From my experience with threads you would need to create a method that would return the weapon value, because you want your Thread to check if the user inputed the value for a weapon.
You also may want to refer to this threading tutorial:
https://docs.oracle.com/javase/tutorial/essential/concurrency/simple.html
String option = (String) JOptionPane.showInputDialog(frame,
"A wooden crate appears! It looks ready to kick your butt!",
"Battle!",
JOptionPane.QUESTION_MESSAGE,
null,
attacks,
attacks[0]);
if (option.equals("slash"))
{
damage = (int)(Math.random()*(stick.getMax()-stick.getMin()) + stick.getMin());
}
else if (option.equals("magic"))
{
if (playerMana >= 25)
{
damage = (int) intellect*((stick.getMax()-stick.getMin())/2) + (int)Math.round(Math.pow(playerLevel, 1.20));
playerMana -= 25;
}
else
{
damage = 0;
}
}
else if (option.equals("run"))
{
out.println("fail! you run from the fight!");
}
else if (option.equals("healing") && healPots >= 1)
{
playerHp+= (playerHp*0.15);
}
else
{
out.println("you have no potions! Get some in town to heal your hp!");
}
Stick is just a weapon object I made with min max damage values. Player hp and mana are both 100. healPots is 0.
I am trying to make a rpg style fighting system where the player picks options and takes turns. However, the loop automatically skips to the final else regardless of what is chosen.
When you ask a question on SO, it is always a good idea to provide a minimal, running example.
I removed the actual game logic from your code and replaced frame with null:
public class ShubhankarsQuestion
{
public static void main(String[] args)
{
String[] attacks = {"slash", "magic", "run", "healing"};
String option = (String) JOptionPane.showInputDialog(null,
"A wooden crate appears! It looks ready to kick your butt!",
"Battle!", JOptionPane.QUESTION_MESSAGE,
null, attacks, attacks[0]);
if (option.equals("slash"))
{
System.out.println("You chose slash...");
}
else if (option.equals("magic"))
{
System.out.println("You chose magic...");
}
else if (option.equals("run"))
{
System.out.println("You chose run...");
}
else if (option.equals("healing"))
{
System.out.println("You chose healing...");
}
else
{
System.out.println("you have no potions! Get some in town to heal your hp!");
}
}
}
This works perfectly. Either you haven't shown us the actual code, or your problem lies elsewhere.
Can you show us the definition of the variable attacks?
String[] attacks = {"slash!", "magic!", "healing!", "run!"};
Well, there you have it. You compare "slash!" with "slash", which certainly isn't equal :)
Either remove the exclamation marks from the array, or add them to the compared strings.