public static GetRandomFunc() {
switch((int)(Math.random()*NUM_FUNCTIONS) {
case 0:
functionA();
break;
case 1:
functionB();
break;
case 2:
functionC();
break;
// ...
}
}
I want to call GetRandomFunc() in main randomly until each function has been called once and then it ends. How do I make sure a function would be called once only, and if all has been called, it prints out System.out.println("All done")
create a list containing 0,1 and 2. shuffle it and iterate over it to call each function once but in random order.
List<Integer> integers = Arrays.asList(0,1,2);
Collections.shuffle(integers)
for (Integer i: integers){
GetRandomFunc(i)
}
and your function will be
public static GetRandomFunc(int index) {
switch(index) {
case 0:
functionA();
break;
case 1:
functionB();
break;
case 2:
functionC();
break;
// ...
}
}
Use a list of Runnables (or of Integers mapping to each function, as you did in your code), shuffle it, then iterate through the list and call each function.
http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#shuffle%28java.util.List%29
Make a list of the functions and take from it at random. When it's empty, you can be sure you used every function exactly once.
public interface Function { void execute(); }
public static runFunctionsRandomly(List<Function> functions) {
while (!functions.isEmpty()) {
int index = Math.random() * functions.size();
Function f = functions.get(index);
f.execute();
functions.remove(index);
}
}
class ExampleFunction implements Function {
void execute() {
System.out.println("Hello world!");
}
}
...
Related
I have an object "JudgesSubmission" with the following methods:
public String getInnovationGrade1() {
return innovationGrade1;
}
public String getInnovationGrade2() {
return innovationGrade2;
}
public String getInnovationGrade3() {
return innovationGrade3;
}
public String getInnovationGrade4() {
return innovationGrade4;
}
Now, when calling these methods, I want to put them in a loop where the called method name gets the index of the loop attached to its end changing the method called. Is this possible?
For example, the following code would never work, but I am writing it to explain what I need:
judgesSubmission metricScores= new judgesSubmission;
int metricSum=0;
for (int i=0;i<4;i++){
metricSum=metricSum
Integer.parseInt(metricScores.getInnovationGrade+"i"());
}
Is there a way to do that or do I always have the full method name written?
What you want to do is not possible... but with reflection such as :
MyObject.class.getMethod("mymethod"+i);
Without reflection you could use a Supplier<String> :
public void process(Supplier<String>... suppliers){
judgesSubmission metricScores= new judgesSubmission;
int metricSum=0;
for (Supplier<String> supplier : suppliers){
Integer.parseInt(supplier.get());
}
}
And call it such as :
MyObject myObject = new MyObject();
process(()->myObject.getInnovationGrade1(),
()->myObject.getInnovationGrade2(),
()->myObject.getInnovationGrade3(),
()->myObject.getInnovationGrade4());
It is not possible without reflection (and is highly not recommended)
Instead you may want to use other methods:
An array of the data (either replacing the 4 methods, or in addition)
String[] getInnovationGrades()
{
return new String[]{innovationGrade1, innovationGrade2, innovationGrade3, innovationGrade4};
}
Then later you can use
for(String innovationGrade : getInnovationGrades())
//do stuff
An argument to get the data you want
String getInnovationGrade(int i)
{
switch(i)
{
case 1:
return getInnovationGrade1();
case 2:
return getInnovationGrade2();
case 3:
return getInnovationGrade3();
case 4:
return getInnovationGrade4();
default:
return ""; //or throw exception, depends on how you wish to handle errors
}
}
Then later you can use
for(int i = 1; i <= 4; i++)
getInnovationGrade(i); //and do stuff with it
I'm trapped within this certain predicament of mine and I would gladly accept any suggestion. So here it is:
I'm currently working in a method where a certain variable is assigned a specific value in the beginning part of the method. During the course of the method, that variable is used as a parameter by an external component which basically returns a result code. In one of those result codes, I have to change the value of the prior mentioned variable and repeat the whole process using the new value. The concept is as follows but I have simplified it as much as possible:
public void myMethod (String args[]) {
String server;
server = "some value";
switch (someExternalOperation(server)) {
case 1:
//process....
break;
case 2:
server = "new value";
//repeat myMethod using new value of server String variable
break;
}
}
public int someExternalOperation (String str) {
//after several operation
return 1; //example purposes
}
By the way, I have checked and researched things like goto and other alternative. I may have overlooked some results and ended up asking here. Any help would be much appreciated. Thank you.
One simple option is to have a private overload taking the server parameter - then you can call it recursively:
public void myMethod(String args[]) {
myMethod(args, "some value");
}
private void myMethod(String[] args, String server) {
switch (someExternalOperation(server)) {
case 1:
// process....
break;
case 2:
myMethod(args, "new value");
break;
}
}
You need to make sure that isn't going to recurse infinitely, of course.
Another option would be to just have a loop inside your method:
public void myMethod (String args[]) {
String server = "some value";
while (true) { // Or ideally a different condition...
switch (someExternalOperation(server)) {
case 1:
// process....
// Done! Exit the method...
return;
case 2:
server = "new value";
// We'll now continue to the next iteration of the loop
break;
default:
// ?
}
}
}
I figured a way instead to address. Thanks everyone for reading. I'll just simply use the external operation and check if it will return case 2.
public void myMethod (String args[]) {
String server;
server = "some value";
if (someExternalOperation(server) == 2)
server = "new value";
switch (someExternalOperation(server)) {
case 1:
//process....
break;
}
}
public int someExternalOperation (String str) {
//after several operation
return 1; //example purposes
}
Thanks for your help anyway.
I wrote a library
This library accept the limited options and print the related string.
public class Lib {
public enum Num {
ZERO,
ONE,
TWO,
THREE
}
public static void main(String[] args) {
Lib obj = new Lib();
obj.print(Num.ONE);
}
public void print(Num num) {
switch (num) {
case ZERO:
System.out.println("ZERO is "+Num.ZERO.ordinal());
break;
case ONE:
System.out.println("ONE is "+Num.ONE.ordinal());
break;
case TWO:
System.out.println("TWO is "+Num.TWO.ordinal());
break;
case THREE:
System.out.println("THREE is "+Num.THREE.ordinal());
break;
default:
break;
}
}
}
In the new version, I will disable option ONE and TWO
public enum Num {
ZERO,
//ONE,
//TWO,
THREE
}
How can I keep the correct values after I disabled the options?
It is not clear what you are asking. If you change any piece of code and thereby "remove" "names" that formerly existed ... than of course, any "reference" to any of the deleted elements is ... first of all: broken.
In case of an enum, you might prefer to not rely on build-in ordinals; instead you could go for this:
enum Whatever {
ONE(1), TWO(2);
private final int value;
private Whatever(value) {
this.value = value;
}
public int getValue() { return value }
But you have to be really careful here. For example, if you are persisting enum objects (into some sort of database for example) then any such change (adding or removing enum "values") will lead to incompatibilities!
I am not sure of what you want to do, but for example you can do this:
public enum Num {
ZERO,
ONE,
TWO,
THREE
}
switch (num) {
case ZERO:
System.out.println("ZERO is "+Num.ZERO.ordinal());
break;
case THREE:
System.out.println("ZERO is "+Num.THREE.ordinal());
break;
case One:
case Two:
default:
break;
You might be disable some of enum now onward and keep stored as it is. To support both the things, you should have a method that returns list of enum that will populate on UI. I.E. List getPopulatedOnUi(). That contains those enum list that you needed.
Don't remove from definition itself. keep as it is. because that will throw error for existing as it might be stored into database.
You can modify the print() method as below: Instead of switch, you can use for loop and make the code little bit generic. Now, even when your enum values changes, you need not to make any changes in this code.
It will handle the case , If you disable some enum values in future.
public void print(Num num) {
for(Num n : Num.values()) {
if(n == num) {
System.out.println(n.name()+ " is " + n.ordinal());
break;
}
}
}
I have a problem returning a result of String type in Java.
Here is the whole code
import java.util.*;
public class Multiplication
{
static Random randomNumbers = new Random();
static Scanner input = new Scanner(System.in);
static int answer;
public static void multiplication()
{
createQuestion(); //display first question
int guess; //student's answer
System.out.print("Your answer is (-1 to quite): ");
guess = input.nextInt();
while(guess != -1)
{
checkAnswer(guess);
System.out.print("Your answer is (-1 to quite): ");
guess = input.nextInt();
}
} //end method multiplication
//create new question
public static void createQuestion()
{
int num_1 = randomNumbers.nextInt(10);
int num_2 = randomNumbers.nextInt(10);
answer = num_1 * num_2;
System.out.printf("How much is %d times %d?\n", num_1, num_2);
}//end method createQuestion
public static String createResponse(boolean correct)
{
if (correct)
switch(randomNumbers.nextInt(4))
{
case 0:
return ("Very good!");
case 1:
return("Excellent!");
case 2:
return("Nice work!");
case 3:
return ("Keep the good work");
} //end switch
//otherwise, assume incorrect
switch(randomNumbers.nextInt(4))
{
case 0:
return("No. Please try again.");
case 1:
return("Wrong. Try once more.");
case 2:
return("Don't give up!");
case 3:
return("No. Keep trying.");
}//end switch
}//end method createResponse
//check in the student answer correctly
public static void checkAnswer(int guess)
{
if(guess != answer)
{
System.out.println(createResponse(false));
}
else
{
System.out.print(createResponse(true));
createQuestion();
}
}//end method checkAnswer
}//end class Multiplication
And here is the main method
public class MultiplicationTest {
public static void main(String[] args) {
Multiplication app = new Multiplication();
app.multiplication();
}
}
The problem is in the createResponse(boolean correct) method. Here JDE is saying that "This method must return a result of type String". I have mentioned there String type return. But the program is not being executed. Showing a red line under the method createResponse(boolean correct).
Does anybody where I have messed up?
Thanks in advance!
The compiler cannot assert that your method returns a String.
This is because your switch-case may fail to return anything.
You can satisfy the compiler by placing a
return null;
at the end of your method.
The method createResponse might not always reach a return statement in your code. If none of the cases in your second switch statement applies, it will reach the bottom of the code block without returning.
Just make sure you return something at the end of the method (or find another nice solution):
return "";
}//end method createResponse
It's because if none of the conditions in either of the switch statements were met there would be nothing to return. Try something like:
public static String createResponse(boolean correct)
{
String result = null;
if (correct)
switch(randomNumbers.nextInt(4))
{
case 0:
result = "Very good!";
// Insert the rest of the code here, assigning to result rather than returning as above.
return result;
}
you are missing the 'else' part for the 'if' and the 'default' case for the 'switch-case' in the createResponse method.
edit:
ok, the 'else' is not necessary, but I missed that in the first place. the indentation of the second 'switch' is confusing. please use parentheses to avoid this.
Furthermore, the compiler believes that it could happen that none of the 'case' branches will get executed since it is not aware of the nextInt returning Integers in the range of 0..3. you'll need to add the default case to satisfy the compiler.
Compiler is not smart enough yet to know that nextInt(4) may return only 0,1,2 and 3 so it assumes that for case like 5 you current code will not return anything, but if method declares that it will return some value must guarantee that some value will always be returned.
To solve this problem you can change case 3: to default:. This would make compiler assume that even for cases which are not 0,1,2 some value will be returned.
Also it seems that your code would be cleaner if you would use else and additional curly brackets like
public static String createResponse(boolean correct) {
if (correct){
switch (randomNumbers.nextInt(4)) {
case 0:
return ("Very good!");
case 1:
return ("Excellent!");
case 2:
return ("Nice work!");
default:
return ("Keep the good work");
}
} else {
switch (randomNumbers.nextInt(4)) {
case 0:
return ("No. Please try again.");
case 1:
return ("Wrong. Try once more.");
case 2:
return ("Don't give up!");
default:
return ("No. Keep trying.");
}
}// end switch
}// end method createResponse
BTW you can simplify your code a little by using arrays which would store your responses. This way your code could look like
private static String[] good = { "Very good!",
"Excellent!",
"Nice work!",
"Keep the good work" };
private static String[] bad = { "No. Please try again.",
"Wrong. Try once more.",
"Don't give up!",
"No. Keep trying." };
public static String createResponse(boolean correct) {
if (correct)
return good[randomNumbers.nextInt(4)];
else
return bad[randomNumbers.nextInt(4)];
}
or even
public static String createResponse(boolean correct) {
return correct ? good[randomNumbers.nextInt(4)]
: bad[randomNumbers.nextInt(4)];
}
public static GetRandomFunc() {
switch((int)(Math.random()*NUM_FUNCTIONS) {
case 0:
functionA();
break;
case 1:
functionB();
break;
case 2:
functionC();
break;
// ...
}
}
I want to call GetRandomFunc() in main randomly until each function has been called once and then it ends. How do I make sure a function would be called once only, and not called again.
It would be easier to store values in an collection, and draw them out randomly until the collection is empty. Or better yet, shuffle the collection and then walk over it sequentially.
The values in the collection could be integers, or they could be objects of different classes (with a common superclass or interface), which provide different implementations of a call() method.
For example:
import java.util.*;
import java.util.concurrent.*;
List<Runnable> functions = new ArrayList<Runnable>();
functions.add(new Runnable() {
public void run() { /* do something */ }
});
functions.add(new Runnable() {
public void run() { /* do something else */ }
});
Collections.shuffle(functions);
for(Runnable function : functions)
function.run();
The other posts on this thread show other potential solutions, but all of them are more complex and error-prone than this one, and most of them would be very slow if the number of functions is large. (The one from #AndersLinden is an exception -- it would still be fast even if there are thousands of functions to call.)
Bit fields to record whether a function has been called and an if statement to not call the function if it's bit is already set - keep looping until all of the bits are set.
(or as Alex D says, create a collection of numbers to use up front)
Either way the trick is to make sure you generate each number once and once only - if you screw this bit up you can end up in an infinite loop (e.g. waiting to get numbers 1, 2 and 3, but your random function is generating 0, 1 and 2)
You could create an array to keep track of which functions have already been used.
For example:
boolean[] usedFunctions = new boolean[NUM_FUNCTIONS];
public static GetRandomFunc() {
switch((int) (Math.random() * NUM_FUNCTIONS) {
case 0:
if(!usedFunctions[0]) {
functionA();
usedFunctions[0] = true;
}
break;
case 1:
if(!usedFunctions[1]) {
functionB();
usedFunctions[1] = true;
}
break;
// etc.
}
}
Then all you need to do is repeatedly call GetRandomFunc() until all elements in usedFunctions are true.
You keep an array of integers that tells which indexes that are still not used.
When you have used an integer, you fill it in the hole with the last index in the list and treat it as a list with one item shorter.
int indexes[] = new int[3];
for (int i = 0; i < 3; i++)
indexes[i] = i;
for (int i = 0; i < 3; i++)
{
int index = (int)(Math.random()*(3 - i));
switch (indexes[index])
{
case 0:
functionA();
break;
case 1:
functionB();
break;
case 2:
functionC();
break;
}
indexes[index] = indexes[2 - i];
}