I am writing a Minesweeper game, and I am trying to use a hashset. My question is can a hashset contain both integers and strings? The hastset I am using has mainly strings and one that is a integer. Can this be done? When I compile it, it gives me the error that the variable _minecount cannot be found, nothing about it not being a string. This is my code:
import java.util.Set;
import java.util.HashSet;
/**
* Represents a single square in Minesweeper.
*
* #author Sophia Ali
*/
public class MineSquare
{
//Constants:
// Fields:
private String _shown; // What a square is showing now
private boolean _mined; // Square is mined or not
private boolean _flagged; // Square is flagged or not
private boolean _questioned; // Square is question marked or not
private int _minecount; // Square's surrounding mine count
private boolean _opened; // Player has opened this square or not
private static final String[] VALID_SHOWN_TEXT = {"X", 0 < minecount && _minecount < 8, " ", "F", "?"};
private HashSet<String> validShownTextSet =
new HashSet<String>(java.util.Arrays.asList(VALID_SHOWN_TEXT));
// Constructors & Methods:
/**
* Default constructor
* Sets _mined and _opened to false.
*/
public MineSquare()
{
_mined = false;
_opened = false;
setShown(" ");
}
/**
* Returns flagged status of square.
* #return _flagged Flagged status
*/
public boolean isFlagged() {
return _flagged;
}
/**
* Sets or unsets flag on a square.
* #param flagged True or false (square is flagged or not)
*/
public void setFlagged(boolean flagged, boolean opened) {
_flagged = flagged;
_opened = opened;
// If Minesquare opened do nothing:
if (opened == true)
setShown(" ");
// If flagged, square should show "F":
if ( isFlagged() == true )
setShown("F");
else
setShown(" ");
}
public int getMinecount() {
return _minecount;
}
public void setMinecount(int minecount) {
_minecount = minecount;
if ( 0 < minecount && minecount < 8 )
{
setShown("Error:" + minecount);
}
}
public boolean isMined() {
return _mined;
}
public void setMined(boolean mined) {
_mined = mined;
}
public boolean isOpened() {
return _opened;
}
/**
* Open a square.
* (Once opened, a square can't be unopened.)
*/
public void setOpened() {
_opened = true;
if ( isMined() == true )
setShown("X");
else if ( getMinecount() > 0 )
setShown(_minecount + "");
else // blank space for _minecount = 0
setShown(" ");
}
public boolean isQuestioned() {
return _questioned;
}
public void setQuestioned(boolean questioned, boolean opened) {
_questioned = questioned;
_opened = opened;
// If Minesquare opened do nothing:
if (opened == true)
setShown(" ");
// If Questioned, square should show "F":
if ( isQuestioned() == true )
setShown("F");
else
setShown(" ");
}
public String getShown() {
return _shown;
}
public void setShown(String shown) {
_shown = shown;
/*if (shown.equals("X")) {
this.shown = shown;
} else if (shown.equals( 0 < minecount && minecount < 8 )) {
this.shown = shown;
} else if (shown.equals(" ")) {
this.shown = shown;
} else if (shown.equals("F")) {
this.shown = shown;
} else if (shown.equals("?")) {
this.shown = shown;
} else {
this.shown = "Error + shown";
}
*/
if (validShownTextSet.contains(shown)) {
this.shown = shown;
} else {
this.shown = "Error" + shown;
}
}
}
This line
private static final String[] VALID_SHOWN_TEXT = {"X", 0 < minecount && _minecount < 8, " ", "F", "?"};
has a few problems. There is no minecount variable in scope here. The variable _minecount is not a static variable, so it is inaccessible from the static scope you have made by making VALID_SHOWN_TEXT static.
And as it looks like you've guessed, you cannot store the boolean from the expression 0 < minecount && _minecount < 8 into a String array. Even if you can get a boolean expression working, you'll have to convert it to a String to store it into a String array.
// or a working boolean expression here.
..., String.valueOf(0 < minecount && _minecount < 8), ...
A HashSet<Object> can contain both integers and strings, but here, it looks like you can simply convert what you need into a string array, which should be able to be converted into a HashSet<String>.
Related
My two functions isSorted and hasDuplicate created below should work, right? My test class for the assignment wasn't working. The instructions for both are in the comments below. isSorted returns true if the string array is sorted alphabetically, and false - if not. hasDuplicate returns true if there's at least one set of duplicate strings and false - if not.
public class CheckStrings {
/**
* Returns true if the Strings in w appear in sorted order
* (alphabetical order) and false otherwise.
*
* #param w the array of Strings to check
* #return true if the Strings in w appear in sorted order
* and false otherwise.
*/
public static boolean isSorted(String[] w) {
boolean bob = true;
for (int i = 0; i < w.length-1; i++)
{
if (w[i].compareTo(w[i+1]) >= 0)
{
bob = true;
}
else
{
bob = false;
i = w.length + 50;
}
}
return bob;
}
/**
* Returns true if at least one String in w appears more than once
* and false otherwise.
*
* #param w the array of Strings to check
* #return true if at least one String in w appears more than once
* and false otherwise.
*/
public static boolean hasDuplicate(String[] w) {
boolean bob = true;
for (int i = 0; i < w.length-1; i++)
{
if (w[i].equals(w[i+1]))
{
bob = true;
i = w.length + 50;
}
else
{
bob = false;
}
}
return bob;
}
}
Submit this for your homework:
public static boolean isSorted(String[] w) {
return Arrays.stream(w).reduce("",(a, b) -> a == null || a.compareTo(b) > 0 ? null : b) != null;
}
public static boolean hasDuplicate(String[] w) {
return Arrays.stream(w).distinct().count() == w.length;
}
And who is Bob?
In case you're not allowed yet to use Java 8 Stream API, implementation of the isSorted and hasDuplicate may look as follows:
public static boolean isSorted(String[] w) {
if (null == w || w.length == 0) {
return false;
}
for (int i = 0; i < w.length-1; i++) {
if (w[i].compareTo(w[i+1]) > 0) { // or compareToIgnoreCase if case insensitive is ok
return false;
}
}
return true;
}
public static boolean hasDuplicate(String[] w) {
if (null == w || w.length < 2) return false;
Set<String> set = new HashSet<>();
for (int i = 0; i < w.length-1; i++) {
String s = w[i]; // if case-insensitive lookup needed use s = w[i].toLowerCase();
if (set.contains(s)) {
return true;
}
set.add(s);
}
return false;
}
public final class CheckStrings {
private CheckStrings() {
}
public static boolean isSorted(String... w) {
if (w == null || w.length == 0)
return false;
for (int i = 0, j = w.length - 1; j < w.length; i++, j++)
if (w[i].compareToIgnoreCase(w[j]) > 0)
return false;
return true;
}
public static boolean hasDuplicate(String... w) {
if (w == null || w.length == 0)
return false;
Set<String> unique = new HashSet<>();
for (String str : w)
if (!unique.add(str.toLowerCase()))
return false;
return true;
}
}
Output:
String[] arr = {"a", "a", "b", "b", "c", "c"};
System.out.println(CheckStrings.isSorted(arr)); // true
System.out.println(CheckStrings.hasDuplicate(arr)); // true
I'm trying to learn java using the basic tictactoe example, but just for fun I wanted to design an ai later.
I'm having an issue flattening the char[] to Array. I'm so confused is there a better way to do this?
Do I need to create another method to specific convert this char[] to array?
ERROR:
The method mapToCharater(Charater.class::cast) is undefined for the type Stream<Object>
CONSOLE OUTPUT
EDIT:
Exception in thread "main" java.lang.ClassCastException: Cannot cast [C to java.lang.Character
at java.base/java.lang.Class.cast(Class.java:3610)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:411)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:274)
at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:550)
at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:517)
at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:523)
at aiPackage.game.Board.<init>(Board.java:17)
at aiPackage.game.Tester.main(Tester.java:15)
package aiPackage.game;
import java.util.*;
import java.util.stream.*;
public class Board {
//declaration of private members
private int score;
private Board previousB = null;
private char[][] thisBoard;
// ------------------------------------------------------;
public Board (char [][] inBoard) {
//what
//char[] flats = flatten(inBoard).map
Object[] flats = flatten(inBoard).map(Character.class::cast).toArray(); //mapToCharater(Charater.class::cast).toArray();
int[] flat = flatten(inBoard).mapToInt(Integer.class::cast).toArray();
int flatSize = flat.length;
// ------------------------------------------------------;
//check if square
if (Math.sqrt(flatSize)==3) {
if(inBoard.length == 3) {
thisBoard = inBoard;
}
else {
System.out.println("The array isnt a square.");
}
}
else {
System.out.println("It doesnt match the dimensions of a tictactoe board.");
}
//we'll assume its not gonna break from the input atm
setThisBoard(inBoard);
}
//https://stackoverflow.com/questions/31851548/flatten-nested-arrays-in-java
private static Stream<Object> flatten(Object[] array) {
return Arrays.stream(array)
.flatMap(o -> o instanceof Object[]? flatten((Object[])o): Stream.of(o));
}
public Board getPreviousB() {
return previousB;
}
public void setPreviousB(Board previousB) {
this.previousB = previousB;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public char[][] getThisBoard() {
return thisBoard;
}
public void setThisBoard(char[][] thisBoard) {
this.thisBoard = thisBoard;
}
//if there are even elements on the board, its x's turn
public ArrayList<Board> getChildren(){
return null;
}
public void checkIfEnded() {
for (int i = 0; i < 3; i++) {
//check row wins
if (thisBoard[i][0] != '-' &&
thisBoard[i][0] == thisBoard[i][1] &&
thisBoard[i][1] == thisBoard[i][2]) {
//updates score based on winner
if (thisBoard[0][2] == 'x') {
updateScore(1);
}
else {
updateScore(-1);
}
return;
}
//check column wins
if (thisBoard[i][0] != '-' &&
thisBoard[0][i] == thisBoard[1][i] &&
thisBoard[1][i] == thisBoard[2][i]) {
//updates score based on winner
if (thisBoard[0][2] == 'x') {
updateScore(1);
}
else {
updateScore(-1);
}
return;
}
}
//check diagnals
if (thisBoard[0][0] != '-' &&
thisBoard[0][0] == thisBoard[1][1] &&
thisBoard[1][1] == thisBoard[2][2]) {
//updates score based on winner
if (thisBoard[0][2] == 'x') {
updateScore(1);
}
else {
updateScore(-1);
}
return;
}
if (thisBoard[0][2] != '-' &&
thisBoard[0][2] == thisBoard[1][1] &&
thisBoard[1][1] == thisBoard[2][0]) {
//updates score based on winner
if (thisBoard[0][2] == 'x') {
updateScore(1);
}
else {
updateScore(-1);
}
return;
}
}
//outputs the board's contents as a string
public String toString() {
String result = "";
//gets the previous board's info to output first
result = "" + previousB;
//gets this boards info to output
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
result += thisBoard[i][j] + " ";
}
//adds newline char at end of row
result += "\n";
}
//adds an extra newline char at end of board
result += "\n";
return result;
}
private void updateScore(int win) {
if (win > 0) {
score = 1;
} else if(win == 0){
score = 0;
}else {
score = -1;
}
}
}
package aiPackage.game;
import java.util.*;
public class Tester {
private static Board start;
private static Board finish;
public static void main(String[] args) {
char temp [][] = {
{'o','-','x'},
{'-','-','-'},
{'-','-','-'}};
start = new Board(temp);
finish = minMax(start.getChildren());
System.out.println();
}
public static Board minMax(ArrayList<Board> resultList) {
return null;
}
}
The reason it fails is because Arrays.stream() does not accept char[] The following should work.
Arrays.stream(inBoard)
.flatMap(x -> (Stream<Character>)new String(x).chars().mapToObj(i->(char)i))
.collect(Collectors.toList())
check out
Want to create a stream of characters from char array in java for
and
Why is String.chars() a stream of ints in Java 8?
for better understanding.
Your problem is here:
private static Stream<Object> flatten(Object[] array) {
return Arrays.stream(array)
.flatMap(o -> o instanceof Object[]? flatten((Object[])o): Stream.of(o));
}
You are using the comparation with Object[] to decompose the array, but in reality is a char[].
That makes that your result instead of being an Stream Object is a Stream char[].
The main point is that you can't use a Stream to work with primitives. Stream only works with Objects and char is a primitive.
you can manually flatten the char[][] using a classic loop.
flattening char[][] or impossible doesn't count
char[] array = Stream.of( inBoard ).flatMap( arr -> Stream.of( String.valueOf( arr ) ) )
.collect( Collectors.joining() ).toCharArray(); // [o, -, x, -, -, -, -, -, -]
I am trying to get my bet system to detect if the input numbers are duplicates. When you run the program, press 2 on the "for box" bet and follow instructions from there. The issue lies in the winlose duplicate and also for the non duplicate. I don't know how I am supposed to fix the issue.
Error stacktrace :
at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)
at java.util.LinkedList$ListItr.next(LinkedList.java:888)
at numbersgame.Test.winLoseBetDuplicate(NumbersGame.java:190)
at numbersgame.Test.checkDuplicate(NumbersGame.java:167)
at numbersgame.Test.WinLoseBox(NumbersGame.java:134)
at numbersgame.Test.getValues(NumbersGame.java:117)
at numbersgame.NumbersGame.main(NumbersGame.java:24)
C:\Users\cymmm1\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 6 seconds)
Code :
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package numbersgame;
import java.lang.reflect.Array;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JOptionPane;
/**
*
* #author cymmm1
*/
public class NumbersGame {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Test numbers = new Test();
numbers.getValues();
boolean win = numbers.win; //this checks if you won, either as a duplicate or not.
if (win) {
System.out.println("You won");
switch (numbers.bet_Type) {
case 1:
System.out.println("You waged " + numbers.bet_Amount
+ "dollars and you will get "
+ numbers.bet_Amount * 600 + " back.");
break;
case 2:
if (numbers.dupwin) {
System.out.println("You waged " + numbers.bet_Amount
+ "dollars and you will get "
+ numbers.bet_Amount * 200 + " back.");
} else {
System.out.println("You waged " + numbers.bet_Amount
+ "dollars and you will get "
+ numbers.bet_Amount * 100 + " back.");
}
break;
}
} else {
System.out.println("Sorry, you lost $" + numbers.bet_Amount + " dollars");
}
System.exit(0);
}
}
class Test {
public int bet_Type;
public int bet_Amount;
public int player_Number;
public int winning_Number;
private JOptionPane panel;
public boolean win;
public List<Integer> digits = new LinkedList<>();
List<Integer> digits2 = new LinkedList<>();
public void getValues() {
panel = new JOptionPane();
this.bet_Type = (Integer.parseInt(panel.showInputDialog("What is the bet type. 1 for straight, 2 for box")));
this.bet_Amount = (Integer.parseInt(panel.showInputDialog("How much is the bet")));
boolean bad = true;
while (bad) {
this.player_Number = (Integer.parseInt(panel.showInputDialog("What is the player's Number. 3 numbers must be inputted")));
int playerNumCopy = this.player_Number;
while (playerNumCopy > 0) {
digits.add(0, playerNumCopy % 10);
playerNumCopy = playerNumCopy / 10;
}
int lengthOfNum = digits.size();
if (lengthOfNum != 3) {
bad = true;
} else {
bad = false;
}
}
bad = true;
while (bad) {
this.winning_Number = (Integer.parseInt(panel.showInputDialog("What is the winning Number")));
int winningnumbercopy = this.winning_Number;
while (winningnumbercopy > 0) {
digits2.add(0, winningnumbercopy % 10);
winningnumbercopy = winningnumbercopy / 10;
}
int lengthOfNum = digits2.size();
if (lengthOfNum != 3) {
bad = true;
} else {
bad = false;
}
}
//========END OF CHECK FOR PROPER NUMBERS=================================
//Now to check for type of bet and se the method appropriate
if (this.bet_Type == 1) {
win = WinLoseStraight();
} else {
win = WinLoseBox();
}
}
private boolean WinLoseStraight() {
if (this.player_Number == this.winning_Number) {
return true;
} else {
return false;
}
// this goes back to getValues
}
private boolean WinLoseBox() {
//this checks for duplicates. if it isnt a duplicate then check for a box non-dup
boolean duplicatewin = checkDuplicate();
if (duplicatewin) { //you either won with a duplicate number or nonduplicate. check Duplicate does to things at once
return true;
} else {
return false;
}
}
public boolean duplicate;
public boolean dupwin;
//this checks for duplicated numbers
public boolean checkDuplicate() {
duplicate = false;
int[] array = new int[digits.size()];
int i = 0;
for (int numbers : digits) {
array[i] = numbers;
System.out.println(array[i]);
i++;
}
for (int j = 0; j < array.length; j++) {
for (int k = j + 1; k < array.length; k++) {
if (array[k] == array[j]) {
duplicate = true;
System.out.println(array[k] + " equals " + array[j]);
break; //if duplicated found, it will exit out of the for loop
}
}
if (duplicate) {
System.out.println("we found duplicate.");
dupwin = winLoseBetDuplicate(); //if it has duplicated numbers, it will check if your numbers match up
break;
} else {
dupwin = winLostBetNonDuplicate();
}
}
return dupwin; //this will return if you have won the prize with a duplicated number. goes back to getValues
}
private boolean winLoseBetDuplicate() {
/*how this method works is we make a linked list.
use a advanced for loop and when we encounter
a hit, we remove the number from it.
if there is still a number in the linkedlist of
player number it is a lose. we still have digits as a linked list. */
//
boolean won = false;
boolean match;
for (int digitsnumbers : digits) {
System.out.println("Checking the number: " + digitsnumbers);
for (int digits2numbers : digits2) {
if (digitsnumbers == digits2numbers) {
digits.remove(digits.indexOf(digitsnumbers));
digits2.remove(digits2.indexOf(digits2numbers));
System.out.println("we found a duplicated numer match. Removing from choosing. ");
System.out.println(digits);
System.out.println(digits2);
match = true;
} else {
match = false;
}
}
}
if (digits.size() > 0) {
won = false;
} else {
won = true;
}
return won;
}
private boolean winLostBetNonDuplicate() {
boolean won;
for (int digitsnumbers : digits) {
for (int digits2numbers : digits2) {
if (digitsnumbers == digits2numbers) {
digits2.remove(digits.indexOf(digits2numbers));
digits.remove(digits.indexOf(digitsnumbers));
break;
}
}
}
if (digits.size() > 0) {
won = false;
} else {
won = true;
}
return won;
}
}
I was given this project by a friend who is coding in school, but I am trying to find a better way to code it. It is calling different Boolean methods, checking if true and adding to a count for latter use.
public static void testHand(PokerHand d) {
if (d.isRoyalFlush()) {
royalFlush++;
} else if (d.isStraightFlush()) {
straightFlush++;
} else if (d.is4OfAKind()) {
fourtOfAKind++;
} else if (d.isFullHouse()) {
fullHouse++;
} else if (d.isFlush()) {
flush++;
} else if (d.isStraight()) {
straight++;
} else if (d.is3OfAKind()) {
threeOfAKind++;
} else if (d.is2Pair()) {
twoPair++;
} else if (d.isPair()) {
pair++;
} else if(d.isHighCard()){
highCard++;
}
}
The code for PokerHand is as follows:
public class PokerHand {
private Card[] hand; // the hand of 5 cards
// the default constructor
public PokerHand() {
hand = new Card[5];
}
// A constructor to help with testing
public PokerHand(Card c0, Card c1, Card c2, Card c3, Card c4) {
hand = new Card[5];
hand[0] = c0;
hand[1] = c1;
hand[2] = c2;
hand[3] = c3;
hand[4] = c4;
}
/* This methods fills the hand with cards from the deck.
It uses an insertion sort so that the cards are ordered by rank.*/
public void fillHand(Deck deck) {
for (int i = 0; i < 5; i++) {
int j = i - 1;
Card temp = deck.dealCard();
while (j >= 0 && hand[j].getRank() > temp.getRank()) {
hand[j + 1] = hand[j];
j--;
}
hand[j + 1] = temp;
}
}
//PLACE ADDITIONAL METHODS AFTER THIS COMMENT
/*Checking for Royal flush by first checking if straight flush
and then if highest card is an Ace.*/
public boolean isRoyalFlush() {
return (isStraightFlush() && hand[4].getRank() == 14);
}
//Check for Straight Flush by seeing if it is both a straight and a flush
public boolean isStraightFlush() {
return (isFlush() && isStraight());
}
/*Checking if hand is a Four-of-a-kind. Done by looking at first card and
checking if it equals next 3 cards. If not, then checking second card and
checking if it equals next three cards.*/
public boolean is4OfAKind() {
boolean isFour = false;
for (int i = 0; i < hand.length - 3; i++) {
int card = hand[i].getRank();
if (card == hand[i + 1].getRank()
&& card == hand[i + 2].getRank()
&& card == hand[i + 3].getRank()) {
isFour = true;
}
}
return isFour;
}
//Checking if hand holds a Full House By:
public boolean isFullHouse() {
//Setting two boolean values
boolean a1, a2;
//First checking if it is a pair followed by a 3-of-a-kind.
a1 = hand[0].getRank() == hand[1].getRank() &&
hand[2].getRank() ==hand[3].getRank() && hand[3].getRank() == hand[4].getRank();
//Second, checking if it is 3-of-a-cind followed by a pair
a2 = hand[0].getRank() == hand[1].getRank() && hand[1].getRank() == hand[2].getRank() &&
hand[3].getRank() == hand[4].getRank();
//Returns true if it is either.
return (a1 || a2);
}
/*Checking if hand is a Flush by first getting the first card's suit
and checking if it is the same for all cards.*/
public boolean isFlush() {
String suit = hand[0].getSuit();
return hand[1].getSuit().equals(suit)
&& hand[2].getSuit().equals(suit)
&& hand[3].getSuit().equals(suit)
&& hand[4].getSuit().equals(suit);
}
/*Checking id hand is a Straight by first getting the rank of the first
card, then checking if the following cards are incremented by 1*/
public boolean isStraight() {
int card = hand[0].getRank();
return (hand[1].getRank() == (card + 1) &&
hand[2].getRank() == (card + 2) &&
hand[3].getRank() == (card + 3) &&
hand[4].getRank() == (card + 4));
}
/*Checking if hand is a Three-of-a-kind. Done by looking at first card and
checking if it equals next 2 cards. If not, then checking next card and
checking if it equals next 2 cards. This is done three times in total.*/
public boolean is3OfAKind() {
boolean threeKind = false;
for (int i = 0; i < hand.length - 2; i++) {
int card = hand[i].getRank();
if (card == hand[i + 1].getRank() &&
card == hand[i + 2].getRank()) {
threeKind = true;
}
}
return threeKind;
}
//Checking hand for 2 pairs by:
public boolean is2Pair() {
int count = 0; // Number of pairs.
int firstPair = 0; //If pair found, store rank.
//Go through hand
for (int i = 0; i < hand.length - 1; i++) {
int card = hand[i].getRank();
//Finding pairs. Cannot be same rank pairs.
if (card == hand[i + 1].getRank() && card != firstPair) {
firstPair = card;
count++;
}
}
return count == 2;
}
/*Checking if hand is a Pair. Done by looking at first card and
checking if it equals the next card. If not, then it checks the next card and
sees if it equals the next card. This is done four times in total.*/
public boolean isPair() {
boolean isPair = false;
for (int i = 0; i < hand.length - 1; i++) {
int card = hand[i].getRank();
if (card == hand[i + 1].getRank()) {
isPair = true;
}
}
return isPair;
}
//If hand is not equal to anything above, it must be High Card.
public boolean isHighCard() {
return !(isRoyalFlush() || isStraightFlush() || is4OfAKind()
|| isFullHouse() || isFlush() || isStraight()
|| is3OfAKind() || is2Pair() || isPair());
}
}
You could use the ternary operator ? : to shorten the code. Like
public static void testHand(PokerHand d) {
royalFlush += d.isRoyalFlush() ? 1 : 0;
straightFlush += d.isStraightFlush() ? 1 : 0;
fourtOfAKind += d.is4OfAKind() ? 1 : 0; // <-- this appears to be a typo.
fullHouse += d.isFullHouse() ? 1 : 0;
flush += d.isFlush() ? 1 : 0;
straight += d.isStraight() ? 1 : 0;
threeOfAKind += d.is3OfAKind() ? 1 : 0;
twoPair += d.is2Pair() ? 1 : 0;
pair += d.isPair() ? 1 : 0;
highCard += d.isHighCard() ? 1 : 0;
}
Alternatively, you could encode the hand types with an enum. Give the PokerHand a HandType (or create a factory method). Something like,
enum HandType {
ROYALFLUSH, STRAIGHTFLUSH, FOUROFAKIND, FULLHOUSE, FLUSH,
STRAIGHT, THREEOFAKIND, TWOPAIR, PAIR, HIGHCARD;
static HandType fromHand(PokerHand d) {
if (d.isRoyalFlush()) {
return ROYALFLUSH;
} else if (d.isStraightFlush()) {
return STRAIGHTFLUSH;
} else if (d.is4OfAKind()) {
return FOUROFAKIND;
} else if (d.isFullHouse()) {
return FULLHOUSE;
} else if (d.isFlush()) {
return FLUSH;
} else if (d.isStraight()) {
return STRAIGHT;
} else if (d.is3OfAKind()) {
return THREEOFAKIND;
} else if (d.is2Pair()) {
return TWOPAIR;
} else if (d.isPair()) {
return PAIR;
} else {
return HIGHCARD;
}
}
}
Then you can create an array of counts for testHand like
private static int[] handCounts = new int[HandType.values().length];
public static void testHand(PokerHand d) {
handCounts[HandType.fromHand(d)]++;
}
I would suggest you model the potential hands as an enum. They are a good use case because they have a fixed set of members.
Something like the following:
enum Rank {
ROYAL_FLUSH(Hand::isRoyalFlush),
FOUR_OF_A_KIND(Hand::isFourOfAKind),
...
public static Rank getRank(Hand hand) {
for (Rank rank: values()) {
if (rank.test.test(hand))
return rank;
}
throw new IllegalStateException("No rank for hand " + hand.toString());
}
private final Predicate<Hand> test;
Rank(Predicate<Hand> test) {
this.test = test;
}
}
Then all your if statements can be replaced by Rank.getRank(hand).
Maybe the switch statement will suit your needs :
switch (d) {
case d.isRoyalFlush() : royalFlush++; break;
case d.isStraightFlush(): straightFlush++; break;
... ... ...
default : do-something();
}
For some reason, my program seems to keep crashing because it's reading a token wrong.On line 362 and 363, where it reads token[i], no matter what happens it seems to read it as a '(' character, even though it's clearly not. If I input something like a 100*(5+5) , it will call recursion after i = 2 on 0*(5+5) instead of correctly going to i=4 and calling it on (5+5). Any help debugging would be great!
package apps;
import java.io.IOException;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.StringTokenizer;
import structures.Stack;
public class Expression {
/**
* Expression to be evaluated
*/
String expr;
/**
* Scalar symbols in the expression
*/
ArrayList<ScalarSymbol> scalars;
/**
* Array symbols in the expression
*/
ArrayList<ArraySymbol> arrays;
/**
* Positions of opening brackets
*/
ArrayList<Integer> openingBracketIndex;
/**
* Positions of closing brackets
*/
ArrayList<Integer> closingBracketIndex;
/**
* String containing all delimiters (characters other than variables and constants),
* to be used with StringTokenizer
*/
public static final String delims = " \t*+-/()[]";
/**
* Initializes this Expression object with an input expression. Sets all other
* fields to null.
*
* #param expr Expression
*/
public Expression(String expr) {
this.expr = expr;
scalars = null;
arrays = null;
openingBracketIndex = null;
closingBracketIndex = null;
}
/**
* Matches parentheses and square brackets. Populates the openingBracketIndex and
* closingBracketIndex array lists in such a way that closingBracketIndex[i] is
* the position of the bracket in the expression that closes an opening bracket
* at position openingBracketIndex[i]. For example, if the expression is:
* <pre>
* (a+(b-c))*(d+A[4])
* </pre>
* then the method would return true, and the array lists would be set to:
* <pre>
* openingBracketIndex: [0 3 10 14]
* closingBracketIndex: [8 7 17 16]
* </pe>
*
* See the FAQ in project description for more details.
*
* #return True if brackets are matched correctly, false if not
*/
public boolean isLegallyMatched()
{
Stack<Character> brack = new Stack<Character>();
Stack<Integer> opens = new Stack<Integer>();
openingBracketIndex = new ArrayList<Integer>();
closingBracketIndex = new ArrayList<Integer>();
char x;
char y;
String expr = this.expr;
for(int i=0; i<expr.length(); i++)
{
x = expr.charAt(i);
if(x!='(' && x!= '[' && x!=')' && x!=']')
{
continue;
}
if(x=='(' || x== '[')
{
opens.push(i);
brack.push(x);
}
else if(x==')' || x==']')
{
closingBracketIndex.add(i);
if(opens.isEmpty())
{
return false;
}
openingBracketIndex.add(opens.pop());
if(brack.isEmpty())
{
return false;
}
y = brack.pop();
if(y=='(' && x==')')
{
continue;
}
else if(y=='[' && x==']')
{
continue;
}
else if(y=='{' && x=='}')
{
continue;
}
else
{
return false;
}
}
}
if(!brack.isEmpty())
{
return false;
}
selectionSort(openingBracketIndex);
if(openingBracketIndex.isEmpty()!= true)
{
System.out.print("Opening Bracket Index: [ ");
for(int i=0;i<openingBracketIndex.size(); i++)
{
System.out.print(openingBracketIndex.get(i) + " ");
}
System.out.print("]");
System.out.println();
System.out.print("Closing bracket Index: [ ");
for(int i=0;i<openingBracketIndex.size(); i++)
{
System.out.print(closingBracketIndex.get(i) + " ");
}
System.out.println("]");
}
return true;
}
/**
* Populates the scalars and arrays lists with symbols for scalar and array
* variables in the expression. For every variable, a SINGLE symbol is created and stored,
* even if it appears more than once in the expression.
* At this time, values for all variables are set to
* zero - they will be loaded from a file in the loadSymbolValues method.
*/
public void buildSymbols()
{
scalars = new ArrayList<ScalarSymbol>();
arrays = new ArrayList<ArraySymbol>();
for(int i=0;i<expr.length();i++)
{
String symb = "";
while(i<expr.length() && Character.isLetter(expr.charAt(i)))
{
symb = symb + expr.charAt(i);
i++;
}
if(i==expr.length())
{
i--;
}
if(expr.charAt(i) == '[')
{
ArraySymbol arr = new ArraySymbol(symb);
boolean dupe = checkArrDupes(arr, arrays);
if(symb!="" && dupe == true)
{
arrays.add(arr);
}
}
else
{
ScalarSymbol scal = new ScalarSymbol(symb);
boolean dupe = checkScalDupes(scal,scalars);
if(symb!="" && dupe==true)
{
scalars.add(scal);
}
}
}
// COMPLETE THIS METHOD
}
/**
* Loads values for symbols in the expression
*
* #param sc Scanner for values input
* #throws IOException If there is a problem with the input
*/
public void loadSymbolValues(Scanner sc)
throws IOException {
while (sc.hasNextLine()) {
StringTokenizer st = new StringTokenizer(sc.nextLine().trim());
int numTokens = st.countTokens();
String sym = st.nextToken();
ScalarSymbol ssymbol = new ScalarSymbol(sym);
ArraySymbol asymbol = new ArraySymbol(sym);
int ssi = scalars.indexOf(ssymbol);
int asi = arrays.indexOf(asymbol);
if (ssi == -1 && asi == -1) {
continue;
}
int num = Integer.parseInt(st.nextToken());
if (numTokens == 2) { // scalar symbol
scalars.get(ssi).value = num;
} else { // array symbol
asymbol = arrays.get(asi);
asymbol.values = new int[num];
// following are (index,val) pairs
while (st.hasMoreTokens()) {
String tok = st.nextToken();
StringTokenizer stt = new StringTokenizer(tok," (,)");
int index = Integer.parseInt(stt.nextToken());
int val = Integer.parseInt(stt.nextToken());
asymbol.values[index] = val;
}
}
}
}
/**
* Evaluates the expression, using RECURSION to evaluate subexpressions and to evaluate array
* subscript expressions.
*
* #return Result of evaluation
*/
public float evaluate()
{
printScalars();
printArrays();
String expr = this.expr;
System.out.println("Hello");
float result = evaluate(expr, 0);
return result;
}
public float evaluate(String base, int brackIndex)
{
System.out.println("Method Start");
Stack<Float> numStack = new Stack<Float>();
Stack<String> opStack = new Stack<String>();
Stack<String> op2Stack = new Stack<String>();
Stack<Float> num2Stack = new Stack<Float>();
float x;
float y;
float result;
int swag = findParenIndexes(base);
Stack<Integer> open = new Stack<Integer>();
Stack<Integer> close= new Stack<Integer>();
for(int i=0;i<base.length();i++)
{
if(open.size()==1 && close.size()==1)
{
System.out.println(open.pop() + " " + close.pop());
break;
}
if(base.charAt(i)=='(' || base.charAt(i)=='[')
{
open.push(i);
}
if(base.charAt(i)==')'|| base.charAt(i)==']')
{
open.pop();
close.push(i);
}
}
String expr = base;
String orig = this.expr;
for(int i=0;i<scalars.size();i++)
{
expr = expr.replaceAll(scalars.get(i).name, scalars.get(i).value + "");
}
System.out.println(expr);
StringTokenizer st = new StringTokenizer(expr,delims,true);
String[] tokens = new String[st.countTokens()];
int z=0;
while(st.hasMoreTokens())
{
tokens[z] = st.nextToken();
z++;
}
for(int i=0;i<tokens.length;i++)
{
System.out.println(tokens[i]);
}
for(int i=0;i<tokens.length;i++)
{
String currToken = tokens[i];
if(isNumeric(currToken))
{
numStack.push(Float.parseFloat(currToken));
System.out.println("Number pushed to stack.");
}
if(currToken.charAt(0)=='+')
{
opStack.push(currToken);
System.out.println("+ pushed to stack.");
}
else if(currToken.charAt(0)=='-')
{
opStack.push(currToken);
System.out.println("- pushed to stack.");
}
else if(currToken.charAt(0)=='*')
{
System.out.println("Multiplying...");
System.out.println("Current bracket index is "+ brackIndex);
x = numStack.pop();
i++;
String next = tokens[i];
if(next.charAt(0)=='(')
{
try{
System.out.println("Evaluating " + expr.substring(i+1, swag));
}
catch(Exception e)
{
swag = findParenIndexes(expr.substring(swag,expr.length()));
}
System.out.println("i: " + i + " swag: ") ;
y=evaluate(expr.substring(i+1, swag), brackIndex+1);
result = x*y;
System.out.println("Multiplication worked - evaluate() returned " + result + " and jumped to the "+closingBracketIndex.get(brackIndex)+" index");
i = swag;
System.out.println("i: " + i);
numStack.push(result);
}
if(isNumeric(next))
{
y = Float.parseFloat(next);
result = x*y;
System.out.println(result + " pushed to stack");
numStack.push(result);
}
}
else if(currToken.charAt(0)=='/')
{
System.out.println("Dividing...");
x = numStack.pop();
i++;
String next = tokens[i];
if(next.charAt(0)== '(')
{
y=evaluate(expr.substring(i+1, swag), brackIndex+1);
i = swag;
}
else
{
y = Float.parseFloat(next);
}
if(y==0)
{
System.out.println("Divide by Zero encountered! Please check your input");
throw new IllegalArgumentException();
}
result = x/y;
System.out.println(result + " pushed to stack");
numStack.push(result);
}
else if(currToken.charAt(0)=='(')
{
System.out.println("Evaluating parentheses and adding the term to the stack.");
numStack.push(evaluate(expr.substring(i+1,swag), brackIndex+1));
System.out.println("Jumping to " + swag);
i = swag;
System.out.println("i: " + i);
}
if(arrays.contains(currToken))
{
System.out.println("array variable detected. looking up" + currToken);
int k = arrays.indexOf(currToken);
int cool = arrays.get(k).values[10];
}
// 5+(5*6+(5*3)-4)-9
}
// (a+(b-c))*(d+4)
while(!opStack.isEmpty())
{
op2Stack.push(opStack.pop());
}
while(!numStack.isEmpty())
{
num2Stack.push(numStack.pop());
}
while(op2Stack.isEmpty() == false)
{
String currOp = op2Stack.pop();
if(currOp.charAt(0) == '+')
{
x = num2Stack.pop();
y = num2Stack.pop();
System.out.println("adding "+ x +" and "+ y);
result = x+y;
System.out.println(result + " pushed to stack");
num2Stack.push(result);
if(!opStack.isEmpty())
System.out.println("next op... " + op2Stack.peek());
}
if(currOp.charAt(0) == '-')
{
System.out.println("subtracting...");
x = num2Stack.pop();
y = num2Stack.pop();
result = x-y;
System.out.println(result + " pushed to stack");
num2Stack.push(result);
if(!opStack.isEmpty())
System.out.println("next op... " + op2Stack.peek());
}
}
Float end = num2Stack.pop();
System.out.println("pls work - " + end);
return end;
}
private int findParenIndexes(String expr)
{
Stack<Integer> open = new Stack<Integer>();
Stack<Integer> close = new Stack<Integer>();
for(int i = 0;i<expr.length();i++)
{
if(expr.charAt(i)=='(' || expr.charAt(i)==']')
{
open.push(i);
}
if(expr.charAt(i)==')' || expr.charAt(i)==']')
{
close.push(i);
if(open.size()==1)
{
return close.pop();
}
open.pop();
}
}
return 0;
// COMPLETE THIS METHOD
}
private static boolean isNumeric(String str)
{
try
{
float f = Float.parseFloat(str);
}
catch(Exception e)
{
return false;
}
return true;
}
// test 5*(2+6-(5*3)-6)
/**
* Utility method, prints the symbols in the scalars list
*/
public void printScalars() {
for (ScalarSymbol ss: scalars) {
System.out.println(ss);
}
}
/**
* Utility method, prints the symbols in the arrays list
*/
public void printArrays()
{
for (ArraySymbol as: arrays)
{
System.out.println(as);
}
}
private boolean checkArrDupes(ArraySymbol sym, ArrayList<ArraySymbol> list)
{
if(list.size()!=0)
{
for(int i=0;i<list.size();i++)
{
if(sym==list.get(i))
{
return false;
}
}
}
return true;
}
private boolean checkScalDupes(ScalarSymbol sym, ArrayList<ScalarSymbol> list)
{
if(list.size()!=0)
{
for(int i=0;i<list.size();i++)
{
if(sym==list.get(i))
{
return false;
}
}
}
return true;
}
private void selectionSort(ArrayList<Integer> data)
{
if (data == null)
return;
if (data.size() == 0 || data.size() == 1)
return;
int smallestIndex;
int smallest;
for (int i = 0; i < data.size(); i++)
{
smallest = data.get(i);
smallestIndex = i;
for (int z = i + 1; z < data.size(); z++)
{
if (smallest > data.get(z))
{
// update smallest
smallest = data.get(z);
smallestIndex = z;
}
}
if (smallestIndex != i)
{
int temp = data.get(i);
data.set(i, data.get(smallestIndex));
data.set(smallestIndex, temp);
temp = closingBracketIndex.get(i);
closingBracketIndex.set(i,closingBracketIndex.get(smallestIndex));
closingBracketIndex.set(smallestIndex,temp);
}
}
}
}