Repeat an increment of loop - java

For my science fair project, I'm wanting to give a graphical update to a French-teaching program that's so old it's emulated in DosBOX. That's all well and good but I'm having problems. I'm writing the base logic of the program in a console application just to get that together. I've created a Question class that's in a array list/collection known as "test1".
I have a loop that iterates through the list and with each iteration, it runs another method called evaluate:
public static boolean evaluate(Question question, Scanner scanner)
{
System.out.println(question.getPhrase()); // prints the question
String answer = scanner.nextLine(); // gets the answer
if (answer.compareTo(question.getCorrectAnswer()) == 0)
return true; // compares the answer to the correct answer w/i the current instance of "Question"
else
return false; // if it's not right, returns "false" meaning the question wasn't correct
}
The loop looks as such:
for (Question question : test1)
{
if (evaluate(question, scan))
{
incorrect = 0;
continue;
}
else
{
incorrect++;
System.out.println(incorrect);
}
if (incorrect == 3)
System.out.println("you have failed");
break;
}
I want to make it so that if you answer a question incorrectly, it spits out the phrase again and increases "incorrect" by 1 and, if you hit 3, terminates the list (I think I've got this implemented correctly if I could just get it to repeat the question). Right now it moves to the next item in the list and thus the next question even if and I don't want that.
Sorry if my code is awful, I'm still relatively new to programming.

Create a while loop inside of the for loop that says if the question isn't answered correctly, then repeat so that way in each question the question will be asked until its correct. Keep everything inside the for loop in the while loop that you should create:
for (Question question : test1)
{
while(!evaluate(question, scan)) {
if (evaluate(question, scan))
{
incorrect = 0;
continue;
}
else
{
incorrect++;
System.out.println(incorrect);
}
if (incorrect == 3)
System.out.println("you have failed");
break;
}
}

Instead of doing a foreach loop the way you're doing it now, you can do the following:
for (int i = 0; i < test1.size(); i++) {
Question question = test1.get(i);
if (evaluate(question, scan)) {
...
} else {
incorrect++;
test1.add(question);
}
if (incorrect == 3) { ... }
}
This is assuming you're using a data structure that uses size() and add() as methods; you can adjust it to what you're using.
This will repeat questions later, though not immediately after. If you want to repeat it immediately after, just decrement i-- in the else case:
for (int i = 0; i < test1.size(); i++) {
Question question = test1.get(i);
if (evaluate(question, scan)) {
...
} else {
incorrect++;
i--;
}
if (incorrect == 3) { ... }
}
You can also nest a loop for the else case:
for (Question question : test1) {
boolean passed = True;
incorrect = 0;
while (!evaluate(question, scan)) {
incorrect++;
if (incorrect == 3) { passed = False; break; }
}
if (!passed) { System.out.println("you have failed"); break; }
}

Related

For if loop wont loop: any pointers to why that might be?

This is supposed to loop 24 times; it does not, and I'm pretty confused as to why. Please help me various Kenobis out there :
private boolean simpleMove(Board bd)
{
int b = rn.nextInt(3);
for (int i = 0; i < 24; i++) {
if (bd.isVacant(i) && rul.isLegalMove(tigerLocs[b], i)) {
bd.swap(tigerLocs[b],i);
bd.setTiger(i);
tigerLocs[b] = i;
System.out.println(i);
return true;
}
else {
System.out.println(i);
}
}
System.out.println("invalid");
return false;
As the comments point out your loop will execute a maximum of 24 times.
But the return statement inside the if statement may cause it to return 'early'.
It looks like it's some kind of board game thing.
The board appears to have 24 'squares' and it makes the first legal move and returns true.
If it fails to find a legal move, it returns false.
I can't confirm the logic overall but that rationale seems sound:
If there's a move available, take it and return true.
If no move is available, make no move and return false.
If you expected it to continue, even after finding a "valid" move, then simply store the fact that a valid move has been found. This can be done in a separate boolean variable:
private boolean simpleMove(Board bd) {
int b = rn.nextInt(3);
boolean valid = false; // until proven otherwise below
for (int i = 0; i < 24; i++) {
if (bd.isVacant(i) && rul.isLegalMove(tigerLocs[b], i)) {
bd.swap(tigerLocs[b],i);
bd.setTiger(i);
tigerLocs[b] = i;
valid = true;
}
System.out.println(i); // why output HERE when we have a return value?
}
if (!valid) {
System.out.println("invalid"); // why output HERE when we have a return value?
}
return valid;
}
It's unclear if multiple "valid" moves could be found, and whether that would be a problem when you "swap" or not. If there is only ever one possible move, then there would be no need to continue iterating with the for loop; simply return in the body like you were doing.

Why does for readelements() fro loop not print out?

So I've been stuck trying to get my array list to print out in the right order but it keeps printing the original input i inserted backwards for some reason, i've tried reading the array in reverse order but it doesn't work either.
public static void Add()
{
System.out.println("You may now enter your virtual diary entry...");
System.out.println("You may END the program at any time by typing in endp...\n");
boolean loop = true;
while(loop)
{
String Stop = Cons.nextLine();
if (Stop.equals("endp")| Stop.equals(""))
{
readelements();
break;
} else {
for (int i =0 ; i <= Notes.size(); ) {
Notes.add(i, Stop);
i++;
break;
}
}
}
}
public static void readelements()
{
if (Empty()) {
Empty();
}
for(int i =0; i < Notes.size(); i++) {
System.out.println(i + " = " + Notes.get(i).toString());
Notes.toString();
}
}
In your else block, you break after one iteration (when i = 0) so you're always running Notes.add(0, Stop). This prepends Stop to Notes, so Notes will be in reverse order. Removing the break will cause you to insert duplicate elements into Notes (note that you're looping but always inserting Stop). Try changing your entire else block to just Notes.add(Stop);. This will add the current value of Stop to the end of Notes and should fix your problem.

Find bug in implementation of algorithm that finds minimum of an array of integers

Recently, I tried to write a Java program which searches for the minimum of an array.
I tried to write it in a different way, I know there are more simple ways to do that but I want to know why my program does not work.
Here is the source code :
public int minimum(int [] t) {
int min,i,j;
i=j=t.length/2;
min=t[t.length/2];
while(j!=0 || i!=t.length-1) {
while( t[i]>=min) {
i++;
if(i==t.length) {
i=t.length-1;
continue;
}
}
while(t[j]>=min) {
j--;
if(j==-1) {
j=0;
continue;
}
}
if(t[i]<=min && t[j]<=min) {
if(t[i]<=t[j]) min=t[i];
else min=t[j];
}
}
return min;
}
Thanks.
Before you read the answer you should try debugging your code to figure this out by yourself.
I think your code loops infinitely in one of those inner while loops because the end condition
if(i==t.length) {
i=t.length-1;
continue;
}
only resets the i one step back and the continue restarts the while loop. You probably meant to have the break keyword there instead of the continue in which case your code will continue with the other inner while loop.
there is some logic errors in my code , and it get infinitely going through the two loops , i fixed the loops by changing continue with break and i modify the last condition by setting || instead of && (that was a logic mistake), and it works now .
thanks guys.
here is the new source code:
public int minimum(int [] t) {
int min,i,j;
i=j=t.length/2;
min=t[t.length/2];
while(j!=0 || i!=t.length-1) {
while( t[i]>=min) {
i++;
if(i==t.length) {
i=t.length-1;
break;
}
}
while(t[j]>=min) {
j--;
if(j==-1) {
j=0;
break;
}
}
if(t[i]<=min || t[j]<=min) {
if(t[i]<=t[j]) min=t[i];
else min=t[j];
}
}
return min;
}

How can I check an else statement correctly using &&?

Just a quick question, can i use this to include "left" "right"
back" and "forward" all together or do i have to do them separately?
An error came up, so if anyone knows how to include them all together then please help. Thanks
Scanner console = new Scanner(System.in);
for (int i = 0; i < 100; i++) {
System.out.println("Please type in either the word \"left\" or \"right\" or \"back\" or \"foward\": ");
String s = console.next();
if (s.equalsIgnoreCase("left")) {
myFinch.setWheelVelocities(90,90,S);
myFinch.setWheelVelocities(0,100,S);
} if (s.equalsIgnoreCase("right")) {
myFinch.setWheelVelocities(90,90,S);
myFinch.setWheelVelocities(100,0,S);
} if (s.equalsIgnoreCase("back")) {
myFinch.setWheelVelocities(-100,-100,S);
} if (s.equalsIgnoreCase("foward")) {
myFinch.setWheelVelocities(130,130,S);
} else if (s.equalsIgnoreCase != ("left" && "right" && "back" && "foward")) {
myFinch.quit();
}
I would go with a switch statement :
switch (s.toLowerCase()) {
case "left":
myFinch.setWheelVelocities(90,90,S);
myFinch.setWheelVelocities(0,100,S);
break;
case "right":
myFinch.setWheelVelocities(90,90,S);
myFinch.setWheelVelocities(100,0,S);
break;
}
First off to answer your question, in Java you should use String.equals to compare strings, or String.equalsIgnoreCase. This is because this example will fail:
String a = "a";
if (a == "a") {
// Will not be true because you are comparing the reference to the string "a"
} else if (a.equals("a")) {
// Will work because you are comparing on the value of the two strings
}
ref: == vs .equals
I noticed you did this in the first few statements, but on the last statement, the one in question, you did not.
While the statement you were trying to form was not necessary I find it would be useful to share the correct way to do it:
// OMITTED CODE
} else if (s.equalsIgnoreCase("left") && s.equalsIgnoreCase("right") && s.equalsIgnoreCase("back") && s.equalsIgnoreCase("foward") ) {
myFinch.quit();
}
You must make each boolean statement complete, in the sense that it must evaulate to a boolean.
s.equalsIgnoreCase != x// this is simply method so it could not be compared to anything using the != operator
("left" && "right" /* etc */ ) // "left", "right" are not booleans but simply strings.
Java is a very explicit language so shortcuts as the one you attempted are often far and few between.
Secondly you should use the format:
if (/* condition 1*/) {
// code if condition 1 is true
} else if (/* condtion 2 */) {
// code if condition 2 is true but condition 1 is false
} else {
// code if condition 1 and condition 2 are false
}
The else if statement is used to simplify code that would take the following format:
if (/* condition */) {
// code will run if condtion is true
} else {
if (/* sub-condition */) {
// code will run if sub-condition is true, but condition is false
} else {
if (/* sub-sub-condition */) {
// code will run if sub-sub-condition is true, but sub-condition and condition are false
} else {
// code will run if condition, sub-sub-condition, and sub-condition is false
}
}
}
To avoid long chains of such code:
if (/* condition */) {
// code will run if condtion is true
} else { if (/* sub-condition */) {
// code will run if sub-condition is true, but condition is false
} else { if (/* sub-sub-condition */) {
// code will run if sub-sub-condition is true, but sub-condition and condition are false
} else {
// code will run if condition, sub-sub-condition, and sub-condition is false
}}}
The formatting can be seen clearly from here to the current setup:
if (/* condition */) {
// code will run if condtion is true
} else if (/* sub-condition */) {
// code will run if sub-condition is true, but condition is false
} else if (/* sub-sub-condition */) {
// code will run if sub-sub-condition is true, but sub-condition and condition are false
} else {
// code will run if condition, sub-sub-condition, and sub-condition is false
}
These statements were created to read in a logical way:
If the first condtion is met follow the first set of instructions,
else if the first condition wasnt met then try the second condition and instructions,
else if the first two conditions failed try the third set!,
else Damn! Just resort to these instructions
Imagine a scenario where you are taking care of your friend's cat. You are unable to talk about how to care for the cat before your friend leaves but they left you a set of instructions:
Dear friend,
Thank you for looking after muffins. She is a very high maintenance cat.
She has four kinds of food and depending on her mood you should feed her one of
these four: "Purina Super Awesome Cat Time", "Cat Feast 2000", "Cat Chow", and
"Canned".
If you come over and she is waiting at the door give her the "Cat Fest 2000",
If she is not waiting at the door, but instead attacks your leg as you enter the
house you should give her the "Cat Chow",
If she is not at the door, and didn't attack you but is instead wearing a small hat
you should give her the "Purina Super Awesome Cat Time" and play a game of Bridge with
her.
If none of those things happened then give her the "Canned".
Thanks! See you Caturday!
Instead of sending yourself on this monstrous task, with clearly outlined danger, perhaps we want to write a very intelligent robot to go in and take care of the cat each day.
// Upon arrival
if ( Cat.isWaitingAtTheDoor() ) {
Cat.feed("Cat Fest 2000");
} else if ( Cat.didAttackWhenYouWalkedIn() ) {
Cat.feed("Cat Chow");
} else if ( Cat.isWearingSmallHat() ) {
Cat.feed("Purina Super Awesome Cat Time");
Cat.playBridgeWith(self);
} else {
Cat.feed("Canned");
}
So reformat your code to match that structure and you will find you don't need that last condition:
Scanner console = new Scanner(System.in);
for (int i = 0; i < 100; i++) {
System.out.println("Please type in either the word \"left\" or \"right\" or \"back\" or \"foward\": ");
String s = console.next();
if (s.equalsIgnoreCase("left")) {
myFinch.setWheelVelocities(90,90,S);
myFinch.setWheelVelocities(0,100,S);
} else if (s.equalsIgnoreCase("right")) {
myFinch.setWheelVelocities(90,90,S);
myFinch.setWheelVelocities(100,0,S);
} else if (s.equalsIgnoreCase("back")) {
myFinch.setWheelVelocities(-100,-100,S);
} else if (s.equalsIgnoreCase("foward")) {
myFinch.setWheelVelocities(130,130,S);
} else {
myFinch.quit();
}
}
The way you had it set up initially you essentially are not creating a branch structure.
consider this:
int i = 0;
if (i == 0) {
System.out.println("i = 0");
i = 1;
} if (i == 1) {
System.out.println("i = 1");
} else {
System.out.println("i is neither 1 or 0");
}
This will out put:
i = 0
i = 1
Not what we intended!
This is because the above code is equivalent to:
int i = 0;
if (i == 0) {
System.out.println("i = 0");
i = 1;
}
// Two separate statements altogether
if (i == 1) {
System.out.println("i = 1");
} else {
System.out.println("i is neither 1 or 0");
}
Whereas:
int i = 0;
if (i == 0) {
System.out.println("i = 0");
i = 1;
} else if (i == 1) {
System.out.println("i = 1");
} else {
System.out.println("i is neither 1 or 0");
}
Will give:
i = 0
What we wanted, now it is a branched statement, it checks the first if statement then all else if statements following and lastly if none were true resorts the else statement. This seems to be your intention since there is no space for variab;e reassignment between these if statements.
Since JDK 7 you can use strings in switches.
Means:
switch(s.toLowerCase()) {
case "left":
myFinch.setWheelVelocities(90,90,S);
myFinch.setWheelVelocities(0,100,S);
break;
case "right":
myFinch.setWheelVelocities(90,90,S);
myFinch.setWheelVelocities(100,0,S);
break;
case 'back':
myFinch.setWheelVelocities(-100,-100,S);
break;
case "foward"
myFinch.setWheelVelocities(130,130,S);
break;
/** .. and other cases **/
default:
myFinch.quit();
}

Need to convert this for loop to a while loop

I solved a problem recently. But I have this one piece of code where I dont utilize the for loop initialization and condition check. It looks a bit odd that way for a for loop. I want to convert it into a while loop. Please help me do it. I tried many times, but somewhere something is missing.
for(;;current =(current+1)%n){
if(eliminated[current%n]){
continue;
}else{
inkiPinki++;
if(inkiPinki == m){
eliminated[current%n] = true;
printStatus(eliminated, people);
remainingGuys--;
break;
}
}
}
In the above code eliminiated[index] is a boolean.
Edit: Thanks to Geoff who provided me with a solution which I further minimized like this.
while( eliminated[current] || ++inkiPinki != m )
current = (current+1) % n;
eliminated[current] = true;
printStatus( eliminated, people );
remainingGuys--;
All for loops can be converted to while loops using the following pattern:
for (..xxx..; ..yyy..; ..zzz..) {
..aaa..
}
becomes
...xxx...
while (...yyy...) {
..aaa..
..zzz..
}
remember that
for (;;) {
..aaa..
}
is equivalent to
for (nop; true; nop) {
..aaa..
}
where "nop" means no operations.
In your example this makes your loop:
for(;;current =(current+1)%n){
if(eliminated[current%n]){
continue;
}else{
inkiPinki++;
if(inkiPinki == m){
eliminated[current%n] = true;
printStatus(eliminated, people);
remainingGuys--;
break;
}
}
}
equivalent to
// no initialzation needed
while(true) {
//if(eliminated[current%n]){
// continue;
//}else{
if(!eliminated[current%n]){
inkiPinki++;
if(inkiPinki == m){
eliminated[current%n] = true;
printStatus(eliminated, people);
remainingGuys--;
break;
}
}
current =(current+1)%n;
}
From there, you can simplify it further, if you wish.
Try
while( true ) {
if( !eliminated[current] ) {
if( ++inkiPinki == m ) {
break;
}
}
current = (current+1) % n;
}
eliminated[current] = true;
printStatus( eliminated, people );
remainingGuys--;
It should be logically equivalent.
How I would do it:
while (inkiPinki < m) {
if (!eliminated[current % n]) {
inkiPinki++;
if (inkiPinki == m) {
eliminated[current % n] = true;
}
}
if (inkiPinki < m) {
current = (current + 1) % n;
}
}
printStatus(eliminated, people);
remainingGuys--;
This code accomplishes exactly the same thing as your original for loop, except it uses logical tests to determine whether or not it should continue to loop. There's no need for continue or break. If you find yourself using either of these statements, there's probably some refactoring that should be done.
I seem to have an inordinate fondness for using Booleans as integers:
for (;inkiPinki<m; inkPinki += !eliminated[current])
current = (current + 1) %n;
eliminated[current] = true;
printStatus(eliminated, people);
remainingGuys--;
I've also changed current%n to simply current in a couple of places, because the %n is already done where current is incremented, so current should already be reduced modulo n.
If I were doing it, I'd probably change the sense, so instead of eliminated, it was something like remaining:
for (;inkiPinki<m; inkPinki += remaining[current])
current = (current + 1) %n;
remaining[current] = false;
printStatus(remaining, people);
remainingGuys--;

Categories