Output copied twice in Nim game in Java - java

Im learning java with "programmingbydoing" and i have a problem with Nim game, everything works fine apart from one thing, which is that both:
"System.out.print(n1 + ", choose a pile: ");"
and
"System.out.print(n2 + ", choose a pile: ");"
is out printed twice after the first time.
Here is code:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Player one, enter your name: ");
String n1 = input.nextLine();
System.out.print("Player two, enter your name: ");
String n2 = input.nextLine();
int a = 3;
int b = 4;
int c = 5;
int count = 1;
System.out.println("A: "+a+" B: "+b+" C: "+c);
nim_loop:while(a > 0 || b > 0 || c > 0) {
while(count % 2 != 0 ) {
System.out.print(n1+", choose a pile: ");
String first = input.nextLine();
if (first.contains("a") || first.contains("A")) {
System.out.print("How many to remove from pile " + first + "? ");
int second = input.nextInt();
count = count + 1;
a = a - second;
System.out.println("A: " + a + " B: " + b + " C: " + c);
if(a <= 0 && b <= 0 && c <= 0){
break nim_loop;
}
}
else if (first.contains("b") || first.contains("B")) {
System.out.print("How many to remove from pile " + first + "? ");
int second = input.nextInt();
count = count + 1;
b = b - second;
System.out.println("A: " + a + " B: " + b + " C: " + c);
if(a <= 0 && b <= 0 && c <= 0){
break nim_loop;
}
}
else if (first.contains("c") || first.contains("C")) {
System.out.print("How many to remove from pile " + first + "? ");
int second = input.nextInt();
count = count + 1;
c = c - second;
System.out.println("A: " + a + " B: " + b + " C: " + c);
if(a <= 0 && b <= 0 && c <= 0){
break nim_loop;
}
}
}
while(count % 2 == 0) {
System.out.print(n2 + ", choose a pile: ");
String third = input.nextLine();
if (third.contains("a") || third.contains("A")) {
System.out.print("How many to remove from pile " + third + "? ");
int fourth = input.nextInt();
count = count + 1;
a = a - fourth;
System.out.println("A: " + a + " B: " + b + " C: " + c);
} else if (third.contains("b") || third.contains("B")) {
System.out.print("How many to remove from pile " + third + "? ");
int fourth = input.nextInt();
count = count + 1;
b = b - fourth;
System.out.println("A: " + a + " B: " + b + " C: " + c);
} else if (third.contains("c") || third.contains("C")) {
System.out.print("How many to remove from pile " + third + "? ");
int fourth = input.nextInt();
count = count + 1;
c = c - fourth;
System.out.println("A: " + a + " B: " + b + " C: " + c);
}
}
}
if (count % 2 != 0) {
System.out.println("Game ended, Player " + n1 + " is a winner.");
} else if (count % 2 == 0){
System.out.println("Game ended, Player " + n2 + " is a winner.");
}
}
}
And here are the pictures of what happens when i run it:

When the first if condition in first inner loop is true and when you get the user input by using nextInt() it only reads the int value and does not consume the last new line character i,e \n. So the subsequent call to nextLine() will be skipped i,e the nextLine() call in second inner while loop will be skipped without any value but System.out.print(n2 + ", choose a pile: "); will be printed as it is before nextLine() call and control goes back to outer while loop.
Now the count value is 2 so first inner while condition will be false and control goes to second inner while loop. And again it prints b, choose a pile:. Hope this clears your question
Workaround is fire a blank nextLine() call after every nextInt() or use nextLine() inside if condition and parse the user input using Integer.parseInt(String) method.
Example code :
if (first.contains("a") || first.contains("A")) {
System.out.print("How many to remove from pile " + first + "? ");
int second = input.nextInt();
input.nextLine(); // firing an blank nextLine call
count = count + 1;
a = a - second;
System.out.println("A: " + a + " B: " + b + " C: " + c);
if(a <= 0 && b <= 0 && c <= 0){
break nim_loop;
}
For more information - Scanner is skipping nextLine() after using next(), nextInt() or other nextFoo() methods

Related

Java - get out of the do-while loop with an input of user

I am trying to write a program that allows generate random numbers inside a infinite loop. If the user press 'c' it will get out of loop. But the loop only starts when I press c, it should start before and it should stop when I press 'c'.
import java.util.Random;
import java.util.Scanner;
public class main{
public static void main (String[] args) {
Random rand = new Random();
int[] randNumber = new int[100];
Scanner scanner = new Scanner(System.in);
char c = scanner.next().charAt(0);
do {
for (int i = 0; i <= 99; i++) {
randNumber[i] = rand.nextInt(100);
}
for (int i = 0; i < 99; i++) {
if (randNumber[i] < randNumber[i + 1]) {
System.out.println("Number " + randNumber[i] + " smaller than " + randNumber[i + 1]);
} else if (randNumber[i] > randNumber[i + 1]) {
System.out.println("Number " + randNumber[i] + " greater than " + randNumber[i + 1]);
} else if (randNumber[i] == randNumber[i + 1]) {
System.out.println("Number " + randNumber[i] + " equal to " + randNumber[i + 1]);
} else {
System.out.println("Wrong!");
}
}
} while (c == 'c');
}
}
Also I would like to how can I do this program only using while loop instead of do-while loop. When I was doing with only while I started with while(1) then break the loop with if statements from input, but that didn't work neither. Inside still there is two for loops.
Many thanks
Regarding first query move the lines of codes where you are taking input inside the do-while loop, in this way after each iteration it will ask for a input and if you enter 'c', it will continue else it will break free.
Regarding second query, if you use while(1) and check for user input for 'c' using if statements and breaking out if user inputs 'c', it should work.
You need to ask for user input inside of your loop; otherwise, c never changes.
Random rand = new Random();
int[] randNumber = new int[100];
Scanner scanner = new Scanner(System.in);
// Just set it to 'c' as default so it enters the loop at least once. IMO this is better than an infinite loop with breakout or having another default value for c and checking it, or using a do while loop
char c = 'c';
while (c == 'c') {
for (int i = 0; i <= 99; i++) {
randNumber[i] = rand.nextInt(100);
}
for (int i = 0; i < 99; i++) {
if (randNumber[i] < randNumber[i + 1]) {
System.out.println("Number " + randNumber[i] + " smaller than " + randNumber[i + 1]);
} else if (randNumber[i] > randNumber[i + 1]) {
System.out.println("Number " + randNumber[i] + " greater than " + randNumber[i + 1]);
} else if (randNumber[i] == randNumber[i + 1]) {
System.out.println("Number " + randNumber[i] + " equal to " + randNumber[i + 1]);
} else {
System.out.println("Wrong!");
}
}
// Ask for the next input
char c = scanner.next().charAt(0);
}

After asking the user for how many questions they want, how can I get my code to show that number of random problems?

I need to first ask the user to input how many problems they want to do. Then generate the first, then the second after they answer the first and so on.
public static void main(String[] args) {
int number1 = (int) (Math.random() * 40 + 10), number2 = (int) (Math.random() * 40 + 10), uanswer, ianswer, counter, icounter,
acounter, counter1, ui, aacounter, bcounter;
Scanner input = new Scanner(System.in);
System.out.println("How many problems do you want to do?");
ui = input.nextInt();
counter = 1;
icounter = 1;
acounter = counter + icounter;
{
System.out.print("What is " + number1 + " + " + number2 + "? ");
}
uanswer = input.nextInt();
ianswer = number1 + number2;
while (counter < 10000 && icounter < 1000 && acounter < 1000 && number1
+ number2 != uanswer) {
System.out.println("Incorrect, the answer is "
+ ianswer + ", " + icounter + " out of " + icounter + " incorrect. Try again?");
icounter++;
acounter++;
uanswer = input.nextInt();
}
if (ianswer == ianswer) {
aacounter = acounter - 1;
bcounter = icounter - 1;
System.out.println("Correct, the answer is " + ianswer
+ ", " + counter + " out of " + aacounter + " correct, "
+ bcounter + " out of " + aacounter + " incorrect.");
}
}
With my current code, I only see one problem, even though I asked for 2 or more problems at the beginning.
You need to add a loop around this statement:
System.out.print("What is " + number1 + " + " + number2 + "? ");
like:
for(int i=0; i<ui; i++){
System.out.print("What is " + number1 + " + " + number2 + "? ");
...

How can i shorten this code and make it less repetitive?

I made a simple calculator but the if statements are very repetitive and long. I am wondering what other solution I could use to shorten it and make it less repetitive. For example using a method (which i have tried but not succeeded) or any other techniques that are usable. Preferably not too advanced since I'm a beginner.
import static java.lang.System.*;
import static javax.swing.JOptionPane.*;
import static java.lang.Integer.*;
public class SimpleCalc {
public static void main(String[] args) {
String operator = showInputDialog("Choose operation: " + "\n" +
"[1] = Plus" + "\n" +
"[2] = Minus" + "\n" +
"[3] = Multiply" + "\n" +
"[4] = Divide" + "\n");
int c = parseInt(operator);
if (c > 4) {
showMessageDialog(null, "You cant do that.");
} else if (c == 1) {
String textA = showInputDialog("Enter first number: ");
String textB = showInputDialog("Enter second number: ");
int a = parseInt(textA);
int b = parseInt(textB);
showMessageDialog(null, a + " + " + b + " = " + (a + b));
} else if (c == 2) {
String textA = showInputDialog("Enter first number: ");
String textB = showInputDialog("Enter second number: ");
int a = parseInt(textA);
int b = parseInt(textB);
showMessageDialog(null, a + " - " + b + " = " + (a - b));
} else if (c == 3) {
String textA = showInputDialog("Enter first number: ");
String textB = showInputDialog("Enter second number: ");
int a = parseInt(textA);
int b = parseInt(textB);
showMessageDialog(null, a + " * " + b + " = " + (a * b));
} else if (c == 4) {
String textA = showInputDialog("Enter first number: ");
String textB = showInputDialog("Enter second number: ");
int a = parseInt(textA);
int b = parseInt(textB);
showMessageDialog(null, a + " / " + b + " = " + (a / b));
}
}
}
Try something like
String textA = showInputDialog("Enter first number: ");
String textB = showInputDialog("Enter second number: ");
int a = parseInt(textA);
int b = parseInt(textB);
switch(c) {
case 1:
showMessageDialog(null, a + " + " + b + " = " + (a+b));
break;
case 2:
...
default:
showMessageDialog(null, "You cant do that.");
Well, to start; you can move the
String textA = showInputDialog("Enter first number: ");
String textB = showInputDialog("Enter second number: ");
int a = parseInt(textA);
int b = parseInt(textB);
outside of the if blocks so that it only asks once before the if block, which will save you 12 lines of code.
Or you can also use methods or functions as a practice; but that wouldn't shorten your code further, really. I'd also suggest looking into Codegolf, you can learn a LOT about code-shortening.
The following will be identical, but doesn't repeat the same lines over and over. You can also use the switch statement in place of the 4 if/else if statements.
public class SimpleCalc {
public static void main(String[] args) {
String operator = showInputDialog("Choose operation: " + "\n" +
"[1] = Plus" + "\n" +
"[2] = Minus" + "\n" +
"[3] = Multiply" + "\n" +
"[4] = Divide" + "\n");
int c = parseInt(operator);
if (c>4) {
showMessageDialog(null, "You cant do that.");
return;
}
String textA = showInputDialog("Enter first number: ");
String textB = showInputDialog("Enter second number: ");
int a = parseInt(textA);
int b = parseInt(textB);
if(c==1) {
showMessageDialog(null, a + " + " + b + " = " + (a+b));
}
else if (c==2) {
showMessageDialog(null, a + " - " + b + " = " + (a-b));
}
else if (c==3) {
showMessageDialog(null, a + " * " + b + " = " + (a*b));
}
else if (c==4) {
showMessageDialog(null, a + " / " + b + " = " + (a/b));
}
}
}
There are a couple approaches:
Put the common code into a method
Move the common code to a different part of the current method so that it is executed unconditionally.
Put the non-common code into a function / method / class that can be used to parameterize the common code.
In this case, the second approach works best; e.g.
if(c==1) {
String textA = showInputDialog("Enter first number: ");
String textB = showInputDialog("Enter second number: ");
int a = parseInt(textA);
int b = parseInt(textB);
showMessageDialog(null, a + " + " + b + " = " + (a+b));
}
else if (c==2) {
String textA = showInputDialog("Enter first number: ");
String textB = showInputDialog("Enter second number: ");
int a = parseInt(textA);
int b = parseInt(textB);
showMessageDialog(null, a + " - " + b + " = " + (a-b));
}
...
can be transformed into:
String textA = showInputDialog("Enter first number: ");
String textB = showInputDialog("Enter second number: ");
int a = parseInt(textA);
int b = parseInt(textB);
int result;
char op;
if (c == 1) {
result = a + b;
op = '+';
} else if (c == 2) {
result = a - b;
op = '-';
}
...
showMessageDialog(null, a + " " + op + " " + b + " = " + result);
(I have left a problem there for you to notice and sort out ... as a learning exercise.)
Just for fun. Factor out the stuff that's common! And handle the possibility that you'll need to implement unary operators. You'll probably also want to put it in a loop, and add an exit command.
public class SimpleCalc {
public static void main(String[] args) {
String operator = showInputDialog(
"Choose operation: " + "\n" +
"[1] = Add" + "\n" +
"[2] = Subtract" + "\n" +
"[3] = Multiply" + "\n" +
"[4] = Divide" + "\n");
"[5] = Negate" + "\n");
int c = parseInt(operator);
int operand_count = 0;
switch (c) {
case 1:
case 2:
case 3:
case 4:
operand_count = 2;
break;
case 5:
operand_count = 1;
break;
default:
showMessageDialog(null, "You cant do that.");
return(-1);
}
int a = 0;
int b = 0;
if (operand_count >= 1) {
String textA = showInputDialog("Enter first number: ");
int a = parseInt(textA);
}
if (operand_count >= 2) {
String textB = showInputDialog("Enter second number: ");
int b = parseInt(textB);
}
char * opname = "";
int result = 0;
switch (c) {
case 1:
opname = "+";
result = a + b;
break;
case 2:
opname = "-";
result = a - b;
break;
case 3:
opname = "*";
result = a * b;
break;
case 4:
opname = "/";
result = a / b;
break;
case 5:
opname = "-";
result = -a;
break;
}
if (operand_count == 1) {
showMessageDialog(null, opname + " (" + a + ") = " result);
} else {
showMessageDialog(null, a + " " + opname + " " + b + " = " + result);
}
}
}

Hanging token from user input is not allowing me to proceed in my program

My program is not allowing me to enter user input if i do not enter a number and i want to go through the program again, it think its due to a hanging token somewhere but i cannot seem to find it.
import java.util.Scanner;
public class LessonTwo {
static Scanner userInput = new Scanner(System.in);
public static void main(String[] args) {
char answer = ' ';
do {
System.out.print("Your favorite number: ");
if (userInput.hasNextInt()) {
int numberEntered = userInput.nextInt();
userInput.nextLine();
System.out.println("You entered " + numberEntered);
int numEnteredTimes2 = numberEntered + numberEntered;
System.out.println(numberEntered + " + " + numberEntered
+ " = " + numEnteredTimes2);
int numEnteredMinus2 = numberEntered - 2;
System.out.println(numberEntered + " - 2 " + " = "
+ numEnteredMinus2);
int numEnteredTimesSelf = numberEntered * numberEntered;
System.out.println(numberEntered + " * " + numberEntered
+ " = " + numEnteredTimesSelf);
double numEnteredDivide2 = (double) numberEntered / 2;
System.out.println(numberEntered + " / 2 " + " = "
+ numEnteredDivide2);
int numEnteredRemainder = numberEntered % 2;
System.out.println(numberEntered + " % 2 " + " = "
+ numEnteredRemainder);
numberEntered += 2; // *= /= %= Also work
numberEntered -= 2;
numberEntered++;
numberEntered--;
int numEnteredABS = Math.abs(numberEntered); // Returns the
int whichIsBigger = Math.max(5, 7);
int whichIsSmaller = Math.min(5, 7);
double numSqrt = Math.sqrt(5.23);
int numCeiling = (int) Math.ceil(5.23);
System.out.println("Ceiling: " + numCeiling);
int numFloor = (int) Math.floor(5.23);
System.out.println("Floor: " + numFloor);
int numRound = (int) Math.round(5.23);
System.out.println("Rounded: " + numRound);
int randomNumber = (int) (Math.random() * 10);
System.out.println("A random number " + randomNumber);
} else {
System.out.println("Sorry you must enter an integer");
}
System.out.print("Would you like to try again? ");
answer = userInput.next().charAt(0);
}while(Character.toUpperCase(answer) == 'Y');
System.exit(0);
}
}
Yes you are right you need to consume the characters first after the user inputted character in the nextInt before allowing the user to input data again
just add this in your else block and it will work:
else {
System.out.println("Sorry you must enter an integer");
userInput.nextLine(); //will consume the character that was inputted in the `nextInt`
}
EDIT:
change this:
answer = userInput.next().charAt(0);
to:
answer = userInput.nextLine().charAt(0);

program will not go to else statement

This program is supposed to print an error if you enter too many seats. If i enter an invalid number of seats ex: economy section has 8 seats. but if I enter a number greater than that it, the program doesn't go on to the else statement and print the error message.
Instead it just goes through the if statement and does the calculations with the invalid seat number.
import java.util.Scanner;
public class FlightProfit
{
String location;
int TOLEDO_FARE = 200;
int HOUSTON_FARE = 300;
int BOISE_FARE = 400;
int economySeats;
int businessSeats;
int firstClassSeats;
int economySales;
int businessSales;
int firstClassSales;
//int totalSales = economySales + businessSales + firstClassSales;
Scanner in = new Scanner(System.in);
public int addEconomySeats()
{
System.out.print("Enter number of economy seats 1-8: ");
economySeats = in.nextInt();
if(economySeats > 0 || economySeats < 9)
{
return economySeats;
}
else
{
System.out.println("Error: Only 8 seats available in economy.");
}
return 0;
}
public int addBusinessSeats()
{
System.out.print("Enter number of business seats sold: ");
businessSeats = in.nextInt();
if(businessSeats > 0 || economySeats < 7)
{
return businessSeats;
}
else
{
System.out.println("Error: Only 6 seats available in business.");
}
return 0;
}
public int addFirstClassSeats()
{
System.out.print("Enter number of first class seats sold: ");
firstClassSeats = in.nextInt();
if(firstClassSeats > 0 || firstClassSeats < 5)
{
return firstClassSeats;
}
else
{
System.out.println("Error: Only 4 seats available in first class.");
}
return 0;
}
public void getProfit(String loc)
{
location = loc;
if(location.equalsIgnoreCase("toledo"))
{
economySales = economySeats * TOLEDO_FARE;
businessSales = businessSeats * (2 * TOLEDO_FARE);
firstClassSales = firstClassSeats * (4 * TOLEDO_FARE);
System.out.println("Economy Sales: " + economySeats + " seats: " + economySales);
System.out.println("Business Sales: " + businessSeats + " seats: " + businessSales);
System.out.println("First Class Sales: " + firstClassSeats + " seats: " + firstClassSales);
//System.out.println("Total Sales: " + totalSales);
}
else if(location.equalsIgnoreCase("houston"))
{
economySales = economySeats * HOUSTON_FARE;
businessSales = businessSeats * (2 * HOUSTON_FARE);
firstClassSales = firstClassSeats * (4 * HOUSTON_FARE);
System.out.println("Economy Sales: " + economySeats + " seats: " + economySales);
System.out.println("Business Sales: " + businessSeats + " seats: " + businessSales);
System.out.println("First Class Sales: " + firstClassSeats + " seats: " + firstClassSales);
// System.out.println("Total Sales: " + totalSales);
}
else
{
economySales = economySeats * BOISE_FARE;
businessSales = businessSeats * (2 * BOISE_FARE);
firstClassSales = firstClassSeats * (4 * BOISE_FARE);
System.out.println("Economy Sales: " + economySeats + " seats: " + economySales);
System.out.println("Business Sales: " + businessSeats + " seats: " + businessSales);
System.out.println("First Class Sales: " + firstClassSeats + " seats: " + firstClassSales);
//System.out.println("Total Sales: " + totalSales);
}
}
}
==MAIN==
import java.util.Scanner;
public class Aviation
{
public Aviation()
{
}
public static void main(String[] args)
{
int option;
FlightCost newFlight = new FlightCost();
FlightProfit flight = new FlightProfit();
Scanner in = new Scanner(System.in);
System.out.print("Enter new flight location: ");
String location = in.next();
do{
String menu = "\n Please select an option to perform"
+ "\n1 (1) Get flight costs."
+ "\n2 (2) Get flight profits."
+ "\n3 (3) Enter names/meals."
+ "\n4 (4) Exit.";
System.out.println(menu);
option = in.nextInt();
}while (option < 0 || option > 4);
switch(option)
{
case 1:
newFlight.getCost(location);
break;
case 2:
flight.addEconomySeats();
flight.addBusinessSeats();
flight.addFirstClassSeats();
flight.getProfit(location);
break;
case 3:
//newFlight.flyers();
break;
case 4:
System.out.println("Exit");
break;
default:
System.out.println("Error: must select menu option.");
}
}
}
if (economySeats > 0 || economySeats < 9)
This condition is always true (since any number is either positive or less than 9), so of course you don't reach the else clause.
You probably want the && (and) operator :
if (economySeats > 0 && economySeats < 9)
And your other conditions have the same error.
if (economySeats > 0 && economySeats < 9)
As economySeats should be greater then 0 and smaller then 9. then only the condition will follow to the else statement.
when you use if (economySeats > 0 || economySeats < 9)
it means that economySeat should be greater then 0 (so if you input value greater then 0 then this condition will be true) so, that's why you are thinking that the if statement isnt working.
The reason why your number range check does not work as you intend to was already given. I'd howver like to hint that you could do range checks somewhat more elegant and less error-prone by using Guava's 'Range' type:
Range economySeatsRange = Range.atLeast(1).atMost(8);
//...
boolean inAllowedRange = economySeatsRange.apply(economySeats);
if(inAllowedRange)
// between 1 and 8
else
// signal error
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Range.html

Categories

Resources