Checking Poker Hands - java

I been having some issues checking poker hands. So in this code we choose how many decks we want to play with and then the rest is like video poker. My issue is that some of the hands checked are "seen". For the straight, I assume because I have it set as though my arraylist is sorted by assumption, how would I fix that?
Also, for two pair, my friend said that a few times it would not properly check if I actually had the two pair, saying it wasn't checking correctly. Here are my check algorithms, can anyone tell me how to fix them? Also, if there are any problems you see besides the straight and two pair having issues. I haven't hit full house or greater yet to test. The .get(#) gets the card suit or rank (getsuit or getrank) from my hand (arraylist). I also think my royal flush may be incorrect.
private boolean flush(){
if (currentHand.get(0).getSuit() == currentHand.get(1).getSuit()
&& currentHand.get(1).getSuit() == currentHand.get(2).getSuit()
&& currentHand.get(2).getSuit() == currentHand.get(3).getSuit()
&& currentHand.get(3).getSuit() == currentHand.get(4).getSuit()){
return true;
}
return false;
}
private boolean royal(){
if ((currentHand.get(0).getRank() == 1)
&& (currentHand.get(1).getRank() == 10)
&& (currentHand.get(2).getRank() == 11)
&& (currentHand.get(3).getRank() == 12)
&& (currentHand.get(4).getRank() == 13)) {
return true;
}
return false;
}
private boolean straight(){//look up
if (currentHand.get(0).getRank() + 1 == currentHand.get(1).getRank()
&& currentHand.get(1).getRank() + 1 == currentHand.get(2).getRank()
&& currentHand.get(2).getRank() + 1 == currentHand.get(3).getRank()
&& currentHand.get(3).getRank() + 1 == currentHand.get(4).getRank()) {
return true;
}
return false;
}
private boolean four(){
if (currentHand.get(0).getRank() == currentHand.get(1).getRank()
&& currentHand.get(1).getRank() == currentHand.get(2).getRank()
&& currentHand.get(2).getRank() == currentHand.get(3).getRank()) {
return true;
} else if (currentHand.get(1).getRank() == currentHand.get(2).getRank()
&& currentHand.get(2).getRank() == currentHand.get(3).getRank()
&& currentHand.get(3).getRank() == currentHand.get(4).getRank()) {
return true;
}
return false;
}
private boolean fullHouse() {
if (currentHand.get(0).getRank() == currentHand.get(1).getRank()
&& currentHand.get(1).getRank() == currentHand.get(2).getRank()) {
if (currentHand.get(3).getRank() == currentHand.get(4).getRank()) {
return true;
}
}else if(currentHand.get(0).getRank() == currentHand.get(1).getRank()){
if(currentHand.get(2).getRank() == currentHand.get(3).getRank()
&& currentHand.get(3).getRank() == currentHand.get(4).getRank()){
return true;
}
}
return false;
}
private boolean threeOfKind(){
if ((currentHand.get(0).getRank() == currentHand.get(1).getRank()
&& currentHand.get(1).getRank() == currentHand.get(2).getRank())
|| (currentHand.get(1).getRank() == currentHand.get(2).getRank()
&& currentHand.get(2).getRank() == currentHand.get(3).getRank())
|| (currentHand.get(2).getRank() == currentHand.get(3).getRank()
&& currentHand.get(3).getRank() == currentHand.get(4).getRank())){
return true;
}
return false;
}
private boolean twoPair() {
if (currentHand.get(0).getRank() == currentHand.get(1).getRank()
&& currentHand.get(2).getRank() == currentHand.get(3).getRank()){
return true;
}
else if((currentHand.get(1).getRank() == currentHand.get(2).getRank())&&
(currentHand.get(3).getRank() == currentHand.get(4).getRank())){
return true;
}
else if((currentHand.get(0).getRank() == currentHand.get(1).getRank())&&
(currentHand.get(3).getRank() == currentHand.get(4).getRank())){
return true;
}else
return false;
}
private boolean jackOrBetter() {
for (int i = 11; i <= 14; i++) {
int comp;
if (i == 14)
comp =1;
else comp = i;
for (int j = 0; j < 4; j++) {
if (currentHand.get(j).getRank() ==comp ) {
if (currentHand.get(j).getRank() == currentHand.get(j + 1).getRank()) {
return true;
}
}
}
}
return false;

Typically the kind of code you'll find in the known (and very fast) poker evaluators are much lower-level than that: no fancy OO or anything like that. Just plain fast bit manipulation and crazy, crazy fast table lookups. The fast hand evaluators out there can evaluate hundreds of millions (!) of hands... Per second! But let's leave that aside and start from your OOish code.
I take it you want a five cards evaluator and then if you play, say, Texas Hold'em then you're going to test the C(7,5), which gives 21, possible ways to take 5 cards out of seven (5 on the board + 2 holecards). And keep the best hand.
So on to your five-cards evaluator.
A "trick" is simplify your job by keeping intermediate information. Your logic is then greatly simplified.
Here's one way you could do it (once again: this is an over-simplification compared to real fast evaluators but it should help you get the job done):
final boolean isFlush = flush();
final int[] nbPerRank = findNumberForEachRank();
final boolean isStraight = straight( nbPerRank );
Where the nbPerRank array for, say, "Queens full of five" (three queens and two fives) may look like this:
; 2 3 4 5 6 7 8 9 T J Q K A
int[] nbPerRank = [ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 0, 0 ]
Then your main method shall look a bit like this:
if ( isStraight ) {
final int highCard = findStraightHighCard();
if ( isFlush ) {
if ( highCard == 13 ) { // starting with the 'A'
System.out.println( "You have a royal flush" );
else if ( highCard = 4 ) { // starting with the '5'
System.out.println( "You have a wheel straight flush" );
} else {
System.out.println( "You have a straight flush " );
}
} else {
... // rinse and repeat for normal straight
}
} else {
...
Note that seen that your evaluator is a 5 card evaluator, once you have a straight you know there are only two possible cases: straight and straight flush (with five cards, it is impossible to have even a pair if you already have a straight with these five cards).
So by now you already have taken the straight flush and the straight into account, you now need to check, in order, for :
four of a kind
full house / boat
flush (but not straight flush anymore)
set
two pairs
one pair
To check if you have four of kind you then see if you have the number 4 in your nbPerRank int array.
Pseudo-code could be like this:
// no need to test for straight an straight flush anymore...
if ( hasFourSameRank ) {
" You have four of a kind ";
} else if ( hasThreeSameRank && hasTwoSameRank ) {
" You have a full house ";
} else if ( isFlush ) {
" You have a flush";
} else if ( hasThreeSameRank ) {
" You have a set ";
} else if ( hasTwoSameRank ) {
// two possible cases here: two pairs or one pair
if ( hasTwoPairs ) {
"You have two pairs";
} else {
"You have one pair";
} else {
"You have no pair";
}
The nested if / else are quite normal in such evaluators (at least the ones not using lookup tables / LUT).
Note that this is just one way to do it. You can go "fancier" and instead of returning simply an int[] containing the number of each card per rank you can also return the max card, the max number of similar rank, etc.
You'll then have to find a way to assign a value (hence the "evaluator" name) for each hand, so that "two pairs, eights and deuces, kicker jack" beats "two pairs, eights and deuces, kicker nine" etc.
But this should get you started.
Another solution would be to simply reuse one of the existing evaluator out there (which, in addition to be tried and tested, shall be really fast: it's only bit manipulation and lookup tables, no slow OO).
(slightly related) you may also want to read my old answer here: On Two Plus Two poker hand evaluator, how do you get the best 5 cards combination out of the 7 that you passed to it?

Related

Finding an Object in an Array List, Defined by a Boolean

I'm working on a project that is supposed to be a maze solver. The code I have is nearly complete, except for one bit. I need to get the index of a point in my array list, but I have a boolean regulating what point I need. I need to be able to get the index of the point that will satisfy the boolean as true, but I'm not quite sure how to do that. I've attached some of the code below. I hope it's enough to show you what I mean!
Here's the boolean with the conditions for what the point will be:
public static boolean adjacent( Point p1, Point p2 )
{
int pointX1 = p1.getX();
int pointX2 = p2.getX();
int pointY1 = p1.getY();
int pointY2 = p2.getY();
while (pointY1 == pointY2)
{
if(pointX1 + 1 == pointX2)
{
return true;
}
else if(pointX1 - 1 == pointX2)
{
return true;
}
}
while (pointX1 == pointX2)
{
if(pointY1 + 1 == pointY2)
{
return true;
}
else if(pointY1 - 1 == pointY2)
{
return true;
}
}
return false;
}
Here's what I have so far for my array list:
public static boolean isSolvable( ArrayList<Point> points )
{
ArrayList<Point> second = new ArrayList<Point>();
second.add(points.get(0));
points.remove(0);
while(second.size() >= 1)
{
//if second contains adjacent point. (Add adjacent to array list, and subtract from other array list[point])
if(points.contains(adjacent(second.get(0), points.get(0))) == true)
{
}
}
return false;
}
As far as I see, you have one major problem in your adjacent(Point, Point) method. Instead using whiles (I don't know why you would use them here) change them to ifs:
if(pointY1 == pointY2)
{
if(pointX1 + 1 == pointX2
|| pointX1 - 1 == pointX2)
return true;
}
if(pointX1 == pointX2)
{
if(pointY1 + 1 == pointY2
|| pointY1 - 1 == pointY2)
return true;
}
EDIT: As #Lars says, you can write this in a one-liner function as:
return Math.abs(p1.getX() - p2.getX()) + Math.abs(p1.getY() - p2.getY()) == 1;
Also, I would try a backtracking, a greedy, or even a branch and bound algorithm to solve your maze too.

Trying to get the code to check if there are even brackets

I am currently trying to come up with a code that will scan a string
and check to see if there is an even number of open and closing brackets on each line. If so, it would return true. (Excuse me for the incorrectness in formatting but I could not get the examples to properly take shape unless I identified it as code)
{} // The code would return true
{{}}
{}{}
{{{}{{}}}}
} // The code would return false
{}
}}{
{{{}{}
What I tried so far:
public boolean bracketsMatch(String brackets)
{
int lb = 0;
int rb = 0;
int i = 0;
while (brackets.charAt(i) == '{' || brackets.charAt(i) == '}' || brackets.charAt(i) == '')
{
if (brackets.charAt(i) == '{')
{
lb += 1;
}
if (brackets.charAt(i) == '}')
{
rb += 1;
}
if (brackets.charAt(i) == '')
{
if (lb / rb == 2)
{
// Is it possible to get the code scan the next line to next line?
// need an extra statement here for ^^ before I can place the if statement below
if (bracket.charAt(i + 1) == '')
{
return true;
}
}
else
{
return false;
}
}
i++
}
}
I apologize in advance for any experienced programmers as this would be an inefficient nightmare. I am relatively new to programming in general. I attempted to have the code check for the number of left brackets (lb) and right brackets (rb). Whenever the code came to an empty string, it would divide lb by rb. If the code did not equal 2, the code would return false. I probably have more than a dozen errors in this code, but I was wondering if there was any way to have the code go onto the next line to scan the next set of brackets. Thanks for any help in advance.
EDIT 1:
public boolean bracketsMatch(String brackets)
{
int balance = 0;
for (int i = 0; i < brackets.length(); i++)
{
char value = brackets.charAt(i);
if (value == '{')
{
balance += 1;
}
else if (value == '}')
{
balance -= 1;
}
}
if (balance != 0)
{
return false;
}
else
{
return true;
}
}
This won't compile, as '' is an invalid character literal:
if (brackets.charAt(i + 1) == '')
And your current approach of counting opening and closing brackets,
and checking the value of lb / rb won't yield the right result.
You don't need to count the right brackets. You only need to count the open brackets, and reduce that count as they get closed.
Here's a sketch of an algorithm you can use,
I hope to not spoil the exercise:
For each character in the string
If it's an open bracket, increment the count
If it's a close bracket
If the open count is 0, there's nothing to close, so they are not balanced, we can stop
Decrement the count
After all characters, if the open count is 0, the brackets are balanced
As an additional code review note, this is bad in many ways:
if (brackets.charAt(i) == '{') {
// ...
}
if (brackets.charAt(i) == '}') {
// ...
}
What's bad:
Calling brackets.charAt(i) repeatedly is unnecessary if the result will always be the same. Call it once and save the result in a variable.
The two if conditions are exclusive: if the first is true, the second won't be true, so it's pointless to evaluate it. The second condition should be if else instead of if. And instead of an if-else chain, a switch could be more interesting here.
Instead of calling the string brackets, it would be better to call it something more general. What if the actual input is "{something}"? Then it contains more than just brackets, but the algorithm would work just the same. Calling it brackets is misleading.
Alternative way to do
You can use Java Stack class [As it represent the List-In-First-Out stack of object].You can use the push and pop method of Stack class. Here is the implementation.
public class BracketMatching {
public static boolean bracketMatch(String input){
Stack<Character> st = new Stack<>();
for(char c : input.toCharArray()){
if( c == '{')
st.push(c);
else if(c == '}'){
if(st.isEmpty())
return false;
st.pop();
}
}
if(st.isEmpty())
return true;
return false;
}
public static void main(String[] args){
String input1 = "{}{{}}{}{}{{{}{{}}}}";
String input2 = "}{}}}{{{{}{}";
System.out.println(bracketMatch(input1));
System.out.println(bracketMatch(input2));
}
}

if there a better way to write this if statment in java

So is there a way to simplify this to make is smaller in anyway?
else if(selectedCards.size() == 3
&& cardAt(selectedCards.get(0)).pointValue() + cardAt(selectedCards.get(1)).pointValue() + cardAt(selectedCards.get(2)).pointValue() == 0
&& !cardAt(selectedCards.get(0)).rank().equals(cardAt(selectedCards.get(1)).rank())
&& !cardAt(selectedCards.get(0)).rank().equals(cardAt(selectedCards.get(2)).rank())
&& !cardAt(selectedCards.get(1)).rank().equals(cardAt(selectedCards.get(2)).rank()))
From what I can see you're trying to test if the 3 cards have different ranks. An easier way to test this is to put them into a Set and see if the set size is same as selected set. This scales to any number of selected cards...
public boolean differentRanks(List<Integer> selectedCards) {
Set<Integer> ranks = new HashSet<Integer>();
for (int card : selectedCards) {
ranks.add(cardAt(card).rank());
}
return ranks.size() == selectedCards.size();
}
I'd also create a method to total the points for the selected cards...
public int sum(List<Integer> selectedCards) {
int total;
for (int card : selectedCards) {
total += cardAt(card).pointValue();
}
return total;
}
So the condition would end up
} else if (selectedCards.size() == 3 && sum(selectedCards) == 0 &&
differentRanks(selectedCards) {
This would be one option:
else if(selectedCards.size() == 3
&& cardAt(selectedCards.get(0)).pointValue() + cardAt(selectedCards.get(1)).pointValue() + cardAt(selectedCards.get(2)).pointValue() == 0
&& !(cardAt(selectedCards.get(0)).rank().equals(cardAt(selectedCards.get(1)).rank())).equals(cardAt(selectedCards.get(2)).rank()) )
To make more readable this condition you could do something like this:
//here you extract the values you need only once and use them in your condition block below
int cardsSize = selectedCards.size();
int pointValue0 = cardsSize == 3 ? cardAt(selectedCards.get(0)).pointValue() : 0;
int pointValue1 = cardsSize == 3 ? cardAt(selectedCards.get(1)).pointValue() : 0;
int pointValue2 = cardsSize == 3 ? cardAt(selectedCards.get(2)).pointValue() : 0;
bool rankEquals = CompareRanks(cardAt(selectedCards.get(0)),cardAt(selectedCards.get(1)),cardAt(selectedCards.get(2));
if (<condition>) {
//block of sentences
} else if (cardsSize == 3 && (pointValue0 + pointValue1 + pointValue2) == 0 && !rankEquals )
I'm suggesting the creation of a function called "CompareRanks" where you receive 3 different objects (result of "cardAt") and you get the rank in there and compare if the values are the same or not.
This option leads you to more lines of code but is cleaner and more readable for any person besides you.
In my opinion most readable:
else if(selectedCards.size() == 3 && checkRanks(selectedCards))
{
//...
}
//...
private boolean checkRanks(List<Card> cards)
{
Card zeroCard = cardAt(selectedCards.get(0));
Card firstCard = cardAt(selectedCards.get(1));
Card secondCard = cardAt(selectedCards.get(2));
boolean isZero = zeroCard.pointValue() + firstCard.pointValue() + secondCard.pointValue() == 0;
boolean zeroCardRankNotEqualFirst = !zeroCard.rank().equals(firstCard.rank())
boolean zeroCardRankNotEqualSecond = !zeroCard.rank().equals(secondCard.rank())
boolean firstCardRankNotEqualsSecond = !firstCard.rank().equals(secondCard.rank());
return isZero && zeroCardRankNotEqualFirst && zeroCardRankNotEqualSecond && firstCardRankNotEqualsSecond;
}

Java if-statement being skipped

The method below takes in a string and a pattern and returns true if they match each other. A '.' matches 1 char and a '*' matches 0 or more (e.g. expMatch("abc", "a.c") should return true). I added a bunch of print statements to see where I went wrong and it seems like the if statement is being skipped even if the str.length() == 1.
I call it with System.out.println(expMatch("abc", "a*c"));
Here is the code:
public static boolean expMatch(String str, String pat)
{
if (str.charAt(0) == pat.charAt(0) || pat.charAt(0) == '.')
{
System.out.println("in if");
System.out.println(str.charAt(0));
System.out.println(pat.charAt(0));
System.out.println(str.length());
if (str.length() == 1)
return true;
expMatch(str.substring(1), pat.substring(1));
}
else if (pat.charAt(0) == '*')
{
System.out.println("in else");
System.out.println(str.charAt(0));
System.out.println(pat.charAt(0));
if (str.length() == 1)
return true;
if (str.charAt(0) == pat.charAt(1)) //val of * = 0
expMatch(str, pat.substring(1));
else if (str.charAt(1) ==pat.charAt(1))
expMatch(str.substring(1), pat.substring(1));
}
return false;
}
and the output is:
in if
a
a
3
in else
b
*
in if
c
c
1
false
Even if the length is 1 it skips the if? Any idea why?
P.S. I'm not looking for the solution, just why the if statement is being skipped.
You always return false from the method at the very end. You are calling expmatch recursively but never using the return value. The code comes in to the first if, recurses (because length is not 1) and upon returning will go to the final return statement which returns false.
You need to add a return before your expMatch() calls - because the false comes from your last line return false;
What happens is this:
you call expMatch() with the two Strings.
you enter the if clause
the if clause enters expMatch() recursively
you enter the else clause
the else clause enters expMatch() recursively
you enter the if clause again
you leave the expMatch() method
you leave the other expMatch method
false is returned
Your approach is logically incorrect even if you apply the fixes the others suggested. Try this test case:
System.out.println(expMatch("abddddc", "a*c"));
This is because when you encounter a * in the pattern, you have no way to know how many characters "to eat" from the search string.
To say the least, you need a loop somewhere, not just an if. Let me try to fix it for you (not sure if it's possible though, not sure if you always know which path to take, I mean in your recursion). Think some more about it. Here is another unpleasant test case:
System.out.println(expMatch("adddcac", "a*c"));
// the * needs to eat dddca (despite the c present in dddca),
// it should not stop recursing there at that c
I think you need some sort of full search here.
Just an if or a while loop is not good enough.
EDIT: Here is a fixed version with a bunch of nasty tests. I think this is called non-linear recursion (as it's not a single path you try). Not 100% sure though about that term.
public class Test055 {
public static void main(String[] args) {
// System.out.println(expMatch("abddddc", "a*c"));
System.out.println(expMatch("adcax", "a*c"));
System.out.println(expMatch("adcax", "a*c*"));
System.out.println(expMatch("adcacm", "*"));
System.out.println(expMatch("adcacmmm", "a*c"));
System.out.println(expMatch("adcacmmmc", "a*c"));
System.out.println(expMatch("adcac", "a*c"));
System.out.println(expMatch("adcacxb", "a*c.b"));
System.out.println(expMatch("adcacyyb", "a*c.b"));
System.out.println(expMatch("adcacyyb", "a*c*b"));
}
public static boolean expMatch(String str, String pat)
{
// System.out.println("=====================");
// System.out.println("str=" + str);
// System.out.println("pat=" + pat);
if (pat.length() == 0 && str.length() > 0) {
return false;
} else if (pat.length() == 0 && str.length() == 0) {
return true;
} else if (pat.charAt(0) == '.'){
return str.length() >= 1 && expMatch(str.substring(1), pat.substring(1));
}else if (pat.charAt(0) != '*'){
return str.length() >= 1 && pat.charAt(0) == str.charAt(0) && expMatch(str.substring(1), pat.substring(1));
}else{
// Now let's handle the tricky part
// (1) Look for the 1st non-star in pattern
int k=-1;
char ch = ' ';
for (int i=0; i<pat.length(); i++){
if (pat.charAt(i) != '*'){
k = i;
ch = pat.charAt(k);
break;
}
}
if (k==-1){
// (2A) only stars found in pattern, OK, any str matches that
return true;
}else{
// (2B) do full search now checking all
// possible candidate chars in str that
// match the char ch from pattern
for (int i=0; i<str.length(); i++){
if (str.charAt(i)==ch){
boolean b = expMatch(str.substring(i+1), pat.substring(k+1));
if (b) return true;
}
}
return false;
}
}
}
}

How can I remove one of these if statements and shorten the code?

I have the following code. The only problem is that we run it through a checkstyle program and it comes up with the error Cyclomatic Complexity is 11 (max allowed is 10). I would like to know how can remove one of the if statement to make it do the same thing and let the program pass the test.
/**
* Check if there is a winner on the board
* #return the winner if BLANK there is no winner
**/
public char checkWinner(){
this.winner = BLANK;
int totalTiles = GRIDSIZE*GRIDSIZE;
//Check if the game has a win
for (int i=0; i < GRIDSIZE; i++) {
if((grid[i][0] == grid[i][1]) && (grid[i][1] == grid[i][2])){
winner = grid[i][0];
return winner;
}
if((grid[0][i] == grid[1][i]) && (grid[1][i] == grid[2][i])){
winner = grid[0][i];
return winner;
}
}
if((grid[0][0] == grid[1][1]) && (grid[1][1] == grid[2][2])){
winner = grid[0][0];
return winner;
}
if((grid[0][2] == grid[1][1]) && (grid[1][1] == grid[2][0])){
winner = grid[0][2];
return winner;
}
//Check if the game is a tie
if (movesMade == totalTiles){
winner = TIE;
}
return winner;
}
I don't know how the checker works but how about this:
if(((grid[0][0] == grid[1][1]) && (grid[1][1] == grid[2][2])) ||
((grid[0][2] == grid[1][1]) && (grid[1][1] == grid[2][0]))) {
winner = grid[1][1];
return winner;
}
If this does work, the irony of course is that this seems a little less readable than your code.
You could extract methods for checking rows and column and rewrite your code something like this:
public char checkWinner()
{
for (int i=0; i < GRIDSIZE; i++) {
if (checkRow(i)) return winner;
if (checkColumn(i)) return winner;
}
if (checkDiagTopLeft()) return winner;
if (checkDiagBottomLeft()) return winner;
}
Easier to read and less complexity.
Side note: Obviously, the winner stuff could use a redesign, but that was not part of the question and is left as an exercise for the reader (and commenters) if they feel like it.
The solution is already up there (combining the if statements), but I would not let Cyclomatic Complexity dictate my coding if the code of a method fits on a single page. The measure you want to aim for in a big project is readability and ease of understanding. Remember that code will be written potentially only once, but read quite a few times.
The first step can be to remove some redundancy from the equal expression. The allEqual makes the intent a bit clearer.
Assinging the winner to a field is strange. I've removed that in the refactoring. If you really need the assignment you could do it in a separate method calling checkWinner. The problem with returning and assigning is that it's unexpected for a caller to have this side effect.
public char checkWinner() {
// Check if the game has a win
for (int i = 0; i < GRIDSIZE; i++) {
if (allEqual(grid[i][0], grid[i][1], grid[i][2])) return grid[i][0];
if (allEqual(grid[0][i], grid[1][i], grid[2][i])) return grid[0][i];
}
if (allEqual(grid[0][0], grid[1][1], grid[2][2])) return grid[0][0];
if (allEqual(grid[0][2], grid[1][1], grid[2][0])) return grid[0][2];
// Check if the game is a tie
int totalTiles = GRIDSIZE * GRIDSIZE;
return movesMade == totalTiles ? TIE : BLACK;
}
private boolean allEqual(char... c) {
for(int i=1;i<c.length;i++) if(c[i-1] != c[i]) return false;
return true;
}
Open Problems:
The char[][] array is not the most efficient data structure to represent the board. You could use a BitSet.
You defined GRIDSIZE constant but you're could would break down if you actually changed it from 3 to another value.
You can use the fact that checking row/columns and diagonals is symmetric. The parameters have to be transposed use this.
Using the GRIDSIZE constant you do not have to address all cells explicitly:
public char checkWinner() {
// Check if the game has a win
for (int i = 0; i < GRIDSIZE; i++) {
if (rowEqual(i)) return grid[i][0];
if (columnEqual(i)) return grid[0][i];
}
if (diagonalLeftToRightEqual()) return grid[0][0];
if (diagonalRightToLefttEqual()) return grid[0][GRIDSIZE];
// Check if the game is a tie
int totalTiles = GRIDSIZE * GRIDSIZE;
return movesMade == totalTiles ? TIE : BLACK;
}
private boolean rowEqual(int r) {
for(int i=1;i<GRIDSIZE;i++) if(grid[r][i-1] != grid[r][i]) return false;
return true;
}
private boolean diagonalLeftToRightEqual() {
for(int i=1;i<GRIDSIZE;i++) if(grid[i-1][i-1] != grid[i][i]) return false;
return true;
}
Cyclometric complexity is a measure of the number of paths through your code. Your function is composed almost exclusively of if statements.
You can combine two or more if statements with or:
if(a)
do_something();
if(b)
do_something();
Should be replaced by:
if(a || b)
do_something();

Categories

Resources