Comparing poker hand in java - java

I am working on a poker game. So far I am stuck on comparing poker hands. I sort of have an idea on how to do it but I am not sure what is wrong with my code. Can somebody please point out what's wrong?
So let me give a brief description of what my code is doing.
My other part of the program will go through the cards in my hand and list the frequency of a card value in an array.
h = Hearts
c = Clubs
d = Diamonds
s = Spades
d4 = 4 of Diamond
So let's say in my hand I have
c3, h4, d4, s4, 2d
I will call the other part of my program to read the cards in my hand and return a tally array. The tally array for my hand above will be [0,0,1,1,3,0,0,0,0,0,0,0,0,0] So pretty much what this array is saying is that my hand has one 2, one 3 and three 4.
Now here is my method on trying to find Three of a Kind, it should return false for full house (which is three of a kind plus a pair)
public boolean hasThreeOfAKind() {
int [] temp;
temp = this.getCounts();
for (int i = 0; i< temp.length; i++){
if (temp [i] == 3 ){
for (int j = 0; j < temp.length ; j++)
if ( temp [j] != 2){
return true;
}
}
}return false;
So what I am trying to do above is first, I run through the array, and if if there is any 3. If there is a 3, I run through the array again and see if there is a 2. and if there is not a 2, then I know it is three of a kind. If there is a 2, then it is full house and I should return false. I think my logic is correct, but there is something wrong with my code.
And the second hand that I am having trouble is how to determine if my hand has EXACTLY one pair. It only return true if there is only one pair. Return false if there are two pairs etc.
public boolean hasOnePair() {
int [] temp;
temp = this.getCounts();
for (int i = 0; i< temp.length; i++){
if (temp [i] == 2 ){
return true;
}
}return false;
For this one, I am thinking of sort the value in the array either in descending or ascending order. If I chose the descending order, I first read the array and see if there is a 2, then I could scan the next one and see if the next value after the first 2 is also a 2. If there is another 2, then it would return false.
Can somebody please take a look at my code and point out what's wrong? Thank you very much.

Why are you working with such low level primitives? Is there a reason you're not using a full fledged Card class? Your code would be much simpler.
class Card
enum Value {
TWO,
...
ACE
};
enum Suit {
SPADES,
...
CLUBS
};
private Suit suit;
private Value value;
public Card(Suit suit, Value value) {
this.suit = suit;
this.value = value;
}
}
public class Hand {
private final List<Card> cards;
public Hand(Card first, Card second, Card third, Card fourth, Card fifth) {
// add to cards list.
// sort ascending by value
}
public boolean hasThreeOfAKind() {
for (int i = 0; i < 3; i++) {
Value firstValue = cards.get(i).getValue();
Value secondValue = cards.get(i+1).getValue();
Value thirdValue = cards.get(i+2).getValue();
if (firstValue == secondValue && secondValue == thirdValue) {
return true;
}
}
return false;
}
}
This doesn't directly answer your question, but in my opinion this sort of code is much more readable and maintainable and will be easier to debug than one involving only integers. Java isn't C and you don't really gain much by treating it like C.

In your hasThreeOfAKind() you have the following error:
for (int j = 0; j < temp.length ; j++)
if ( temp [j] != 2){
return true;
}
}
This will return true the first time it finds a non-2 j (which will be statisfied with the 3 you just checked above it -- thus returns true for a full house. You need instead:
boolean foundTwo = false;
for (int j = 0; j < temp.length ; j++)
if ( temp [j] == 2){
foundTwo = true;
}
}
if (!foundTwo) {
return false;
}
Similarly for the other: you need to check if you find another 2 that is different from the one you already found:
for (int i = 0; i< temp.length; i++) {
if (temp [i] == 2 ){
boolean foundAnother = false;
for (int j = 0; j< temp.length; j++) {
if (i != j && temp [j] == 2 ){
foundAnother = true;
}
}
if (!foundAnother) {
return true;
}
}
}
return false;
Another thing you could do is have filters for each recognized hand: a pair-filter, a three-filter, a full-house-filter, etc. and run all those filters through the hand. Don't worry if there is a better (higher value) match, just see which filters return true (found the pattern they were looking for) and select the highest point value among the ones that passed

In your threeOfAKind method, the second for loop will only get executed once unless the first number stored in your array is a 2, it should look more like this:
public boolean hasThreeOfAKind() {
int [] temp;
temp = this.getCounts();
for (int i = 0; i< temp.length; i++){
if (temp [i] == 3 ){
for (int j = 0; j < temp.length ; j++)
if ( temp [j] == 2){
return false;
}
}
}
return true;
}
in the above code, the first time it hits a pair it realizes that the hand is a full house instead of a three of a kind, and returns false.
and as for your other method hasOnePair() it should look more like:
public boolean hasOnePair() {
int [] temp;
temp = this.getCounts();
int count = 0;
for (int i = 0; i< temp.length; i++){
if (temp [i] == 2 ){
count++;
}
}
return count == 1;
}

Look for the number of each similar card and make arrays. SO cards{1,1,2,2,2,5,7} (lets ignore the suits for now) will map to (3,2,1,1) i.e a full house you can check the second array easily

I'm helping my son with a similar problem for his Java Course at college (the course I used to teach) and this is what I would suggest.
First sort your cards from lowest to highest 2 to Ace regardless of suit.
Then do comparing.
If card[0]==card[3] or card[1]==card[4], you have 4 of a kind, ignore next 2 lines.
If card[0]==card[2] or card[1]==card[3] or card[2]==card[4], you have 3 of a kind, ignore the next line.
If card[0]==card[1] or card[1]==card[2] or card[2]==card[3] or card[3]==card[4], you have a pair.

Related

Java: How to compare every two elements in an array once?

This is an assignment we have and I'm a little bit lost with his directions. He tells us to write a program with a method called equals to compare the salary of EVERY TWO EMPLOYEES in the array (I've already created this) and prints the SSN of every two employees that have the same salary in pairs. He made a disclaimer that
the code should only compare two different employees and only once. Every two different employees are compared only once. The array is size 10.
I've already asked multiple peers on what he meant but they are also confused. This is what I have:
For the Class:
public boolean equals(Employee e)
{
boolean status;
if(salary == e.getSalary())
{
status = true;
}
else
status = false;
return status;
}
For the Demo:
for(int i = 0; i < employees.length; i++)
{
for(int j = i+1; j < employees.length; j++)
{
if(employees[i].equals(employees[j]))
System.out.println(employees[i].getSsn() + "\t" +
employees[j].getSsn());
}
}
It compiles, however it skips comparing index 0 and index 1. Any help is appreciated.
Initialize j with int j = i+1 instead of int j = i+2

Java 2D array encirclement

I am tasked to make a program which returns true if in a 2D array 1-s encircle 0-s.
I tried something like this, but i cant find the right solution.
public boolean checkGameState(){
for(int i=0;i<fields.length;i++){
for(int j=0;j<fields.length;j++){
if(fields[i][j]!=0){
if(row(i,j){
return true;
}
}
}
}
return false;
}
private boolean row(int a, int b){
int checkI=a;
int checkJ=b;
while(fields[checkI][checkJ]==1){
checkJ++;
}
while(fields[checkI][checkJ]==1){
checkI++;
}
while(fields[checkI][checkJ]==1){
checkJ--;
}
while(fields[checkI][checkJ]==1){
checkI--;
}
return a==checkI && b==checkJ;
}
The 2D array looks something like this:
111100
100100
100101
111100
001100
For this array the method should return true.
The easiest way might be to use a flood fill algorithm to eliminate all the zeros that are not encircled by ones, and then checking whether there are any left.
First, put all the zeros directly on the "fringe" of the 2D array into a queue. Then, use the flood fill algorithm to turn all of those into a different number (e.g., 2), and add the nodes next to them to the fringe set (either diagonally or only direct neighbours). Repeat until there are no more nodes in the fringe. Finally, check whether there are any more zeros in the array. If so, those were not connected to the fringe region and thus had to be "encircled" by ones.
// test data set up
int[][] data = {{1,1,1,1,0,0},
{1,0,0,1,0,0},
{1,0,0,1,0,1},
{1,1,1,1,0,0},
{0,0,1,1,0,0}};
int N = data.length, M = data[0].length;
// create queue of zeros on the "fringe"
Queue<int[]> fringe = new LinkedList<>();
for (int i = 0; i < N; i++) {
if (data[i][0 ] == 0) fringe.add(new int[]{i,0 });
if (data[i][M-1] == 0) fringe.add(new int[]{i,M-1});
}
for (int j = 0; j < M; j++) {
if (data[0 ][j] == 0) fringe.add(new int[]{0 ,j});
if (data[N-1][j] == 0) fringe.add(new int[]{N-1,j});
}
// do flood fill until no more zeros reachable
while (! fringe.isEmpty()) {
int[] next = fringe.poll();
int i = next[0], j = next[1];
data[i][j] = 2;
for (int di = -1; di <= 1; di++) {
for (int dj = -1; dj <= 1; dj++) {
try {
if (data[i+di][j+dj] == 0) fringe.add(new int[]{i+di, j+dj});
} catch (ArrayIndexOutOfBoundsException e) {}
}
}
}
// check for remaining zeros
boolean encircled = false;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
System.out.print(data[i][j]);
encircled |= data[i][j] == 0;
}
System.out.println();
}
System.out.println(encircled);
Example output:
111122
100122
100121
111122
221122
true
The complexity should be on the order of O(NxM), since each of the NxM nodes can only appear once in the queue (plus a bit of overhead for constructing the queue and finding remaining zeros).
Please note that I have assumed that you need rectangle shape surrounding
You need to find sequences for 3 or more 1 in one row.
xx1111xx // x means any number
For each sequence check if there is sequence of the same length 2 or more rows lower.
xx1111xx
xxxxxxxx
xx1111xx
For each "pair" of sequences check if they are connected with 1 on the edges.
xx1111xx
xx1xx1xx
xx1111xx

What is wrong with this method using an int[][]?

This method is supposed to return true if there is more than one 1 in a column of a 2D array, yet it doesn't work. I can't figure out what's wrong with it so I thought I'd get some expert opinions.
Example:
10010
01001
10100
will return true because there are 2 ones in the first column.
Here is the code
public static boolean isVert(int[][] x) { //checks for more than one 1 in columns
int count = 0;
boolean break2 = false;
boolean check = false; //false means no 2 (or more) queens in same column
for (int i = 0; i < x.length; i++) {
count = 0;
for (int j = 0; j < x[i].length; j++) {
if (x[i][j] == 1) {
count++;
}
if (count > 1) {
break2 = true;
check = true;
break;
}
}
if (break2) {
break;
}
}
return check;
}
You break at the first occurance of 1 in whole array, which is probably not the expected result.
Explanation of how your code works:
loop until counter i is less than length of array (number of rows in array)
loop until counter j is less than length of i-th row (number of columns or elements in array)
check if element on i-th row and j-th column is 1, if true, increase variable count by one
if count is greater than 1 (this means it has to be 2 or greater) set break2 and check to true, break
if break2 is true (which is as count is > 2 and first loop breaks), break this loop too:
this happens in 1st row of your example table
end of loops, return check (which is true because 1st row contains 2 ones)
The problem in your code is that you break when you find your first row that satisfies your condition, but you do not (necessarily) check all the rows in given array.
I have corrected the code for you, hopefully it works (untested)
public static boolean isVert(int[][] x) { //checks for more than one 1 in columns
int count = 0;
for (int i = 0; i < x.length; i++) {
int rowCount = 0;
for (int j = 0; j < x[i].length; j++) {
if (x[i][j] == 1) {
rowCount++;
}
if(rowCount > 1) {
count++;
break;
}
}
}
// returns true if count of lines containing 1 equals length of array,
// if not, returns false
return count == x.length;
}
Start of by improving your naming convention. Your code has many variables named by their contents, instead of named by how they are used. For example:
boolean check = false; // false means no two queens in the same column.
instead of
boolean twoQueensInColumn = false;
and the other example
boolean break2 = false;
instead of the more reasonable
boolean continueLooking = true;
Plus, it is a very good idea to avoid using variables as place holders for loop escaping logic. For example, the two stanzas
...
if (count > 1) {
break2 = true;
check = true;
break;
}
}
if (break2) {
break;
}
are a breeding ground for bugs, requiring a lot of debugging to ensure they work "right now" which will break just as soon as you modify the code. Much better would be
boolean keepLooking = false;
for (int row = 0; keepLooking && (row < board.length); row++) {
int queensInColumn = 0;
for (int column = 0; keepLooking && (column < board[row].length, column++) {
if (board[row][column] != 0) {
queensInColumn++;
}
if (queensInColumn > 1) {
keepLooking = false;
}
}
}
The main difference being the control logic is in the loop "conditional" block, where it belongs.
I would recommend turning your integers to string and using the .contains() method and looping through that. This would make the code easier to understand.

finding the number of pairs of numbers in an array that add up to a number

I am trying to come up with a program that will search inside of an array that is given a length by the user that picks out whether there is a pair of numbers that sum to 7. The idea is that if there is k amount of dice being thrown, how many pairs of numbers out of those dice thrown add up to 7. So far this is all that I could come up with but I am very stuck.
This is the driver class for the program. I have to write a class that will make this driver function properly.
import java.util.Scanner;
public class SevenDriver{
public static void main(String[] args){
System.out.println("Enter number of dice to toss");
Scanner s = new Scanner(System.in);
int diceCount = s.nextInt();
SevenTally t = new SevenTally(diceCount);
int experiments = 1000000;
int wins = 0;
for(int j = 0; j < experiments; j++)
if(t.experiment()) wins++;
System.out.println((double)wins/experiments);
}
}
This is what I have so far. It does not currently work or compile. I am just looking for some ideas to get me going. Thanks!
public class SevenTally{
private int diceCount;
public SevenTally(int die){
diceCount = die;
}
public int genDice(){
return 1 + (int)(Math.random()*6);
}
public boolean experiment(){
boolean[] nums = new boolean[diceCount];
int ranNum;
int sum = 7;
for(int i = 0; i < nums.length; i++){
ranNum = genDice();
if (nums[ranNum] == sum){
return true;
}
}
int left = 0;
int right = nums.length - 1;
while(left<right){
int tempSum = nums[left] + nums[right];
if(tempSum == 7){
return true;
}
else if(tempSum>7){
right--;
}
return false;
}
}
First populate your array of length k with random int in [1;6]
The number of possible pairs in an array of length k is the number of 2-combinations in the array, which is (k-1)*k/2 (http://en.wikipedia.org/wiki/Combination)
You can test all the possible pairs (i,j) in your array like so:
int win = 0;
int tally = 7;
for(int i=0; i<k-1; i++){
for(int j=i+1; j<k; j++){
if(array[i]+array[j] == tally){
win++;
}
}
}
What this does is that it sets the first element of the pair to be the first element of the array, and sums it with the other elements one after the other.
It pairs array[0] with array[1] to array[k-1] at the first pass of the i for loop, that's k pairs.
Then k-1 pairs at second pass, and so on.
You end up with (k)+(k-1)+(k-2)+...+1 pairs, and that's exactly (k-1)*k/2 pairs.
done =]
edit: sorry, haven't read the whole thing. the method experiment() is supposed to return a boolean. you can return win>0?true:false; for example...
This Wiki page has some algorithms to do that. Its not a trivial problem...
You're generating a random number in ranNum, and then using it as an index into the array nums. Meanwhile, nums never gets filled, so no matter which box you index into, it never contains a 7.
What you want to do, if I understand your problem correctly, is fill each space in the array with the result of a die roll, then compare every two positions (rolls) to see if they sum to seven. You can do that using a nested for loop.
Essentially, you want to do this: (written in pseudocode as I'm not a java programmer)
int[] results[numrolls]
for (count = 0 to numrolls-1) { results[numrolls]=dieRoller() }
for (outer = 0 to numrolls-2)
for (inner = outer+1 to numrolls-1)
if (results[outer] + results[inner] == 7) return true
return false;
However, in this case there's an even easier way. You know that the only ways to get a sum of 7 on 2d6 are (1,6),(2,5),(3,4),(4,3),(5,2),(6,1). Set up a 6-length boolean array, roll your dice, and after each roll set res[result] to true. Then return (1-based array used for simplicity) ( (res[1] && res[6]) || (res[2] && res[5]) || (res[3] && res[4]) ).
ArrayIndexOutOfBoundsException means you are trying to access an element of the array that hasn't been allocated.
In your code, you create a new array d of length diceCount, but then you genDice() on always 6 elements.

Finding pairs out of five

I am having trouble finding pairs in a string of size five. So therefore, there can only be two pairs. For every pair that I have found, I should increase the score by 2 points.
Here is what I have so far, but it is incorrect.
String temp = "4 5 4 3 3";
String tempLine = temp.replaceAll(" ", "");
String[] hand = temp.split(" ");
for(int i = 0; i < hand.length; i++)
{
if(hand[i].equals(tempLine.substring(0, 1)) && i !=0 )
score += 1;
if(hand[i].equals(tempLine.substring(1, 2)) && i != 1 )
score += 1;
if(hand[i].equals(tempLine.substring(2, 3)) && i!= 2 )
score += 1;
if(hand[i].equals(tempLine.substring(3, 4)) && i!= 3)
score += 1;
if(hand[i].equals(tempLine.substring(4)) && i != 4)
score += 1;
}
EDIT: I am trying to find pairs in the hand that have similar value, for example 4 would be one pair found in this hand
Sort the hand first and then loop though looking for hand[i] == hand[i-1]. Note that you might have to be slightly clever as to not count sets of 3s or 4s twice but this should get you started.
Create an actual Hand class and don't use Strings to represent your cards. A Card's rank and suit are suitable candidates for an enum:
class Card {
enum Suite { ... };
enum Rank { ... };
private final Suite s;
private final Rank r;
// ...
}
class Hand {
private Card[] cards;
// ...
}
And sort the Card[] in your Hand class which makes it easier to evaluate .
Checkout Oracle's enum tutorial which has an example with cards: http://download.oracle.com/javase/1.5.0/docs/guide/language/enums.html
I think this fits what you're trying to do.
char[] hand = {'a','b','c','b','c'};
/* sort the hand to ensure pairs are next to each other */
for(int x=0;x<hand.length - 1;x++){
for(int y=(x+1);y<hand.length;y++){
if((int)hand[x] > (int)hand[y]){
char temp = hand[y];
hand[y] = hand[x];
hand[x] = temp;
}
}
}
int score = 0;
for(int x=0;x<hand.length - 1;x++){
if(hand[x] == hand[x + 1]){
score++;
/*if you want to make sure you only get pairs
add an "x++;" that way it'll skip over the
letter you just tested*/
}
}
1) Why aren't you comparing elements of the hand array to other elements? You already did the work to interpret the string and create the array data; use it.
2) There are more possible pairs of elements than that. Put down five similar objects in a row in front of you at the computer and try it out for yourself. You should be able to identify ten pairs. You should also be able to identify a pattern to how to find/label the pairs.
This example below is one possibility of how to count pairs. The question is how it should behave (increase the score) in case there are three equal values in the string or array or whatever. Shall this be counted as three pairs or not at all...?
123 is in fact three combinations 12 && 13 && 23
111 is in fact three combinations 11 && 11 && 11
package edu.harris.pairs;
public class FindPairs {
public static void main(String[] args) {
String s = "hello";
int score = 0;
for (int i = 0; i < s.length() - 1; i++) {
for (int j = i + 1; j < s.length(); j++) {
if (s.charAt(i) == s.charAt(j)) {
score++;
}
}
}
System.out.println(score);
}
}
Hope this helps a bit.

Categories