Java Scanner.next is blocked seemingly without reason - java

I'm trying to get user inputs in a while:
package com.projet.geometrie;
import java.util.List;
import java.util.ArrayList;
import java.util.Scanner;
class TestGeo{
public static void main(String[] args) {
Scanner input_reader = new Scanner(System.in);
boolean retour = false;
boolean first = true;
List<Vertex> listePoints = new ArrayList<>();
while (!retour) {
System.out.println("Entrez une coordonnée au format : x,y");
String coord = input_reader.next();
String[] coordSplit = coord.split(",");
int x = Integer.parseInt(coordSplit[0]);
int y = Integer.parseInt(coordSplit[1]);
if (!first) {
if (x != listePoints.get(0).getX() && y != listePoints.get(0).getY()) {
Vertex nouveauPoint = new Vertex(x, y);
listePoints.add(nouveauPoint);
if (listePoints.size() > 1) {
}
} else {
retour = true;
}
} else {
first = false;
Vertex nouveauPoint = new Vertex(x, y);
listePoints.add(nouveauPoint);
}
}
input_reader.close();
Section test = new Section(listePoints);
System.out.println("Nombre de sommets : " + listePoints.size());
System.out.println("Aire du polygone : " + test.getAire());
System.out.println("Centroide X : " + test.getCoordCentroide().get(0) + " Y : " + test.getCoordCentroide().get(1));
}
}
But at some point, after I enter the input, my code just gets stuck. I write the input, press enter and it just skips a line, as it is no longer reading the input. It mostly happens after 3 iterations, but sometimes it's 2, other times it's 4. In debug mode it just get stuck at trying to read.
Anyone has an idea of what I did wrong?
I'm using jdk 10.0.2, let me know if any other information could be useful, I'm new to java.
*EDIT : Posted the full code with which I'm experiencing the bug. The class Vertex is just a grouping of 2 int and was tested, I know it works. This class is supposed to take coordinates input from the user and add the point to a list of point. If the last point entered is the same as the first one, it stops and show some information about the created polygon.

Finally got it to work by using .nextInt() and asking the user to enter the x and the y separately (as 2 different inputs). I think it had something to do with the fact that strings were involved in the process, though I'm not sure why it would be problematic. If anyone has an explanation I would be glad to know more even if it's working now.

Related

function not entering a loop

Hi i'm trying to program a tool that allow us to manage a small shop , i've managed to get evey functionality to work`but this last function is getting me crazy
public void ajoutCommandesCli() {
Commandes com = new Commandes();
Magasin m = this;
Client c = new Client();
Scanner sc = new Scanner(System.in);
System.out.println("quel est votre numero client ?");
int numcli = sc.nextInt();
System.out.println("testosterone");
System.out.println(this.listecli.capacity());
for (int i = 0; i <= this.listecli.size(); i++) {
if (numcli == listecli.get(i).num) {
int index = this.listecli.indexOf(i);
c = this.listecli.get(index);
System.out.println("test aaaa");
com.saisirCommandes(this, c);
} else {
System.out.println("réessayer?");
System.out.println("1-oui");
System.out.println("2-non");
int choix = sc.nextInt();
if (choix == 1) {
this.ajoutCommandesCli();
} else {
System.out.println("testitestos");
MenuMagasin.afficherMenu(this);
}
}
}
}
this function doesnt even enter the first for loop and i dont know why .
Magasin has a vector of client ,but java tells me my vector capacity is 10 but the teacher told us vector just has no definite capacity , i havent inputed any lenghth for the vector.this is getting me crazy please help me guys .I'm sorry if my question sounds stupid but i need help.
Your question lacks information, you should make a minimal-reproducible-example as shown here.
I'd recommend running your program in debug mode, and view the value of this expression :
numcli==listecli.get(i).num
does your program ever run the if statement's code ?
is you list listecli empty ?
what's the error message you getting ?

QuizCreator: Whats the best way to safe Questions and Answers? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I want to code a QuizCreator, but I don't really know how I should save the Questions and Answers. Would it be better to save them in one file or separate them into two files?
Also, how could I display the questions and then check if the answers are correct?
I am new to programming, I would greatly appreciate any advice you have.
I would store them in a single file, and I'd use a file format like JSON. The file would look something like this:
[
{ "question": "What is your favorite color?",
"answers": [
{ "correct": true, "Blue" },
{ "correct": false, "Red" },
{ "correct": false, "Green" }
]
},
{ "question": "What is the airspeed of an unladed swallow?",
"answers": [
{ "correct": true, "I don't know that" },
{ "correct": true, "42 mph" },
{ "correct": false, "10 kmh" }
]
}
]
Then you can use a JSON parsing tool like GSON to parse the file for you. You'll have to read the file in, but you'll be able to find tons of examples of how to use GSON.
That's what I would do. Of course, you might want to use a format that's easier for you to parse.
Q: question 1
FA: 1
FA: 2
TA: 3
Q: question 2
...
Then you can just split the line at the : and see if it starts with Q (and new question) or FA/TA (false or true answers) assuming you're doing multiple choice.
You'll need to know how to open and read the contents of a file. If you use GSON, you'll spend some time learning how to use it. Otherwise you can read lines of the file at a time and parse them into your data structure yourself.
This is a pretty good practice program to write.
In my opinion... keep it simple, keep it all in a single Text file regardless of what format you decide to use. One text file per Quiz. This way you can always re-use these files. As a matter of fact, have everything related to a particular quiz in that one particular file. Let the file do the work for you.
For some file examples, one quiz might be a Math Quiz, another Quiz might be on History, and yet another Quiz on Sciences. The rules for each quiz should be displayed to the student before any test starts. These Rules should be contained within each Quiz File so that all your code needs to do is acquire these rules from the Quiz File being run and display them to the Student before the quiz begins. Allow the Student to start the Quiz when ready (after reading the rules).
An Example Math Quiz File (MathTest001.txt):
; QUIZ FILE - For the TimedQuestions class.
; The Quiz Message (optional) - This information is displayed to the User within
; a dialog box before the test begins.
; Quiz Message lines always begin with a Colon (:).
; As you can see below, basic HTML can be used to make the dialog message.
; This can add some pizzaz to your Quiz Message.
; ONLY EVER supply one Quiz Message in any Quiz File! Feel free to copy/paste
; the below message from Quiz File to Quiz File.
; Message Tags (if you decide to use them) are optional and are filled by the
; application:
;
; %flc Number of Quiz Questions in file.
; %sft Number of seconds to answer each Question
:<html>Within this Test there are <font color=blue><b>%flc</b></font> multiple choice questions that need<br>
:to be answered.<br><br>You will have <font color=blue><b>%sft</b></font> seconds to answer each test question
:unless<br>otherwise indicated above the question.<br><br>If a question runs out of time before it is answered
:then that<br>question will be considered as <font color=red><b>WRONG</b></font>.<br><br>
:<center>Press the <b>OK</b> button to start the Test</center><br><br></html>
; As a matter of fact, the above message is default and the lines above
; merely show how to make your own.
; Comment Lines always begin with a semicolon (;) and can go anywhere
; providing they are on their own line.
; Comment and Blank lines are always ignored within a Quiz File.
; MATH QUIZ QUESTIONS:
; The \n in Question Lines forces a CarriageReturn/Linefeed in Console. Format the
; questions as you see fit.
; Question & Multiple Choice Options | Correct Answer | Seconds To Answer Question
1: What is: 1 + 1 = ?\n a: 1 b: 2 c: 3 d: 4\n|b|10
2: What is: 5 + 5 = ?\n a: 1 b: 12 c: 10 d: 15\n|c|20
3: What is: 6 + 4 = ?\n a: 10 b: 11 c: 12 d: 13\n|a
4: What is: 2 + 3 = ?\n a: 3 b: 4 c: 5 d: 6\n|c|10
5: What is: 4 + 3 = ?\n a: 7 b: 6 c: 5 d: 8\n|a|10
An Example History Quiz File (HistoryTest001.txt):
; HISTORY QUIZ QUESTIONS:
; The \n in Question Lines forces a Carraige Return/Linefeed in Console.
; Question & Multiple Choice Options | Correct Answer | Seconds To Answer Question
1: Two of Henry VIII's six wives were executed. Anne Boleyn was one. Who was the second?\n a: Katherine Parr b: Jane Seymour c: Catherine Howard d: Lady Jane Grey\n|c|10
2: Who had his head chopped off in 1649?\n a: James I b: James II c: Charles I d: Charles II\n|c|10
3: When was William Shakespeare born?\n a: 1554 b: 1564 c: 1574 d: 1584\n|b
4: The Merry Wives of ...?\n a: Wandsworth b: Wycombe c: Walberswick d: Windsor\n|d|10
5: Approximately how long ago was Stonehenge built?\n a: 10,000 years b: 7,000 years c: 5,000 years d: 3,000 years\n|c|10
An Example Science Quiz File (ScienceTest001.txt):
; SCIENCE QUIZ QUESTIONS:
; The \n in Question Lines forces a Carraige Return/Linefeed in Console.
; Question & Multiple Choice Options | Correct Answer | Seconds To Answer Question
1: What was the Manhattan Project?\n a: Golf Ball Invention b: First US Satelite c: The development of the Atomic Bomb d: New York Housing Project\n|c|10
2: At what speed does light travel?\n a: 12,000 miles per second b: 186,000 feet per second c: 186,000 miles per second d: 186,000 meters per second\n|c|10
3: What is the largest moon of Saturn called?\n a: Titan b: CRT4 c: Quadra d: Sat76\n|a|12
4: The molecule DNA is described as having which shape?\n a: Sine Wave b: Elipsicle c: Tripple Spiral d: Double Helix\n|d|10
5: Percy Spencer invented which time saving kitchen appliance?\n a: Convection Oven b: The Microwave cooker c: Toaster d: Refridgerator\n|b|10
You will notice that within each of the above Quiz Files there is a value supplied for each question which relates to the number of seconds a Student has in order to answer any one question. The code supplied below contains a mechanism that places a time limit on how long the Student has to answer the question.
And the code to utilize any one of these files as a console application:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
public class TimedQuestions {
private final String ls = System.lineSeparator(); // OS Specific Line Separator for console messages
private boolean questionAnswered = false; // Keeps track of whether a question was answered
private int questionCount = 0; // Keeps count of number of questions asked to User
private int rightAnswers = 0; // Keeps count of questions answered Correctly
private int wrongAnswers = 0; // Keeps count of questions answered Incorrectly
private final int DEFAULTSECONDSFORTIMEOUT = 10; // The default question time limit
private int secondsPerQuestion = 10; // Current set time limit for question (can change by question)
private boolean timeOut = false; // Keeps track of whether or not the question has timed out.
/* If you are going to run this class on its own
through your IDE then supply the Quiz File name
to the testFilePath variable below, for example:
private String testFilePath = "C:\\Quizes\\MathTest001.txt";
*/
private String testFilePath;
// Constructors...
//================================================
public TimedQuestions() {}
public TimedQuestions(String testFilePath, int... secondsPerQuestion) {
this.testFilePath = testFilePath;
if (secondsPerQuestion.length > 0) {
this.secondsPerQuestion = secondsPerQuestion[0];
}
}
// ================================================
public static void main(String[] args) {
/* I like to start the application this way
because I don't like the need for statics. */
new TimedQuestions().startTest(args);
}
public void startTest(String... args) {
/* Get Command Line argument (if supplied) which needs
to be the path and file name of the Quiz File. */
if (args.length > 0) {
File f = new File(args[0]);
if (!f.exists()) {
System.err.println("Quiz Error! The supplied Quiz File can not be "
+ "found!" + ls + "[" + args[0] + "]" + ls);
return;
}
this.testFilePath = args[0];
}
// Start the test...
if (testFilePath == null || testFilePath.equals("")) {
System.err.println("Error! - No Quiz File Supplied!");
return;
}
start(testFilePath);
if (questionCount == 0) { return; }
// Calculate and display score for test...
double scr = (double) ((rightAnswers/questionCount)*100);
int score = (int) Math.ceil((double)rightAnswers/(double)questionCount*100.0);
System.out.println(ls + "======================================================");
System.out.println("Out of a total of " + questionCount + " questions" + ls
+ "you got " + rightAnswers + " questions Correct and" + ls
+ "you got " + wrongAnswers + " questions Wrong." + ls
+ "Your score is " + + score + "% "
+ "which gives you a grade of '" + getLetterGrade(score) + "'.");
System.out.println("======================================================");
// Done.
}
private void start(String testFilePath) {
// Get the number of lines (questions) within the supplied Test file...
int fileLinesCount = getNumberOfQuestions(testFilePath);
if (fileLinesCount == 0) { return; }
// Get Quiz Message from file (if there is any).
String msg = getQuizMessage(testFilePath);
// Display test information to the User via a Message Box
// and allow User to start the test.
if (msg.equals("")) {
// Default Quiz Message in case there is none in file.
msg = "<html>Within this Test there are <font color=blue><b>%flc" +
"</b></font> multiple choice questions that need<br>" +
"to be answered.<br><br>" +
"You will have <font color=blue><b>%sft</b></font> " +
"seconds to answer each test question unless<br>" +
"otherwise indicated above the question.<br><br>" +
"If a question runs out of time before it is answered then that<br>" +
"question will be considered as <font color=red><b>WRONG</b></font>.<br><br>" +
"<center>Press the <b>OK</b> button to start the Test</center><br><br></html>";
}
// Replace any custom tags (%flc and %sft) for their proper values.
// The %flc tag holds the total number of questions within the test file.
// The %sft tag holds the default Seconds For Timeout.
msg = msg.replace("%flc", String.valueOf(fileLinesCount))
.replace("%sft", String.valueOf(secondsPerQuestion));
// Display test information to the User bvia a Message Box
// and allow User to start the test.
JDialog dialog = new JDialog();
dialog.setAlwaysOnTop(true);
int response = JOptionPane.showConfirmDialog (dialog, msg, "Test Information...",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE);
dialog.dispose();
// If anything but the OK button was selected then quit application
if (response != 0) {
System.exit(0);
}
// Open a Bufferreader to read in questions from the Test file.
try (BufferedReader fileReader = new BufferedReader(new FileReader(testFilePath))) {
// Iterate through the Test file and process one question at a time....
String testFileLine;
while ((testFileLine = fileReader.readLine()) != null) {
// Skip Blank lines, Quiz Message Lines (lines that start with a
// semicolon [;]), and Header Lines (lines that start with a Colon
// [:]).
if (testFileLine.trim().startsWith(";") ||
testFileLine.trim().startsWith(":") ||
testFileLine.trim().equals("")) {
continue;
}
// Split the file line question into specific parts.
// 1st part will be the question itself, 2nd part will be
// the answer and the 3rd part will be the number of seconds
// allowed to answer question. If the 3rd part is not supplied
// within the file line question then a default of 10 seconds
// is used as set by the defaultSecondsForTimout class global
// variable.
String[] fileQuestionParts = testFileLine.split("\\|");
String question = fileQuestionParts[0];
// Allow for newline and tab tags within text string.
question = ls + question.replaceAll("\\\\n", "\n").replaceAll("\\\\t", "\t");
//Get the question answer from file line
String questionAnswer = fileQuestionParts[1];
// If the seconds time out is provided within the question file
// line then grab it for use.
if (fileQuestionParts.length > 2) { secondsPerQuestion = Integer.parseInt(fileQuestionParts[2]); }
// otherwise use the default of 10 seconds.
else { secondsPerQuestion = DEFAULTSECONDSFORTIMEOUT; }
String answerResult;
questionCount++; // Increment the questionCount variable
questionAnswered = false; // Set the qustionAnswered variable
// Ask the retrived question to User....
answerResult = askTimedQuestion(question, secondsPerQuestion);
questionAnswered = true;
// If the User entered then quit the test.
if (answerResult.equalsIgnoreCase("quit")) { break; }
// If the Usert supplied input is the right answer then...
if (answerResult.equalsIgnoreCase(questionAnswer)) {
System.out.print(" CORRECT " + ls);
rightAnswers++; // Increment the rightAnswers variable.
}
// If the Usert supplied input is the wrong answer then...
else {
wrongAnswers++; // Increment the wrongAnswers variable.
System.out.print(" WRONG " + ls); }
}
// Close the file reader.
fileReader.close();
}
catch (IOException e) {
// Display file errors
System.out.println(ls + "ERROR! - " + e.getMessage());
}
}
private int getNumberOfQuestions(String filePath) {
int q = 0;
try (BufferedReader fileReader = new BufferedReader(new FileReader(filePath))) {
// Iterate through the Test file and gather the number
// of file lines that are actually quiz questions.
String testFileLine;
while ((testFileLine = fileReader.readLine()) != null) {
// Skip Non-Quiz Question lines...
if (testFileLine.equals("") ||
testFileLine.startsWith(";") ||
testFileLine.startsWith(":")) {
continue;
}
q++;
}
// Close the file reader.
fileReader.close();
}
catch (IOException e) {
// Display file errors
System.err.println(ls + "ERROR! - " + e.getMessage());
}
return q;
}
private String getQuizMessage(String filePath) {
String msg = "";
try (BufferedReader fileReader = new BufferedReader(new FileReader(filePath))) {
// Iterate through the Test file and the quiz message if there is one.
// Any file line that starts with a colon (:) will be added together
// to create the Quiz Message (regardless of where it is in file). Make
// your Quiz Messsage one of the very first things you place into the
// Test File.
String testFileLine;
while ((testFileLine = fileReader.readLine()) != null) {
if (testFileLine.equals("")) { continue; } // Skip any blank lines
if (testFileLine.startsWith(":")) {
msg+= testFileLine.substring(1);
}
}
// Close the file reader.
fileReader.close();
}
catch (IOException e) {
// Display file errors
System.err.println("\nERROR! - " + e.getMessage());
}
return msg;
}
// Method for asking the questions retrieved from the supplied Test file
private String askTimedQuestion(String question, int secondsPerCurrentQuestion) {
// The secondsPerCurrentQuestion parameter allows you to change
// the number of seconds for each question if seconds are
// applied to a particular question within the Test file.
// (See Test file information)
secondsPerQuestion = secondsPerCurrentQuestion;
// Establish a new Thread for perform our question timing...
#SuppressWarnings("Convert2Lambda")
Thread timerThread = new Thread(new Runnable() {
#Override
#SuppressWarnings("SleepWhileInLoop")
public void run() {
try {
// See if this thread has been interrupted. If it has then
// we stop our timer While/Loop (a gracefull Thread Stop).
while (!Thread.currentThread().isInterrupted()) {
for (int seconds = secondsPerQuestion; seconds >= 1; seconds--){
// Break out of this timer FOR loop if the question
// was answered by using Thread.interrupt().
if (questionAnswered) { Thread.currentThread().interrupt(); break;}
// Show that timer is ticking away...
System.out.print("*");
// ==========================================================
// Or you can use this...
//if (seconds < secondsForTimout) { System.out.print("-"); }
//System.out.print(seconds);
// ==========================================================
Thread.sleep(1000);
}
// If the question wasn't answered and our timer loop has
// expired then inform User that time is up and set the
// timeOut variable to true.
if (!questionAnswered) {
System.out.print("\b\b\b\Your time is up for this question!");
timeOut = true;
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
// Catch Exceptions for BufferReader()/InputStreamReader()...
try {
// Declare a BufferReader object so as to get input from User.
// We use BufferReader along with InputStreamReader(System.in)
// for this.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// Display the supplied Question from file to User...
if (questionCount > 1) {
System.out.println(ls + "------------------------------------------------------");
}
System.out.print("[" + secondsPerQuestion + " seconds]");
System.out.println(question);
// Declare User input variable & initialize to a Null String
String input = "";
// Reset the timeOut variable
timeOut = false;
// Make sure our timer thread is dead before restarting it.
//while (timerThread.isAlive()){}
// Start the Timer Thread
if (secondsPerQuestion > 0) { timerThread.start(); }
// Loop through input from the User
do {
// Wait until we have User input data to complete a readLine()
// or until our timer thread has set the timeOut variable to
// true.
while (!br.ready()) {
// If our timer thread has set the timeOut variable to
// true then let's get outta this question altogether.
// First we get out of our 'wait for input' loop...
if (secondsPerQuestion > 0 && timeOut) { break; }
}
// Then we get out of our Do/While Loop.
if (secondsPerQuestion > 0 && timeOut) { break; }
// No time-out so let's move on...
// Let's see what the User supplied for an answer.
// If just ENTER was supplied then input will contain
// a Null String and the User can still enter an answer
// until the question is timed out.
input = br.readLine();
// remove any unwanted text from System.out.print()
// that had made its way through the timer thread.
System.out.print("\b\b\b\b\b");
} while ("".equals(input));
// Stop the timer thread.
timerThread.interrupt();
return input;
}
catch (IOException ex) { return ""; }
}
// Determine & return the Letter Grade for the
// supplied integer test percentage score. This
// is a typical North American Standard (I think?).
private String getLetterGrade(int score) {
String grade = "";
if (score >= 90) { grade = "A"; }
if (score >= 80 && score <= 89) { grade = "B"; }
if (score >= 70 && score <= 79) { grade = "C"; }
if (score >= 60 && score <= 69) { grade = "D"; }
if (score >= 0 && score <= 59) { grade = "F"; }
return grade;
}
public int getSecondsPerQuestion() {
return secondsPerQuestion;
}
public void setSecondsPerQuestion(int secondsPerQuestion) {
this.secondsPerQuestion = secondsPerQuestion;
}
public String getTestFilePath() {
return testFilePath;
}
public void setTestFilePath(String testFilePath) {
this.testFilePath = testFilePath;
}
public boolean isQuestionAnswered() {
return questionAnswered;
}
public int getQuestionCount() {
return questionCount;
}
public int getRightAnswers() {
return rightAnswers;
}
public int getWrongAnswers() {
return wrongAnswers;
}
public int getDEFAULTSECONDSFORTIMEOUT() {
return DEFAULTSECONDSFORTIMEOUT;
}
}
You can use the above class on its own or add it to another project.
To use on its own within your IDE:
Create a new Project named TimedQuestions;
Create a new Java Class named TimedQuestions;
Copy/paste the above code into the new Class;
Modify the private String testFilePath; class member variable to
private String testFilePath = "Your_Quiz_path_And_File_Name";
Run the project.
To use within an existing Java Project:
Create a new Java Class named TimedQuestions within your project;
Copy/paste the above code into the new Class;
Somewhere within your project code activate the class:
TimedQuestions tq = new TimedQuestions();
tq.startTest("C:\\Quizes\\ScienceTest001.txt");
This is a very broad question and it requires an answer with some amount of opinion.
To address your first concern:
Before you being programming, you should separate the questions and answers into two separate files. One file for questions, one file for answers. Both files should be indexed 1 to N. Also, you should mark each answer to indicate which question it belongs to, and you should mark each answer with incorrect or correct.
Common file types like .txt or .csv are fine (Notepad, Excel). Database systems are good too, but they are more complex (MS SQL, MySql).
How to program the game:
Once this is done, you can use a common programming language like Java to access the question-file and access and display question by line-number. Then, you can access the answer-file and display all associated answers.
Next, you will prompt the user to make an answer-choice. Using the user's response, you will compare it against the correct answer's index. If they are the same, the user has selected correctly. If not, the user's answer is wrong. Whatever the case, you return the result of the user's decision to them.
The actual implantation of this code is pretty straightforward. You will need statements like:
read from file
read from console
write to console
if and else statements
You can find all the documentation for these statements at Java Tutorials
Joseph's answer is pretty good, and you can definitely use his suggestions to great effect. That said, another option is XML. There's a great tutorial here that breaks it down pretty nicely. I suggest you take a look at it.
You could structure your XML something like this:
<quiz>
<question type="mc">
<prompt>What color is an orange?</prompt>
<a>orange</a>
<b>blue</b>
<c>red</c>
<d>yellow</d>
<answer> a </answer>
</question>
<question type="mc">
<prompt>What color is a banana?</prompt>
<a>orange</a>
<b>blue</b>
<c>red</c>
<d>yellow</d>
<answer> d </answer>
</question>
<question type="tf">
<prompt>The sky is blue</prompt>
<a>true</a>
<b>false</b>
<answer> a </answer>
</question>
</quiz>
Of course, you could structure this however you want. But its a good way to get used to the nature of Java while also integrating a robust and customizable solution into your project.

Java: Comparing [All] Instance Variables of an Object

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;

Java NullPointerException in agent based model

I am using the MASON library to run a simple agent-based model.
As per specifications, I meant to access an agent's inspector by double-clicking on such agent in the Portrayal.
However, when I do so I get the following console error:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at sim.display.Display2D.createInspectors(Display2D.java:1737)
at sim.display.Display2D$8.mouseClicked(Display2D.java:1392)
I went to Display2D.java:1737 to find:
public void createInspectors( final Rectangle2D.Double rect, final GUIState simulation )
{
Bag inspectors = new Bag();
Bag names = new Bag();
Bag[] hitObjects = objectsHitBy(rect);
for(int x=0;x<hitObjects.length;x++)
{
FieldPortrayal2DHolder p = (FieldPortrayal2DHolder)(portrayals.get(x));
for( int i = 0 ; i < hitObjects[x].numObjs ; i++ )
{
LocationWrapper wrapper = (LocationWrapper) (hitObjects[x].objs[i]);
inspectors.add(p.portrayal.getInspector(wrapper,simulation));
names.add(p.portrayal.getName(wrapper));
}
}
simulation.controller.setInspectors(inspectors,names); //1737
}
However, this is a library file so I'm not familiar with it.
Any advice?
Library: cs.gmu.edu/~eclab/projects/mason/
Update:
Ok, it gets interesting...
I did an echo on the toString method of inspectors and names, returning:
insepectors sim.util.Bag#1b2202a names sim.util.Bag#16b334d
Ok so they're bags, a type of collection. Time to get their sizes...
insepectors 1 names 1
Good, they're not empty.
Let's follow the error stack
Next bit:
at sim.display.Display2D$8.mouseClicked(Display2D.java:1392)
// add mouse listener for the inspectors
insideDisplay.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
if (handleMouseEvent(e)) { repaint(); return; }
else
{
// we only care about mouse button 1. Perhaps in the future we may eliminate some key modifiers as well
int modifiers = e.getModifiers();
if ((modifiers & e.BUTTON1_MASK) == e.BUTTON1_MASK)
{
final Point point = e.getPoint();
if( e.getClickCount() == 2 )
1392-> createInspectors( new Rectangle2D.Double( point.x, point.y, 1, 1 ),
Display2D.this.simulation );
if (e.getClickCount() == 1 || e.getClickCount() == 2) // in both situations
performSelection( new Rectangle2D.Double( point.x, point.y, 1, 1 ));
repaint();
}
}
}
Ok, the error is clearly in the CreateInspectors method:
public void createInspectors( final Rectangle2D.Double rect, final GUIState simulation )
{
Bag inspectors = new Bag();
Bag names = new Bag();
Bag[] hitObjects = objectsHitBy(rect);
for(int x=0;x<hitObjects.length;x++)
{
FieldPortrayal2DHolder p = (FieldPortrayal2DHolder)(portrayals.get(x));
for( int i = 0 ; i < hitObjects[x].numObjs ; i++ )
{
LocationWrapper wrapper = (LocationWrapper) (hitObjects[x].objs[i]);
inspectors.add(p.portrayal.getInspector(wrapper,simulation));
names.add(p.portrayal.getName(wrapper));
}
}
System.out.println("insepectors " + inspectors.size() + " names " + names.size());
simulation.controller.setInspectors(inspectors,names);
}
First thing I do:
System.out.println(rect.getCenterX() + " " + rect.getCenterY());
Which gives me 646.5 659.5. Seem to make sense as coordinates.
So next thing I want to look at hitObjects:
System.out.println(hitObjects.length);
Returns 2. So I had two agents at that coordinates.
I assume the NPE is somewhere here:
for(int x=0;x<hitObjects.length;x++)
{
FieldPortrayal2DHolder p = (FieldPortrayal2DHolder)(portrayals.get(x));
for( int i = 0 ; i < hitObjects[x].numObjs ; i++ )
{
LocationWrapper wrapper = (LocationWrapper) (hitObjects[x].objs[i]);
inspectors.add(p.portrayal.getInspector(wrapper,simulation));
names.add(p.portrayal.getName(wrapper));
}
}
The outer loop looks fine, but I'm having issues with the inner one. Advice?
I'm actually going to write how to reason through the library code given as far as you've come since you sound capable.
You found the code. That's a good start. You've also found the line that it's on:
simulation.controller.setInspectors(inspectors,names); //1737
And given what you know about NPEs you can reason that simulation or controller is null.
Do you know which? Can you reason about your code which you may have failed to set, or passed incorrectly? Can you put a debugger breakpoint or simple println statements in your code to determine which?
If not and you're using an IDE (you probably are), then from the source you just opened up, put a breakpoint before line 1737. When that line is reached, use the debugger to inspect the variable simulation then simulation.controller to see which is null. Exactly how to do this will depend on your IDE but it shouldn't be hard to find using XKCD's tech support cheat sheet.
Then you will probably know the cause. If not, continue reading source code, e.g. look a level up to line 1737.

Scanner no such element exception

got this code:
private void runGame() {
boolean won = false;
while(won == false) {
System.out.println("DEBUG A");
Player p = this.nextPlayer();
System.out.println("DEBUG B");
Scanner s = new Scanner(System.in);
if(p.getPlayerType() == 0) {
System.out.println("DEBUG C");
// is Human
BoardPrinter.printBoard(this.b);
// Choose figure
BoardPrinter.printFigureChoose(this.b.getFiguresFromPlayer(p.getSymbol()),p);
int id = this.checkInput(1,this.b.getFiguresFromPlayer(p.getSymbol()).size(),s.nextInt());
Figure f = this.b.getFiguresFromPlayer(p.getSymbol()).get(id - 1);
// Choose move
ArrayList<Move> moves = b.checkMoves(f);
BoardPrinter.printMoveChoose(moves,p);
int moveID = this.checkInput(1,moves.size(),s.nextInt());
Move m = moves.get(moveID - 1);
// Execute the chosen move
this.b.getCellAt(f.getLocation().getX(), f.getLocation().getY()).setSymbol(Symbol.EMPTY);
f.setLocation(m.getTarget());
this.b.getCellAt(m.getTarget().getX(), m.getTarget().getY()).setSymbol(p.getSymbol());
// Check win conditions
won = this.checkVictory(p);
System.out.println("DEBUG D");
}
else {
// KI stuff
KI k = new KI(this.b,p,p.getPlayerType());
Move m = k.think();
// Execute chosen move
Figure f = this.b.getFigureAt(m.getStart());
this.b.getCellAt(m.getStart().getX(), m.getStart().getY()).setSymbol(Symbol.EMPTY);
f.setLocation(m.getTarget());
this.b.getCellAt(m.getTarget().getX(), m.getTarget().getY()).setSymbol(p.getSymbol());
}
// Decomment this to get debug info
//DebugPrinter.print(this.b);
s.close();
}
}
At the moment i do get an java.util.NoSuchElementException. Yes i know what i means and i googled a lot. Still i don't understand why it get's thrown. Also, i do get my Debug output only until "C".
If i move the Scanner initialization outside of the while loop i don't get that Exception anymore. However i do get stuck to, with the Code stopping at Debug "A" and nothing else.
I've encountered this both when having 2 human players. Fun fact: The first player will always work perfectly. The Player can see the Board, choose a Figure, choose a move and execute it. Whenever the next while() run starts and the 2nd player comes into account it fails as i described it above depended on where my Scanner initialization is.
Any guesses what's the problem? Thanks a lot! :)
You close your scanner at the end of your while loop. This means that the next time you try to read something from the scanner you'll get a NoSuchElementException.

Categories