straights algorithm in yahtzee - java

For a school assignment we are working on implementing the yahtzee game in java, but I am having some problems with making algorithms for the straights (small and large straight, which means 4/5 consecutive numbers for a small straight and 5/5 for a large).
I have made one algorithm that I believe should be working, but in reality it always puts out 0 so I should be missing something:
private void straights(int category) {
Arrays.sort(dices);
int nonConsecCount = 0;
for(int currDice = 0; currDice < N_DICE - 2; currDice++) {
if(dices[currDice] != dices[currDice + 1] + 1) {
nonConsecCount++;
}
}
if(nonConsecCount == 0 && category == LARGE_STRAIGHT) {
score[currPlayer - 1][category - 1] = 40;
display.updateScorecard(category, currPlayer, 40);
} else if(nonConsecCount <= 1 && category == SMALL_STRAIGHT) {
score[currPlayer - 1][category - 1] = 30;
display.updateScorecard(category, currPlayer, 30);
} else {
score[currPlayer - 1][category - 1] = 0;
display.updateScorecard(category, currPlayer, 0);
}
}
N_DICEis equal to 5.
My theory behind this algorithm was; everytime you find a number in the (sorted) array of dicevalues that doesn't have a consecutive number as the next one, add one to the non consecutive count, and in the end check for this counter when handing out the score to the player.
Any help would we greatly appreciated!

According to the rules of the game which I quickly skimmed through the article in the wikipedia
Small Straight - Is 4 sequential dices (30 score) that is
1,2,3,4 or 2,3,4,5 or 3,4,5,6
Large Straight - Is 5 sequential dices (40 score) that is
1,2,3,4,5 or 2,3,4,5,6
If small straight, then you should have a nonConsecCount equal to 1 because 5 - 1 is 4 and that gives us the four consecutive dices. If large straight, then you should have a nonConseCount equal to 0 because 5 - 0 gives us all five elements as consecutive.
If I understand the game correctly (taking into account the fact that I just skimmed it), you need the following modifications in your code:
Your for loop condition should be N_DICE - 1, this would result the
for loop to execute 4 times, one less than size of array hence, you
are guaranteed not to get ArrayOutOfBoundException
You need to change your if condition such that, add to the value
of the left part of condition and then check that with value of right part of the condition that is one ahead. As a result of this, swapping you can use N_DICE - 1 instead of N_DICE - 2. N_DICE - 2 skips one array element and only checks 3 consecutive elements (not what the games rules say).
Make the following changes to your code:
int nonConsecCount = 0;
for(int currDice = 0; currDice < N_DICE - 1; currDice++) {
if(dices[currDice] + 1 != dices[currDice + 1]) {
System.out.println("failed consecutive match!");
nonConsecCount++;
} else {
System.out.println("passed consecutive match for "+ dices[currDice]);
}
}
System.out.println(nonConsecCount);
I provided the above code the following dices and got nonConsecCount as show in the comment line:
int[] dices = new int[]{3,4,5,1,2};
//output 0 - this is largest straight
int[] dices = new int[]{3,4,5,6,2};
//output 0 - this is largest straight too
int[] dices = new int[]{3,4,5,2,2};
//output 1 - this is smallest straight
int[] dices = new int[]{3,4,2,2,2};
//output 2 - this is none of the two

Related

How is the dynamic program designed for this problem?

I am working on this problem: Maximum games played by winner
. Quoted here for convenience:
There are N players which are playing a tournament. We need to find the maximum number of games the winner can play. In this tournament, two players are allowed to play against each other only if the difference between games played by them is not more than one.
Input :
N = 4
Output : 2
Maximum games winner can play = 2
Assume that player are P1, P2, P3 and P4
First two pairs will play lets (P1, P2) and
(P3, P4). Now winner of these two games will
play against each other, making total games
played by winner = 2
My confusion is with this below approach explained:
We can solve this problem by first computing minimum number of players required such that the winner will play x games. Once this is computed actual problem is just inverse of this. Now assume that dp[i] denotes minimum number of players required so that winner plays i games. We can write a recursive relation among dp values as,
dp[i + 1] = dp[i] + dp[i – 1] because if runner up has played (i – 1) games and winner has played i games and all players against which they have played the match are disjoint, total games played by winner will be addition of those two sets of players.
Above recursive relation can be written as dp[i] = dp[i – 1] + dp[i – 2]
Here is my understanding.
Let's say 4 players p1, p2, p3, p4.
The games are
Game 1: (p1, p2) winner p1
Game 2: (p3, p4) winner as p3
Game 3: (p1,p3) winner as p1
The winner is p1 and the runner is p3.
At Game 1, Runner p3 has played 0 games. so dp[i-1] = 0. Winner has played 1 game so dp[i] = 1. so dp[2] = 1 + 0 = 1. I am totally confused how to understand this approach towards solution.
Finally the solution is this:
int maxGameByWinner(int N)
{
int[] dp = new int[N];
// for 0 games, 1 player is needed
// for 1 game, 2 players are required
dp[0] = 1;
dp[1] = 2;
// loop until i-th Fibonacci number is
// less than or equal to N
int i = 2;
do {
dp[i] = dp[i - 1] + dp[i - 2];
} while (dp[i++] <= N);
// result is (i - 2) because i will be
// incremented one extra in while loop
// and we want the last value which is
// smaller than N, so one more decrement
return i - 2;
}
Also I am not clear what it means // result is (i - 2) because i will be incremented one extra in while loop and we want the last value which is smaller than N, so one more decrement return (i - 2);
Clarification
Just as the comments point out, the problem is actually missing some requirements. However, from the suggested solution, we can guess that the missing requirement is that the loser of any match will get eliminated immediately and cannot participate in future matches.
Idea
The number of winning matches between two players need to be smaller than or equal to 1. How to approach this? Let's start with n=2 first
1 2
\ /
1 (winner)
It is obvious that the winner can win with at most 1 match. How about n=3?
1 2 3
\ / /
1 /
\ /
1 (winner)
The winner can win with at most 2 matches in this case, now think about how to find minimal n such that the answer is 3. In fact, we can just combine the above two trees!
1 2 3 Round 1
\ / /
1 / 4 5 Round 2
\ / \ /
1 4 Round 3
\ /
\ /
\ /
1 (winner)
Observe how is the above tree a combination of the n=2 and n=3 cases. In Round 3, 1 has won two matches (as n=2) and 4 has won one match (as n=1) so the competition between them is legal. Therefore, it can be seen that to the minimal n such that answer is 4 is
(the minimal n such that the answer is 3) + (the minimal n such that the answer is 2)
This idea can be applied in the same way for larger n. This is where the dp[n] = dp[n - 1] + dp[n - 2] comes from.
Implementation
Once you get the idea, you should be able to understand the c++ code. We get the dp array as follows: (where dp[i] means that the minimal n such that the answer is i)
dp[0] dp[1] dp[2] dp[3] dp[4]
1 2 3 5 8
What we want to do is just find i such that dp[i] <= n < dp[i + 1]. For example, for n=2, i=1; for n=6, i=3, etc
do {
dp[i] = dp[i - 1] + dp[i - 2];
} while (dp[i++] <= N);
The above code is one way to implement it, although it must not be the most readable code on earth. One could easily achieve the same purpose with two loops.
If you really want to understand why the answer is i - 2, here is a brief explanation. The above loop stops only when n < dp[i++], which is equivalent to n < dp[i]; i++ in c++. But in fact, what we want to find is an element in dp that is smaller than or equal to n, so the value is offset by 1. Also, i++ results in another offset by 1. Therefore, i - 2 would be the answer.
To understand the problem better, let's first list out the answer for small values of N. When there are N players, the maximum number of wins of the winners are as follow:
N 1 2 3 4 5 6 7 8 9
ans 0 1 2 2 3 3 3 4 4
As you can see, for increasing value of N, the answer can only increase. We can now denote dp[i] as the minimum N such that ans >= i, i.e.
dp[0] will be the minimum N such that ans >= 0, which will be N = 1
dp[1] will be the minimum N such that ans >= 1, which will be N = 2
dp[2] will be the minimum N such that ans >= 2, which will be N = 3
dp[3] will be the minimum N such that ans >= 3, which will be N = 5
How to find dp[i] for any i.
As dp[i] denotes the minimum N (number of players) such that ans (number of wins of the winner) is at least i, we will need someone who has won i - 1 match to win one more match. We can do that by matching the player who won i - 1 match with someone who won i - 2 match, this will require the minimum number of players for the winner to win i matches.
Therefore, dp[i] = dp[i - 1] + dp[i - 2]
We need dp[0] = 1 and dp[1] = 2 before calculating because we need 2 elements in dp array to apply the formula above.
Why we need i - 2 in the end
Let's revisit the original question. Now that we have the dp array, how can we find the answer now?
The answer is now same as finding i such that N >= dp[i] and N < dp[i + 1], we can see that there will only be one such i as N can only be between 2 element in the dp array. (refer to the table above)
After the do while loop, the last thing that got executed is dp[i++] <= N which will be false as we exited the loop.
Therefore, we have dp[i - 1] > N and dp[i - 2] <= N now. Now we get the answer i - 2 because it is the only number that satisfy the above requirement.
Why is dp[i - 1] > N?
Because of how i++ works, dp[i++] <= N is actually dp[i] <= N; i++; therefore there will be an extra increment in the end. Therefore dp[i - 1] > N must be satisfied in the end.
Why is dp[i - 2] <= N?
Because in the loop before, we executed the last loop because dp[i++] <= N evaluated to true when i is the final i minus 2, thus continuing the loop.
I believe there are only three ways of understanding this problem (or maybe four if we want to be very creative).
If loser of any match can no longer compete, then above explanation solver the problem and we have to solve recursion for Fibonacci numbers.
In the second way of understanding the statement the player who loses a game can still compete with other contestants. Here we will have a trivial solution, that the winner will be able to win i matches if there are i+1 players at the beginning of the tournament. It is easy to show using recursion that this is true for two players and each next player will win with all previous players.
The third approach comes to my mind from the chess world where in the single round of the tournament all, or all but one player have to play, but in this case I believe there could be some cases where due to problem constraints it would be impossible to create such matching for some round.
And last (very stretched) way is to think that players can play with each other arbitrary number of times. In such case two players can reach any number of wins if they only win every other game.
The last, quoted sentence in Your question also seems to make sense. If we look at i after the process, due to implementation, it will be one greater than the first number greater than the answer, so we should return i-2.
First we want to compute function F, this function takes the number of players as input and its output is the maximum number of games the winner can plays given the requirements of the problem. now I claim F is equivalent with the function P, and function P takes the number of games that the winner played and its output is the minimum number of players that are required to create that many games. i.e.
P(#games) = minimum number of players
F(#players) = maximum number of games
you can consider P like this: maximum number of games that n players can create for winner. from now we work with P
now consider James is the winner and his #games is n. before the last game James played with the Bob according to the requirements of the problem the number of games for James and Bob must be one of the following:
#games James played = n-1 and #games Bob played=n-1 (state 1)
#games James played = n-1 and #games Bob played=n-2 (state 2)
James(#games = n)
/ \
/ \
James(#games = n - 1) vs Bob(#games = n - 2) or (#games = n - 1)
some facts until now
we want to compute P(n) = minimum number of players can create n games or [read it like maximum number of games that those players can create for winner.]
The players in left and right sub trees are disjoint you can easily verify there is not a player who exist in both sub trees.
P(n) = P(n-1) + p(n-2) or P(n) = 2P(n-1) we can verify that 2P(n-1) >= P(n-1) + p(n-2) and we want minimum number of players so we consider P(n) = P(n-1) + p(n-2)
for implementation part, I have N players what is the maximum number of games that the winner can play or what is the minimum number of players that can create M wins? it is actually P function
M = 0 --> 1 players needed
M = 1 --> 2 players needed
M = 2 --> 3 players needed
M = 3 --> 5 players needed (5 players can create at most 3 games for the winner)
.....
when the computed players exceeds the N(number of available players) we should return previous index. for example if the number of players is 4 when we compute the number of players for M=3 it is 5 and 5 > 4 so we must return 2
To be very simple, if you want a winner that is winning N matches, you need a winner that is winning N - 1 matches and a winner that is winning N - 2 matches, as the number of wins from two competitors needs to be smaller or equal than 1.
So the recurrence relation is simply dp[i] = dp[i - 1] + dp[i - 2].

How can I convert this Recursive function to Iterative/Dynamic_Programming?

This recursive program solves the problem of "In how many ways you can score at least 6 in 6 balls/deliveries?"
The details can be found here, https://stackoverflow.com/questions/60117310
This program works fine. Recently I've generalized the program for any amount of Runs with any amount of Balls/deliveries.
My program works fine but it is very slow even for some moderate inputs like Runs = 20, Balls = 10.
I am trying to avoid recursion with Dynamic Programming approach (DP) but couldn't construct the Table correctly since the total runs will not be exactly 20 (in this case) it could be 20 to 25 (considering a 6 when the score was at 19) and balls could be much less than 10 (considering 6, 6, 6, 6 or some other high scoring options).
Any help will be appreciated.
Here is my modified code,
static long count=0;
static int myTarget=20, balls = 10;
public static void waysToDo(int score, int target, List<Short> waySoFar)
{
if(waySoFar.size() > balls ) return; // total balls
if(score >= target)
{
count++;
return;
}
for(short i=0; i<=6; i++) // scoring options per ball
{
waySoFar.add(i);
waysToDo(score+i, target, waySoFar);
waySoFar.remove(waySoFar.size()-1);
}
}
public static void main(String[] args)
{
waysToDo(0, target, new ArrayList<Short>());
System.out.println("Total ways: "+count);
}
Let start from base case.
What happens if we have only one iteration? Every outcome can be achieved only one way, so:
result[0][0] = 1
result[0][1] = 1
result[0][2] = 1
result[0][3] = 1
result[0][4] = 1
result[0][5] = 1
First index is iteration, second is score. Value is number of possible way to achieve it
On second iteration:
0 can be achieved only 1 way.
1 can be achieved two ways: we can score 1 if previous score was 0 or we can score 0 if previous score was 1
2 can be achieved 3 ways: 2 + 0, 1 + 1 and 0 + 2
and so on.
If we generalize we have on step n result be:
0 only 1 way
1 numbers of way to get 1 on step n-1 plus number of ways to get 0 on step n-1
2: result[n-1][0] + result[n-1][1] + result[n-1][2]
m: sum result[n-1][x] where x is between 0 and m
6: you don't need to take into account previous value for 6. So sum result[n-1][x] where x is between 0 and 5.
So you end up with something like
for(int i=1; i<6; i++){
result[0][i]=1;
}
for(int n=1; n<=maxStep; n++){
for(int i=0; i<6; i++){
result[n][i]=0;
for(int j=0; j<5; j++){
result[n][i] += result[n-1][j];
}
}
}
System.out.println(result[maxStep][5]);
If you noticed we only need current and previous, so there is opportunity for memory optimization.

Coin Change - Java Fail to pass example 3

Problem: You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
Example 1:
Input: coins = [1, 2, 5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1
Example 2:
Input: coins = 2, amount = 3
Output: -1
You may assume that you have an infinite number of each kind of coin.
My code:
public int coinChange(int[] coins, int amount) {
Arrays.sort(coins);
int new_amount=amount;
int count_coin=0;
int q=0,r=0,a=0;
int k=coins.length-1;
while(amount>0 && k>=0) {
q = new_amount / coins[k];
count_coin = count_coin + q;
r = new_amount % coins[k];
new_amount=r;
a+=q*coins[k];
k--;
}
if(a==amount){
return count_coin;
}
else{
return -1;
} }
My code work well for given two example. After working with this example I took another test case.
Example 3:Input: coins = [186,419,83,408], amount = 6249
Output: 20
My output: -1
I fail to understand this example. If any one have any idea about this example or any other better algorithm besides mine please share it with me.
I see Coin Change (Dynamic Programming) link. But cannot understand.
I also studied Why does the greedy coin change algorithm not work for some coin sets?
but cannot understand what does it try to say.So I raised this question.
Thank you in advance.
Your code uses greedy approach that does not work properly for arbitrary coin nominals (for example, set 3,3,4 cannot produce answer 6)
Instead use dynamic programming approach (example)
For example, make array A of length amount+1, fill it with zeros, make A[0] = 1 and traverse array for every coin nominal from n-th entry down, choosing the best result for every cell.
Pseudocode:
for (j=0; j < coins.length; j++) {
c = coins[j];
for (i=amount; i >= c; i--){
if (A[i - c] > 0)
A[i] = Min(A[i], A[i - c] + 1);
}
}
result = A[amount] - 1;

Create random String of numbers with specific requirements

I want to create a random String of numbers.
From 0-9.
10 digits long.
First digit cannot be a 0.
One of the digits has to be in the String 2 times and one has to not be there at all.
Or one digit has to be there 3 times, and 2 other digits can not be there at all.
To make this a little bit clearer here are some examples:
1223456789 - 10 digits, no starting zero, one digit (2) is there 2 times and one digit (0) is not there at all
1000345678 - 10 digits, no starting zero, one digit (0) is there 3 times and two digits (2,9) are not there at all
The starting zero is pretty easy caught with startsWith - method, but I have not found a way to check for the rest and I am not particularly good at regex while I am also not entirely sure you can even do this using regex.
For generating the random String itself, I have worked with the Random class as well as RandomStringUtils, both of which don't have restrictions on creating numbers.
Has anyone of you an idea how to achieve this?
Imagine you have 10 sacks, each one of them has its corresponding number embroided on it, from 0 to 9, like this:
.---.._
{------';
}====={
.´ '.
/ .´| \ inside there are
| | | <--- stones with '1' engraved
\: _|_ /
-__ =.´
You also have a coin to flip heads or tails on your hand.
.------..-
´ . /___ `.`.
; / / ´} ; ; ______________________________
: "|'__' // : : / |
' .|/__\. } \ ' ' /_ HEAD! You shall pick 3 |
' /"../ ' ' | stones from the 1st sack! |
; / \/ ͷ ; ; \____________________________/
`_/ ´ ´
" -------´-´
First, we will decide if we will have 3 repeating numbers or 2 repeating numbers. Flip the coin to decide! Tail is 3, Head is 2. We will call this result ͷ.
Remove the sack embroided with 0 (Zero) for a moment.
Now pick ͷ (2 or 3) stones from a random sack of the 9 sacks you have in front of you. Remember, you cannot start with 0, that is why we removed it for a moment! Remove the sack you just picked from the line of sacks, forever. You cannot pick from this one anymore. Put back the 0 (Zero) sack on the line.
Place one of the stones you just picked in front of yourself. Hold ͷ-1 in your hand.
Now repeat this until you have 9 stones in your hand:
Select a random sack, pick ONE stone from it and hold it in your hand. Remove the sack from the
line.
By the end of this process, you will have 9 stones in your hand, one in front of yourself. Shuffle up the ones in your hand. Place them in a straight line in front of yourself, next to the stone that was already in front of you.
You will end with 10 numbers, ͷ repetitions of the same number, won't start with zero, and the remaining sack(s) in front of you are just a side-effect of removing the sacks along the way.
What about trying to make what you want first using the rules then construct the rest.
Here is a possible idea
Using the first rule
One of the digits has to be in the String 2 times and one has to not be there at all.
Create a LinkedList then add the numbers 1 to 9 to it.
Generate a random number between 0-8 (range of the indexes of the list), use the index to retrieve a value out of the list (as in delete it) then add that to the String so the first number isn't 0.
Add 0 back to the list so it can be used somewhere else.
There are now 9 numbers left in the LinkedList with the first number being non zero and already in the String variable as per step 2. From here, generate another random number in the range of the LinkedList indexes. Whatever this number is, remove it from the LinkedList add it twice to the ArrayList.
There are now 8 numbers left in the LinkedList, 1 non zero number in the String. and 3 numbers in the ArrayList for a total of 4 numbers in your sequence that are confirmed to be correct. You have to get another 6 numbers to complete it. So far it would look something like this.
String sequence => "4"
ArrayList beingBuilt => [2, 6, 6]
LinkedList available => [1, 3, 4, 5, 7, 8, 9, 0]
Seems you only can have 10 numbers, loop 6 more times through the LinkedList using a random number to pluck at a random index, delete it from LinkedList add it to ArrayList.
After this the ArrayList should have 9 numbers, you could shuffle it to make it more random then convert it to a String and append to on the end of the sequence. Your rule should be satisfied now.
To make it more random you could manipulate how you pluck out numbers from the LinkedList and also the last rule you had you could change it for that too fairly simply. I used a LinkedList due to faster deletes, I did think about using a set but perhaps more work to handle the random number index being mapped to a number that actually exists in the set.
Just an idea though
The idea is: first generate a random string with 0-9 each once and not starts with 0, then: 1. replace one of the digital will another or 2.replace two digitals with another.
import java.util.Random;
public class Main {
public static void main(String[] args) {
System.out.println(generateRandomString());
System.out.println(generateRandomString());
}
public static String generateRandomString() {
String alphabet = "0123456789";
String result = "";
Random random = new Random();
// build a random string construct will 0-9 and each digital appear once
for (int i = 0; i < 10; i++) {
int index = random.nextInt(alphabet.length());
if (i == 0) { // first cannot be 0
index = random.nextInt(alphabet.length() - 1) + 1;
}
String c = alphabet.substring(index, index + 1);
result += c;
alphabet = alphabet.replace(c, "");
}
return random.nextInt(2) == 0 ? shuffle1(random, result) : shuffle2(random, result);
}
// One of the digits has to be in the String 2 times and one has to not be there at all.
private static String shuffle1(Random random, String result) {
int from = random.nextInt(10);
int to = random.nextInt(9) + 1;
while (from == to) {
to = random.nextInt(9) + 1;
}
result = result.replace(result.substring(to, to + 1), result.substring(from, from + 1));
return result;
}
// One digit has to be there 3 times, and 2 other digits can not be there at all
private static String shuffle2(Random random, String result) {
int from = random.nextInt(10);
int to1 = random.nextInt(9) + 1;
int to2 = random.nextInt(9) + 1;
while (from == to1) {
to1 = random.nextInt(9) + 1;
}
while (from == to2 || to2 == to1) {
to2 = random.nextInt(9) + 1;
}
result = result.replace(result.substring(to1, to1 + 1), result.substring(from, from + 1));
result = result.replace(result.substring(to2, to2 + 1), result.substring(from, from + 1));
return result;
}
}
If you're not too concerned about performance then the simplest thing would be to just generate random lists of numbers and check them against your conditions until you get one that works. Best to do the filtering as numbers and then convert to a string at the end rather than using regular expressions.
public String getRandomInts() {
Random random = new Random();
int[] ints;
do {
ints = random.ints(10, 0, 10).toArray();
} while (!meetsCriteria(ints));
return Arrays.stream(ints).mapToObj(String::valueOf).collect(Collectors.joining(""));
}
private boolean meetsCriteria(int[] ints) {
if (ints[0] == 0) {
return false;
}
if (frequency(ints, 0) == 1
&& frequency(ints, 1) == 8
&& frequency(ints, 2) == 1) {
return true;
}
if (frequency(ints, 0) == 2
&& frequency(ints, 1) == 7
&& frequency(ints, 3) == 1) {
return true;
}
return false;
}
private int frequency(int[] ints, int count) {
return (int) IntStream.range(0, 10)
.filter(n1 -> Arrays.stream(ints).filter(n2 -> n1 == n2).count() == count)
.count();
}

Coin toss simulation/game in Java

I'm currently doing a course in computer science which is technically for beginners, but I feel all the assignments they are giving me are more complicated than I can handle.
This assignment asks me to make a coin toss simulation. Three people play the game and each of them has specific requirements to win:
One wins if there are 2 results head and the total number of tosses
is even
One wins if there are 2 results tails and the total number of tosses is even
One wins if there are 2 results tails OR heads and the total number of tosses is odd
What I should do is run an experiment 300 times. Each time I should determine who of the three won and how many times. And I'm really stuck. I barely have any code but I do have an very basic idea of what the code should be like, but I can't put it into Java language.
For my assignment, I need to display the binary sequence that caused a person to win.
My idea:
Initialize a counter (1, 2, 3) for every person so that I can keep track of how many times they win
Initialize a head count and a tails count to keep track of the randomly generated sequence
Use a for loop for practically the whole experiment. There should be an outer loop that defines the experiment should be run 300 times and the inner loop should contain the if statements that check who has won. There should be a counter in every if statement, so that I can update it for every person. And I need a System.out.println(); to print every single result of the experiment.
Print the final outcome of the experiment, using the previously determined counters
EDIT:
I've tried to change what everyone said and it does look better now, thanks! But it's still not doing what it's supposed to do and I wonder why. I run the code and I only get one output; not the 300 times I want it to run. Furthermore, the counters at the end don't hold the information about who has won, they reset every single time. And sometimes two people win, while that should not be possible. Could anyone clarify this?
EDIT:
This is another update of the code. I believe it does run 300 times now! A problem now is the output. Sometimes it says; 1 Bernie wins, while you obviously need at least 2 results for Bernie to win. Also, it says 1 Penny wins, while that also shouldn't be possible. Did I mess something up in my if statements?
import java.util.Random;
public class Assignment3e
{
public static void main(String[] args)
{
int counter1 = 0;
int counter2 = 0;
int counter3 = 0;
Random coin = new Random();
for(int i = 0; i <= 300; i++){
int headCount = 0;
int tailsCount = 0;
for(int coinToss = 0; coinToss <= 3; coinToss++){
int random = (int) (Math.random() * 6) + 1;
String binary = Integer.toBinaryString(random);
boolean result = coin.nextBoolean();
if(result){
headCount++;
}
else{
tailsCount++;
}
if(headCount == 2 && binary.length() % 2 ==0){
//Amy wins
counter1 = counter1 + 1;
System.out.println(binary + " Amy wins.");
}
else if(tailsCount == 2 && binary.length() % 2 == 0){
//Penny wins
counter2 = counter2 + 1;
System.out.println(binary + " Penny wins.");
}
else if(headCount == 2 || tailsCount == 2 && binary.length() % 2 != 0){
//Bernie wins
counter3 = counter3 + 1;
System.out.println(binary + " Bernie wins.");
}
}
}
System.out.println("Amy wins " + counter1 + " times.");
System.out.println("Penny wins " + counter2 + " times.");
System.out.println("Bernie wins " + counter3 + " times.");
}
}
You almost got it right.
This part is not relevant anymore since OP add a requirement in comments.
Your second for loop only need to run a maximum of 3 times as there will be at least 2 heads or 2 tails, not 10.
Edit: you can do it with a maximun of 2 tosses: if there is 1 head and 1 tail, the winner is the 3rd player (Bernie)
Now, on each iteration, you can draw a random decimal number, between 0 and 1 and assume if it's over 0.5 it's a head so you increment the headCount, else you increment the tailCount. Then you can perform the test on the counters (and the number of tosses).
It's easier than using a binary String.
Edit:
To answer your comment:
Look where you initialized the headCountand tailCount. Remember that once one has won, those counters must be reset.
As it's homework, I won't post code :)
Edit:
OP jsut add a comment stating he need to print the sequence that lead to the result of each game.
We assume a binary 1 is a head, and a 0 is a tail. You need to toss the coin 3 times to know the sequence if Bernie wins. So the integer value random which is converted in binary string only need to be made of 3 bits (1 bit = 1 toss).
random can only take values between 0 and 7.
As you get all values in one shot, you don't need the coinToss for loop anymore. All you need to do is to check if the beginning of the binary string matches any win pattern (11 for 2 heads, 00 for 2 tails, else Bernie wins)
So there are a couple of things I'm noticing here:
You don't update headCount or tailCount anywhere. This should be what you're using to keep track of the number of coin flips.
When you go back to reuse these in subsequent loops, be sure to zero them out again.
You're using a very wide range for your result, when a simple nextBoolean would be all that needs to suffice. You could use it as this in your loop:
boolean result = coin.nextBoolean(); // this renames dice to coin
if(result) {
headCount++;
} else {
tailCount++;
}
The total number of tosses is always the current iteration's current value (plus 1). So, in your case, you could simply replace sum with j, but you'd want to give it a more meaningful name, like coinTosses instead.
If you're using a Random() object anyways for the coin nextBoolean(), why not replace the int random = (int) (Math.random() * 6) + 1; with int random = coin.nextInt([range here])?

Categories