How can I recreate the following table? - java

Hello everyone, I'm trying to re-create the table above for an assignment and I'm stuck due to errors concerning the && function. Note that we are not allowed to use arrays and are limited to "switch" and "If"
This is what I've got so far:
if ((BEAK_MM == 1) && (CLAW_MM == 0) && (COLOR = "Grey")) {
System.out.println ("The type of bird is A.");}
else if ((BEAK_MM == 2) && (CLAW_MM == 1) && (COLOR = "Grey"))
System.out.println ("The type of bird is A.");}
else if ((BEAK_MM == 3) && (CLAW_MM == 2) && (COLOR = "Grey"))
System.out.println ("The type of bird is A.");}
else if ((BEAK_MM == 4) && (CLAW_MM == 3) && (COLOR = "Grey"))
System.out.println ("The type of bird is A.");}
else if ((BEAK_MM <= 4.5) && (CLAW_MM == 4) && (COLOR = "Grey"))
System.out.println ("The type of bird is A.");}

Assuming that BEAK and CLAW are integers and COLOR is a String, then the table could be arranged more like:
// must be grey
if ("Grey".equals(COLOR)) {
if ((BEAK_MM == 1 && CLAW_MM == 0)
|| (BEAK_MM == 2 && CLAW_MM == 1)
|| (BEAK_MM == 3 && CLAW_MM AW == 2)
|| (BEAK_MM == 4 && CLAW_MM == 3)
|| ( (BEAK_MM == 4 || BEAK_MM == 5) && CLAW_MM == 4))) {
System.out.println("The bird is the word");
}
}
The logic here is that according to the table, Bird Type A must be Grey. There are then some specific checks as to beak and claw types, but if it is not Grey, it is not a type A bird. There is also no need for all of the OP's stacked 'else if' statements.
There are many other approaches to solve the problem space, but I'm going with the limits of no arrays, and therefore presumably no other useful data structures such as List or Set.
As noted by #Nicholas K, String objects must be compared with .equals().
I'd also move this stuff to a method isBirdTypeA(int beak, int claw, String color) { ... }
#Test
public void testBirds()
{
final String G = "Grey";
final String P = "Pink";
assertTrue(isBirdTypeA(1, 0, G));
assertFalse(isBirdTypeA(1, 0, P));
assertTrue(isBirdTypeA(2, 1, G));
assertTrue(isBirdTypeA(3, 2, G));
assertTrue(isBirdTypeA(4, 3, G));
assertTrue(isBirdTypeA(4, 4, G));
assertTrue(isBirdTypeA(5, 4, G));
assertFalse(isBirdTypeA(4, 5, G));
assertFalse(isBirdTypeA(4, 0, G));
assertFalse(isBirdTypeA(1, 1, G));
}
private static boolean isBirdTypeA(int beak, int claw, String color)
{
if ("Grey".equals(color)) {
if ((beak == 1 && claw == 0)
|| (beak == 2 && claw == 1)
|| (beak == 3 && claw == 2)
|| (beak == 4 && claw == 3)
|| ( (beak == 4 || beak == 5) && claw == 4)) {
return true;
}
}
return false;
}
public static void main(String[] args) {
int BEAK_MM = Integer.parseInt(args[0]);
int CLAW_MM = Integer.parseInt(args[1]);
String COLOR = args[2];
if (isBirdTypeA(BEAK_MM, CLAW_MM, COLOR)) {
System.out.println("The type of bird is A");
}
}
$ java BirdBeak 1 0 Grey
The type of bird is A

Related

tic tac toe horizontal/vertical and diagonal check not wokring - java

I am writing a tic tac toe game and everything seems to work except the checks (horizontal/vertical and diagonal). I am using an array (int [3][3]) to make the board.
These are my checks:
private boolean wonStraightLines( int player)
{
boolean answer = false;
if (
((board[0][0] & board[0][1] & board[0][2]) == (player * 3)) ||
((board[1][0] & board[1][1] & board[1][2]) == (player * 3)) ||
((board[2][0] & board[2][1] & board[2][2]) == (player * 3)) ||
((board[0][0] & board[1][0] & board[2][0]) == (player * 3)) ||
((board[0][1] & board[1][1] & board[2][1]) == (player * 3)) ||
((board[0][2] & board[1][2] & board[2][2]) == (player * 3))
)
{
answer = true;
}
else {
answer = false;
}
return answer;
}
and for the diagonal:
private boolean wonDiagonal( int player)
{
boolean answer = false;
if (
((board[0][0] & board[1][1] & board[2][2]) == (player * 3)) || ((board[0][2] & board[1][1] & board[2][0]) == (player * 3))
)
{
answer = true;
}
else {
answer = false;
}
return answer;
}
when I run the program whenever X or O get 3 from any direction the game keeps running rather than throwing out a "you win" message. Any help would be appreciated. Not sure if any other parts of the code are needed or not.
EDIT: I also tried using the + instead of the & between the board array values but did not work as well.
I'm assuming there are 3 unique values for the states of each element such as for example:
board[row][col] = 0 // no entry
board[row][col] = 1 // player 1
board[row][col] = 2 // player 2
Without being clever a horizontal check for player (using row-major structure) would look like:
(board[0][0] == player && board[0][1] == player && board[0][2] == player)
and repeat for each row.
And similar for vertical, repeating for each column:
(board[0][0] == player && board[1][0] == player && board[2][0] == player)
And one diagonal:
(board[0][0] == player && board[1][1] == player && board[2][2] == player)
If you were determined to use an arithmetic operation then you'd have to change the "player" values to avoid overlap, as in player 1 == 1 and player 2 == 4, such as:
board[row][col] = 0 // no entry
board[row][col] = 1 // player 1
board[row][col] = 4 // player 2
Then you could do something like for a horizontal row:
((board[0][0] + board[0][1] + board[0][2]) == (player * 3))
Note in Java 8 and later adding an int array (a row or column in your case) can be slightly more succinct:
// sum the first row
(IntStream.of(board[0]).sum() == (player * 3))
Now if you really wanted to use the bit-wise "and" operation then this is your check assuming the initial element values (0,1,2) as stated at top:
// check if the player's "bit" is set in all elements of first row.
(board[0][0] & board[0][1] & board[0][2]) == player

What is difference between using logical operators using parentheses?

I am getting different results: -1 if I use parentheses and 1 if I don't use parentheses.
For test case "30/10/2019" I am getting -1 if I use parentheses and 1 if I don't use parentheses in the following line:
else if((mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12) && mm<13 && mm>0 && dd>0 && dd<32) return 1;
What is the difference between above line and below line?
else if(mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12 && mm<13 && mm>0 && dd>0 && dd<32) return 1;
public class Utility {
public static int checkDate(String date){
String []st;
if((date.charAt(2)=='.' && date.charAt(5)=='.')||(date.charAt(2)=='/' && date.charAt(5)=='/')||(date.charAt(2)=='-' && date.charAt(5)=='-'))
{
String token = Character.toString(date.charAt(2));
if(date.charAt(2) == '.') st = date.split("\\.");
else st = date.split(token);
int dd = Integer.parseInt(st[0]);
int mm = Integer.parseInt(st[1]);
int yy = Integer.parseInt(st[2]);
if(mm == 2 && dd>0 && dd<30 && mm<13 && mm>0) return 1;
else if((mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12) && mm<13 && mm>0 && dd>0 && dd<32) return 1;
else if((mm==4||mm==6||mm==9||mm==11) && dd>0 && dd<31 && mm<13 && mm>0) return 1;
else return -1;
}
else return -1;
}
}
import java.util.Scanner;
public class DateValidation {
public static void main(String[] args) {
// STUDENT CODE BEGINS HERE
Scanner sc = new Scanner(System.in);
String dt=sc.next();
Utility ut = new Utility();
int flag = ut.checkDate(dt);
if(flag==1)
System.out.println("Valid");
else
System.out.println("Invalid");
// STUDENT CODE ENDs HERE
}
}
It will execute the following (in highest order of precedence):
Parentheses ()
Not !
And &&
Or ||
else if((mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12) && mm<13 && mm>0 && dd>0 && dd<32)
return 1;
It will evaluate (mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12) first, then && mm<13 && mm>0 && dd>0 && dd<32
else if(mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12 && mm<13 && mm>0 && dd>0 && dd<32)
return 1;
As for the other, it will evaluate mm<13 && mm>0 && dd>0 && dd<32 first, then mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12 &&
Parentheses decide the order these booleans are resolved. And binds stronger than Or. In your case you ask for:
mm==12 && mm<13
So left comparison and right comparison must resolve to true. They don't, as you are in month 10. With parenthesis you decide to check if your month value is valid at all, this resolves to true, and then the && check resolves to true as well.
Consider this example.
int a = 5;
System.out.println((a == 5 || a == 10) && a == 8 || a == 9); // false
// evaluates to true && false || false which is false
System.out.println(a == 5 || a == 10 && a == 8 || a == 9); // true
// evaluate to true || false && false && false
// the first true, wins because it is followed by an || so the whole
// expression evaluates to true.
With a && b both both a and b must be true for the statement to be true
With a || b only one of a and b must be true.
This also goes for grouped expressions.
If one expression is true and the other is false, the complete expression is false for && and true for ||. These operators work from left to right so you need to group appropriately, just like arithmetic expressions.
The best advice is always use parentheses to ensure proper evaluation of expressions.

Tic-Tac-Toe minimax algorithm doesn't work with 4x4 board

So I've been working on this project for the past 3 weeks now. I managed to get the minimax function to work early on for a 3x3 board, however problems started arising when I tried using it for a 4x4 board, namely Java heap space errors. Since then, with the help of Alpha beta pruning, I've managed to bring down the number of required minimax calls within the minimax function from aprox. 59000 to 16000 to 11000 and then finally to 8000 calls(This is assuming an initial minimax call for a board with one slot already filled). The problem now however, is that the method just keeps running for 4x4 games. It simply keeps calling itself non stop, no errors, no result, nothing. Theoretically, the way I see it, my function should work for arbitrary board sizes, the only problem was memory. Now, since I've reduced the memory greed of my function greatly, I'd expected it to work. Well, it does for the 3x3. However, it doesn't for the 4x4.
A brief explanation of what the function does:
The function returns an array of size 2 containing the most favorable next move from amongst all the possible next moves along with the score expected to be achieved from that move. The scoring system is simple. +10 for an O win, -10 for an X win and 0 for a draw. The function is of course recursive. Within it you will find certain shortcuts that reduce the number of required calls to itself. For example if it's X's turn and the returned score is -10(which is the best possible score for X) then exit the loop, i.e. stop observing other potential moves from this state. Here's the code for class State:
private String [] state; //Actual content of the board
private String turn; //Whose turn it is
private static int n; //Size of the board
public State(int n) {
state = new String[n*n];
for(int i = 0; i < state.length; i++) {
state[i] = "-";
}
State.n = n;
}
public int[] newminimax47(int z) {
int bestScore = (turn == "O") ? +9 : -9; //X is minimizer, O is maximizer
int bestPos = -1;
int currentScore;
int lastAdded = z;
if(isGameOver() != "Not Gameover") {
bestScore= score();
}
else {
int i = 0;
for(int x:getAvailableMoves()) {
if(turn == "X") { //X is minimizer
setX(x);
currentScore = newminimax47(x)[0];
if(i == 0) {
bestScore = currentScore;
bestPos = x;
if(bestScore == -10)
break;
}
else if(currentScore < bestScore) {
bestScore = currentScore;
bestPos = x;
if(bestScore == -10)
break;
}
}
else if(turn == "O") { //O is maximizer
setO(x);
currentScore = newminimax47(x)[0];
if(i == 0) {
bestScore = currentScore;
bestPos = x;
if(bestScore == 10)
break;
}
else if(currentScore > bestScore) {
bestScore = currentScore;
bestPos = x;
if(bestScore == 10)
break;
}
}
i++;
}
}
revert(lastAdded);
return new int [] {bestScore, bestPos};
}
Complementary functions used by newminimax47():
isGameOver():
public String isGameOver() {
if(n == 3) {
//Rows 1 to 3
if((state[0] != "-") && (state[0] == state[1]) && (state[1] == state[2]))
return (state[0] == "X") ? "X Won" : "O Won";
else if((state[3] != "-") && (state[3] == state[4]) && (state[4] == state[5]))
return (state[3] == "X") ? "X Won" : "O Won";
else if((state[6] != "-") && (state[6] == state[7]) && (state[7] == state[8]))
return (state[6] == "X") ? "X Won" : "O Won";
//Columns 1 to 3
else if((state[0] != "-")&&(state[0] == state[3]) && (state[3] == state[6]))
return (state[0] == "X") ? "X Won" : "O Won";
else if((state[1] != "-") && (state[1] == state[4]) && (state[4] == state[7]))
return (state[1] == "X") ? "X Won" : "O Won";
else if((state[2] != "-") && (state[2] == state[5]) && (state[5] == state[8]))
return (state[2] == "X") ? "X Won" : "O Won";
//Diagonals
else if((state[0] != "-") && (state[0]==state[4]) && (state[4] == state[8]))
return (state[0] == "X") ? "X Won" : "O Won";
else if((state[6] != "-") && (state[6] == state[4]) && (state[4] == state[2]))
return (state[6] == "X") ? "X Won" : "O Won";
//Checking if draw
else if((state[0] != "-") && (state[1]!="-") && (state[2] != "-") && (state[3]!="-") &&
(state[4] != "-") && (state[5] != "-") && (state[6] != "-") && (state[7] != "-") &&
(state[8] != "-"))
return "Draw";
else
return "Not Gameover";
}
else {
//Rows 1 to 4
if((state[0] != "-") && (state[0] == state[1]) && (state[1] == state[2]) && (state[2] == state[3]))
return (state[0] == "X") ? "X Won" : "O Won";
else if((state[4] != "-") && (state[4] == state[5]) && (state[5]==state[6]) && (state[6] == state[7]))
return (state[4] == "X") ? "X Won" : "O Won";
else if((state[8] != "-") && (state[8] == state[9]) && (state[9]==state[10]) && (state[10] == state[11]))
return (state[8] == "X") ? "X Won" : "O Won";
else if((state[12] != "-") && (state[12] == state[13]) &&(state[13] == state[14]) && (state[14] == state[15]))
return (state[12] == "X") ? "X Won" : "O Won";
//Columns 1 to 4
else if((state[0] != "-") && (state[0] == state[4]) && (state[4] == state[8]) && (state[8] == state[12]))
return (state[0] == "X") ? "X Won" : "O Won";
else if((state[1] != "-") && (state[1] == state[5]) && (state[5] == state[9]) && (state[9] == state[13]))
return (state[1] == "X") ? "X Won" : "O Won";
else if((state[2] != "-") && (state[2] == state[6]) && (state[6] == state[10]) && (state[10] == state[14]))
return (state[2] == "X") ? "X Won" : "O Won";
else if((state[3] != "-") && (state[3] == state[7]) && (state[7] == state[11]) && (state[11] == state[15]))
return (state[3] == "X") ? "X Won" : "O Won";
//Diagonale
else if((state[0] != "-") && (state[0] == state[5]) && (state[5] == state[10]) && (state[10] == state[15]))
return (state[0] == "X") ? "X Won" : "O Won";
else if((state[12] != "-") && (state[12] == state[9]) && (state[9] == state[6]) && (state[6] == state[3]))
return (state[0] == "X") ? "X Won" : "O Won";
//Pruefe ob Gleichstand
else if((state[0] != "-") && (state[1] != "-") && (state[2] != "-") && (state[3]!="-") &&
(state[4] != "-") && (state[5] != "-") && (state[6] != "-") && (state[7] != "-") &&
(state[8] != "-") && (state[9] != "-") && (state[10] != "-") && (state[11] != "-") &&
(state[12] != "-") && (state[13] != "-") && (state[14] != "-") && (state[15] != "-"))
return "Draw";
else
return "Not Gameover";
}
}
Please excuse the bluntness of the isGameOver() method, it merely checks the state of the board( i.e. Win, Draw, Game not Over)
The getAvailableMoves() method:
public int[] getAvailableMoves() {
int count = 0;
int i = 0;
for(int j = 0; j < state.length; j++) {
if(state[j] == "-")
count++;
}
int [] availableSlots = new int[count];
for(int j = 0; j < state.length; j++){
if(state[j] == "-")
availableSlots[i++] = j;
}
return availableSlots;
}
This method merely returns an int array with all available next moves(regarding the current state) or returns empty array if no moves are available or if game is over.
The score() method:
public int score() {
if(isGameOver() == "X Won")
return -10;
else if(isGameOver() == "O Won")
return +10;
else
return 0;
}
setO(), setX() and revert():
public void setX(int i) {
state[i] = "X";
turn = "O";
lastAdded = i;
}
public void setO(int i) {
state[i] = "O";
turn = "X";
lastAdded = i;
}
public void revert(int i) {
state[i] = "-";
if(turn == "X")
turn = "O";
else
turn = "X";
}
My main method looks like this for a 3x3 game:
public static void main(String args[]) {
State s = new State(3);
int [] ScoreAndRecommendedMove = new int[2];
s.setX(8);
ScoreAndRecommendedMove = s.newminimax47(8);
System.out.println("Score: "+ScoreAndRecommendedMove[0]+" Position: "+ ScoreAndRecommendedMove[1]);
}
In this game, X has started the game with a move at position 8. The method in this case will return
Score: 0 Position: 4
Meaning that O's most promising move is at position 4 and in the worst case will yield a score of 0(i.e a draw).
The following image is meant to give an idea of how newminimax47() works. In this case our starting state(board) is given the number 1. Note: The numbers indicate the precedence in creation of the regarded states. 1 was created before 2, 2 was created before 3, 3 was created before 4 and so on.
In this scenario, the score and position eventually returned to state 1 will be
Score: 0 Position: 6
coming from state 8.
Note: The code you see is just snippets of the actual State class. These snippets on their own should allow you to recreate, and play around with, the newminimax47 function without problems(at least for 3x3). Any bugs you may find are not really bugs, they were simply not included in the snippets I copied here and the code should work without them. The lastAdded variable in the setO and setX functions for example is not included in the snippets here but I just realized you don't need it to be able to work with the minimax function, so you can just comment that out.
I played around with your code and there is quite a bit to say
bug
first of all there is a bug. I don't think your code actually works for a 3x3 board. The problem is the location you revert the move you add to the board. You do this at the end of the newminimax47 method exactly once, even though in the method you add moves to the board inside a for loop. This means that calling the method does not only compute something but also changes the board state, and the rest of the code expects it not to.
So remove the revert where it is now and in revert as soon as you can:
setX(x);
currentScore = newminimax47(x)[0];
revert(x);
this also implies you don't need the lastAdded variable.
play
It's a lot easier to see what is happening if you actually play against your own algorithm. Add a method to your State class
public void dump() {
for (int y = 0; y < n; y++) {
for (int x = 0; x < n; x++) {
System.out.print(state[y * n + x]);
}
System.out.println();
}
}
and in you main something like
public void play() {
State s=new State(3);
Scanner in = new Scanner (System.in);
while (s.isGameOver().equals("Not Gameover")) {
int[] options = s.getAvailableMoves();
s.dump();
System.out.println ("Your options are " + Arrays.toString(options));
int move = in.nextInt();
s.setX(move);
int [] ScoreAndRecommendedMove=new int[2];
ScoreAndRecommendedMove=s.newminimax47(0);
System.out.println("Score: "+ScoreAndRecommendedMove[0]+" Position: "+ ScoreAndRecommendedMove[1]);
s.setO(ScoreAndRecommendedMove[1]);
}
s.dump();
}
and you can actually play against it. On a 3x3 board this works just fine for me. Unfortunately I estimated computing the first move on a 4x4 takes my computer approximately 48 hours.
data types
Your choice of data types is often a bit... strange. If you want to remember a single character, use char instead of String. If you want to return a yes/no decision, try use boolean. There are also some parts of the program that could be replaces by less code doing the same. But that wasn't your question, so on to...
algorithm
Ok, so what's wrong with minimax to solve this problem?
Suppose the first four moves are X5, O8, X6 O7. Another possibility is to start the game with X5, O7, X6, O8. Yet another one is X6, O7, X5, O8. And finally there's X6, O8, X5, O7.
All four of those possibilities for the first four moves of the game lead to the exact same gamestate. But minimax will not recognise they're the same (basically there is no memory of parallel branches) so it will compute them all four. And the number of times each board state is computed will increase rapidly if you search deeper.
The number of possible games vastly outnumbers the number of possible board states. To estimate the number of games: at first there are 16 possible moves, then 15, then 14, 13, ... and so on. A rough estimation is 16!, although minimax won't have to compute all of them, because many of them will have finished before the 16th move.
An estimation for the number of game states is: every square on the board can be either empty, or an X, or an O. So that's 3^16 boards. Not all of them are actually valid boards, because the number of Xs on the board can be at most one more then the number of Os, but still it's close to 3^16.
16! possible games is about half a million times more then 3^16 possible board states. Which means we're approximately computing every board half a milion times in stead of just once.
The solution is to start remembering every gamestate you compute. Every time the recursive function is called first check if you already know the answer, and if so just return the old answer. It's a technique called memoization.
Memoization
I'll describe how to add memoization while using the data structures you already choose (even though I don't agree with them). To do memoization you need a collection on which you can do quick adds and quick lookups. A list (for example ArrayList) won't do us any good. It's fast to add values but to do a lookup is very slow in long lists. There are some options but the easiest one to use is HashMap. In order to use HashMap you need to create something that represents your state and you can use as a key. The most straight-forward is to just make a String with all the X/O/- symbols in it that represent your board.
So add
Map<String,int[]> oldAnswers = new HashMap<String,int[]>();
to your State object.
Then at the start of your newminimax47 method create the String that represents the State and check if we already know the answer:
String stateString = "";
for (String field : state) stateString += field;
int[] oldAnswer = oldAnswers.get(stateString);
if (oldAnswer != null) return oldAnswer;
Finally when you compute a new answer the end of newminimax47 you should not only return it, but also store it in the map:
int[] answer = {bestScore, bestPos};
oldAnswers.put (stateString, answer);
return answer;
With memoization in place I was able to play a 4x4 game against your code. The first move is still slow (20 seconds) but after that everything is computed and it's very fast. If you want to speed it up further, you could look into alpha beta pruning. But the improvement won't be near as much as memoization. Another option is using more efficient data types. It won't reduce the theoretical order of your algorithm, but could still easily make it 5 times faster.
As user3386109 explained, the problem here is how many times you calculate everything. There are a few things that may help you out though, considerin an N-sized grid:
a user cannot win if there are less than N of his symbols, so you can use that in the isGameOver function as a first check
the first thing that you have to do is to prevent your opponent from winning if there's a chance that his next move is a winning one
Keep track of how many "X" and "O" are in each row and column and in the two diagonals by incrementing counters every move. If there are N-1 of the same symbol, the next one will be a winning move for either you or your opponent.
By doing so, you can easily tell which is the best move, because then:
if you have a winning move you put the symbol there
check your opponent, if he has N-1 symbols on the same row/column/diagonal you put it there
if your opponent has more symbols than you on some place, you even out the place (that means +1 or +2, depending on who's starting the game)
if that's not the case, you put your next symbol on the row/colum/diagonal where you have more symbols
if you have the same number of symbols on some places, you just put it where your opponent has more symbols
if you and your opponent are entirely even, just go for your own strategy (random would not be bad, I guess :-) )
Unless you really need it (for example as homework), I wouldn't use recursion for this one.
Just as a side note: I don't think it's good practice to have what is actually a boolean function return a string and then compare that with a fixed value. A true/false return value for the isGameOver function looks much better to me.

Straight hand in Java poker game

I am having trouble finishing the straight method for a poker hand. I don't understand why my code doesn't work.
public static boolean containsStraight(int [] hand)
{
boolean straight = false;
for(int i = 0; i < 5; i++)
{
if (hand[i] == 2 && hand[i] == 3 && hand[i] == 4 && hand[i] == 5 && hand[i] == 6)
{
straight = true;
}
if (hand[i] == 3 && hand[i] == 4 && hand[i] == 5 && hand[i] == 6 && hand[i] == 7)
{
straight = true;
}
if (hand[i] == 4 && hand[i] == 5 && hand[i] == 6 && hand[i] == 7 && hand[i] == 8)
{
straight = true;
}
if (hand[i] == 5 && hand[i] == 6 && hand[i] == 7 && hand[i] == 8 && hand[i] == 9)
{
straight = true;
}
}
return straight;
}
As pL4Gu33 has already stated in his answer, your comparison is faulty. Essentially, each step through the for-loop leaves hand[i] at a constant value (say, 4). That means that your if-statements are checking:
if(4 == 4 && 4 == 5 && 4 == 6 && 4 == 7 && 4 == 8) {
...
}
This will never evaluate to true. If you knew for certain that you had five elements in the hand and that the hand was already sorted, you could do
if (hand[0] == 2 && hand[1] == 3 && hand[2] == 4 && hand[3] == 5 && hand[4] == 6) {
...
}
However, I'm going to show you a better answer.
The first thing you should do is to sort your hand. Once you do that, it's easy to step through the hand and check to see if the next card in the hand is exactly one greater than the previous card. If you get to the end and this holds true, then it's a straight.
/*
* You will need to import java.util.Arrays
*/
public boolean isStraight(int[] hand) {
if(hand == null || hand.length != 5) {
return false;
}
else {
// Automatically sort the hand
Arrays.sort(hand);
// Set the "previous" variable to a theoretically impossible value
int prev = -1;
// Iterate through the hand and see if the next card is exactly one more than
// the previous one.
for(int i = 0; i < hand.length; i++) {
// If prev is -1, then this is the first time through the for-loop
// If the card that we're on has a value of the previous card + 1,
// we still have the possibility of a straight.
if(prev == -1 || (prev + 1) == hand[i]) {
prev = hand[i];
}
else {
return false;
}
}
return true;
}
}
You say in every iteration hand[i] must be 2 AND 3 AND 4 AND 5. That is impossible. There is only one number in hand[i].
The problem is, that you are using the cycle incorrectly, because you are always checking the value of the same card in hand[i]. My suggestion would be either to do a sort first, or if you want to be more efficient, you can use a second field of booleans, that would indicate, whether a card of given value is present in your hand. This way you can easily check, if you have any number of cards in succesion.
public static boolean containsStraight(int[] cards) {
int count = 0;
boolean[] valueInHand = new boolean[10];
for (int card : cards) {
valueInHand[card] = true;
}
for (boolean value : valueInHand) {
if (value == true) {
count++;
} else {
count = 0;
}
// works for any number of cards
if (count == cards.length) {
return true;
}
}
return false;
}

JAVA - Figuring out the difference

I'm given the problem below, however I'm unable to have it pass all the tests no matter what approach I take. Could anyone point out where I'm going wrong?
The problem has to be solved using Math.abs() and IF statements, no loops/functions/etc.
////////////////////////////// PROBLEM STATEMENT //////////////////////////////
// Given three ints, a b c, print true if one of b or c is "close" //
// (differing from a by at most 1), while the other is "far", differing //
// from both other values by 2 or more. Note: Math.abs(num) computes the //
// absolute value of a number. //
// 1, 2, 10 -> true //
// 1, 2, 3 -> false //
// 4, 1, 3 -> true //
///////////////////////////////////////////////////////////////////////////////
My code:
if ((Math.abs(a-b) <= 1 || Math.abs(a+b) <= 1) && (Math.abs(a-c) >= 2 || Math.abs(a+c) >= 2)) {
if (Math.abs(a-c) >= 2 || Math.abs(a+c) >= 2) {
System.out.println("true");
} else {
System.out.println("false");
}
} else if (Math.abs(a-c) <= 1 || Math.abs(a+c) <= 1) {
if (Math.abs(a-b) >= 2 || Math.abs(a+b) >= 2) {
System.out.println("true");
} else {
System.out.println("false");
}
} else {
System.out.println("false");
}
Seems overly complex, you might want to go for something more simple:
boolean abIsClose = Math.abs(a-b) <= 1;
boolean acIsClose = Math.abs(a-c) <= 1;
boolean bcIsClose = Math.abs(b-c) <= 1;
boolean result = abIsClose && !acIsClose && !bcIsClose;
result = result || (!abIsClose && acIsClose && !bcIsClose);
result = result || (!abIsClose && !acIsClose && bcIsClose);
Abs always gives a positive number, that way you don't need to confirm a value is between -1 and 1, you only need to confirm <= 1.
You can break this down into two possible situation when it's true
b is close and c is far
c is close and b is far
Now, what does 1. mean?
b is close - Math.abs(a-b) <= 1
c is far - Math.abs(a-c) >= 2 && Math.abs(b-c) >= 2
So we end up with
if (Math.abs(a - b) <= 1 && Math.abs(a - c) >= 2 && Math.abs(b - c) >= 2) {
return true;
}
Now apply the same logic to the second condition:
if (Math.abs(a - c) <= 1 && Math.abs(a - b) >= 2 && Math.abs(b - c) >= 2) {
return true;
}
So the final method looks like:
public static boolean myMethod(int a, int b, int c) {
if (Math.abs(a - b) <= 1 && Math.abs(a - c) >= 2 && Math.abs(b - c) >= 2) {
return true;
}
if (Math.abs(a - c) <= 1 && Math.abs(a - b) >= 2 && Math.abs(b - c) >= 2) {
return true;
}
return false;
}
Output:
public static void main(String[] args) {
System.out.println(myMethod(1, 2, 10));
System.out.println(myMethod(1, 2, 3));
System.out.println(myMethod(4, 1, 3));
}
true
false
true

Categories

Resources