I made a method should pull up a menu with a list of actions, allows users to choose an action, execute the action, then goes back to the menu and repeats until the user chooses to end the session. I'm currently at a bit lost on what to do with the while loop and the boolean endSession(), which I've been shuffling around in the code that sometimes lets me compile it and never does what I want it to do. The place I currently have it causes it to not only skip the action, but loop infinitely. I don't really need to know what's exactly wrong, I just want to know where to put the while loop/boolean endSession (and although not necessary, an explaination for why the answer works would be nice).
//package bookStoreLab;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
public class BookStoreDriver {
private static final int PRINT_INVENTORY=1;
private static final int SEARCH_TITLE=2;
private static final int SEARCH_AUTHOR=3;
private static final int AVAILABLE_BOOKS=4;
private static final int NEW_RELEASES=5;
private static final int PURCHASE=6;
private static final int ADD_INVENTORY=7;
//include rest of constants here for all choices
private static Scanner keyboard;
public static void main(String[] arg) throws IOException, FileNotFoundException{
System.out.println("\f");
keyboard = new Scanner(System.in);
BookStore booky = new BookStore();
System.out.println("*****" +
"Welcome To Your Local Book Store!" + "*****");
booky.inputBooks();
boolean endSession = false;
int choice = getChoice(endSession);
if(choice==0){
endSession = true;
}
if(choice==PRINT_INVENTORY){
booky.printInventory();
}
if(choice==SEARCH_TITLE){
booky.searchByTitle();
}
if(choice==SEARCH_AUTHOR){
booky.searchByAuthor();
}
if(choice==AVAILABLE_BOOKS){
booky.printAvailableBooks();
}
if(choice==NEW_RELEASES){
booky.printNewReleases();
}
if(choice==PURCHASE){
booky.purchase();
}
if(choice==ADD_INVENTORY){
booky.addToInventory();
}
else{
System.out.println("Please choose an option that's actually listed.");
}
printFarewell();
}
public static int getChoice(boolean a){
int choice=-1;
while(!a){
System.out.println("\n\nWhat store service would you like" +
"to perform? (Enter 0-7)");
System.out.println("\t0. Enter 0 to end your session");
System.out.println("\t1. View all books");
System.out.println("\t2. Search by title");
System.out.println("\t3. Search by author");
System.out.println("\t4. View available books for purchase");
System.out.println("\t5. View new releases");
System.out.println("\t6. Purchase one or more copies of a book");
System.out.println("\t7. Add book(s) to inventory");
System.out.println("Enter your choice: ");
choice = keyboard.nextInt();
}
return choice;
}
public static void printFarewell(){
System.out.println("\n\nThank you for using the system!");
}
}
So far I've tried:
-getting rid of parameter a for getChoice() and moving the while loop to before if(choice==0) and ended it at the else statement
while(!endSession){
if(choice==0){
endSession = true;
}
if(choice==PRINT_INVENTORY){
booky.printInventory();
}
if(choice==SEARCH_TITLE){
booky.searchByTitle();
}
if(choice==SEARCH_AUTHOR){
booky.searchByAuthor();
}
if(choice==AVAILABLE_BOOKS){
booky.printAvailableBooks();
}
if(choice==NEW_RELEASES){
booky.printNewReleases();
}
if(choice==PURCHASE){
booky.purchase();
}
if(choice==ADD_INVENTORY){
booky.addToInventory();
}
else{
System.out.println("Please choose an option that's actually listed.");
}
}
which resulted in the action looping infinitely (for example: repeatly doing printInventory() until I forced the console to stop).
-moving the boolean endSession to inside getChoice() (no parameters), which almost works, except for the part where it skips doing the action (for example: entering 1, and the menu immediately popping back up without doing printInventory()).
Put the while loop in the main method. Your boolean value never changes inside your method, so your while loop will either run 0 times or infinite times.
Let your helper method collect a single input, and let the loop in your main method inspect the last returned value and determine whether to execute another iteration of the loop.
public static void main(String[] args) {
int choice = getChoice();
while(choice != 0) {
choice = getChoice();
}
}
public static int getChoice() {
// display menu
// collect user input
// return user input
}
1) get rid of the parameters,
2) put the while loop before int choice = getChoice(),
3) end it after the else loop.
I have no idea why that works but I'm too tired to care so yeet!
Related
New to this website and coding in java in general. I have about 5 months experience from last year's classes. and another half spent in python. We have reached our second lab this semester and I have ran into a slight problem that my new professor refuses to help / guide with.
The lab is as described.
Make a to do list that has 2 classes. One class (the main tester one) takes in all the IO and gives all the output. The other class contains the todo list itself (arraylist) and provides methods for the main class to call on. The scanner object is in the main tester class. the arraylist is in the other class.
The following commands of input are necessary.
List, New, Change, Delete, Quit.
The program basically prompts the message to add something to your to do list. add whatever the whole line is. Then modify it as you do them.
My current questions regards how to take the input from the tester program and pass it to the other class to store into the arraylist. We have done labs where they were all in the main class and I would just add with the method calls of the Arraylist class. however now we must do it this way and I am having troubles getting them to communicate. Im guessing that I just have some sort of constructor wrong or some object misreferenced. Here is a short snippet of what I have.
(Main Tester Class)
import java.util.Scanner;
public class ToDoTester
{
public static void main(String[] args)
{
Scanner in = new Scanner (System.in);
ToDo info = new ToDo();
while(true)
{
System.out.println("* * * Start To Do List * * *");
System.out.println("Enter a command (List, New, Change, Done) or Quit
");
String x = in.next();
if(x.equals("List"))
{
System.out.println(info.getList());
//Print out the array list
}
else if(x.equals("New"))
{
//System.out.println(info.addList(addedListOption));
//Add new thing to do to arraylist
}
(Other Class With Methods)
public class ToDo {
ArrayList<String> data = new ArrayLst<String>();
ToDoTester scan = new ToDoTester();
private String list;
public void addList() {
//tring takeIn = ToDoTester.scan.next();
//data.add(scan.nextLine());
}
public String getList() {
System.out.println(data.size());
return list;
}
}
I realize this may be a very nooby problem and perhaps i'm making more of a deal out of it than I have to. But i truly want to understand what I am doing and this new professor as compared to my old one is slightly worse in the helping understanding department. Thus, i come here for help, not for someone doing my work! So any help would be appreciated and I can supply any other information as needed. Can even post a picture of the lab if necessary or easier.
Original answer
You are doing well, but you probably forgot that we can pass in objects to methods via method arguments.
class ToDo {
public void addToList(String newToDo) {
data.add(newToDo);
}
}
class ToDoTester {
public static void main(String[] args) {
...
} else if (x.equals("New")) {
info.addToList(in.nextLine());
}
}
}
Expanded answer
Here is a simplified version of how I would perform the task.
As I mentioned in the comments, there is room for improvement: we can replace the switch with the command pattern, we can separate the entry point from our domain classes, we can handle exceptions more accurately, we can customise the output messages more elaborately.
Anyway, first take a look at this, and then let me know if you want to see a more enhanced version.
final class ToDoTester {
private final Scanner reader = new Scanner(System.in);
public static void main(String[] args) {
final ToDo toDo = new ToDo();
final ToDoTester toDoTester = new ToDoTester();
final Scanner reader = toDoTester.getReader();
while (true) {
System.out.println("Enter a command (List, New, Change, Delete) or Quit:");
switch (reader.nextLine()) {
case "List":
toDoTester.display(toDo.list());
break;
case "New":
toDo.add(toDoTester.readToDo());
break;
case "Change":
final Pair<Integer, String> input = toDoTester.readInputToChange();
toDo.update(input.getKey(), input.getValue());
break;
case "Delete":
toDo.remove(toDoTester.readIndex());
break;
case "Quit":
return;
default:
System.out.println("Incorrect choice, let's try again.");
}
}
}
public Scanner getReader() {
return reader;
}
public void display(List<String> list) {
IntStream.range(0, list.size())
.mapToObj(i -> String.format("[%d] %s", i, list.get(i)))
.forEach(System.out::println);
}
public Pair<Integer, String> readInputToChange() {
return new Pair<>(readIndex(), readToDo());
}
public String readToDo() {
System.out.println("Enter a to-do:");
return reader.nextLine();
}
public int readIndex() {
System.out.println("Enter the index of the to-do:");
return Integer.valueOf(reader.nextLine());
}
}
final class ToDo {
private final List<String> list = new ArrayList<>();
public void add(String toDo) {
list.add(toDo);
}
public void remove(int position) {
validatePosition(position);
list.remove(position);
}
public void update(int position, String substitute) {
validatePosition(position);
list.set(position, substitute);
}
private void validatePosition(int position) {
if (position < 0 || position >= list.size()) {
// should be thrown an exception
System.out.println("Incorrect input.");
}
}
public List<String> list() {
return new ArrayList<>(list);
}
}
An example of execution:
Enter a command (List, New, Change, Delete) or Quit:
List
Enter a command (List, New, Change, Delete) or Quit:
New
Enter a to-do:
first to-do
Enter a command (List, New, Change, Delete) or Quit:
List
[0] first to-do
Enter a command (List, New, Change, Delete) or Quit:
Change
Enter the index of the to-do:
0
Enter a to-do:
my first to-do
Enter a command (List, New, Change, Delete) or Quit:
List
[0] my first to-do
Enter a command (List, New, Change, Delete) or Quit:
Delete
Enter the index of the to-do:
0
Enter a command (List, New, Change, Delete) or Quit:
List
Enter a command (List, New, Change, Delete) or Quit:
Your todo class must have arraylist and puplic methods, that are get string (for add method) or int (for delete) or nothing (for list) as arguments, and operate on arraylist. Your ToDoTester class must contain example of todo class (ToDo info = new ToDo();) and operate on its methods in loop. Hope that helps
Here are the parameters:
Create a method called get8BallAnswers (2 point)
The method should have no parameters
The method will build the array of possible String answers (from BA5), and return the entire array
Overload the get8BallAnswers method (2 points)
The method should have 1 integer parameter, where the user can pass a random number to it
The method should return 1 possible String answer from the array. Hint: You can use the method you created in step 2 to retrieve the array of answers.
Create a method called magic8Ball that will basically run the whole program. (2 point)
It should ask the user to enter a question for the 8 Ball, generate a random number, and pass that to one of the methods above to get a response.
You will call this magic8Ball method in the main method.
The method should be called within the do-while loop, and repeat if the user wants to run the program again or not.
here's what I have:
package magic8;
import java.util.Random;
import java.util.Scanner;
public class magic8Ball {
public static String[] get8BallAnswers() {
String[] ball;
return ball = new String[] {"Yes, of course!", "Without a doubt, yes.",
"You can count on it.", "For sure!", "Ask me later.", "I'm not sure.", "I can't tell you right now", "I'll tell you after my nap.", "No way!", "I don't think so.", "Without a doubt, no.", "The answer is clearly No."};
}
public static void main(String[] args) {
boolean run = true;{
while (run) {
magic8Ball();
System.out.println("Do you want to try again, yes or no?");
Scanner scnr = null;
String go = scnr.nextLine();
go = go.toLowerCase();
if (go.equals("n")) {
System.out.println("Goodbye");
run = false;
}
if (go.equals("no")) {
System.out.println("Goodbye");
run = false;}
}
}
}
public static void magic8Ball() {
Scanner input = new Scanner(System.in);
String response;
System.out.println("Please ask me a question.");
response = input.nextLine();
Random gen = new Random();
int pick = gen.nextInt(ball.length);
System.out.println(ball[pick]);
return;
}
}
I can't get the random number generator to pass a integer into the array ball to get a response.
Try this
private static Scanner scanner = new Scanner(System.in);
private static String[] get8BallAnswers() {
return new String[] {"Yes, of course!", "Without a doubt, yes.", "You can count on it.",
"For sure!", "Ask me later.", "I'm not sure.", "I can't tell you right now",
"I'll tell you after my nap.", "No way!", "I don't think so.",
"Without a doubt, no.", "The answer is clearly No."};
}
private static String get8BallAnswers(int num) {
return get8BallAnswers()[num];
}
public static void main(String[] args) {
while (true) {
magic8Ball();
System.out.println("Do you want to try again, yes or no?");
if (scanner.nextLine().toLowerCase().contains("n")) {
System.out.println("Goodbye");
break;
}
}
}
private static void magic8Ball() {
System.out.println("Please ask me a question.");
scanner.nextLine();
System.out.println(get8BallAnswers(new Random().nextInt(get8BallAnswers().length)));
}
I'm building a console game in Java that works like this: It prints you an operation (e.g: 3 x 4) and you must write the result (12 in this case), and it will give you operations during a period of 1 minute and then it will finish.
I knew from the beginning I had to use threads to catch the user input, so this is the thread's logic:
public class UserInput extends Thread {
private int answer;
#Override
public void run() {
Scanner in = new Scanner(System.in);
while(true){
answer = in.nextInt();
}
}
public int getAnswer(){
return answer;
}
}
quite simple, now the game's logic:
public static void play() {
Game game = new EasyGame();
UserInput ui = new UserInput();
long beginTime = System.currentTimeMillis()/1000;
ui.start();
boolean accepted = true;
while(timeLeft(beginTime)){
//PrintChallenge() prints an operation and store its result in game
if(accepted) game.PrintChallenge();
accepted = false;
if(ui.getAnswer() == game.getResult()) accepted = true;
}
}
//returns if current time is 60 seconds after initial time
public static boolean timeLeft(long time){
return (System.currentTimeMillis()/1000) < (time + 60);
}
but it isn't working, it simply never matches ui's getAnswer() with game's getResult(). What am I doing wrong on this thread and game logics?
I think your problem is Java caching the value of your int locally, though it could be due to something in your game.getResult(), since I cannot check this. Thread safety is difficult in java.
To confirm:
I built a dumb version of the game, without any game logic or timer.
I added a volatile keyoword to your answer int, this makes Java check main memory rather than local cache for the value of the int.
The following code outputs once the user enters "30", removing the "volatile" keyoword in user input leads to your situation.
See below:
package stackOverflowTests;
import java.util.Scanner;
public class simpleGame {
public static class UserInput extends Thread {
volatile private int answer;
public void run() {
Scanner in = new Scanner(System.in);
while(true){
System.out.print("Answer meeee!:");
answer = in.nextInt();
}
}
public int getAnswer(){
return answer;
}
}
public static void play() throws InterruptedException {
UserInput testInput = new UserInput();
testInput.start();
while(true){
//PrintChallenge() prints an operation and store its result on game
Thread.sleep(10);
if(testInput.getAnswer()==30)System.out.println(testInput.getAnswer()+ " : "+(testInput.getAnswer()==10));
}
}
public static void main(String[] args) throws InterruptedException{
play();
}
}
private int answer;
This variable needs to be volatile, as you are reading and writing it from different threads. Or else you need to synchronize all access to it, both reads and writes.
I am creating a java program that runs in tie with another file to help create what is called Object oriented programming.
So I have the whole program completed but I am having a hard time understanding how to make it compile and run. I know my problem is within the name of the method. However I dont quiet understand how to know what to call the method. From what I read there is several different types you can call it.
(Also I know the indentation looks messed up, it's right in my actual program)
Here is what I am looking at to help make sense of my question:
import java.util.Scanner;
import java.util.Random;
public class RockPaperScissors
{
public static void main(String[] args)
{
class getUserChoice
{
System.out.println("Would you you like to play rock, paper scissors?");
userChoice = in.nextLine();
while (!userChoice.equalsIgnoreCase("Rock") && !userChoice.equalsIgnoreCase("Paper") && !userChoice.equalsIgnoreCase("Scissors"))
{
System.out.println("Invalid entry please try again");
userChoice = in.nextLine();
}
userChoice = userChoice.toUpperCase();
return userChoice;
} //end of UserChoice
class getCPUChoice
{
computerRandom = r.nextInt(3)+1;
if (computerRandom == 1) cpuChoice = "Rock";
else if (computerRandom == 2) cpuChoice = "Paper";
else if (computerRandom == 3) cpuChoice = "Scissors";
}
class pickWinner
{
//tie
if (userChoice.equals(cpuChoice))
{
winner = tie;
}
//user has rock
if (userPlay.equals("rock"))
{
if (cpuChoice.equals("Scissor"))
{
winner = user;
}
else if (cpuChoice.equals("Paper"))
{
winner = Computer;
}
else if (cpuChoice.equals("Rock"))
{
winner = tie;
}
}
if (userPlay.equals("Paper"))
{
if (cpuChoice.equals("Scissor"))
{
winner = Computer;
}
else if (cpuChoice.equals("Paper")
{
winner = tie;
}
else if (cpuChoice.equals("Rock")
{
winner = user;
}
}
if (userPlay.equals("Scissors"))
{
if (cpuChoice.equals("Scissor"))
{
winner = tie;
}
else if (cpuChoice.equals("Paper")
{
winner = user;
}
else if (cpuChoice.equals("Rock")
{
winner = computer;
}
}
}
}//end of RockPaperScissors
}
My error I get is:
RockPaperScissors.java:10: error: expected
System.out.println("Would you you like to play rock, paper scissors?");
Which from what I understand is from not having the class setup up right. Could someone maybe help explain how you know what to name each method correctly?
Thanks!
You can't declare more than one public class in a file
To fix the problem, remove the word public.
However I dont quiet understand how to know what to call the method.
As for this, to call a method, simply use the method name (full example of my answer):
public static void main(String[] args) {
class something{
public void someMethod(int argument){
//this doesn't do anything
}
}
something s = new something();
s.someMethod(1);
}
This isn't valid Java. You don't create a class to get choices; make it a method.
public class RockPaperScissors {
private static final String [] choices = { "ROCK", "PAPER", "SCISSORS" };
private Random random;
public RockPaperScissors() { this(null); }
public RockPaperScissors(Long seed) {
this.random = (seed == null) ? new Random() : new Random(seed.longValue());
}
// An Enum would be better than a number or String
public String nextChoice() {
return choices[this.random.nextInt(choices.length)];
}
}
Classes and methods can be defined inside other classes, but neither can be defined inside methods (functions), with the exception of anonymous functions. If this is a standalone program you intended to write, and you intended for getUserChoice and getCPUChoice to be methods, just remove the class keyword before both names and perhaps replace them with static if you want them to be static methods of your RockPaperScissors class. Methods need to have a return type and in your case, it can be String. You would still need to invoke either method in your main method.
I would imagine this is the sort of structure you are looking for in a "standard" program. You can declare other classes in other files and import those too. Your code will generally run in methods within those classes and is all called from the main method which is your entry point.
//imports here
public class ClassName {
public static void main(String[] args) {
//main entry point to your program
}
private String methodName(String param1) {
//do some stuff here
return someValue;
}
}
You can't create several classes in a single file. So it should have only one "class" keyword here.
Your methods are not well formatted, you should take a look at the Java Oracle Tutorial to get started with Java :)
Here is a simple example of class + method :
public class MyClass{
//Attribute
public int myMethod(int x) {
return x+1;
}
}
A method is defined by its visibility (public), the returned type (int), its name (myMethod) and its parameters (int x). So here your methods have a "class" returned type, which is not possible.
It seems like you are trying to write some kind of a guess game between a user and a computer...nice but less easier than it sounds.
As many have said you are having trouble because you are declaring classes with a wrong visibility and not exactly at the right place
The names you gave your two classes gives me the feeling they should be methods rather than classes. So It would be simpler two have three methods.
The main method: that's where you run your game loop
A getUserChoice(): that's where you ask the user to input its choice (Good that you block the user until he inputs a valid choice)
The getCPUChoice: That's where you ask the cpu to input his choice
Some one the variables you use will necessarily be shared between more than one method, so declare them at the class level so that they can be accessible wherever necessary. For example:
public class RockPaperScissors {
static String userChoice = "";
static String cpuChoice = "";
static Scanner in = new Scanner(System.in);
static Random r = new Random();
// ... rest of the code here
You should instantiate your Random object and declare your computerRandom variable before using them.
Just as a practical illustration I created a game loop (there are often infinite :)) in the main method where I receive the user's input and the computer input and then compare then. Success comes with a congratulation and failure with a try again note. I am not assuming that it is exactly where you were trying to get, but it could be.
Here is my complete illustration code
import java.util.Scanner;
import java.util.Random;
/**
* Created by alompo on 07.11.16.
*/
public class RockPaperScissors {
static String userChoice = "";
static String cpuChoice = "";
static Scanner in = new Scanner(System.in);
static Random r = new Random();
public static void main(String[] args) {
while(true) {
getUserChoice();
getCPUChoice();
if (cpuChoice.equalsIgnoreCase(userChoice)) {
System.out.println("Good choice, you have a match with the computer");
} else {
System.out.println("Sorry mismatch between you and the computer...try again");
}
}
}
public static void getUserChoice()
{
System.out.println("Would you you like to play rock, paper scissors?");
userChoice = in.nextLine();
while (!userChoice.equalsIgnoreCase("Rock") && !userChoice.equalsIgnoreCase("Paper") && !userChoice.equalsIgnoreCase("Scissors"))
{
System.out.println("Invalid entry please try again");
userChoice = in.nextLine();
}
} //end
public static void getCPUChoice()
{
int computerRandom = r.nextInt(3)+1;
if (computerRandom == 1) cpuChoice = "Rock";
else if (computerRandom == 2) cpuChoice = "Paper";
else if (computerRandom == 3) cpuChoice = "Scissors";
}
}
First of all and before posting my question let me ask you people to stop downvoting my questions even if they seem stupid to you ,this site is an important place for me, it helps me a lot with my java doubts which are many,a question ban would be an heavy setback for me, so be helpful even by not answering!
Now for the question,
I have this method were i assign a value to a setter method with user input
public void addName() {
Scanner input = new Scanner(System.in);
System.out.println("Do you want to add a citizen name?");
String answer = input.nextLine();
while (!answer.equals("y") || (!answer.equals("n"))) {
if (answer.equals("y")) {
String giveName = input.nextLine();
this.setName(giveName);
break;
} else if (answer.equals("n")) {
System.out.println("Not adding a name!");
break;
}else{System.out.println("Please choose y or n!");
answer = input.nextLine();}
}
}
this method is later called in main from object p1 and object p2 and being assigned a differend value for each one to the instance variable name
import java.util.ArrayList;
import java.util.Scanner;
public class MainClass {
public static void main(String[] args) {
ArrayList<Pessoas> lista = new ArrayList<Pessoas>();
Pessoas p1 = new Portugueses();
Pessoas p2 = new Alemaes();
p1.addName();
p2.addName();
System.out.println(p1.getName());
System.out.println(p2.getName());
}
}
but when i call the getName() method at the end of main both p1 and p2 have the same value!
Shouldn't each object get it´s own copy of an instance variable?
The Problem is in your addName()-function. Your running your loop(while (!answer.equals("y") || (!answer.equals("n")))) until a y or n is entered. So as soon as you enter it, your loop will stop.
In your loop your checking if the input that was made cotains a y or n. Now the problem should be clear. Your loop won't run with those two values entered, but inside the loop you want to check if one of those is entered.
Two little personal hints(everyone has another style): Don't use break; let your loops end themselfs. Do it with an boolean-variable and updating it's state.
The second hint would be to use one Scanner-Object. For example you could add a Scanner-parameter to your addName-function. Just init one in your MainClass.
Those hints and fixes of the problem applied to your code could look like that:
public void addName(Scanner input) {
System.out.println("Do you want to add a citizen name?");
String answer;
boolean isAnotherInputNeeded = true;
while (isAnotherInputNeeded) {
answer = input.nextLine();
if (answer.equals("y"))
{
System.out.println("What's the name?");
String giveName = input.nextLine();
this.setName(giveName);
isAnotherInputNeeded= false;
}
else if (answer.equals("n"))
{
System.out.println("Not adding a name!");
this.setName("No name entered");
isAnotherInputNeeded= false;;
}
else
{
System.out.println("Please choose y or n!");
}
input.reset();
}
}
And your MainClass:
import java.util.ArrayList;
import java.util.Scanner;
public class MainClass {
public static void main(String[] args) {
ArrayList<Pessoas> lista = new ArrayList<Pessoas>();
Pessoas p1 = new Pessoas();
Pessoas p2 = new Pessoas();
Scanner input = new Scanner(System.in);
p1.addName(input);
p2.addName(input);
System.out.println("You entered the following names:");
System.out.println(p1.getName());
System.out.println(p2.getName());
}
}
Hope that helps!