Virtual Coin Flip

Started by
27 comments, last by StayFly 11 years, 6 months ago
Pretend you are the computer and follow the flow of the program. You compute a random number once. Then, if it is less than 0.5 you print "head" and do nothing else, because the rest of the code is inside the `else' block. If it is not less than 0.5, you print "tail" and make the comparison again, but without picking another random number. So you look at the number and, again, it is not less than 0.5. Etc.

You need to close the `else' block right after printing "tail". You also need to assign a fresh random number between throws.
Advertisement
alvaro is right. Allow me to demonstrate it another way. I'll read your program as the computer reads it.


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.smile.png ).
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!wink.png

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.
I am not sure if you are still having issues with this assignment, but I got bored today and figured I would lend a final hand. I recoded my example in Java. I generally don't do peoples homework for them, but you have at least given it a shot. For future reference, however, I would look closely at what I have done and learn. Hope this helps.


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");
}
}
}

"The code you write when you learn a new language is shit.
You either already know that and you are wise, or you don’t realize it for many years and you are an idiot. Either way, your learning code is objectively shit." - L. Spiro

"This is called programming. The art of typing shit into an editor/IDE is not programming, it's basically data entry. The part that makes a programmer a programmer is their problem solving skills." - Serapth

"The 'friend' relationship in c++ is the tightest coupling you can give two objects. Friends can reach out and touch your privates." - frob

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 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.)

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 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.)


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!

"The code you write when you learn a new language is shit.
You either already know that and you are wise, or you don’t realize it for many years and you are an idiot. Either way, your learning code is objectively shit." - L. Spiro

"This is called programming. The art of typing shit into an editor/IDE is not programming, it's basically data entry. The part that makes a programmer a programmer is their problem solving skills." - Serapth

"The 'friend' relationship in c++ is the tightest coupling you can give two objects. Friends can reach out and touch your privates." - frob

Hi. I'm also a beginner so I thought I'd share my solution. I'm stuck at how to count the flips without loops because I don't quite yet have a firm grasp of the Java utils.

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!!
Eureka! I solved the "equals() method not working properly!" conundrum!

public boolean equals(Object other)
{
final Coin c = (Coin)other;
return _side == c._side;
}
Hmm... that really isn't a solution. Suppose you pass an object of type Car (or something else) to the function. It throws a ClassCastException and if you don't have the try-catch blocks surrounding it, it leads to premature program termination (as it does if other is null, but that is usually expected behaviour). You should compare that other is of type Coin or a child of Coin either by surrounding with try-catch blocks for ClassCastException or like this.

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;
}
i've seem to of got it working thank a lot for all the help everyone. Hopefully someday i will be just like you guys in the For Beginners section helping out a fellow noob.

This topic is closed to new replies.

Advertisement