So the premise here is that a String array of five "cards" is checked to see what sort of hand is given. The type of hand is an int where the higher number is a better hand. This particular segement of code was not written by me, but by a friend who is having trouble and I can't quite find the problem
int checkHand(String[][] Hand) {
boolean check = true;
for(int i = 0; i < 4; i++) {
if(!Hand[i][1].equals(Hand[i+1][1]))
check = false;
}
//check pair starts
for(int i = 0; i < 5; i++) {
for(int n = i + 1; n < 5; n++) {
if(Hand[i][0].equals(Hand[n][0])) {
BestCard = 1;//###OUTPUTS 1 FOR A PAIR###
temp = Hand[0];
Hand[0] = Hand[i];
Hand[i] = temp;
temp = Hand[1];
Hand[1] = Hand[n];
Hand[n] = temp;
//check three of a kind starts
for(int p = n + 1; p < 5; p++) {
if(Hand[i][0].equals(Hand[p][0])) {
temp = Hand[2];
Hand[2] = Hand[p];
Hand[p] = temp;
BestCard = 3; //Problem starts here- Output 3 for Three of a Kind
if(Hand[3][0].equals(Hand[4][0]))
BestCard = 6;//###OUTPUTS A 6 FOR A FULL HOUSE###
else if(Hand[2][0].equals(Hand[3][0])) {
BestCard = 7;
}
else if(Hand[2][0].equals(Hand[4][0])) {
temp = Hand[3];
Hand[3] = Hand[4];
Hand[4] = temp;
BestCard = 7;//###OUTPUTS A 7 FOR A FOUR OF A KIND###
}
}
}
}
}
}
if(check && BestCard<4)
BestCard = 5;//###OUTPUTS 5 FOR A FLUSH###
else if(check && BestCard == 4)
BestCard = 8;//###OUTPUTS 8 FOR A STRAIGHT FLUSH###
return BestCard;
}
When this runs (and there's more to it, but this is what I believe to be the problem area,) It can determine whether or not said hand is a pair or flush. Aside from that, it does not return the proper number. The strange thing is that everything else in the statement will run- if there is a three of a kind forced but not ordered, the hand will be reordered to be proper. The same occurs with a four of a kind. Comments are given where the value of BestCard is changed. int BestCard and String[] temp are already initialized.
well I found your error.
Lets say your hand is 3 2 K 3 Q
your i = 0 so n = 1 and p = 2
for the initial loop through nothing really happens,
so p goes through
and on the second go through, when p = 2. you hit a problem
the first line is
if(hand i == hand p)
at this point hand i = 3 AND hand p = 3
BUT you do not have 3 of a kind you simply have a pair.
Also the program is going to give this error again once the p for loop finishes and n=2 because then p will again start at 3 and return that you have 3 of a kind, when you really only have a pair.
I hope this helps.
I would suggest making each of them their own for loops instead of trying to do them all at once, a lot less confusing, and easier to do when you are newer to java.
PS you should probably change your bestcard values so you can win by high card if no one has a pair.
Related
I just started with java and while was doing an exercise about permutations (the exercise asked to create a permutation of N elements using an array a[] meeting the requirement that no a[i] is equal to i.) I've created the following code. While testing it, I realized that it entered in a infinite loop sometimes when N = 6 specifically.
Any thoughts on where is the problem?
public class GoodPerm {
public static void main(String arg[]) {
int n = Integer.parseInt(arg[0]);
int[] guests = new int[n];
for (int i = 0; i < n; i++) {
guests[i] = i;
}
for (int i = 0; i < n; i++) {
int r = i + (int) (Math.random() * (n - i));
int q = guests[r];
guests[r] = guests[i];
guests[i] = q;
if(guests[i] == i){
i --;
}
}
for(int q : guests){
System.out.println(q);
}
}
}
Maybe the code enters in a inf-loop in another values, but I didn't found any others.
This code can always enter an inf-loop. As I understand the code, you try to do some random switches to achieve your needed result. But if the last element of your array has never been switched, it won't be possible to switch it to any "later/higher" position (because there are no more). In the "last" iteration of your second for-loop (so i + 1 == n holds at the beginning) r will always evaluate to i thus no real switch happens. If the last element is still in place, you gonna repeat this forever.
I am coding to create two "even teams" based on the players' scores (puntajes).
The algorithm runs through the array of players and compares the score of each one to get a minimum difference and then sorts players into two arrays, one for each team.
Here is my code:
if (listaDeJugadores.size() == 6)
//In this case I'm looking for a 6 player array, to create 3 vs 3 teams, but I'm looking to do until 22 (11 vs 11). Any ideas are welcomed.
{
int dif1 = Math.abs((listaDeJugadores.get(0).getPuntaje() + listaDeJugadores.get(1).getPuntaje() + listaDeJugadores.get(2).getPuntaje())
- (listaDeJugadores.get(3).getPuntaje() + listaDeJugadores.get(4).getPuntaje() + listaDeJugadores.get(5).getPuntaje()));
int jugador1 = 0;
int jugador2 = 1;
int jugador3 = 2;
int jugador4 = 3;
int jugador5 = 4;
int jugador6 = 5;
int a = 0;
int b = 0;
int c = 0;
//The two fors are to search the arrays. The iterador is to find the other three remaining positions to compare.
for (int cont2 = 1; cont2 < listaDeJugadores.size() - 1; cont2++) {
for (int cont3 = cont2 + 1; cont3 < listaDeJugadores.size(); cont3++) {
ArrayList<Integer> arr = new ArrayList<>();
int iterador[] = {0,1,2,3,4,5,6};
int j = 1;
for (int i=0;i<iterador.length;i++)
{
//I look for the missing players to compare from the 6 possible
if (cont2==iterador[i]|cont3==iterador[i])
{
j++;
}
else
{
c=b;
b=a;
a=j;
i--;
j++;
}
}
int dif = Math.abs((listaDeJugadores.get(0).getPuntaje() + listaDeJugadores.get(cont2).getPuntaje() + listaDeJugadores.get(cont3).getPuntaje())
- (listaDeJugadores.get(a).getPuntaje() + listaDeJugadores.get(b).getPuntaje() + listaDeJugadores.get(c).getPuntaje()));
if (dif < dif1) {
dif = dif1;
jugador1 = 0;
jugador2 = cont2;
jugador3 = cont3;
jugador4 = a;
jugador5 = b;
jugador6 = c;
}
}
}
//I add the best available sorted teams to EquipoBlanco or EquipoNegro.
listaEquipoBlanco.add(listaDeJugadores.get(jugador1));
listaEquipoBlanco.add(listaDeJugadores.get(jugador2));
listaEquipoBlanco.add(listaDeJugadores.get(jugador3));
listaEquipoNegro.add(listaDeJugadores.get(jugador4));
listaEquipoNegro.add(listaDeJugadores.get(jugador5));
listaEquipoNegro.add(listaDeJugadores.get(jugador6));
team1.setText("Equipo Blanco: " + (listaEquipoBlanco.get(0).getPuntaje() + listaEquipoBlanco.get(1).getPuntaje() + listaEquipoBlanco.get(2).getPuntaje()));
team2.setText("Equipo Negro: " + (listaEquipoNegro.get(0).getPuntaje() + listaEquipoNegro.get(1).getPuntaje() + listaEquipoNegro.get(2).getPuntaje()));
I think the code is ok, but when I try to run it, it won't open because it has really bad performance. I'm thinking I might have iterated to infinity or something similar, but also when I look at it and see fors inside of fors inside of fors I know something is wrong.
How can I make it run faster and have better performance?
A quick look at it and that inner for loop looks suspicious. I might be wrong without trying ( bad me), but it has a i--; in there and i is the loop index so of that happens all the time or often enough you will never exit that one.
That happens when this isn't true: cont2==iterador[i]|cont3==iterador[i] (bitwise or, should probably be logical or || by the way), Not sure that is guaranteed to be true at some point? Could go back and forth even perhaps. cont2 and contr3 doesn't change but i can change a little bit.
No protection for i to go below zero though either so could crash and burn (exception).
I'm a pretty basic programmer and I'm coding a 'Master-mind' style guessing game program.
Now the part I'm stuck with is that I want to go through an array and increase the pointer when I come across a specific number.
Now thats pretty easy and stuff, but what I want to do is ONLY increase the counter if the number is encountered for the first time. So, for example if there are two numbers (189, 999), I want the counter to increase only once, instead of 3 times, which is what my code is doing. I know why its doing that, but I can't really figure out a way to NOT do it (except maybe declaring an array and putting all the repeated numbers in there and only incrementing it if none of the numbers match, but that's super inefficient) Here's my code:
for (int i = 0; i < mString.length(); i++) {
for (int j = 0; j < nString.length(); j++) {
if (mString.charAt(i) == nString.charAt(j)) {
correctNumbers++;
}
}
}
Thanks for taking the time to read! I'd prefer it if you wouldn't give me a direct answer and just point me in the right direction so I can learn better. Thanks again!
Your question is quite unclear. I suppose 989 and 999 will return 1. Because you only deal with number, so the solution is:
Create a boolean array with 9 element, from 0-9, named isChecked
Initialize it with false.
Whenever you found a matching number, say 9, turn the boolean element to true, so that you don't count it again (isChecked[9] = true).
Here is the code:
var isChecked = [];
function resetArray(input) {
for (var i = 0; i < 10; i++) {
input[i + ''] = false;
}
}
resetArray(isChecked);
var firstNumber = '989',
secondNumber = '999',
correctNumbers = 0,
fNum, sNum;
for (var i = 0; i < firstNumber.length; i++) {
fNum = firstNumber.charAt(i);
// Skip already checked numbers
if (isChecked[fNum]) {
continue;
}
for (var j = 0; j < secondNumber.length; j++) {
sNum = secondNumber.charAt(j);
if (fNum == sNum && !isChecked[sNum]) {
correctNumbers++;
isChecked[sNum] = true;
}
}
}
console.log(correctNumbers);
Tested on JSFiddle.
If you find anything unclear, feel free to ask me :)
(except maybe declaring an array and putting all the repeated numbers in there and only incrementing it if none of the numbers match, but that's super inefficient)
That approach is a good one, and can be made efficient by using a HashSet of Integers. Everytime you encounter a common digit, you do a contains on the set to check for that digit (gets in HashSets are of constant-time complexitiy - O(1), i.e. super quick), and if it's present in there already, you skip it. If not, you add it into the set, and increment your correctNumbers.
I believe this would help
int found=0; for (int i = 0; i < mString.length(); i++) {
for (int j = 0; j < nString.length(); j++) {
if (mString.charAt(i) == nString.charAt(j)) {
if(found==0){
correctNumbers++;
}
}
}
}
You could try making another 1D array of
int size = nstring.length() * mstring.length();
bool[] array = new bool[size];`
and then have that store a boolean flag of whether that cell has been updated before.
you would find the unique index of the cell by using
bool flag = false
flag = array[(i % mString.length()) + j)];
if(flag == true){
<don't increment>
}else{
<increment>
array[(i % mString.length()) + j)] = true;
}
you could also do this using a 2d array that basically would act as a mirror of your existing table:
bool[][] array = new bool[mstring.length()][nString.length()];
Why not just use the new stream api? Then it's just that:
Arrays.stream(mString).flatMapToInt(s -> s.chars()).distinct().count();
I'll explain:
Arrays.stream(mString) -> Create stream of all strings.
flatMapToInt -> create single concatenated stream from many IntStreams
s -> s.chars() -> Used above to create streams of characters (as ints)
distinct -> remove all duplicates, so each character is counted only once
count -> count the (unique) characters
I'm trying to create a list of 20 integers between 0 and 26 (so in the 1-25 range) that does not repeat as a part of an assignment. I thought I had it figured out, but the program keeps looping over and over without ever ending. Can anyone help me out?
import java.util.Random;
public class prog433a
{
public static void main(String args[])
{
Random r = new Random();
int[] list = new int[20];
for (int k = 0; k < list.length; k++)
{
boolean notADupe = false;
while (notADupe == false)
{
list[k] = r.nextInt(25) + 1;
for (int j = 0; j < list.length; j++)
{
if (list[j] == list [k] && j != k)
{
notADupe = true;
}
else
{
notADupe = false;
break;
}
}
System.out.println(list[k]);
}
}
}
}
EDIT: This is different from the other question because I am trying to figure out how to check for uniqueness using the methods that I am allowed to use in my assignment (essentially, the ones I'm already using in the code).
I think you've reversed the condition out there. Inside if, you should set notADup to false, rather than true. However, I would make the variable isDup instead, and change the while loop accordingly.
One more suggestion: instead of while (notADupe == false), you should just use while (!notADupe). Never compare boolean variables like that. It might surprise you at times.
So to solve your issue, just change your if-else block to:
if (list[j] == list [k] && j != k) {
notADupe = false;
break;
} else {
notADupe = true;
}
BTW, your solution is a bit complex. For every element, you are iterating over whole array to find duplicate. Rather I would suggest you to maintain a Set<Integer> storing the already seen numbers, and check in that every randomly generated number. If present, skip it and re-generate.
Pseudo code would look something like this:
arr = [] // Your list array, initialize to size 20
seen = [] // A Set
for i from 1 -> arr.length
num = rand.nextInt(25) + 1
while seen contains num
num = rand.nextInt(25) + 1
seen.add(num)
arr[i] = num
i made this boggle-type game, and so far it works very well. This method here is for searching the 10x10 grid to see if the word the user entered is correct. The problem i have is that this code only works for words that appear left to right, and top to bottom. Now i don't expect to do diagonal, but i would like to make it to where the words that appear in reverse order are also accepted by the system. I've been told that the word that you enter would have to be flipped (reversed) in order to see if it matches properly (which makes sense. After all, you're looking for a word that is backwords). So exactly how would i achieve this? Now, i'm not very good with coding, so please, if you have time then write down what code i would have to use. Thank you.
public static boolean wordSearch (char[][] table, String search)
{
int ctr = search.length();
String temp = "";
// LEFT TO RIGHT / X-AXIS
for (int row = 0; row < 10; row++) //Checks each row (x) one by one
{
for (int a = 0; a <= (10 - ctr); a++)
{
StringBuilder s = new StringBuilder(10-ctr);//Does... something
for (int x = a; x <= (a+ctr-1); x++) //Checks every possibility in the row
{
s.append(table[row][x]);
temp = s.toString();
if (temp.equals(search))
{
return true;
}
}
}
}
// TOP TO BOTTOM / Y-AXIS
for (int column = 0; column < 10; column++)
{
for (int b = 0; b <= (10 - ctr); b++)
{
StringBuilder v = new StringBuilder(10-ctr);
for (int y = b; y <= (b+ctr-1); y++)//checks every possibility in grid
{
v.append(table[y][column]);
temp = v.toString();
if (temp.equals(search))
{
return true;
}
}
}
}
return false;//if word isn't in grid it returns as false, which then displays an error message
}
EDIT ... the Java version!!! (I have no Java compiler handy right now but I think this is right...)
At the second line of your code, we compute the reverse string;
there are thousands of ways to do this, but this one is pretty self-explanatory (I am assuming there is no white space in your string...):
int ls = search.length(); // length of initial string
StringBuilder sb = new StringBuilder(); // temporary place to store growing string
for(int ii=ls-1;ii>=0; ii--) {
sb.append(search.charAt(ii)); // build the string one character at a time
}
hcraes = sb.toString(); // convert to "regular" string
Now, at every point where you have the line
if (temp.equals(search))
change that line to
if (temp.equals(search) || temp.equals(hcraes))
that should do the trick.