Java code stuck in infinitely repeating while loop - java

I have some code that shuffles a deck of cards by assigning randomly chosen cards from a 2D array cards into an ArrayList deck, but when I run the code it gets stuck in an infinite loop.
It was working fine at first but seemed to randomly stop working with little change to the code.
cards is a 13 x 4 array with a different card in each position.
ArrayList<String> deck = new ArrayList<String>();
for (int i = 0; i < 52; i++) {
int v = 0;
int s = 0;
Boolean notInDeck = false;
while (!notInDeck) {
v = rand.nextInt(13);
s = rand.nextInt(4);
if (!deck.contains(cards[v][s])) {
notInDeck = true;
deck.add(cards[v][s]);
}
}
}
I tried adding outputs at different points to try and track what was happening
ArrayList<String> deck = new ArrayList<String>();
for (int i = 0; i < 52; i++) {
System.out.println("1");
int v = 0;
int s = 0;
Boolean notInDeck = false;
while (!notInDeck) {
System.out.println("2");
v = rand.nextInt(13);
s = rand.nextInt(4);
if (!deck.contains(cards[v][s])) {
System.out.println("3");
notInDeck = true;
deck.add(cards[v][s]);
}
System.out.println("4");
}
System.out.println("5");
}
System.out.println("6");
There are no error messages.
The output is fine for the first bunch of run-throughs, being 1 2 3 4 5 1 2 3 4 5, but ends up infinitely repeating 2 4 2 4 2 4...
It should be like 1 2 3 4 5 1 2 3 4 5 then maybe sometimes 1 2 4 2 3 4 5 when it repeats a set of random numbers.
Here is my code for the cards 2D array.
String[][] cards = new String[13][4];
String suit = " ";
String value = "";
for (int i = 0; i < 13; i++) {
for (int j = 0; j < 4; j++) {
if (j == 0) {
suit = "C";
} else if (j == 1) {
suit = "H";
} else if (j == 2) {
suit = "S";
} else if (j == 3) {
suit = "D";
}
if (i == 0) {
value = "A";
} else if (i == 10) {
value = "J";
} else if (i == 11) {
value = "Q";
} else if (i == 12) {
value = "K";
} else {
value = Integer.toString(i+1);
}
cards[i][j] = value;
}
}
Edit:
I realised the issue was with this line
cards[i][j] = value;
It should be
cards[i][j] = value + " " + suit;

You are making your life harder.
In real life, you are not taking gazillion of cards and you are not randomly picking cards until you complete full 52 cards deck. In fact, you start with 52 cards and you suffle them. Do the same here
Create collection of 52 cards
Shuffle that collection (eg. with Collections.shuffle)
While this is simply linear operation, your solution is indeterministic.

It shouldn't run indefinitely unless you are having an unlucky day or have initialized cards array with wrong values.
So, this is what happening. Since you are using a random guess to put a card into the deck, with each attempt it's harder and harder for random generator to find, so to say, a card that was not placed in the deck yet. At the of the day you will have more and more attempts to place last cards correctly. The number of those attempts could reach hundreds and even thousands.
I have added a couple of lines to your code and visualized the problem on Ideone.
ArrayList<String> deck = new ArrayList<String>();
HashMap<Integer, Integer> guesses = new HashMap<>();
for (int i = 0; i < 52; i++) {
int guess = 0;
int v = 0;
int s = 0;
Boolean notInDeck = false;
while (!notInDeck) {
v = rand.nextInt(13);
s = rand.nextInt(4);
guess++;
if (!deck.contains(cards[v][s])) {
notInDeck = true;
deck.add(cards[v][s]);
guesses.put(i, guess++);
}
}
}
for (Map.Entry<Integer, Integer> entry: guesses.entrySet()) {
System.out.printf("%2s : %s\n", entry.getKey(), entry.getValue());
}
If you execute the code several times, you will clearly see the pattern—the number of guesses grows significantly at the end.

Related

Some test cases not running but some are in terms of probability

I have a program in which it rolls five dice and assigns a hand to the rolls. i.e. nothing, a pair, two pair, three of a kind, full house, four of a kind, five of a kind. The code runs 1000000 times and gives percentage chances for each roll. Below I have attached general percentages my code should output near:
Case 1, None alike, is 0.092533
Case 2, One pair, is 0.462799
Case 3, Two pair, is 0.231789
Case 4, Three of a kind, is 0.154192
Case 5, Full house, is 0.038595
Case 6, Four of a kind, is 0.019316
Case 7, Five of a kind, is 0.000776
However my code gives the following output:
Case 1, None alike is 0.093099
Case 2, One pair is 0.384768
Case 3, Two pair is 0.076921
Case 4, Three of a kind is 0.15485
Case 5, Full House is 0.270349
Case 6, Four of a kind is 0.019281
Case 7, Five of a kind is7.33E-4
I don't understand why my programs percentages are off for one pair, two pairs, and full house. I have gone through and tested my logic but it is sound from what I have seen. Originally, my one pair was correct but my two pair was 0.0. Below is my original logic which causes the two pair to be 0 and my pair to be correct.
I, however, changed it to the current logic to get the current output. I would appreciate another set of eyes to take a look and let me know if they could catch something. Below is my code:
Change 1 :
if (hand < 6) {
int counter3 = 0;
int counter2 = 0;
for (int j = 0; j < length; j++) {
if (counts[j] == 3) {
counter3++;
}
if (counts [j] == 2) {
counter2++;
}
}
if (counter3 == 1 && counter2 == 1) {
hand = 5;
}
}
Change 2:
if (hand < 4) {
int newcounter = 0;
for (int j = 0; j < length; j++) {
if (counts[j] == 2) {
newcounter++;
}
}
if (newcounter==2) {
hand = 3;
}
if (newcounter == 1) { hand = 2; }
}
Change 3 :
Please remove if( hand < 3) part of code.
Updated my answer. In your code the counter variable (when you're trying to check "full house") was becoming 2 due to two pairs (ex : counts = 020200) not due to full house (ex: counts = 300200). Hence, it wasn't counting the two pairs in the following code where it was supposed to because hand was already becoming 5, so it didn't go inside any other if parts below although it was supposed to go inside if(hand<3). Hope it will fix the issue.
See comment in code
if (hand < 4) {
int newcounter = 0;
boolean firstp = false;
boolean secondp = false;
for (int j = 0; j < length; j++) {
firstp = false;
secondp = false;
if (counts[j] == 2) {
firstp = true; <---- THIS
}
if (counts[j] == 2) {
secondp = true; <---- AND THIS will always hit together as j never changes from the first if to second if
// break;
}
}
if (firstp && secondp) {
hand = 3; <---- firstp always equal to secondp, I would be surprised to see hand ever = 2
}
}
I modified your code. The original logic is a little bit messy. I made some slight improvement but hopefully better. Not perfect though.
import java.util.*;
public class PokerDice {
public static void main(String[] args) {
double none = 0;
double pair = 0;
double twop = 0;
double threep = 0;
double full = 0;
double fourp = 0;
double fivep = 0;
for (int i = 0; i<=1000000; i++) {
int [] rolls = new int[5];
for (int j = 0; j < 5; j++) {
rolls[j] = (int)(1 + (Math.random()*(6)));
}
int[] counts = Counts(rolls);
boolean has_two = false;
boolean has_three = false;
none++;
for (int j = 0; j < counts.length; j++) {
if (counts[j] == 4) {
fourp++;
none--;
break;
}
if (counts[j] == 5) {
fivep++;
none--;
break;
}
if (counts[j] == 3) {
has_three = true;
if (has_two) {
full++;
pair--;
break;
} else {
none--;
threep++;
}
}
if (counts[j] == 2) {
if (has_two) {
twop++;
pair--;
break;
}
else if (has_three) {
full++;
threep--;
break;
} else {
has_two = true;
pair++;
none--;
}
}
}
}
fivep/=1000000;
fourp/=1000000;
full/=1000000;
threep/=1000000;
twop/=1000000;
pair/=1000000;
none/=1000000;
System.out.println("Poker Dice Probability Calculator");
System.out.println("Running 1,000,000 trials");
System.out.println();
System.out.println("Case 1, None alike is "+none);
System.out.println("Case 2, One pair is "+pair);
System.out.println("Case 3, Two pair is "+twop);
System.out.println("Case 4, Three of a kind is "+threep);
System.out.println("Case 5, Full House is "+full);
System.out.println("Case 6, Four of a kind is "+fourp);
System.out.println("Case 7, Five of a kind is"+fivep);
}
public static int[] Counts (int [] rolled) {
int one = 0;
int two = 0;
int three = 0;
int four = 0;
int five = 0;
int six = 0;
int len = rolled.length;
int [] rolltimes = new int[6];
for (int i = 0; i<len; i++) {
if (rolled [i] == 1) {
one++;
}
else if (rolled [i] == 2) {
two++;
}
else if (rolled [i] == 3) {
three++;
}
else if (rolled [i] == 4) {
four++;
}
else if (rolled [i] == 5) {
five++;
}
else if (rolled [i] == 6) {
six++;
}
}
rolltimes[0] = one;
rolltimes[1] = two;
rolltimes[2] = three;
rolltimes[3] = four;
rolltimes[4] = five;
rolltimes[5] = six;
return rolltimes;
}
}

How can i use a nested loops to help identify if i have 2 different matching pairs of dices

So I just had a lesson on loops and nested loops. My professor said that nested loops can help us do tasks such as knowing if we rolled 2 different matching pairs with 4 dices (4242) I'm a bit confused on how that would work.
So I started to work it out and this is what I was able to create.
public boolean 4matchDice(String dice){
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
}
}
I used boolean as the return as it will tell us whether or not we have 2 different matching pairs.
Thing is, what do I put in the the loops? That's what's confusing me the most.
Here's a solution I came up with, seems to be returning the correct outcome for all the test cases I ran.
public static boolean matchDice(String dice) {
char[] diceArray = dice.toCharArray();
int pairs = 0;
for (int i = 0; i < 4; i++) {
for (int j = i + 1; j < dice.length(); j++) {
if (diceArray[i] == diceArray[j]) {
diceArray[i] = 'X';
diceArray[j] = 'Y';
pairs++;
}
}
}
return (pairs > 1);
}
If you're only comparing two sets with two dice each, this is enough:
public boolean match4Dice(int first, int second, int third, int fourth) {
if ((first == third && second == fourth) || (first == fourth && second == third)) {
return true;
}
return false;
}
But if you're comparing 2 sets with any number of dice, the following algorithm would suit you better.
public boolean matchDice(String firstDiceSet, String secondDiceSet) {
// validate input, string must contain numbers from 1 - 6 only.
// lenghts of strings firstDiceSet & secondDiceSet must be equal
// works for any number of dice in each set.
// The dice only match if all numbers in the firstDiceSet all present in the secondDiceSet also.
// Let us count the matching numbers to check if this true.
int numberOfMatches = 0;
for (int i = 0; i < firstDiceSet.length(); i++) {
for (int j = 0; j < secondDiceSet.length(); j++) {
if (firstDiceSet[i] == secondDiceSet[j]) { // and not used
// increment number of matches
// mark secondDiceSet[j] as used, so that you do not count the same match twice.
// account for cases where firstDiceSet = "33" and the secondDiceSet = "35"
}
}
}
// your dice set match if the following condition is true
return (numberOfMatches == secondDiceSet.length());
}
Hi I just coded up a solution that will take "4242" as an input, although sindhu_sp's method is more practical i believe. I just wanted to show you another example to help your learning of java!
public static boolean fourMatchDice(String dice){
int match = 0;
for (int i = 0; i < dice.length(); i++){
for (int j = i+1; j < dice.length(); j++){
if (dice.toCharArray()[i] == dice.toCharArray()[j]){
System.out.println("does " + dice.toCharArray()[i] + " = " + dice.toCharArray()[j]);
match ++;
}
}
}
if(match == 2) *EDIT* //Change to (match >= 2) if 4 of the same pair is allowed.
return true;
return false;
}
public static void main(String[] args) {
System.out.println(fourMatchDice("4242"));
}
output:
does 4 = 4
does 2 = 2
true

java fill 2D array with specific method

I have an 2D array(matrix) and a Integer n.n is full square
for example if n equals 16 fill matrix like this.
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
what can I do?
public static void main(String args[]) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter the dimension of the matrix : ");
int dimension = Integer.parseInt(br.readLine());
System.out.print("Enter the number of elements : ");
int n = Integer.parseInt(br.readLine()); // total number of elements to be filled
n = n/dimension; // Get the number of rows and columns
if(n % dimension != 0){
// Not a Square matrix
}
int circularArray[][] = new int[n][n];
int k = 1, c1 = 0, c2 = n - 1, r1 = 0, r2 = n - 1;
while (k <= n * n) {
for (int i = c1; i <= c2; i++) {
circularArray[r1][i] = k++;
}
for (int j = r1 + 1; j <= r2; j++) {
circularArray[j][c2] = k++;
}
for (int i = c2 - 1; i >= c1; i--) {
circularArray[r2][i] = k++;
}
for (int j = r2 - 1; j >= r1 + 1; j--) {
circularArray[j][c1] = k++;
}
c1++;
c2--;
r1++;
r2--;
}
/* Printing the Circular matrix */
System.out.println("The Circular Matrix is:");
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.print(circularArray[i][j] + "\t");
}
System.out.println();
}
}
Here is a tiny example how this could look like.
What is actually happening is written as comments.
public class TestArray {
// A simple enum for each direction
public enum Mode {
right, down, left, up;
}
public static void main(String[] args) {
final int size = 4; // We set a fixed size for the square
int[][] arr = new int[size][size]; // create the array from the size
// Running vallues
// i and j to refer to the array.
// val holds the current value to be inserted
// circle holds how often we are going up. Each time we go up it´s increased by one
// In the end this should reduce the amount of steps we do to not override
// already assigned values.
int i = 0,j = 0, val = 1, circle = 0;
Mode runningMode = Mode.right; // We start by going to the right.
while(size*size >= val) { // loop until we reached the last value
arr[j][i] = val++; // Assign the value and increase the value by one afterwards.
// We go right.
if(runningMode == Mode.right) {
// we reached the last assignable item.
// subtract one to not get an index out of bound,
// subract the variable trips that is used to get the last item for the inner circle
if(i==arr.length-1-circle) {
// We are going down now and increase j
runningMode = Mode.down;
++j;
} else {
// go on going right.
++i;
}
} else if(runningMode == Mode.down){
// we reached the last assignable item.
// subtract one to not get an index out of bound,
// subract the variable trips that is used to get the last item for the inner circle
if(j==arr.length-1-circle) {
// We are going left now and decrease i
runningMode = Mode.left;
--i;
} else {
// go on going down.
++j;
}
} else if(runningMode == Mode.left){
// we reached the last assignable item.
// add the variable trips that is used to get the last item for the inner circle
if(i==0+circle) {
// We are going up now and decrease j
// Simultaniosly we are about to end our next circle, so we increase circle
runningMode = Mode.up;
++circle;
--j;
} else {
// go on going left.
--i;
}
} else if(runningMode == Mode.up){
// we reached the last assignable item.
// add the variable trips that is used to get the last item for the inner circle
if(j==0+circle) {
// We are going right now and increase i
runningMode = Mode.right;
++i;
} else {
// go on going up.
--j;
}
}
}
// Print the result
for(int[] a : arr) {
for(int b : a) {
System.out.print(b + "\t" );
}
System.out.println();
}
}
}

How to get the first value in array, then second and so on?

I generate and store numbers in an array (these numbers are 1 to 4) I want to have a loop that checks if the first number is 1 and if it is do action, if its not move on to 2 and so on..
final ArrayList<Integer> listInteger = new ArrayList<>();
final int[] NumbersArray = new int[20];
for (int generatedNumbers = 0; generatedNumbers < 2 + temp; generatedNumbers++) {
value = (int) (Math.random() * 4 + 1);
NumbersArray[generatedNumbers] = value;
I tried
for(Integer i : NumbersArray) {
if (i == 1) {
System.out.println("1");
Color1.setBackgroundColor(Color.parseColor("#FF7F7500"));
}
else if (i == 2) {
else if (i == 2) {
System.out.println("2");
Color2.setBackgroundColor(Color.parseColor("#FF0000"));
}
for(Integer i : listInteger){
if(i == 1){
// do smth
break; // quit loop you found your number 1
}
}
This is how you loop over it.

poker dice in java - not giving scores properly

I want to create a poker dice game in java, and when the player rolls the dice, I want the program to tell the results and the current score. However, something is wrong. It isn't giving me properly the score. For example, I changed the the Math Random algorithm to always give me always (1,1,1,1,1), so the result would be 50. Unfortunately,it is giving me 0. Can I have some help please? Thanks.
This is my code:
public class DiceGame {
public static int [] rollDice() {
int [] diceSide = new int[5];
Random diceRoller = new Random();
for (int i = 0; i<diceSide.length; i++) {
int roll = diceRoller.nextInt(1) + 1;
diceSide[i] = roll;
}
System.out.print(diceSide[0] + "" + diceSide[1] + "" + diceSide[2] + "" + diceSide[3] + "" + diceSide[4]);
return diceSide;
}
public static int getResult(int[] dice) {
int resValue = 0;
for (int i = 0; i < dice.length; i++) {
if (dice[i] == 5) {
resValue = 50;
} else if (dice[i] == 4) {
resValue = 40;
} else if (dice[i] == 3) {
resValue = 30;
}
}
System.out.print(resValue);
return resValue;
}
public static void main(String[] args) {
int player1=0;
int player2;
int player3;
int player4;
int player5;
player1 += getResult(rollDice());
}
}
Math.Random returns a value thats between 0 and 1.
You have to multiply this value with the Max-Value you want to recieve - 1 and add +1 to the whole thing. Don't forget to cast this whole thing to (int).
It should look something like this:
(int) (Math.Random(5) + 1)
This way, you're getting values between 1 and 6.
In rollDice you take a value from java.util.Random. However, the upper limit is excluded, so you always end up with one by doing diceRoller.nextInt(1) + 1.
An array of integers is good for representing multiple dice, so if that's what you want, you could use diceRoller.nextInt(6) + 1 to set the value of each dice. If you want a single dice, you only need a single integer variable.
You are doing something different. You are creating random numbers from 0 to the max value of an integer.
diceRoller.nextInt(1)
This create a random number from 0 to 1. So it's rare you get 5 times 1. If you wanted to mock it, you should have put one as an assignment
Then, because this piece of code:
for (int i = 0; i < dice.length; i++) {
if (dice[i] == 5) {
resValue = 50;
} else if (dice[i] == 4) {
resValue = 40;
} else if (dice[i] == 3) {
resValue = 30;
}
}
Means that if the last of the dice[i] values are 3, 4 or 5, it gets a new value. What I think you were trying to do is this (adding ten times the value of the dice for the whole array):
int resValue = 0;
for (int i = 0; i < dice.length; i++) {
resValue += dice[i] * 10;
}
In the last case, if all the 5 direRoll results are 1, you would get 50.

Categories

Resources