Can't find a bug in my code - java

I am trying to finish my assignment but I can't seem to find the bug in my code. It is not a compiler error, and I have been looking at it for hours.
This code is for a game called Mastermind. These are the guidelines (a bit long, I know, but all necessary info for the assignment):
Computer chooses a random 4 digit number, and no digit may repeat itself. (ex: 0462, 2930, 6103 are valid numbers)
The user's goal is to try and guess the computer's chosen number
Once the user makes a guess, the computer will tell the user how class that guess was by giving the following information:
The number of digits matched perfectly (are in the right place)
The number of digits that are off place
When you scan the input from the user, use a String to store it. Your
program must have 4 methods in addition to the main method:
One method named isValidNumber that checks if a given String corresponds to a valid 4 digit number.
One method named perfectMatches that returns the number of perfect matches between two Strings that represent valid 4 digit numbers.
One method named offPlaceMatches that returns the number of ‘off place’ matches between two Strings that represent valid 4 digit
numbers.
One method named generateRandomValidNumber that returns a String that represents a random valid 4 digit number.
Hint: Generate a random 4 digit number by generating a random single
digit 4 times and concatenating them. Then using your isValidNumber
method, check if this String you created is valid. If it is not,
repeat the first part and pick 4 new random digits.
This is my code:
import java.util.Scanner;
public class Question1 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
//print welcome, what 4 digit number do you guess...
System.out.println("Welcome to Mastermind.");
System.out.println("I have a 4 digit number in mind. Can you guess it?");
System.out.println("");
System.out.println("What is your guess?");
//string guess is number that is scanned
String guess = input.nextLine();
String validNumber = generateValidNumber();
System.out.print("Perfect matches: " + perfectMatches(guess, validNumber));
System.out.println("off place: " + offPlaceMatches(guess, validNumber));
while(!(perfectMatches(guess, validNumber) == 4)) {
System.out.println("");
System.out.println("What is your guess?");
guess = input.nextLine();
validNumber = generateValidNumber();
System.out.print("Perfect matches: " + perfectMatches(guess, validNumber));
System.out.println("off place: " + offPlaceMatches(guess, validNumber));
}
System.out.println("Yes! You guessed my number correctly. Well done.");
}
static boolean isValidNumber(String number) {
if(number.length() != 4) {
return false; }
char[] numberArray = new char[4];
for (int i = 0; i < 4; i++) {
numberArray[i] = number.charAt(i);
if(!((number.charAt(i) <= '9') && (number.charAt(i) >= '0'))) {
return false;
}
}
for (int i = 0; i < 4; i++) {
char c = numberArray[i];
int count = 0;
for(int j = 0; j < 4; j++)
if(numberArray[j] == c)
count++;
if(count > 1) {
return false;
}
}
return true;
}
static int perfectMatches(String one, String two) {
int counter = 0;
for(int i = 0; i < one.length(); i++) {
if(one.charAt(i) == two.charAt(i)) {
counter++;
}
}
return counter;
}
static int offPlaceMatches(String one, String two) {
int counter = 0;
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
if(i == 0)
continue;
if(one.charAt(j) == two.charAt(i)) {
counter++;
}
if(j == i -1) {
i++;
}
}
}
return counter;
}
static String generateValidNumber() {
boolean validNumber = false;
String newNumber = "";
while(!validNumber) {
for(int i = 0; i < 4; i++) {
char c = (char) (int) (Math.random() * (9));
newNumber = newNumber + c;
}
if(isValidNumber(newNumber))
validNumber = true;
}
return newNumber;
}
}

There's a problem in the generateValidNumber method.
You are not re-initializing newNumber when you try to find a new random number.
Changing it to the following function should result in the successful execution of the program. Also, multiply the random number with 10 to get an number in the range [0.0, 10.0) (0 included and 10 excluded)
static String generateValidNumber() {
boolean validNumber = false;
String newNumber = null;
while(!validNumber) {
// add this line
newNumber = "";
for(int i = 0; i < 4; i++) {
char c = (char) ('0' + (Math.random() * 10));
newNumber = newNumber + c;
}
if(isValidNumber(newNumber))
validNumber = true;
}
return newNumber;
}
But there are a few logical errors in the code. For e.g., you are generating a new number everytime a user guesses an invalid number.
Update:
I made a few changes to your code. This should help you get going.
import java.util.Scanner;
public class MastremindString {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// print welcome, what 4 digit number do you guess...
System.out.println("Welcome to Mastermind.");
System.out
.println("I have a 4 digit number in mind. Can you guess it?");
System.out.println("");
System.out.println("What is your guess?");
// string guess is number that is scanned
String guess = input.nextLine();
String validNumber = generateValidNumber();
System.out.print("Perfect matches: "
+ perfectMatches(guess, validNumber));
System.out.println("off place: " + offPlaceMatches(guess, validNumber));
while (!(perfectMatches(guess, validNumber) == 4)) {
System.out.println("");
System.out.println("What is your guess?");
guess = input.nextLine();
System.out.print("Perfect matches: "
+ perfectMatches(guess, validNumber));
System.out.println("off place: "
+ offPlaceMatches(guess, validNumber));
}
System.out.println("Yes! You guessed my number correctly. Well done.");
}
static boolean isValidNumber(String number) {
if (number.length() != 4) {
return false;
}
char[] numberArray = new char[4];
for (int i = 0; i < 4; i++) {
numberArray[i] = number.charAt(i);
if (!((number.charAt(i) <= '9') && (number.charAt(i) >= '0'))) {
return false;
}
}
for (int i = 0; i < 4; i++) {
char c = numberArray[i];
int count = 0;
for (int j = 0; j < 4; j++)
if (numberArray[j] == c)
count++;
if (count > 1) {
return false;
}
}
return true;
}
static int perfectMatches(String one, String two) {
int counter = 0;
for (int i = 0; i < one.length(); i++) {
if (one.charAt(i) == two.charAt(i)) {
counter++;
}
}
return counter;
}
static int offPlaceMatches(String one, String two) {
int counter = 0;
for (int i = 0; i < one.length(); i++) {
for (int j = 0; j < two.length(); j++) {
if (one.charAt(j) == two.charAt(i) && i != j) {
counter++;
}
}
}
return counter;
}
static String generateValidNumber() {
boolean validNumber = false;
String newNumber = "";
while (!validNumber) {
newNumber = "";
for (int i = 0; i < 4; i++) {
char c = (char) ('0' + (Math.random() * 10));
newNumber = newNumber + c;
}
if (isValidNumber(newNumber))
validNumber = true;
}
return newNumber;
}
}

It appears that you are generating a new number on every cycle. The best way to fix this is to not assign to the validNumber variable within main(...) on every loop.
Since you get to the point of "What is your guess?" and you enter a number, but then nothing happens (which presumably means you do not get past the two lines following the first guess=input.nextLine(); call), the function to check first is the generateValidNumber(); function. Second, check your perfectMatches(...); function. You can add System.out.println("blah"); calls to see how far your code gets (as a very crude debugging tool).

I'm assuming you're using Eclipse and in an introductory programming course. An important subject often overlooked in programming courses is how to use a debugger to help you troubleshoot problems. If any of your classmates, lab assistants, or fellow students further along in your major can take 15-30 minutes to sit down and show you how to use the debugger, it will help you through the rest of your programming career.
If not, there are a lot of tutorials you can follow to get familiar with Eclipse's debugger.
To start off, double-click along the left of your code, usually just left of the line numbers. This will add a break point, which will pause your program when it reaches. Add a break point at each of your methods besides main and make sure that all the methods you think should be called are actually called.
When your program is at a break point, you can also take a look at the value of variables in the "Variables" view. If one of them has an unexpected value, you may have found your culprit.
There is a resume button you'll have to hit to resume program execution when you're done at a given break point. It should be next to the Pause and Stop buttons in the top bar by default, and is easy to confuse with the Run button.

First: You never call isValidNumber to check if the user's input is valid. You should call this method and if the number is invalid, the program should terminate or prompt the user for a new number

Related

Java isPrime function: Check if input integer values are prime

In short, again I found the task on internet:
Input integers from the keyboard, check whether prime numbers or not. When you input 0, the program ends.
So far, I wrote the logic for checking the integer if it's prime or not. The main stumbling block was that I should read several integers from one string and stop program if last integer is 0. So when I tried to add a loop to iterate over the input and check whether the integer is prime or not, my logic doesn't work and it returns only 1 st integer without others.
import java.util.Scanner;
public
class PrimeNumber
{
public
static void main(String[] args)
{
int temp;
boolean isPrime = true;
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
int[] arr = new int[num];
for (int i = 0; i < arr.length; i++)
{
arr[i] = sc.nextInt();
for (int y = 2; y <= num / 2; i++)
{
temp = num % i;
if (temp == 0)
{
isPrime = false;
break;
}
}
}
if (isPrime)
System.out.println(num + " is a Prime Number");
else
System.out.println(num + " is not a Prime Number");
}
}
I recommend if you can check this link: Check if an int is prime Java
Write a boolean function that checks an integer if it is prime or not. You do not need to create a O N^2 algorithm from input box.
Step 1: Check one integer and see if returns true( means it is prime )
Step 2: Try random numbers and see if they work as well.
Step 3: Add an array and see if contents of the array has prime numbers or not. Then you can print out any message you like.
See this example from the same reference to get started.
https://onecompiler.com/java/3y2cxy9ea
Your thought process was good.
The snippet with the if-else statement is outside of the for loop, so it will only happen once.
The value of num is just the number of int values the user will type in (basically arr.length). It should instead be checking primality of arr[i]. If arr[i] is divisible by some number other than 1 or arr[i], it is not prime. Also, if arr[i] is not greater than 1, it is not prime, either.
Lastly, make sure isPrime gets reset to true.
I recommend adding instructions in the form of print(), so it becomes clearer which number is which:
public static void main(String[] args)
{
int temp;
boolean isPrime;
Scanner sc = new Scanner(System.in);
System.out.print("Number of integer values: ");
int numberOfInts = sc.nextInt();
int[] arr = new int[numberOfInts];
for (int i = 0; i < numberOfInts; i++)
{
isPrime = true;
System.out.print("Int " + (i+1) + " = ");
arr[i] = sc.nextInt();
for (int y = 2; y <= arr[i] - 1; y++)
{
temp = arr[i] % y;
if (temp == 0)
{
isPrime = false;
break;
}
}
if (arr[i] <= 1) {
isPrime = false;
}
if (isPrime)
System.out.println(arr[i] + " is a Prime Number");
else
System.out.println(arr[i] + " is not a Prime Number");
}
}
As for exiting the program, put this at the start of the enclosing for loop:
if (arr[i] == 0) {
break;
}
There are better solutions than this, but on a basic level, this is fine.
You can try using this function to check that the number is prime:
private static boolean isPrime(int number) {
return java.math.BigInteger.valueOf(number).isProbablePrime((int) Math.log(number));
}
Then you can iterate through the array and check each of its elements with this function
My version of this program:
public class Main {
public static void main(String[] args) {
try(java.util.Scanner sc = new java.util.Scanner(System.in)) { //use try-with-resources block to avoid resources leak
//filling an array
int[] ints = new int[sc.nextInt()];
//if program gets 0, it stops filling
for(int i = 0; i < ints.length; i++) {
int temp = sc.nextInt();
if(temp == 0) break;
ints[i] = temp;
}
//check
for(int i = 0; i < ints.length; i++)
if(ints[i] != 0) System.out.printf("%s is%s a prime number.\n", ints[i], isPrime(ints[i]) ? "" : "n't");
}
}
private static boolean isPrime(int number) { //Some maths
return java.math.BigInteger.valueOf(number).isProbablePrime((int) Math.log(number));
}
}

Small java program prints invisible newline?

I'm doing an assignment and I am done. This is a simple program that prints out pyramids of chars. However, I can't figure out why the program prints a newline when I never specified it with some input, even if it's meant to: https://i.imgur.com/gPs5oC5.png
Why do I have to have an extra newline when printing the pyramid upside down? Where is the newline printed?
import java.util.Scanner;
public class Test23 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
boolean state = true;
String messageL = "Length: ";
String messageD = "Position: ";
String messageS = "Shutdown!";
while(state) {
int limit = 0;
int degree;
System.out.print(messageL);
int length = input.nextInt();
while ((length < 1 && length == -1) || length > 26) {
if (length == -1 ) {
System.out.println(messageS + "\n");
state = false;
break;
} else {
System.out.print(messageL);
length = input.nextInt();
}
}
if (!state)
break;
System.out.print(messageD);
degree = input.nextInt();
while((degree > 1) || (degree < 0)) {
System.out.print(messageD);
degree = input.nextInt();
}
if (degree == 0)
//No newline is needed here for some reason.
length++;
else if (degree == 1)
limit = length;
//New line here for the pyramids to print symmetrically.
//System.out.println("");
for (int i = 0; i < length; ++i) {
for (int counter = 0; counter < limit; counter++) {
char letter = (char)(counter + 'A');
System.out.print(letter);
}
if (degree == 0)
limit++;
else if (degree == 1)
limit--;
System.out.println("");
}
System.out.println("");
}
}
}
Small java program prints invisible newline?
In your program the last System.out.println(""); causes an extra line at the end of your program, i.e while(state) is true at the end, So either you comment the print statement or make your state=false at end.
while(state) {
...
System.out.println("");
}
The most inner loop won't run if the input is 0. limit will be 0, and hence the loop condition is false. As of this it will print en empty line, proceeding to add 1 too limit and then print chars.
for (int i = 0; i < length; ++i) {
for (int counter = 0; counter < limit; counter++) {
char letter = (char)(counter + 'A');

Java program on "friendly numbers "

I am working on a assignment about so called "friendly-numbers" with the following definition: An integer is said to be friendly if the leftmost digit is divisible by 1, the leftmost two digits are divisible by 2, and the leftmost three digits are divisible by 3, and so on. The n-digit itself is divisible by n.
Also it was given we need to call a method (as I did or at least tried to do in the code below). It should print whether a number is friendly or not. However, my program prints "The integer is not friendly." in both cases. From what I have tried, I know the counter does work. I just cannot find what I am missing or doing wrong. Help would be appreciated, and preferably with an adaptation of the code below, since that is what I came up with myself.
import java.util.Scanner;
public class A5E4 {
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
System.out.print("Please enter an integer: ");
int friendlyNumber = in.nextInt();
boolean result = isFriendly(friendlyNumber);
if (result)
{
System.out.println("The integer is friendly");
}
else
{
System.out.println("The integer is not friendly");
}
}
public static boolean isFriendly(int number)
{
int counter = 1;
while (number / 10 >= 1)
{
counter ++;
number = number / 10;
}
boolean check = true;
for (int i = 1; i <= counter; i++)
{
if (number / Math.pow(10, (counter - i)) % i == 0 && check)
{
check = true;
}
else
{
check = false;
}
}
return check;
}
}
while (number / 10 >= 1){
counter ++;
number = number / 10;
}
In this bit, you are reducing number to something smaller than 10. That is probably not what you want. You should make a copy of number here.
Also, proper software design would recommend that you extract this to a dedicated method.
private int countDigits(int number){
if(number < 1) throw new IllegalArgumentException();
int n = number;
int counter = 1;
while (n / 10 >= 1){
counter ++;
n = n / 10;
}
return counter;
}
You need to copy the number which you use to find out how much digits your number has. Otherwise you change the number itself and don't know anymore what it was.
The second mistake is that you divide an integer by Math.pow() which returns a double. So your result is double. You want to have an integer to use the modulo operator.
public static boolean isFriendly(int number)
{
int counter = 1;
int tmpNumber = number;
while (tmpNumber / 10 >= 1)
{
counter ++;
tmpNumber = tmpNumber / 10;
}
boolean check = true;
for (int i = 1; i <= counter; i++)
{
if ((int)(number / Math.pow(10, (counter - i))) % i == 0 && check)
{
check = true;
}
else
{
check = false;
}
}
return check;
}
The first problem is that you are modifying the value of the number you are trying to check. So, if your method is called with 149, then after the while loop to count the digits, its value will be 1. So, you are always going to find that it is 'unfriendly'. Assuming you fix this so that number contains the number you are checking. Try this instead of your 'for' loop:
while ( counter && !( ( number % 10 / counter ) % counter ) )
{
number = number / 10;
counter--;
}
It works by taking the last digit of your number using the modulus or remainder operator and then divides this by the digit position and checks that the remainder is zero. If all is good, it decrements the counter until it reaches zero, otherwise it terminates before counter is zero.
Try something like this (change your isFriendly() method):
public static boolean isFriendly(int number)
{
String numberAsString = String.valueOf(number); //Convert the int as a String to make it easier to iterate through
for(int i = 0; i < numberAsString.length(); i++) {
int currentDigit = Character.getNumericValue(numberAsString.charAt(numberAsString.length() - i - 1)); //Iterate over the number backwards
System.out.println(currentDigit); //Print the current digit
if(currentDigit % (i + 1) != 0) {
return false;
}
}
return true;
}
The easy way is to convert to string and then check if it is friendly:
public static boolean isFriendly(int number)
{
String num = Integer.toString(number);
for (int i = 0, dividedBy = 1; i < num.length(); i++, dividedBy++)
{
String numToCheck = "";
for (int j = 0; j <= i; j++)
{
numToCheck += num.charAt(j);
}
if (Integer.valueOf(numToCheck) % dividedBy != 0) {
return false;
}
}
return true;
}

Java - vertical integers and palindrome

I stumbled upon an exercise that asked me to reproduce this (that's the expected output):
11111
3456789012109876543
This is a palindrome (at the bottom) where numbers higher that 9 (double digits) have to be written vertical. This sounds complicated to me, and I needed some help.
This is what I did so far, the palindrome:
class Print {
public static void main(String[] args) {
System.out.println("Insert a number from 1 to 100: ");
int input = Read.anInt();
System.out.println("Insert another number from 1 to 100: ");
int output = Read.anInt();
int a = input;
for (int i = a; i < output; i++){
System.out.print(a);
a++;
}
a = input -1;
for (int j = output; j > a; j--){
System.out.print(output);
output--;
}
}
}
Could you help me by explaining how to make sure numbers higher than 9 will be written vertically?
AdamRice: i mean this:
3456789111119876543
01210
But what I've managed to do so far is this mess:
456789101
0
111
1
121110987654
This is all probably because I'm completely ignoring arrays.
Apologies for being a bit slow. After finally understanding the problem, I think I have a solution.
import java.util.Scanner;
public class VerticalText {
public static void main(String[] args) {
Scanner Read = new Scanner(System.in);
System.out.println("Insert a number from 1 to 100: ");
int start = Read.nextInt();
System.out.println("Insert another number from 1 to 100: ");
int end = Read.nextInt();
String numbers = "";
for(int i = start; i <= end; i++)
{
if(i < 10)
{
numbers += String.format("%02d", i);
}
else
{
numbers += i;
}
}
for(int i = (end-1); i >= start; i--)
{
if(i < 10)
{
numbers += String.format("%02d", i);
}
else
{
numbers += i;
}
}
String row1 = "";
String row2 = "";
char[] chars = numbers.toCharArray();
for(int i = 0; i < chars.length; i++)
{
if(chars[i] == '0')
{
chars[i] = ' ';
}
row1 += chars[i];
i++;
row2 += chars[i];
}
System.out.println(row1);
System.out.println(row2);
}
}
With inputs 5 and 15, it produced the following output:
11111111111
567890123454321098765
Explanation
I build a string of the numbers and if it's less than 10 format it with a leading 0. This extra 0 is just a placeholder. When it comes to printing, we can print a space instead of a zero.

Find the Last Digit In An Array

I need to find the last digit in a array and see if it is equal to zero. Here is the code I'm using;
import java.util.Scanner;
public class NrOccurrence
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.print("Enter the integers between 1 and 100: ");
int[] numbers = new int[100], times = new int[100];
boolean zero = false;
while (zero == false)
{
for (int a = 0; a <= numbers.length; a++)
{
numbers[a] = scan.nextInt();
times[a]++;
if (numbers.equals(0))
{
zero = true;
}
}
}
for (int b = 0; b <= numbers.length; b++)
{
System.out.println(numbers[b] + " occurs " + times[b] + " times");
}
scan.close();
}
}
Create a method like this:
private boolean isLastItemZero(int[] numbers)
{
boolean isLastItemZero = false;
if ((numbers != null) && (numbers.length > 0))
{
isLastItemZero = numbers[numbers.length - 1] == 0;
}
return isLastItemZero;
}
And call it once you're done reading in all of the numbers from the user.
First of all for (int a = 0; a <= numbers.length; a++) will give youIndexOutOfBoundsException .Java uses 0 bases indexing which means that an array of size n has indices up to and including n-1. Change it tofor (int a = 0; a < numbers.length; a++) . Same thing here for (int b = 0; b <= numbers.length; b++)
Second i am not sure what you are trying to check here :
if (numbers.equals(0))
{
zero = true;
}
but you could simply do :
if(numbers[i] == 0);
Now if you wanna check if the last element in the array is 0you can simply do:
if(numbers[numbers.length - 1] == 0)
//do something
By definition, if the remainder of a number divided by 10 is 0, then the last digit must be 0. So you just need;
if(numbers[i] % 10 == 0) { zero = true; }
Hope this helps.

Categories