NullException I increment a variable? [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
Every time I increment the below to update the created by my method, I get a Exception in thread "main" java.lang.NullPointerException error. I have no clue what's causing this, perhaps it's the "do" loop? I've tried everything I can and am not aiming to import any packages
userCardsCount = 2;
boolean trueScore = userSum <= 21;
do{
displayCards(true);
// User turn
int i = 2;
System.out.println("\nUSER'S TURN");
System.out.print("Draw new card (Y/N): ");
input = br.readLine();
if(input.equals("y") || input.equals("Y") || input.equals("yes") || input.equals("YES")) {
userCardsCount++;
userCards[i] = deck.drawCard();
userSum += userCards[i].value;
System.out.print("\n--> User drew a " + "[" + userCards[i].value + "]\n");
//i++;
} else if(input.equals("n") || input.equals("N") || input.equals("no") || input.equals("NO")) {
// You stay as you are and go to the computer's turn
System.out.println("--> User stays.");
}
else {
System.out.println("\t--> Umm please retry input");
}
} while(trueScore);
METHOD
public static void displayCards(boolean showHidden)
{
if(showHidden) {
System.out.print("Computer's cards: [" + computerCards[0].name + "]");
} else {
System.out.print("Computer's cards: [X]");
}
for(int i = 1; i < computerCardsCount; i++) {
System.out.print("[" + computerCards[i].name + "]");
}
if(showHidden) {
System.out.print(" (sum: " + computerSum + ")");
}
System.out.print("\nUser's cards: ");
for(int i = 0; i < userCardsCount; i++) {
System.out.print("[" + userCards[i].name + "]");
}
System.out.print(" (sum: " + userSum + ")");
System.out.print("\n");
}
Any suggestions?

You should look at your array: computerCards. You seem to be entering that method with true always, so you will always call computerCards[0].name which might be empty. You should put a break point at the start of that method, and then debug to see if you have a value in the 0th position.

At the end of file br.readLine() will return null. And your next equals breaks.

Related

Java program that teaches kid simple addition and subtraction

I feel like I'm almost there with the code but the problem is the while loop I am not allowed to use break and continue statements for this program. The first output test its suppose to have 14 questions where you get 12 right and 2 wrong giving you 86%. As for the second test you get a perfect score while the last test takes you to 20 questions that being the max number of questions, 4 of the first 8 questions correctly and 4 of the first 8 incorrectly, and then the next 12 correctly giving you 80% Code below:
package proj3;
import java.util.Scanner;
public class Project4App {
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
int correctNum = 0;
int wrongNum = 0;
double percent = 0;
int subNumCorrect = 0;
int subNumWrong = 0;
int addNumCorrect = 0;
int addNumWrong = 0;
int totalQuestions = 0;
while(!(correctNum == 10 && totalQuestions == 10) && !(percent >= 85.0 && totalQuestions >= 10) && (totalQuestions != 20)) {
Question Quest = new Question();
System.out.println("What is the result?" + "\n" + Quest.toString());
int userInt = scnr.nextInt();
if((Quest.getOperator() == '+') && (userInt == Quest.determineAnswer())) {
addNumCorrect += 1;
}
else if(Quest.getOperator() == '+' && (userInt != Quest.determineAnswer())) {
addNumWrong += 1;
}
if((Quest.getOperator() == '-') && (userInt == Quest.determineAnswer())) {
subNumCorrect += 1;
}
else if((Quest.getOperator() == '-') && (userInt != Quest.determineAnswer())) {
subNumWrong += 1;
}
if(userInt == Quest.determineAnswer()){
correctNum += 1;
System.out.println("Congratulations, you got it correct!");
}
else if (userInt != Quest.determineAnswer()){
wrongNum += 1;
System.out.println("The correct answer for " + Quest.toString() + " is " + Quest.determineAnswer());
}
totalQuestions++;
percent = Math.round((double)(correctNum * 100) / (totalQuestions));
}
System.out.println("\nProgress Report: " + "\nAddition:\nYou got " + addNumCorrect + " correct and " + addNumWrong + " incorrect.");
System.out.println("Progress Report: " + "\nSubtraction:\nYou got " + subNumCorrect + " correct and " + subNumWrong + " incorrect.");
System.out.println("The percent correct: " + percent + "%");
scnr.close();
}
}
I think this largely does what you want. A number of the counters weren't being modified as was intended. This is partly due to the amount going on in your main method making it hard to see what's going on (too much information). I've extracted functionality to smaller, more well defined methods.
You had a whole lot of logic effectively saying you want the user to have achieved 85% with at least 10 questions answered - and stop when 20 questions are asked. You could factor this condition out to a method returning a boolean isGameComplete(totalQuestions) and put this in the while condition-expression.
I've taken the liberty of implementing a question class based on the functionality that I think achieves the intention.
The correctPercent was rounded to an int which made it impossible to be == to 85.5%, say. I've converted this to a double so if you get more than 85%, say 85.25%, the game completes successfully.
Probably some other stuff I've added, which I've tried to comment in-line, if significant. Hopefully this is what you were after.
If it ever gets too difficult to understand, extracting small chunks of code to well named methods (even long ones) helps enormously, since it reduces your mental load.
class Project4App {
static final Scanner scanner = new Scanner(System.in);
static int correctNum = 0;
static int wrongNum = 0;
static int subNumCorrect = 0;
static int subNumWrong = 0;
static int addNumCorrect = 0;
static int addNumWrong = 0;
static int totalQuestions = 0;
static double percentCorrect = 0;
public static void main(String[] args) {
/**
* answer at least 9/10 questions correctly (to get 85%)
*/
while (percentCorrect < 85.0 && totalQuestions >= 10 && totalQuestions <= 20) {
Question question = new Question();
int userInt = getUsersAnswer(question);
boolean isCorrect = question.determineAnswer(userInt);
updateStatistics(question, isCorrect);
printResults(); // can remove this/comment this out - added to help with debugging
}
System.out.println();
System.out.println("------------ Game Complete! ------------");
printResults();
}
private static void printResults() {
System.out.println("\nProgress Report: " + "\nAddition:\nYou got " + addNumCorrect + " correct and " + addNumWrong + " incorrect.");
System.out.println("Progress Report: " + "\nSubtraction:\nYou got " + subNumCorrect + " correct and " + subNumWrong + " incorrect.");
System.out.println("The percent correct: (" + (addNumCorrect+subNumCorrect) + "/" + totalQuestions +") " + percentCorrect + "%");
System.out.println("The percent wrong: (" + (addNumWrong+subNumWrong) + "/" + totalQuestions +") " + (100 - percentCorrect) + "%");
}
private static int getUsersAnswer(Question question) {
System.out.println("What is the result?" + "\n" + question.toString());
int userInt = scanner.nextInt();
return userInt;
}
public static void updateStatistics(Question question, boolean isCorrect){
if (question.getOperator() == '+') {
if (isCorrect) {
addNumCorrect++;
correctNum++; // newly added (wasn't updated)
} else {
addNumWrong++;
wrongNum++; // newly added - unused variable originall
}
} else { // operator is '-'
if (isCorrect) {
subNumCorrect++;
correctNum++; // newly added (wasn't updated)
} else {
subNumWrong++;
wrongNum++; // newly added - unused variable originall
}
}
totalQuestions++; // newly added
percentCorrect = (correctNum * 100) / totalQuestions;
}
}
class Question {
private static final int UPPER_LIMIT_ON_RANDOM_NUMBERS = 20;
private static final Random random = new Random();
private final int number1;
private final int number2;
private final char operator;
public Question() {
operator = Math.random()>0.5 ? '+' : '-';
number1 = random.nextInt(UPPER_LIMIT_ON_RANDOM_NUMBERS); // NOTE THE SUBTRACTION NUMBER COULD BE NEGATIVE IF number2
number2 = random.nextInt(UPPER_LIMIT_ON_RANDOM_NUMBERS); // IS GREATER THAN number1.
}
public char getOperator() {
return operator;
}
public boolean determineAnswer(int userAnswer) {
switch (operator) {
case '+':
return userAnswer == (number1 + number2);
case '-':
return userAnswer == (number1 - number2);
}
return false; // shouldn't end up here - would be better to throw an unchecked exception and crash the program - new RuntimeException()
}
#Override
public String toString() {
return number1 + " " + operator + " " + number2;
}
}
Output:
------------ Game Complete! ------------
Progress Report:
Addition:
You got 7 correct and 0 incorrect.
Progress Report:
Subtraction:
You got 2 correct and 1 incorrect.
The percent correct: (9/10) 90.0%
The percent wrong: (1/10) 10.0%

Guessing game loop

Here is the code for a guessing game I have made. My counter in not increasing past 1. I am passing the parameters choice and generatedNumber from a seperate controller class. Should the do while loop be in the controller class?
public String startGuessingGame(int choice, int generatedNumber) {
int count = 0;
final int attempts = 4;
String result = null;
do {
count++;
if (choice == generatedNumber) {
result = "Attempt " + count + " "
+ "- You have guessed the correct number!";
}
else if (choice > 50 || choice < 0) {
result = "Out of range. "
+ "\nPlease choose a number between 1 and 50.";
}
else if (choice > generatedNumber) {
result = "Attempt " + count + " "
+ " - You have guessed too high!";
}
else if (choice < generatedNumber) {
result = "Attempt " + count + " "
+ "- You have guessed too low!";
}
if (count == attempts) {
result = "You are out of guesses! The number was " + generatedNumber;
}
}
while(count < attempts);
return result;
}
}
There is no loop here.
You're looking for something like while(count < attempts).
Try this:
Incrementing the counter at the end before the while condition:
do{
...
if (count == attempts) {
result = "You are out of guesses! The number was " + generatedNumber;
}
count++;
}while(count < attempts);
return result;
...
You need to make count a class variable (member) of your controller class and have your do/while loop in that class so that the startGuessingGame only handles the validation of the user choice. Something like this but the code is far from complete
public class SomeControllerClass() {
final int attempts = 4;
int count = 0;
public void someMethod() {
int choice = 0;
do {
choice = getChoice();
count++;
String text = otherClass.startGuessingGame(choice, generatedNumber);
while (count < attempts);
}
and the method only does validation
public String startGuessingGame(int choice, int generatedNumber) {
String result = null;
if (choice == generatedNumber) {
result = "Attempt " + count + " "
+ "- You have guessed the correct number!";
} else if (choice > 50 || choice < 0) {
//and so on
return result;
}

No break in nested loop? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Working on a task where I should factorize a prime number. Here's the solution I've come up with:
import java.util.Scanner;
public class Task8 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Which number to factorize:");
int number = input.nextInt();
System.out.println();
int counter = 1;
for (int i = 2; i <= number; i++) {
while (number % i == 0) {
if (counter == 1 && i == number) {
System.out.println("The number is a prime, can’t be factorized.");
break;
} else {
System.out.println("Prime" + " " + "#" + counter + ":" + " " + i);
number = number/i;
++counter;
}
}
}
}
}
However, a book I'm currently studying, strongly advices against using break statements in loops. So how would I do without one in this case?
Cheers!
Here's one method of doing it. I made comments around my changes:
import java.util.Scanner;
public class Task8 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Which number to factorize:");
int number = input.nextInt();
System.out.println();
int counter = 1;
for (int i = 2; i <= number; i++) {
boolean canBeFactored = true; // Add a flag
while (canBeFactored && number % i == 0) { // Add a check
if (counter == 1 && i == number) {
System.out.println("The number is a prime, can’t be factorized.");
canBeFactored = false; // Set that check to false
} else {
System.out.println("Prime" + " " + "#" + counter + ":" + " " + i);
number = number/i;
++counter;
}
}
}
}
}
One possible solution is to do a return in-place of the break. But this will return from the whole function execution, which may not be the desired outcome. Moreover, break statement is not necessarily bad to use. Please refer to this.
I see nothing wrong with using "break" in this case. Although if you would strongly not like to use it, you can make everything you have in main into a new subroutine, and use "return", like this:
import java.util.Scanner;
public class Task8 {
public static void main(String[] args) {
function();
}
public static void function() {
Scanner input = new Scanner(System.in);
System.out.print("Which number to factorize:");
int number = input.nextInt();
System.out.println();
int counter = 1;
for (int i = 2; i <= number; i++) {
while (number % i == 0) {
if (counter == 1 && i == number) {
System.out.println("The number is a prime, can’t be factorized.");
return;
} else {
System.out.println("Prime" + " " + "#" + counter + ":" + " " + i);
number = number/i;
++counter;
}
}
}
return;
}
}
The book probably means that the excessive use of break (and continue, return too) make the code unreadable.
E.g. Instead of
for (int i = 0; i < N; i++) {
if (b)
break;
...
}
You could write
for (int i = 0; i < N && !b; i++) { ... }
In the end I think it's just a matter of style and what you want to express with the code.
You can also break outer loops by labelling them:
outer:
for (;;) {
for(;;) {
if (<some_special_case>)
break outer; // execution...
}
}
// ...continues here
Which can become pretty ugly depending on the scenario without break (additional flag to be set before breaking and checked in all outer loops). So the bottom line is, there are valid use-cases for break where it gets (in my opinion) the job done the cleanest and quickest way (to write the code).

Need help fixing the while loop

Hi i was trying to create a mock database search and, though it works, whenever i enter an input that is not part of the database, it creates an Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4 on line 23. I dont know what else to do as i see no error in the code.
import java.util.*;
public class Database {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scan = new Scanner(System.in);
String[] names = new String[4];
boolean found = false;
int i = 0;
names[0] = "Thor";
names[1] = "Ben";
names[2] = "Zoe";
names[3] = "Kate";
System.out.println("Enter Player Name");
String input = scan.nextLine();
while(found != true){
if(input.equals(names[i])){
System.out.println(input + " has been found");
found = true;
} else {
i = i+1;
}
if(i == 3 && found == false){
System.out.println(input + " was not found");
}
}
}
}
You are not leaving the loop after you print that input + " was not found".
Therefore the next iteration of the loop throws ArrayIndexOutOfBoundsException.
You should leave the loop after you finish testing the entire array.
change
while(found != true){
to
while(!found && i < names.length){
Actually you can move the if statement that tests whether the input wasn't found to be after the loop :
while(!found && i < names.length) {
if(input.equals(names[i])){
System.out.println(input + " has been found");
found = true;
} else {
i = i+1;
}
}
if(!found){
System.out.println(input + " was not found");
}
An even better alternative would be to use a for loop :
for (int i = 0; i < names.length && !found; i++) {
if(input.equals(names[i])){
System.out.println(input + " has been found");
found = true;
}
}
if(!found){
System.out.println(input + " was not found");
}
if your input doesn't matches the value of i will keep on incrementing and your length of an array is 4. Obviously ArrayindexoutofException.
To avoid you need to consider the array length also.
Change your while loop to
while (found != true) {
if (input.equals(names[i])) {
System.out.println(input + " has been found");
found = true;
} else {
i = i + 1;
}
if (i == 4 && found == false) { //changed here
System.out.println(input + " was not found");
//or found == true;
break; //and here
}
}
You need to quit the loop if THIS condition is true
i == 4 && found == false
and to actually quit, you must "break" the while condition
found != true
You can do this by setting found=true (but that's not semantically correct) or add the break instruction.
Here is an alternative solution to your while loop:
while (!found && i<4)
if (input.equals(names[i++]))found = true;
System.out.println(input+(found?" has been":" was not")+" found");
You can simply change to
while(i < names.length)
and forget the additional boolean variable. Since you want to keep iterating i until you find the solution, the stop condition will be the max i. When you do find your solution, you can simply breakthe while statement:
if (input.equals(names[i])) {
System.out.println(input + " has been found");
break;
}

Loop and conditionals not working properly [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 9 years ago.
If I do not roll a 1, and I would like to "hold" my roll. The code ignores the instructions within the "h" bracket conditional statement, and rolls the dice again. I am confused because if I do roll a 1, the code does work and goes to the computer's turn, setting the flags correctly.
while ((humanScore <= 100) && (computerScore <=100))
{
/*loop while human turn is true*/
while ((humanTurn == true) && (computerTurn == false))
{
die = randomGenerator.nextInt(6) + 1;
if(die == 1)
{
System.out.println("Human, you rolled a 1, you lose your points and your turn.");
humanTurn = false;
computerTurn = true;
points = 0;
System.out.println("Your score is now " + humanScore);
System.out.println("Computer, it is now your turn.");
}
else if(die != 1)
{
System.out.println("Human, you currently have " + points + " points to add to score.");
System.out.println("You have rolled a " + die + " would you like to hold, or roll again?");
System.out.println("Please enter either r to roll, or h to hold.");
points = points + die;
decision = scanner.next();
if (decision == "r")
{
humanTurn = true;
}
if(decision == "h")
{
humanScore = humanScore + points;
humanTurn = false;
computerTurn = true;
points = 0;
System.out.println("You hold, your score is now " + humanScore);
System.out.println("Computer, it is now your turn.");
}
}
}
if (decision.equals("r"))
{
humanTurn = true;
}
if(decision.equals("h"))
{
humanScore = humanScore + points;
humanTurn = false;
computerTurn = true;
points = 0;
System.out.println("You hold, your score is now " + humanScore);
System.out.println("Computer, it is now your turn.");
}

Categories

Resources