How can I avoid this error with while JAVA Android - java

I'm designing an app, what it does is a kind of "secret friend", I tell the app obviously not to repeat the person playing with the selected person, see this:
if (lista2.isEmpty())
{
(Toast.makeText(getApplicationContext(), this.getString(R.string.nospace), Toast.LENGTH_LONG)).show();
return;
} else {
Random random = new Random();
int start2;
do
{
start2 = random.nextInt(lista2.size() - 0) + 0;
}
while (lista2.get(start2).equals(spinner1.getSelectedItem().toString()));
}
At the while, sometimes the app crash, because there's no more items on lista2, just the same person(spinner1.selectedItem), how can I solve this?

What you should do is to
first remove the person(spinner1.selectedItem from lista2
Then do a random get
This way, you need not use the do-while loop

just do a check first
if (lista2.isEmpty())
{
(Toast.makeText(getApplicationContext(), this.getString(R.string.nospace), Toast.LENGTH_LONG)).show();
return;
} else {
//do a check here
for(int i = 0; i < lista2.size(); i++){
if(!lista2.get(start2).equals(spinner1.getSelectedItem().toString())){
break;
}
if(i == lista2.size() - 1){
Toast.makeText(getApplicationContext(), this.getString(R.string.nospace), Toast.LENGTH_LONG)).show();
return;
}
}
Random random = new Random();
int start2;
do
{
start2 = random.nextInt(lista2.size() - 0) + 0;
}
while (lista2.get(start2).equals(spinner1.getSelectedItem().toString()));
}

Related

Processing - Array index out of bounds error

I'm trying to use an array of objects to have barrels fall from the top of the screen to the bottom. (Like that old donkey kong game.) However, I can't seem to find a way to create more instances of the object than whatever the initial length of the array was. Anyone know a way to do this?
Here's the code:
Man Man;
Man background;
Man ladders;
PFont font1;
int time;
boolean run;
boolean newBarrel;
int barrelTotal;
Barrel[] barrel = new Barrel[100];
void setup() {
newBarrel = false;
run = true;
barrelTotal = 1;
time = millis();
size(800, 800);
Man = new Man();
background = new Man();
ladders = new Man();
for (int i = 0; i < barrel.length; i++) {
barrel[i] = new Barrel();
}
}
void draw() {
if (run == true) {
for (int i = 0; i < barrel.length; i++) {
if ((Man.bottom-10 >= barrel[i].top)&&(Man.bottom-10 <= barrel[i].bottom)&&(Man.Ladder == barrel[i].randomLadder)) {
print("GAME OVER!");
run = false;
}
if ((Man.top >= barrel[i].top)&&(Man.top <= barrel[i].bottom)&&(Man.Ladder == barrel[i].randomLadder)) {
print("GAME OVER!");
run = false;
}
}
}
if (run == true) {
background.createBackground();
Man.ladders();
Man.movement();
Man.createMan();
//spawns a barrel every second
if (millis()> time + 10) {
newBarrel = false;
print(" " + barrelTotal + " ");
time = time + 10;
barrelTotal = barrelTotal+1;
newBarrel = true;
}
for (int i = 0; i < barrelTotal; i++) {
if (newBarrel == true) {
}
barrel[i].gravity();
barrel[i].createBarrel();
}
//if(barrelTotal == 100){
//for (int i = 0; i < 50; i++){
// barrel[i] = "???";
//}
//}
}
}
Use an ArrayList instead of a native array. ArrayList will expand capacity as needed, whereas an array is fixed size and cannot be changed (you'd need to create a new larger array each time, which under the covers is what an ArrayList handles for you).
You can use ArrayList for this. You will change
// from
Barrel[] barrel = new Barrel[100]; // i suggest naming it to barrels instead of barrel
// to
ArrayList<Barrel> barrel = new ArrayList<>();
// or better
List<Barrel> barrel = new ArrayList<>();
// from
for (int i = 0; i < barrel.length; i++) {
barrel[i] = new Barrel();
}
// to
for (int i = 0; i < barrel.length; i++) {
barrel.add(new Barrel());
}
// from
barrel[i].<some-method()/attribute>
// to
barrel.get(i).<some-method()/attribute>
// etc
I highly recommend this for getting started with lists
https://docs.oracle.com/javase/tutorial/collections/interfaces/list.html

How would i use an Abstract Class or Interface in my code to minimise duplication?

I am currently trying to refactor my code for a basic connect four game.
I have noticed that I have a lot of repetition in my play.java file, with regards to knowing which player creates a winning pattern either horizontally or vertically.
As the horizontal and vertical winning criteria remains constant, how would I go about creating an Abstract Class or Interface to minimise code duplication here?
play.java
public class play {
private Connect4Game connect;
public play(Connect4Game connect) {
this.connect=connect;
}
public void playGame() {
System.out.println("Welcome to Connect 4");
System.out.println("To play the game type in the number of the column you want to drop you counter in");
System.out.println("Player One = r Player 2 = y");
System.out.println("");
board boardObj = new board(connect);
boardObj.printBoard();
boolean win = false;
while(!win){
// player 1
String userInput = getUserInput();
int move = Integer.parseInt(userInput);
counter counterObj = new counter(connect);
counterObj.placeCounter('r', move);
boolean hasWon = false;
int count = 0;
// check horizontal
for(int i=0; i<connect.board.length; i++){
for(int j=0; j<connect.board[i].length; j++){
if(connect.board[i][j] == 'r'){
count = count + 1;
if(count == 4){
hasWon = true;
}
}
else{
count = 0;
}
}
}
// check vertical
count = 0;
for(int i=0; i<connect.board[0].length; i++){
for(int j=0; j<connect.board.length; j++){
if(connect.board[j][i] == 'r'){
count = count + 1;
if(count >= 4){
hasWon = true;
}
}
else{
count = 0;
}
}
}
boardObj.printBoard();
if(hasWon){
win = true;
System.out.println("You Have Won!!!");
}
else {
//player 2
userInput = getUserInput();
move = Integer.parseInt(userInput);
counterObj.placeCounter('y',move);
hasWon = false;
count = 0;
// check horizontal
for(int i=0; i<connect.board.length; i++){
for(int j=0; j<connect.board[i].length; j++){
if(connect.board[i][j] == 'y'){
count = count + 1;
if(count >= 4){
hasWon = true;
}
}
else{
count = 0;
}
}
}
// check vertical
count = 0;
for(int i=0; i<connect.board[0].length; i++){
for(int j=0; j<connect.board.length; j++){
if(connect.board[j][i] == 'y'){
count = count + 1;
if(count >= 4){
hasWon = true;
}
}
else{
count = 0;
}
}
}
boardObj.printBoard();
if(hasWon){
win = true;
System.out.println("You Have Won!!!");
}
}
}
}
public String getUserInput(){
String toReturn = null;
try{
toReturn = connect.input.readLine();
}
catch(Exception e){
}
return toReturn;
}
}
Neither would help in this instance. An abstract class would be used to establish the predetermined methods that would be supported by most subclasses. It would also include method signatures of methods that would be useful where implementations might be different, depending on how that class is be used. Even then, the predefined methods can be overridden as required.
An interface simply formalizes the required methods via signatures (abstract method declarations) for a class to implement to enforce a contract between the user and the class.
As you are not creating multiple classes there would be no benefit.
The best I could recommend would be to consolidate your horizontal and vertical checks into methods and to add other methods as needed to reduce duplicate code.
Start refactoring by using extract method. Your two sets of nested loops can be turned into a method. Maybe you can get it down to one set of nested loops on a method that you call four times.

How to make buttons glow while iterating through array of buttons?

I would like to display how linear search works visually.
I have created and ADT class of just integers. I also have a frame with buttons on it, when I hit the fillButton, it generates an array of random integers which are displayed on an array of buttons.
When i hit the findButton it will look for the specific number entered. As i am iterating through the array, i would like to make corresponding button change color.
I had created a similar program that iterated through an array of buttons, and changed the color as it went through. I had used Thread.sleep(), and it was just the main class. This time i have two classes and i am not sure how to go about it. I dont't know how to go about making a connection between the ADT class and the GUI class. I've used EventObjects and custom EventListeners before, but that was merely to store objects. Any help pointing in the right direction is appreciated. Thank you.
This is part of the ADT class
public class ADT {
private int[] a;
private int nElems;
private int SIZE = 60;
public ADT(){
a = new int[SIZE];
nElems=0;
}
public void initialPlacement(int index, int value,int initialCount){
a[index] = value;
nElems = initialCount;
}
public int linearSearch(int searchKey){
int index = 0;
for(int i = 0; i < nElems; i++){
if(getVal(i) == searchKey){
index = i;
break;
}
else{
index = -1;
}
}
return index;
}
And here is part of the GUI class
public NumberFrame(){///CONSTRUCTOR===========================
arr = new ADT();
//CREATE COMPONENTS
for(int i = 0; i < 60; i++){
listButtons[i] = new JButton(String.valueOf("_"));
}
for(int i = 0; i < 60; i++){
listLabels[i] = new JLabel(String.valueOf("["+i+"]"));
}
for(int i = 0; i < 60; i++){
listMiniPanels[i] = new JPanel();
listMiniPanels[i].add(listLabels[i]);
listMiniPanels[i].add(listButtons[i]);
}
fillButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
boolean sort = true;
if(linearRadio.isSelected()){
System.out.println("linear is checked");
fill(!sort);//fills half the array and array of buttons with random numbers, unsorted
}else if(binaryRadio.isSelected()){
System.out.println("binary is checked");
fill(sort);//fills half the array with random numbers and sorts it
}else{
JOptionPane.showMessageDialog(null, "Please check a sorting method");
}
}
})
findButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
int index= 0;
if(numberField.getText().equals("")){
System.out.print("Arr size = " + arr.size());
JOptionPane.showMessageDialog(null, "You did not enter a number");
}else {
try {
int searchKey = Integer.parseInt(numberField.getText());
if(linearRadio.isSelected()){
index = arr.linearSearch(searchKey);
listButtons[index].setBackground(Color.GREEN);
if(index > -1)
JOptionPane.showMessageDialog(null, "Found number " +searchKey + " # index [" + index + "]");
else
JOptionPane.showMessageDialog(null, "No such number");
}else{
index = arr.binarySearch(searchKey);
if(index > -1)
JOptionPane.showMessageDialog(null, "Found number " + searchKey+ " # index [" + index + "]");
else
JOptionPane.showMessageDialog(null, "No such number!");
}
} catch (NumberFormatException nfe) {
System.out.println("Arr size = " + arr.size());
JOptionPane.showMessageDialog(null, "Not an integer, pleas try again!");
}
}
}
});
}//=======CONSTRUCTOR END=============================

Java JLabel array remove element after use

So I have a JFrame in Netbeans that holds 20 labels of math equations.
mathLabel1 is "2 + 2"
mathLabel2 is "4 * 4"
etc...
and if mathLabel1 is shown and the user guesses the right answer (4) then I want to setVisible(false) and remove that element from my array, so it doesn't come up as a question again.
Basically, no repeats.
Here is a short version of my code:
//declare variables
String strUserAnswer;
int i;
Random r = new Random();
int randvalue = r.nextInt(19);
JLabel[] math = {mathLabel1, mathLabel2, mathLabel3, mathLabel4, mathLabel5, mathLabel6, mathLabel7, mathLabel8, mathLabel9, mathLabel10,
mathLabel11, mathLabel12, mathLabel13, mathLabel14, mathLabel15, mathLabel16, mathLabel17, mathLabel18, mathLabel19, mathLabel20};
JLabel test;
//method that chooses random math equation
public void random(JLabel test) {
r = new Random();
randvalue = r.nextInt(19);
test = math[randvalue];
if (test == math[0]) {
mathLabel1.setVisible(true);
}
else if (test == math[1]){
mathLabel2.setVisible (true);
}
else if (test == math[2]){
mathLabel3.setVisible (true);
}
else if (test == math[3]){
mathLabel4.setVisible (true);
}
else if (test == math[4]){
mathLabel5.setVisible (true);
}
else if (test == math[5]){
mathLabel6.setVisible (true);
}
else if (test == math[6]){
mathLabel7.setVisible (true);
}
else if (test == math[7]){
mathLabel8.setVisible (true);
}
else if (test == math[8]){
mathLabel9.setVisible (true);
}
else if (test == math[9]){
mathLabel10.setVisible (true);
}
else if (test == math[10]){
mathLabel11.setVisible (true);
}
else if (test == math[11]){
mathLabel12.setVisible (true);
}
else if (test == math[12]){
mathLabel13.setVisible (true);
}
else if (test == math[13]){
mathLabel14.setVisible (true);
}
else if (test == math[14]){
mathLabel15.setVisible (true);
}
else if (test == math[15]){
mathLabel16.setVisible (true);
}
else if (test == math[16]){
mathLabel17.setVisible (true);
}
else if (test == math[17]){
mathLabel18.setVisible (true);
}
else if (test == math[18]){
mathLabel19.setVisible (true);
}
else if (test == math[19]){
mathLabel20.setVisible (true);
}
}
private void guessButtonActionPerformed(java.awt.event.ActionEvent evt) {
// User clicks guess to enter answer, if correct part of puzzle appears
strUserAnswer = answerText.getText();
test = math[randvalue];
//if the math equation chosen is 2+2...
if (test == math[0]) {
//show math equation
mathLabel1.setVisible(true);
//if answer is right...
if (strUserAnswer.equals("4")) {
JOptionPane.showMessageDialog(null, "Yay!! That is right!");
//show puzzle piece, hide equation, and choose a new one
label1.setVisible(true);
mathLabel1.setVisible(false);
//test.remove(math[0]);
test = math[randvalue];
answerText.setText(null);
random(test);
//if answer is wrong...
} else {
JOptionPane.showMessageDialog(null, " Sorry, try again!");
answerText.setRequestFocusEnabled(true);
}
}
and that's repeated for math[1], math[2], math[3], etc...
So how would I do this? I tried the remove() method but that was a shot in the dark...
ok, so this might make your day or break your heart, but you are doing way more than you need to with your random() method. first off, it doesn't seem like you need to take in a parameter
because it looks like you are manually changing the value before you ever use it. also, because each value in the array is in fact a JLabel, you can just say math[randValue].setVisible(true) instead of going through the whole if statement thing. and to solve your problem of removing stuff, there is a quick and dirty way you can do it that i will show you, but you are better off using an ArrayList instead of an Array.
public void random() {
Random r = new Random();
randValue = r.nextInt(math.length); //make sure the index is always within the array
JLabel[] temp = new JLabel[math.length - 1]; //this will do the trick
math[randValue].setVisible(true);
for (int i = 0; i < randvalue; i++) {
temp[i] = math[i]; //fill the new array up to the chosen label
}
for (int i = randValue; i < temp.length; i++) {
temp[i] = math[i + 1]; //fill the rest, omitting the chosen label
}
math = new JLabel[temp.length]; //math is now shorter
math = temp; //put everything back in the original array
}
this should work as a solution using arrays.
hope it helps.
If your data structure will constantly be changing, try using a List instead of an Array:
List<JLabel> labels = new ArrayList<JLabel>();
int numLabels = 20;
for (int i = 0; i < numLabels; i++) {
labels.add(new JLabel(i + " " + i));
}
From there you could always call:
labels.get(4).setVisible(false);
or
labels.remove(4);
And then revalidate your JPanel.
EDIT 2:
I may have misunderstood your question - it seems you want to remove a number and never create a label for it again. This is the correct way to do it:
int numIntegers = 20;
Set<Integer> possibleNumbers = new HashSet<Integer>();
for (int i = 0; i < numIntegers; i++) {
possibleNumbers.add(i);
}
When you want to remove an item, use:
possibleNumbers.remove(14);
Then when you want to present this data, you can use:
panel.clear();
for (Integer number : possibleNumbers) {
panel.add(new JLabel(number + " " + number));
}
(Please note I was incorrect calling JLabels data - they are part of the presentation.)

creating a team of players from a list

Hey im trying to create a random way to pick a team of 4 from a linkedlist and am wondering if this code will work.
heres an example code
public static void enterGame(Client c) {
int n = teamSize;
boolean startNewGame = false;
if(waitingPlayers.size() <= 3) {
return; // not enough players
}
startNewGame = true;
if(startNewGame) {
System.out.println("Starting new game");
for(int i=0; i<n; i++) {
Collections.shuffle(waitingPlayers);
System.out.println("Picking random player");
waitingPlayers.remove(c);
System.out.println("removing from random player list");
players.add(c);
System.out.println("adding player to ingame list");
}
}
}
I would use Collections.shuffle() and a sublist. In order to know if your code works why don't you test it (unit test or just some try)?
Also, this part:
boolean startNewGame = false;
if(waitingPlayers.size() > 3) {
startNewGame = true;
} else {
startNewGame = false;
return;
}
if(startNewGame) {
is over complicated, I would replace it by:
if(waitingPlayers.size() <= 3) {
return; // not enough players
}
Full code:
public static void enterGame(final Client c) {
if(waitingPlayers.size() <= 3) {
return; // not enough players
}
System.out.println("Starting new game");
Collections.shuffle(waitingPlayers);
System.out.println("Picking random players");
// ? to be replaced by the real type of objects inside waitingPlayers
final List<?> picked = waitingPlayers.subList(0, 3);
players.addAll(picked);
waitingPlayers.removeAll(picked);
}
You have a bug - you are picking a number from 0 to n. If n is selected, you will get an out of bounds exception. Other fhan that it seems fine.

Categories