Virtual Coin Flip
#21 Members - Reputation: 6197
Posted 11 October 2012 - 06:34 PM
You need to close the `else' block right after printing "tail". You also need to assign a fresh random number between throws.
#22 Members - Reputation: 633
Posted 12 October 2012 - 08:34 AM
public static void main (String[] args){
double start = 0;
double end = 1;
double random = new Random().nextDouble(); //hey Random, assign some number between <0-1) to variable random
double result = start + (random * (end - start)); //now assign 0 + (random * (1-0)) = 0 + (random * 1) = random to variable result
System.out.println(result); //I will tell the user the value of vairable result
//is result is smaller than 0.5
if (result < 0.5)
{ //block T
//I will tell the user that it's a head
System.out.println("head");
//there aren't any statements, so I'll just skip over the block B, there's nothing relevant there
} //end of block T
else
{ //block F
//I will tell the user it's a tail
System.out.println("tail");
//the programmer wants me to do something (compute another flip) more before I end...
//wait... random, end and start probably didn't change, shouldn't the result be the same?
//not my problem, i'll compute it
result = start + (random * (end - start));
//the value of result is the same as before... whatever
//so let's compare again!
if (result < 0.5)
{
//I never get to this, the result is always smaller than 0.5
System.out.println("head");
//but if I did, I would see that there's nothing more and continue after the else branch
}else{ //block F-F
//yeah... we print it
System.out.println("tail");
//ANOTHER TIME? This guy is crazy!
result = start + (random * (end - start));
//and we compare! yes!
if (result < 0.5){
//also never happens
System.out.println("head");
}else{ //block F-F-F
/*and comparing and comparing...
and comparing*/
} // end of block F-F-F
} //end of block F-F <-- this is where I WOULD continue from if the heads come the second time
} //end of block F <-- this is where I continue from if the heads come the first time
//this is where I stop! No more work for me! YEAH!
}Can you see what is wrong with the code?
1. If the heads come first time, the compiler prints "heads" and skips the whole else branch all down to end of the block F. Nothing else happens.
Solution: Remember, the parent block MUST be executed for the child block to be executed too. So just make all the ifs children of main() block! That way, they will be executed independently. You want to say to computer: "Flip the coin ten times and tell me the result after every flip." Instead, you are saying this: "Flip the coin and tell me the result. If it's tails, do the same thing once more. But flip the coin ten times at most." You must change the code to match its meaning.
2. The computer flips the coin only the first time. Remember, the act of flipping is
random = new Random().nextDouble();This code
result = start + (random * (end - start));just converts the result of flipping to another range (or the same range, in your case).
The computer just looks at the coin and says which side is up. But it doesn't flip the coin before checking it, so the result must be the same as before. (Variables, as is the case with coins, usually don't change the side lying up unless moved.
SOLUTION: This one is easy, flip the coin (random = new Random().nextDouble();) before checking.
Also, it would be better to do it with procedures, but you seem you need to grasp the meaning of blocks ({}) and ifs. And those are probably the most important flow control in your code, so learn them and love them!
EDIT: How do the code tags work? They don't accept line-breaks?
EDIT 2: Okay, got it. You can't start a code tag with a multi-line comment, or it will be displayed only on one line. Strange.
Edited by ifthen, 12 October 2012 - 11:30 AM.
#23 Crossbones+ - Reputation: 338
Posted 12 October 2012 - 12:10 PM
import java.util.Random;
public class flip
{
public static void main(String[] args)
{
//Since these values never get changed, it is good practice to make them
//final.
final double start = 0;
final double end = 1;
//Declare this as an instantiation of Random, not a double.
Random random = new Random();
//Set the initial value of the result variable. Notice how I use the
//"random" object. Intead of using a double that has an initial value,
//I generate a new value ("random.nextDouble()")
double result = start + (random.nextDouble() * (end - start));
System.out.println(result);
//First result check.
if(result <= 0.5)
{
System.out.println("head");
}
else
{
System.out.println("tail");
}
//Generate a new value and shove it in the result variable. Same thing
//as the first call. I use random to generate a new value. If I didn't
//and just used a double, the double variable would still have the same
//value I set in the beginning.
result = start + (random.nextDouble() * (end - start));
//Second result check.
if(result <= 0.5)
{
System.out.println("head");
}
else
{
System.out.println("tail");
}
//Generate a new value and shove it in the result variable.
result = start + (random.nextDouble() * (end - start));
//Third result check.
if(result <= 0.5)
{
System.out.println("head");
}
//Generate a new value and shove it in the result variable.
result = start + (random.nextDouble() * (end - start));
//Fourth result check.
if(result <= 0.5)
{
System.out.println("head");
}
else
{
System.out.println("tail");
}
//Generate a new value and shove it in the result variable.
result = start + (random.nextDouble() * (end - start));
//Fifth result check.
if(result <= 0.5)
{
System.out.println("head");
}
else
{
System.out.println("tail");
}
//Generate a new value and shove it in the result variable.
result = start + (random.nextDouble() * (end - start));
//Sixth result check.
if(result <= 0.5)
{
System.out.println("head");
}
else
{
System.out.println("tail");
}
//Generate a new value and shove it in the result variable.
result = start + (random.nextDouble() * (end - start));
//Seventh result check.
if(result <= 0.5)
{
System.out.println("head");
}
else
{
System.out.println("tail");
}
//Generate a new value and shove it in the result variable.
result = start + (random.nextDouble() * (end - start));
//Eighth result check.
if(result <= 0.5)
{
System.out.println("head");
}
else
{
System.out.println("tail");
}
//Generate a new value and shove it in the result variable.
result = start + (random.nextDouble() * (end - start));
//Ninth result check.
if(result <= 0.5)
{
System.out.println("head");
}
else
{
System.out.println("tail");
}
//Generate a new value and shove it in the result variable.
result = start + (random.nextDouble() * (end - start));
//Tenth result check.
if(result <= 0.5)
{
System.out.println("head");
}
else
{
System.out.println("tail");
}
}
}
Edited by ByteTroll, 12 October 2012 - 12:14 PM.
I see the future in 1's and 0's
▬▬▬▬▬▬▬▬▬▬▬ஜ۩۞۩ஜ▬▬▬▬▬▬▬▬▬▬▬▬▬
#24 Members - Reputation: 633
Posted 12 October 2012 - 01:43 PM
Also, it prints the result at start, so remove that line if you don't want to see that floating point number printed in your output.
If you cannot use the static keyword elsewhere than in main, you have to do either the ten ifs trick or use a class with recursive function (if anyone knows another approach, share your knowledge). That could look like this
import java.util.Random;
public class Coin {
//Is the head upwards?
protected boolean head;
//Reference to random generator used.
protected Random randomGenerator;
//Init the coin to the init values
Coin(boolean _head, Random _randomGenerator) {
head = _head;
randomGenerator = _randomGenerator;
}
//Flips the coin so it is heads 50% of time and tails 50% of time.
void flip() {
//notice that you can assign results of expressions to booleans
head = randomGenerator.nextDouble() < 0.5;
}
//Prints the name of side that is upwards side
void print() {
if (head)
System.out.println("head");
else
System.out.println("tail");
}
//Flips the coin repeat times and prints its upwards side after every flip
void flipAndPrint(int repeat) {
if ( repeat > 0) {
flip();
print();
flipAndPrint(repeat-1);
}
}
//and some other functions if necessary (e.g. getter of the upwards side)
//Flips a coin and prints the result ten times.
public static void main (String[] args)
{
Random randomGenerator = new Random();
//it doesn't matter if we choose heads or tails as the starting upwards side because it will be flipped anyway
Coin coin = new Coin(true, randomGenerator);
coin.flipAndPrint(10);
}
}
Yeah, that's probably an overkill for now, but suppose that you would develop betting game software or something like that. Using ten ifs to flip ten coins would be rather unprofessional. (Of course you would be using for loops. But it is good practice in Java to split every non-simple task to a separate class - divide and conquer, so this applies a bit.)
#25 Crossbones+ - Reputation: 338
Posted 12 October 2012 - 03:07 PM
Bytetroll got it almost right, although the else branch of the third result check is missing! That could lead to nasty bugs in your code (hey, why does it sometimes print 10 lines and sometimes just 9?), so fix it if you are going to use it. THAT is the reason why you shouldn't write programs copy-paste-style, if you have many same or almost same snippets in your program, you will at some point make a mistake when creating/editing it and the program will not work properly. So be wary of it and try to minimize it!
Also, it prints the result at start, so remove that line if you don't want to see that floating point number printed in your output.
If you cannot use the static keyword elsewhere than in main, you have to do either the ten ifs trick or use a class with recursive function (if anyone knows another approach, share your knowledge). That could look like thisimport java.util.Random; public class Coin { //Is the head upwards? protected boolean head; //Reference to random generator used. protected Random randomGenerator; //Init the coin to the init values Coin(boolean _head, Random _randomGenerator) { head = _head; randomGenerator = _randomGenerator; } //Flips the coin so it is heads 50% of time and tails 50% of time. void flip() { //notice that you can assign results of expressions to booleans head = randomGenerator.nextDouble() < 0.5; } //Prints the name of side that is upwards side void print() { if (head) System.out.println("head"); else System.out.println("tail"); } //Flips the coin repeat times and prints its upwards side after every flip void flipAndPrint(int repeat) { if ( repeat > 0) { flip(); print(); flipAndPrint(repeat-1); } } //and some other functions if necessary (e.g. getter of the upwards side) //Flips a coin and prints the result ten times. public static void main (String[] args) { Random randomGenerator = new Random(); //it doesn't matter if we choose heads or tails as the starting upwards side because it will be flipped anyway Coin coin = new Coin(true, randomGenerator); coin.flipAndPrint(10); } }
Yeah, that's probably an overkill for now, but suppose that you would develop betting game software or something like that. Using ten ifs to flip ten coins would be rather unprofessional. (Of course you would be using for loops. But it is good practice in Java to split every non-simple task to a separate class - divide and conquer, so this applies a bit.)
Oh dear! That was a copy and paste fail. As ifthen stated... that is why you do not write programs copy and paste style. I wrote one block and then copy and pasted; missing one. Sorry about that one. Thank you for catching that ifthen!
Edited by ByteTroll, 12 October 2012 - 03:09 PM.
I see the future in 1's and 0's
▬▬▬▬▬▬▬▬▬▬▬ஜ۩۞۩ஜ▬▬▬▬▬▬▬▬▬▬▬▬▬
#26 Members - Reputation: 128
Posted 12 October 2012 - 05:28 PM
I enjoyed this. Thanks to all!
import java.util.Random;
import java.util.Arrays;
import java.util.Collections;
public class Coin
{
public enum Side { heads, tails, edge };
public Coin()
{
_side = Side.edge;
}
public Coin(Side side)
{
_side = side;
}
public Coin(Random generator)
{
flip(generator);
}
public void flip(Random generator)
{
double value = generator.nextDouble();
if(value < 0.5 )
{_side = Side.heads;}
else if(value > 0.5)
{_side = Side.tails;}
else
{_side = Side.edge;}
}
public boolean equals(Coin other)
{
return _side == other._side;
}
public String toString()
{
return _side.toString();
}
private Side _side;
public static void main(String[] args)
{
Coin heads = new Coin(Side.heads);
Coin tails = new Coin(Side.tails);
Random rand = new Random();
Coin[] coins = new Coin[]
{
new Coin(rand),
new Coin(rand),
new Coin(rand),
new Coin(rand),
new Coin(rand),
new Coin(rand),
new Coin(rand),
new Coin(rand),
new Coin(rand),
new Coin(rand)
};
System.out.println(Arrays.toString(coins));
int numHeads = Collections.frequency(Arrays.asList(coins), heads);
System.out.println("There are " + numHeads + " heads.");
int numTails = Collections.frequency(Arrays.asList(coins), tails);
System.out.println("There are " + numTails + " tails.");
}
}
I encountered some challenges while finding the "right way"
- no easy way to "apply"
- countif/equality not working here
- *()&(SFHKJHSF(&(*&:>( code tags!!
Edited by m3mb3rsh1p, 12 October 2012 - 06:33 PM.
#28 Members - Reputation: 633
Posted 13 October 2012 - 12:41 AM
public boolean equals(Object other) {
Class thisClass = this.getClass();
Class otherClass = other.getClass();
while (otherClass != thisClass) {
otherClass = otherClass.getSuperclass();
if (otherClass == null)
return false;
}
final Coin otherCoin = (Coin)other;
return _side == otherCoin._side;
}






