I'm trying to make this app for android, but here's the problem, I fill 2 lists, then I shuffle them, then I make a for to mix them and make the "couples", but before this I made a while to see if the final list(the list with the couples), is the same size as the original list (if this is true so everything is ok, since the couples will be the same size as the people playing), ALWAYS if the app goes to the while, it crashes, only if never goes to the while, I get the couples, here's my code:
protected void onCreate(Bundle savedInstanceState) { //when the app starts
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_amigo__secreto);
spinner1 = (Spinner) findViewById(R.id.spinner);
lista = new ArrayList<String>();
AdminSQLiteOpenHelper admin = new AdminSQLiteOpenHelper(this, "amigoS", null, 1);
this.llenarLista();
this.llenarLista2();
if (lista.size() > 1){ //if there are more than 2 people do this
Collections.shuffle(lista);
Collections.shuffle(lista2);
reproductor = MediaPlayer.create(this, R.raw.cancion);
reproductor.setLooping(true);
reproductor.start();
sorteo(); //here is the problem, look
}
}
public int sorteo() {
do {
listaParejas.clear();
listaSalidos.clear();
int start2;
for (int i = 0; i < lista.size(); i++) {
start2 = random.nextInt(lista2.size() - 0) + 0;
if (lista2.get(start2).equals(lista.get(i))) { if the person who receives is equals to the one who gives, continue
continue;
} else { //here I add who gives and receives
listaParejas.add(lista.get(i) + "->" + lista2.get(start2));
listaSalidos.add(lista2.get(start2));
lista2.remove(start2); //And remove the person who receives so that he'll never get out again
}
}
} while (listaParejas.size() != lista.size());
return 0;
}
Please any advice, I don't know what to do next, I've trying and trying, but I have no idea why always in the while, the app fails... Thanks
I think your process is based on the luck of your random factor to make the process to finish. This is not ok at all, specially because you are doing it in the main thread. What I would do is:
Take the first list, make a copy and shuffle it using a random sort. See for example Collections.shuffle(list).
Take the first list and make the couples using the following logic:
Take the first element of the first list and couple it with the first element of the second list.
If the element from the first list is the same as the element in the second, take the next one.
Remove the elements from both lists.
Repeat until the lists are empty.
This is also ensuring you have the same number of elements and that they are not the same. You can also use a queue or a stack to make your life easier.
Related
I am passing some parameters in the URL and then I add them in a list. My list has a limit of 5 elements. So if someone adds 6th element in the URL the list would simply ignore it. So I am trying to use a counter but the logic is not working as desired. I am using While loop to achieve this. So if list size is smaller than 5 set the agencyCds otherwise just return the list.
private List<IUiIntegrationDto> generateViewIntegrationReportData(ESignatureIntegrationConfig eSignConfig) throws Exception {
int counter = 1;
if(eSignConfig.getAdditionalAgencyCds() != null ) {
List<String> combinedAgencyCds = new ArrayList<String>();
for(String agencyCd : eSignConfig.getAgencyCd()) {
combinedAgencyCds.add(agencyCd);
}
StringTokenizer token = new StringTokenizer(eSignConfig.getAdditionalAgencyCds().toString(), StringConstants.COMMA);
while(token.hasMoreTokens()) {
combinedAgencyCds.add(token.nextToken());
}
while(combinedAgencyCds.size() < 5) {
counter = counter + 1;
eSignConfig.setAgencyCd(combinedAgencyCds);
}
// eSignConfig.setAgencyCd(combinedAgencyCds);
}
List<IUiIntegrationDto> intgList = getUiIntegrationManager().retrieveUiIntegrationReportData(eSignConfig.getAgencyCd(), eSignConfig.getCreatedDays(),
eSignConfig.getLob(), eSignConfig.getTransactionStatus(), eSignConfig.getAccounts(), eSignConfig.getSortKey(), eSignConfig.getSortOrder());
return intgList;
}
I am not completely sure about this logic if it is correct or if there is nay better approach.
Thanks
Try this instead of the last while in your code:
if(combinedAgencyCds.size() <= 5) {
eSignConfig.setAgencyCd(combinedAgencyCds);
} else {
eSignConfig.setAgencyCd(combinedAgencyCds.subList(0, 5));
}
The full combined list will then be used if it is less than 5 in size. Otherwise, only the first 5 elements are used.
Edit: Or even better:
eSignConfig.setAgencyCd(combinedAgencyCds.subList(0, Math.min(5, combinedAgencyCds.size())));
Ok so let's break down what your code is currently doing.
int counter = 1;
while(combinedAgencyCds.size() < 5) {
counter = counter + 1;
eSignConfig.setAgencyCd(combinedAgencyCds);
}
This snippet of code has a couple things wrong best I can tell. First, this loop has the possibility of running forever or not at all. Because combinedAgencyCds is never being manipulated, the size won't ever change and the logic being checked in the while loop never does anything. Second, there's a more efficient loop for doing this, assuming you don't need the counter variable outside of its usage in the while loop and that is using for loops.
Example syntax is as follows:
for (int i = 0; i < combinedAgencyCds.size(); i++) {
if (i < 5) {
// Do your logic here.
}
else {
break; // Or handle extra values however you want.
}
}
Notice there is no need for the explicit declaration for a counter variable as "i" counts for you.
Now in your actual logic in the loop, I'm not sure what the setAgencyCd method does, but if it simply sets a list variable in the eSignConfig like it appears to, repeating it over and over isn't going to do anything. From what I can see in your code, you are setting a variable with the same value 5 times. If you need any more explanation just let me know and I will be happy to revise the answer.
I am having a weird issue with java list. Please see the code below:
for ( int i=0; i < tripList.size(); i++ ) {
ModeChoiceTrip trip = tripList.get(i);
int newUniqueId = tripListIds[trip.uniqueId];
int newLinkedId = trip.linkedId >= 0 ? tripListIds[trip.linkedId] : -1;
int jointTripNum = trip.linkedId >= 0 && trip.tourType != TourTypes.SPECIAL_EVENT ? jointTripListIds[trip.linkedId] : 0;
trip.uniqueId = newUniqueId;
trip.linkedId = newLinkedId;
trip.jointTripNum = jointTripNum;
}
In the above code, the values in tripList seem correct but after executing a few iterations (up to i = 6), the values in tripList changes for all the positions.
I cannot provide the whole source code here but showing the snippet of the code where I have an issue.
I found that there are some duplicate trips in tripList. When one of the trips is changed, the copy of it (located at different position) is also changed.
I am guessing this piece of code is executed by multiple threads, Then there is every chance that List could be modified by another thread while this loop is going on.
you could try synchronizing the loop and see if issue gets resolved.
Also, you could try using for-each loop instead of the loop with counter.
for (ModeChoiceTrip trip : tripList) {
.....
}
The issues was the duplicate values in the list. Thus, when I update a value in list the copy to that value changes as well
You set the unique id to -1. So if the trip list id comes in as -1, you grab the index like tripListIds[-1]; which might be the second to the last item in the list.
What i am shooting for is to be able to take the input from my text field in my GUI and put it into an ArrayList. Then I need to check the array and see if I already have the Integer in the array. If so I need to remove both Integers so the Integer is no longer inside the array. I also need to be able to add the Integer if it is not a duplicate to the ArrayList.
The purpose of this is to be able to have users sign in with a number. The vision I have is for them to put their unique number in when they sign in or sign out (Like a time clock). If their number is not in the array, they are signing in. If their number is in the arraylist then they are signing out.
This is what i have for code so far, i am getting a problem with signing out. It keeps sending the second value in the array back as the only one able to sign out. I have tried fixing it and can't seem to figure out what is wrong. Let me know if it would be more helpful if i posted my whole program or if this code snippet is enough to figure it out.
Thanks,
private void btnSignInActionPerformed(java.awt.event.ActionEvent evt) {
// Get data from form and put it into an Array List
Integer txtUserSignInName = Integer.valueOf(txtUserSignIn.getText());
ArrayList<Integer> userSignInNumber = new ArrayList();
userSignInNumber.add(12345678); //sample data
userSignInNumber.add(55489563); //sample data
userSignInNumber.add(26489564); //sample data
userSignInNumber.add(78654865); //sample data
userSignInNumber.add(txtUserSignInName);
// Setting up HashSet so no duplicate data
Set<Integer> hashSet = new HashSet<>();
hashSet.addAll(userSignInNumber);
userSignInNumber.clear();
userSignInNumber.addAll(hashSet);
// Other settings needed
SimpleDateFormat df = new SimpleDateFormat("hh:mm:ss a");
String time = df.format(new Date());
if ((txtUserSignIn.getText() != null && txtUserSignIn.getText().isEmpty())) {
String userSignInErrorMessage = "Sorry, Please Try Again";
JOptionPane.showMessageDialog(new JFrame(), userSignInErrorMessage, "Incorrect Sign In",JOptionPane.ERROR_MESSAGE);
//setting focus
txtUserSignIn.setText("");
txtUserSignIn.requestFocus();
} else {
for(int i = 1; i < userSignInNumber.size(); i++) {
// If number is already in array, remove it
if(txtUserSignInName.equals(userSignInNumber.get(i))) {
userSignInNumber.remove((Integer)txtUserSignInName);
System.out.println(txtUserSignInName + " has signed out");
txtLoggedInUsers.append(txtUserSignInName + " has signed out at " + time + "\n");
break;
} else { // If number is not in the array, add it to the array
System.out.println(txtUserSignInName + " has signed in");
txtLoggedInUsers.append(txtUserSignInName + " has signed in at " + time + "\n");
break;
}
}
System.out.println(userSignInNumber);
}
}
Lists are not really suitable for what you are trying to do. You would be better off using one of the Set interface implementations. Sets provide fast contains()/add()/remove() methods that you can use, without generally having to iterate over all elements manually in a loop. And if you do need to quickly iterate over all elements for some reason, then a LinkedHashSet would work just fine. For example:
Set<Integer> signedIn = new LinkedHashSet<>();
...
if (signedIn.add(loginNumber)) {
// The set was modified, therefore this is a new login
} else {
// The number was already present, log-off the user.
signedIn.remove(loginNumber);
}
...
if (signedIn.contains(loginNumber)) {
// Allow the user to...
} else {
// Error, user not signed in
}
There are a number of problems with your implementation.
The loop starts at 1 when array indices start at 0, so you are skipping the first entry.
Then you always break out of the loop straight away after checking the 2nd item and so don't check any others.
A better approach would be to use a Set, not just to remove duplicates, but as a primary way to store who is signed in. Then you can check if a number is in the set easily with the contains method so you don't need to loop through manually (which means you don't have to deal with the problems associated with removing items from a list while you are looping through it).
I have a pizza code that iterates through a list of objects and checks whether they are colliding or not. If one is collided with, it is removed from the ArrayList.
for (int i = 0; i < arrayList.size(); i++) {
Object c = arrayList.get(i);
if (Rect.intersects(foo.getRect(), c.getRect())) { //Android function, checks if the two rectangles are inside each other.
foo.setPosY(c.getPosY() + 11); // Always works.
foo.setVelY(bird.getVelY() * -1); // Always works.
arrayList.remove(i); // Occasionally fails under special circumcisions.
}
}
When opening the app fresh for the first time this works fine. However, if I exit with the back button and then quickly reopen the app, it will all work except occasionally, removing the object from the ArrayList wont happen.
If I close the app and then remove it from the recent apps list, it works. If I exit with the home key, or the back button and then immediately reopen, it sometimes fails to remove the object. I don't understand why this happens, as everything else still works. The two lines of code just before it function just fine. I just don't get it.
I suspect the problem is that you're skipping an element after one call to remove, because you're incrementing i and everything in the list is moving up one element. (It's not really clear what the symptoms are at the moment. If this turns out not to be the problem, it's still a problem.)
So if you call remove(2), the next element you want to look at now has index 2.
Common ways of fixing this:
Work backwards:
for (int i = arrayList.size() - 1; i >= 0; i--)
Use an iterator instead:
for (Iterator<Foo> iterator = arrayList.iterator(); iterator.hasNext(); ) {
Foo c = iterator.next();
if (...) {
iterator.remove();
}
}
I'm trying to make a game in Java, and I've got already something. But i want to make the Player shoot bullets.
I've came up with the idea to make an object array, and put all the Bullet instances into the array. then in a thread, I want to make them all move(all the objects in the array).
This is what I put in the main class:
Bullet[] BulletArray;
public int Bullets = 0;
public void run() {
for(int i = 0; i < Bullets; i++){
BulletArray[i].Step();
}
if(Key.FireKey){
BulletArray[Bullets + 1] = new Bullet();
Bullets += 1;
}
}
I've just included the basic stuff, i.e. The run function runs fine, in the original code.
The code doesn't work, it gives me an error when I press Fire. The error is somewhere at
BulletArray[Bullets + 1] = new Bullet();
I hope you understand what I mean.
Well, for starters, your BulletArray is never initialized.
When you enter run(), your for() loop appears to work fine because it does not actually enter the block. Your int i = 0 is declared and is already greater than or equal to your limit, which is the int Bullet = 0. This means that the body of the loop never executes.
Then, when you press the Key.FireKey, it attempts to reference an array index that doesn't exist. It can't exist, because the array has never been initialized.
To initialize your array, you will need to do something more like this:
private int maxBullets = 10;
Bullet[] bulletArray = new Bullet[maxBullets];
Then your for() loop will actually enter. Note that in your Key.FireKey block, however, that you will have to perform some checking to make sure that you don't get an IndexOutOfBoundsException by trying to fire more bullets than you've created. i.e.,
if(Key.FireKey) {
if(bullets < maxBullets) {
bulletArray[++bullets] = new Bullet();
}
}