I would like some help coding these methods. Each method should check to see if a group of 5 cards, stored as an array, is certain hand in poker, like one pair, two pair, Full House, etc. This is what I have so far. Also, sort(), sort the cards from smallest to largest and in the order of Clubs, Diamonds, Hearts and then Spades. Lastly I apologize for any formatting issues with the brackets. Thank you.
private boolean isOnePair(){//checks if one pair exists---Done
sort();
for(int i=0;i<cards.length-2;i++){
if(cards[i].compareTo(cards[i+1])==0){
return true;
}
else{
return false;
}
}
}
In theory this one checks to see if there One pair exists in the hand. I believe it is done and makes sense, but if it aint, please tell me why.
private boolean isTwoPair(){//check if two pair exists---
sort();
for(int i=0;i<cards.length-2;i++){
if(cards[i].compareTo(cards[i+1])==0){
return true;
}
}else{
return false;
}
}
This is where I would like help. It needs to check if there are two different pairs. I'm assuming I need something to check like I did in isOnePair. Also, Since Four of a Kind is technically(in real life, not card terms) considered Two pairs, would this be an issue?
private boolean isThreeOfAKind(){//check if three of a kind---Done
sort();
for(int i=0;i<cards.length-3;i++){
if((cards[i].compareTo(cards[i+1])==0)
&&(cards[i+1].compareTo(cards[i+2])==0)){
return true;
}else{
return false;
}
}
}
This checks to see if there are three kinds of one card. This I believe is good
private boolean isStraight(){//check if all in a row---Done
sort();
for(int i=0;i<cards.length-1;i++){
if(cards[i]<cards[i+1]&&()cards[i+1]-cards[i])==1)){
return true;
}else{
return false;
}
}
}
This checks to see if the cards are a Straight. So they are in numerical order since the difference between each card will have to be 1.
private boolean isFlush(){//check if all have same suit---
sort();
for(int i=0;i<cards.length-1;i++){
}
}
This is also where I would like to most help. My trouble is just the thought behind how to check the suits. I know you guys dont have the actual code that tells you the suit value, but if someone could help me with the thought process of it.
private boolean isFourKind(){//check if four of a kind---Done
sort();
for(int i=0;i<cards.length-4;i++){
if((cards[i].compareTo(cards[i+1])==0)
&&(cards[i+1].compareTo(cards[i+2])==0)
&&(cards[i+2].compareTo(cards[i+3])==0)){
return true;
}else{
return false;
}
}
}
Check Four of a Kind. Should be all good.
private boolean isRoyalFlush(){//check if from 10-Ace and All of same suit---
sort();
for(int i=0;i<cards.length-1;i++){
}
}
This should be a combo of Straight and Flush. But the last condition is that the card in slot card[0]==10.
To check whether you have two pairs, simply create a counter that increments every time you find a pair - instead of instantly returning true. If your counter ever reaches two, you return true.
Also, your worries about two pairs and four of a kind being similar should all be handled outside these methods. As in, check to see if you have the most restrictive (or highest point) hand first, and only if you don't have it do you check the next restrictive hands.
Finally, you cannot program this without your Card class having a visible suit variable (or a getter function that returns the suit). Once you have that, then you can very easily check for flushes, flushes+straights, etc. After you implement this, it should look something like the following
int suit = cards[0].getSuit();
for (int i = 1; i < cards.length; ++i) {
if (suit != cards[i].getSuit()) // checks to see if you have a card of a different suit
return false;
}
return true; // suits of all cards are the same
PS: Don't really know the rules for Poker. Can a straight be composed of cards of different suits?
Related
So I'm writing a Rush Hour solver in Java, which is meant to be able to solve the configurations here. However, even the simplest puzzle from that page results in the solver running infinitely and eventually running out of memory. I'm using a breadth first search to work my way through all possible moves arising from each board state (using a HashSet to ensure I'm not repeating myself), and mapping each state to the move that got it there so I can backtrack through them later.
The thing is, I've tried it with more trivial puzzles that I've come up with myself, and it's able to solve them (albeit slowly).
Is there anything blatantly wrong with how I'm approaching this problem? I can put up some code from the relevant classes as well if I need to, but I've tested them pretty thoroughly and I'm pretty sure the problem lies somewhere in the code below. My gut says it's something to do with the HashSet and making sure I'm not repeating myself (since the Queue's size regularly reaches the hundred thousands).
Any suggestions?
// Start at the original configuration
queue.add(originalBoard);
// We add this to our map, but getting here did not require a move, so we use
// a dummy move as a placeholder move
previous.put(originalBoard, new Move(-1, -1, "up"));
// Breadth first search through all possible configurations
while(!queue.isEmpty()) {
// Dequeue next board and make sure it is unique
Board currentBoard = queue.poll();
if (currentBoard == null) continue;
if (seen.contains(currentBoard)) continue;
seen.add(currentBoard);
// Check if we've won
if (currentBoard.hasWon()) {
System.out.println("We won!");
currentBoard.renderBoard();
return solved(currentBoard);
}
// Get a list of all possible moves for the current board state
ArrayList<Move> possibleMoves = currentBoard.allPossibleMoves();
// Check if one of these moves is the winning move
for (Move move : possibleMoves) {
Board newBoard = move.execute(currentBoard);
// We don't need to enqueue boards we've already seen
if (seen.contains(newBoard)) continue;
queue.add(newBoard);
// Map this board to the move that got it there
previous.put(newBoard, move);
}
}
As requested, here are my initialisations of the HashSet (they're class level variables):
private static HashSet<Board> seen = new HashSet<>();
And my Board.equals() method:
#Override
public boolean equals (Object b) {
Board otherBoard = (Board) b;
boolean equal = false;
if (this.M == otherBoard.getM() && this.N == otherBoard.getN()) {
equal = true;
// Each board has an ArrayList of Car objects, and boards are only
// considered equal if they contain the exact same cars
for (Car car : this.cars) {
if (otherBoard.getCar(car.getPosition()) == null) {
equal = false;
}
}
}
System.out.println(equal);
return equal;
}
You must implement Board.hashCode() to override the default Object-based version, in such a way that, per its contract, any two equal Board objects have the same hash code. If you do not, then your seen set does not in fact accomplish anything at all for you.
On another issue, I suspect that the way you're checking the boards' cars is not fully correct. If it works the way I think it does, it would consider these two boards to be equal:
. = empty space
* = part of a car
......
.**.*.
....*.
.*....
.*.**.
......
......
.*..**
.*....
......
.**.*.
....*.
I'm new to JAVA and am struggling with a specific issue that I couldn't find an answer to so I decided to ask the good people of StackOverflow.
I am trying to build an ATM program. I have created an array of objects (The clients of the bank) with properties such as cardnumber, pin, balance, etc. And when any user will try and "log in" to the ATM he should type in his card number.
In the code below I tried to simulate the ATM going through the array of Clients and checking the input number with all the existing card numbers of each customer until it finds a match, and it works fine. The problem is that if it finds a match with client at position 10 it will display "Inexistent Card" 10 times before succeeding.
So I wanted to ask if there is a way for the program to ignore all these mismatches and only continue if it finds a match. And give me the "Inexistent Card" only when it finds 0 matches.
for (i = 0; i < clients.length; i++) {
if (input.equals(clients[i].accountnumber)) {
System.out.println("Welcome");
} else {
System.out.println("Inexistent Card");
}
}
consider using a found boolean variable
boolean found = false;
for (i = 0; i < clients.length; i++) {
if (input.equals(clients[i].accountnumber)) {
System.out.println("Welcome");
found = true;
break;
}
}
and then after the loop
if (!found) {
System.out.println("Inexistent Card");
}
That is exactly what you've written!
Think about it a bit more: You don't know the account doesn't exist until you've searched all the accounts and not found the one you want. You need to organise your code the same way. Just because clients[0] is not the one you are looking for, clients[1] might be, so you can't say "non existent" just yet...
The most simple way to achieve this:
int indexOfMatchingCard = -1;
for (... {
if (match) {
indexOfMatchingCard = current index
Afterwards, you can check if indexOfMatchingCard is >= 0; at the same time it tells you which of your cards matched. Just make sure to not reset that marker if you later find that other cards are not matching!
If you don't need to remember the matching index; you can use a simple boolean marker (which you initialize to false once; and change to true when on match).
I'm trying to create a hand evaluator that it will allow me to compare if one hand is better than another. I know there many other post on SO about this topic however many of them are old now and the links no longer link to anything useful. The only way I can think of doing this at the moment is to manually check for every different combination. Eg check for ace of any suit, if this doesn't exist then move to the next combination eg straight flush then 4 of a kind and so on. However, then how would you compare a pair of 2s to a pair of 3s unless you gave an integer to every combination of cards that made something interesting. However, that would very hard to do manually. Is there a better way?
Why hard?
class Card{
String suite;
int value;
....
}
// ...if two combinations are equal, Do for both combinations
int power = 0;
for (Card card: combination){
power += card.getValue()
}
// and compare!
I don't know if this is the best approach, but this could be possible and this is all manually.
Let's say you already have the code to determine which hand the player has in this format:
22s, KKs, 98o, 11o
Now you have an array with three values e.g.:
["K", "K", "s"]
...and another array:
[9, 8, "o"]
You first have to class those hands (like flush, straight etc.) to make sure which one will win (royal flush always win). And after those checks, you have to do some checks in the array. Check if it's suited or offsuit, if "K" is higher than 9 etc.
You can give them values like this:
...
8=8
9=9
10=10
J=11
Q=12
K=13
A=14 (or 1)
And then compare with that. This is a hard algorithm to do it properly without doing so many things manually. I hope someone who has experience with this takes my answer over and recover my mistakes or wrong steps/thoughts.
I would separate the problem for each type of combinations, and assign an integer for a specific occurence of a combination called ie. strength (so a Straight Flush of 5-4-3-2-A is the weakest and K-Q-J-10-9 is the strongest).
Individual combinations can be handled pretty well i think. For a royal flush, you sort your 7 cards by their number descending, and check if the first 5 cards are (A-K-Q-J-10) and if they are of the same suit. A royal flush's strength is indefinite.
For flush you can sort your cards by suit, and check if you can move 4 times in your list of card without witnessing a suit change. A Flush's strength is determined by the highest valued card of it.
A very brief template for the idea:
// main logic of who wins, note it doesn't handle when two players have the same
// combo with same strength
class HandComparator {
public Player compare(Player player1, Player player2) {
HandEvaluator handEvaluator = new HandEvaluator();
Combination player1Combo = handEvaluator.evaluate(player1.hand);
Combination player2Combo = handEvaluator.evaluate(player2.hand);
if (player1Combo.type.equals(player2Combo.type)) {
// note, strength is only taken into account if the two players have
// the same combo (ie both has full house)
if (player1Combo.strength < player2Combo.strength) {
return player2;
} else {
return player1;
}
} else if (player1Combo.type.compareTo(player2Combo.type) < 0) {
return player2;
} else {
return player1;
}
}
}
class Card {
int suit;
int number;
}
class Player {
List<Card> hand;
}
// this is built by CombinationRecognisers. Note, that the member 'strength' is
// related to a specific combination, not all possible hands
class Combination {
enum Type {
ROYAL_FLUSH,
STRAIGHT_FLUSH;
// etc.
}
Type type;
int strength;
}
// implement this for all combinations (ROYAL_FLUSH,STRAIGHT_FLUSH, etc)
interface CombinationRecogniser {
public Combination evaluate(List<Card> hand);
}
/*
* this class holds all CombinationRecognisers and iterates throught them. It
* will stop the moment a combo has been found.
*/
class HandEvaluator {
static List<CombinationRecogniser> recognizers = new ArrayList<CombinationRecogniser>();
static {
recognizers.add(new RoyalFlushRecogniser());
recognizers.add(new StraightFlushRecogniser());
}
public Combination evaluate(List<Card> hand) {
for (CombinationRecogniser recogniser : recognizers) {
Combination combination = recogniser.evaluate(hand);
if (combination != null) {
return combination;
}
}
return null;
}
}
class RoyalFlushRecogniser implements CombinationRecogniser {
#Override
public Combination evaluate(List<Card> hand) {
// code goes here that decides if the given hand is a valid royal flush
return null; // of new Combination() if the given hand is a valid royal flush
}
}
class StraightFlushRecogniser implements CombinationRecogniser {
#Override
public Combination evaluate(List<Card> hand) {
// code goes here that decides if the given hand is a valid straight flush
return null; // of new Combination() if the given hand is a valid royal flush
}
}
This code actually works if you implement the CombinationRecogniser interface for all special combinations. An example:
public void PlayforMe()
{
for (int i=game.size()-1;i>=1;i--)
{
Card a = game.get(i);
Card b = game.get(i-1);
if (a.getSuit().equals(b.getSuit()) | (a.getCardNum().equals(b.getCardNum())))
{
game.remove(b);
break;
}
}
for (int j=game.size()-1;j>=3;j--)
{
Card c = game.get(j);
Card d = game.get(j-3);
if (c.getSuit().equals(d.getSuit()) | (c.getCardNum().equals(d.getCardNum())))
{
game.set(j-3,game.get(j));
game.remove(j);
break;
}
}
}
I have written this piece of Java code for a solitaire type game I'm making in Java code. I'm very new to the language (and programming in general). I have an arrayList for my deck and an arrayList for my 'game'. In this method/move I have it so it will find the card nearest the end of the dealt cards and 'swap' it with the card directly before it if the suit or the card number are the same.
If this move isn't an option with the cards dealt then I need it to go through the second loop which finds the card nearest the end of the dealt cards and 'swaps' it with the card [3] places before it if the suit or the card number are the same.
They work individually, but I can't get a condition working (e.g. I've tried the if statement) that will go through the first loop, and if it doesn't successfully remove a card it will go through the second loop.
The method should only preform one move, prioritising moving a card onto the card next(before) it if the conditions are met. I can make it so it'll go through both loops (i.e. putting the piece of code into two methods and calling them both from my menu) but I need it to do the first loop and only do the second if the first one turns out unsuccessful (i.e. card b isn't removed/game.remove(b); isn't called.)
If anyone has any suggestions I'd appreciate it :)
You want to put Boolean finished = false; at the start of the function, then finished = true when you have finished. Then put if (finished) { ... } round your second loop.
Alternatively put a return in the first loop when finished. This will return out your function and execute no more lines of code. Although some people consider this bad style.
If the first for loop succeeds, return instead of breaking.
So I have what I think is pretty good code for a sudoku solver in java but I need some help with this method. It gives me a stack overflow when I embed it in a main method. The problem is that my method doesn't know how to turn around and fix its mistakes. I need a boolean flag (one that, unlike the one used in the code below, actually works preferably) or something to let it know when it should turn back and when it can again go forwards and continue solving the game. Thanks for any help you can give
public void play(int r, int c){//this method throws the StackOverflowError
if(needAtLoc(r,c).size()==9){
int num=1+generator.nextInt(9);
setCell(r,c,num,this);
if(c<8){
System.out.println(this);///////////////
play(r, c+1);
}
else{
play(r+1, 0);
}
}
else{
if(needAtLoc(r,c).size()==0){//no possible moves THIS IS THE PROBLEM LINE!!!
if(c>0){
play(r, c-1);//play last cell, in column to left
}
else{
if(r==0){
play(r,c);//first square, so must play again (can't go back)
}
else{
play(r-1, 8);/*first cell of row so must go to previous row and
the end column*/
}
}
}
else{//if there are possible moves
int num=needAtLoc(r,c).remove(generator.nextInt(needAtLoc(r,c).size()));
setCell(r,c,num,this);//set the value of the cell
System.out.println(this);//////////////
if(r==8 && c==8){//the end of the cell has been reached so must end recursive call
return;
}
else{
if(c<8){
play(r, c+1);//normal, next cell
}
else{
play(r+1, 0);/*last cell in row so we go to next one
in the first column ("return" button)*/
}
}
}
}
}
Rather than solve this for you I would make a few suggestions in how to tackle this. 9 hours is ample.
1) Your code is hard to read. Try to space it out a bit. Give your variables meaningful names that are clear (this helps you and other people read your code). You may have made a simple mistake and clean code will make these easier to spot. Try to break it into smaller methods since this will make it more readable and more maintainable.
2) Stack overflows are caused (generally I believe) when you make too many nested method calls and are typical in recursive code. Therefore make your recursion clear. Make sure you have a base case that will terminate.
Sorry to not give you "the answer" but since this sounds like homework I think there's more value in learning how to solve this yourself. Hope that seems fair.
I think your problem is where you have:
if(r==0)
{
play(r,c);//first square, so must play again (can't go back)
}
That's because you don't seem to modify any state here and you pass the same values in that made you come to this step in the first place. Seems like infinite recursion for me.
Also please align your code correctly as it is too hard to read when it is misaligned and maybe provide some clues what the other methods do. Good luck!
Your code is throwing stack over flow exception because you never reach a terminating condition that ends your recursion, or at least it is not obvious you to see you have a recursion terminating condition by reading your code.
Your code is not well structure, hence you will have a hard time debugging it. Try to restructure your code, it will help you rethink the problem. Also, please comment your code :)
You are recursively calling play without ever returning and it looks as if you are initialising a new set of variables each time at the top of the function.
Try splitting out the initialisation from the recursive part. You also need a clear end condition to end the recursion e.g. (if(isBoardFilled()==true)) return.
Also structure it so that you add a number to the board, test it against the contraints and if it passes add another number (recurse) or backtrack by removing the last number and try again.
I think u are calling play() recursively .Try to check if there is a stopping condition to ur recursive call.
I agree with Tom, but here is a hint.
There is no condition and return statement to end the recursive calls.
I've managed to be more concise and more clear but it still won't run... I just need a push over the edge and I'm home free. I've dumped so many wasted hours into this project:
public ArrayList<Integer> needAtLoc(int r, int c){
int bc=c/3;//the column within the SudokuBoard
int blc;
/*The two posibilities for the column within each SudokuBlock:*/
if(c>=0 && c<3) {
blc=c;
}
else {
blc=c%3;
}
int br=r/3; //the row within the SudokuBoard
int blr;
/*The two possiblities for the row within each SudokuBlock:*/
if(r>=0 && r<3) {
blr=r;
} else {
blr=r%3;
}
ArrayList<Integer> needR = new ArrayList<Integer>();
needR=checkR(r);//
needR.trimToSize();
System.out.println(needR);//////////////
ArrayList<Integer> needC=new ArrayList<Integer>();
needC=checkC(c);
needC.trimToSize();
System.out.println(needC);/////////////
ArrayList<Integer> needBl=new ArrayList<Integer>();
needBl=this.board[br][bc].updateMissing(); //that method updates and returns an ArrayList
needBl.trimToSize();
ArrayList<Integer> poss=new ArrayList<Integer>();
poss.clear();
for(Integer e: needBl){
if(needC.contains(e) && needR.contains(e)){
poss.add(e);
}
}
return poss;
}
//this method throws the StackOverflowError
public void play(int r, int c){
int bc=c/3; //the column within the SudokuBoard
int blc;
/*The two posibilities for the column within each SudokuBlock:*/
if(c>=0 && c<3) {
blc=c;
} else {
blc=c%3;
}
int br=r/3; //the row within the SudokuBoard
int blr;
/*The two possiblities for the row within each SudokuBlock:*/
if(r>=0 && r<3) {
blr=r;
} else {
blr=r%3;
}
if(needAtLoc(r,c).size()==9){
int num=1+generator.nextInt(9);
this.board[br][bc].setValue(blr, blc, num);
if(c<8){
System.out.println(this);///////////////
play(r, c+1);
} else{
play(r+1, 0);
}
} else{
if(needAtLoc(r,c).size()==0){ //no possible moves
if(c>0){
bc=(c-1)/3;
if(c>0 && c<4) {
blc=c-1;
} else {
blc = (c-1) % 3;
}
this.board[br][bc].setValue(blr, blc, 0);
play(r, c-1);
}
else{
blc=0;
bc=0;
if(r==0){
blr=0;
br=0;
this.board[br][bc].setValue(blr, blc, 0);
play(r,c);
}
else{
br=(r-1)/3;
if(r>0 && r<4) {blr=r-1;}
else {blr=(r-1)%3;}
this.board[br][bc].setValue(blr, blc, 0);
play(r-1, 8);
}
}
}
else{//if there are possible moves
int num=needAtLoc(r,c).remove(generator.nextInt(needAtLoc(r,c).size()));
this.board[br][bc].setValue(blr, blc, num);
System.out.println(this);//////////////
if(r==8 && c==8){
return;
}
else{
if(c<8){
play(r, c+1);
}
else{
play(r+1, 0);
}
}
}
}
}