Java do while loops not looping - java

As far as I have read so far in my textbook for the class, in the modules for my class and in 2+ hours of searching, I cannot figure out why my code is not working.
The do while loop in the main method is working properly but the do while loops in my get methods are not looping. I put in the wrong number, I get the error message and then instead of asking for the number again, it moves on to the next get method.
I hope it is something simple that I have overlooked but I would appreciate any help I could get on this.
Here is the code for my getHome method:
public static int getHome()
{
int homeNum;
String home;
do
{
home = JOptionPane.showInputDialog(null,"Enter 1(apartment), 2(house),"
+ " or 3(dorm).","Dwelling Type", JOptionPane.QUESTION_MESSAGE);
homeNum = Integer.parseInt(home);
if(!(homeNum == 1) && !(homeNum == 2) && !(homeNum == 3))
{
JOptionPane.showMessageDialog(null, "The value for dwelling type "
+ "must be 1(apartment), 2(house), or 3(dorm)", "Dwelling"
+ "Type Error", JOptionPane.ERROR_MESSAGE);
}
return homeNum;
}
while(homeNum < 0 || homeNum > 3);
And the code in the main method that calls this method:
public static void main(String[] args)
{
String response;
do
{
petRec(getHome(), getHours());
response = JOptionPane.showInputDialog(null, "Do you want to continue?" +
"\nEnter Y for yes and anything else for no.", "Continue?", +
JOptionPane.QUESTION_MESSAGE);
}
while(response.equalsIgnoreCase("y"));
}
Just for clarification here is the petRec method:
public static void petRec(int homeType, double hoursAtHome)
{
String pet;
if(homeType == 1 && hoursAtHome >= 10)
pet = "Cat";
else
if(homeType == 1 && hoursAtHome < 10)
pet = "Hamster";
else
if(homeType == 2 && hoursAtHome >= 18)
pet = "Pot-Bellied Pig";
else
if(homeType == 2 && hoursAtHome >= 10 && hoursAtHome <= 17)
pet = "Dog";
else
if(homeType == 2 && hoursAtHome < 10)
pet = "Snake";
else
if(homeType == 3 && hoursAtHome > 6)
pet = "Fish";
else
if(homeType == 3 && hoursAtHome < 6)
pet = "Ant Farm";
else
pet = "Nothing";
JOptionPane.showMessageDialog(null, "You should get a " + pet + "!",
"Recommended Pet", JOptionPane.INFORMATION_MESSAGE);
}
Last year I took intro to Visual Basic and had infinite loops, this year I'm taking Java and can't get the loop to repeat.
The getHours method is structured almost identical to the getHome method just with different variables and wording in the prompt.
The program is supposed to display the error message when a number that is not 1, 2 or 3 is entered and then loop to ask you for the number again. It displays the error message but then goes on to ask for the hours.
Again I very much appreciate any help that can be offered. This assignment isn't due until Saturday but I only have 2 days off to work on this.
Thank you in advance for your help :)

Move the return statement to outside the loop:
public static int getHome()
{
int homeNum;
String home;
do
{
home = JOptionPane.showInputDialog(null,"Enter 1(apartment), 2(house),"
+ " or 3(dorm).","Dwelling Type", JOptionPane.QUESTION_MESSAGE);
homeNum = Integer.parseInt(home);
if(!(homeNum == 1) && !(homeNum == 2) && !(homeNum == 3))
{
JOptionPane.showMessageDialog(null, "The value for dwelling type "
+ "must be 1(apartment), 2(house), or 3(dorm)", "Dwelling"
+ "Type Error", JOptionPane.ERROR_MESSAGE);
}
}
while(homeNum < 0 || homeNum > 3);
return homeNum;
}
As it is, you are returning from the method at the end of the first loop iteration. You might also want to catch the potential NumberFormatException that can be thrown by the parseInt call.
Also, be aware that this will allow 0 to be entered. Perhaps that's by design; perhaps an oversight. I can't tell.

Welcome to Java:
do
{
...
return homeNum;
}
while(homeNum < 0 || homeNum > 3);
In Java, the following instruction all finish the current statement: the code after will never be executed or you'll get an error. You must move the return outside the loop for it to work correctly (or as intended):
do
{
...
}
while(homeNum < 0 || homeNum > 3);
return homeNum;
return : when you return a value, like in return homeNum, you exit the method in which you are.
continue : when you continue, you'll go to next iteration; this only works in a loop.
break : when you break, you'll end the execution of a loop or a switch statement. For instance, if you had put break; instead of return h omeNum; the loop would have ended here.
throw new Exception("Foobar") : when you throw an error, it will exit the current try .. catch block method up one matching the exception kind.
As an example of break, throw and continue:
public static int getHome()
{
int n = -1;
for (;;) { // infinite loop powered !
try {
String home = JOptionPane.showInputDialog(null,"Enter 1(apartment), 2(house),"
+ " or 3(dorm).","Dwelling Type", JOptionPane.QUESTION_MESSAGE);
int homeRun = Integer.parseInt(home);
if(homeNum != 1 && homeNum != 2) && homeNum != 3) {
// note: this is an example. You should NEVER use exception in these case
throw new IllegalArgumentException("Damn!");
}
n = homeRun;
break;
} catch (NumberFormatException|IllegalArgumentException e) {
JOptionPane.showMessageDialog(null, "The value for dwelling type "
+ "must be 1(apartment), 2(house), or 3(dorm)", "Dwelling"
+ "Type Error", JOptionPane.ERROR_MESSAGE);
continue;
}
}
return n;
}
This is an ugly example showing you the four instructions.
Throwing an exception in this case is bad practise. But it'll go to the catch block because it catches the NumberFormatException (from Integer.parseInt) and the thrown IllegalArgumentException.
The break could be replaced by a return homeRun;
The continue is useless in this case because there is nothing left after the try catch block.
Beside, if you are learning Java, you should perhaps read that because I think you are not doing think right. There exists GUI components that does the cumbersome work of handling input conversion for you.
Or even, instead of JOptionPane, you should rely on System.in and Scanner: it is pretty strange to execute a code in a terminal/console, then being asked in a window on some input, to then come back in the terminal/console.

Related

Using try, catch and a label for the first time [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
We just covered the try-catch topic in last night's lecture. It's not required to put it in this assignment, but I thought I would give it a shot.
I've been struggling with this for a while. Using a continue statement kicked it back to the start of the catch block so that the println inside it executed in a never ending loop.
So apparently there are these things called labels. I found that when I was trying to figure out how to solve the continue problem. I tried putting in a label just as I saw being done in the example code, and now it just gives me a compiler error on the break statement that says "the process flag is missing".
What am I doing wrong?
do {
// Prompt
try {
process: nbPlayers = keyboard.nextInt();
}
catch(Exception e) {
nbPlayers=0;
if (attempts<4) {
System.out.println("Incorrect input type. You have now made " + attempts +". Please enter an integer from 2 to 4.");
++attempts;
break process;
}
else {
System.out.println("Invalid input. You have now made " + attempts +". This game only allows 4 chances to input the requested number of players.\n Shutting down the program now.");
System.exit(0);
}
}
if(attempts < 4 && nbPlayers >= 2 && nbPlayers <= 4) {
valid = true;
} else if(attempts < 3) {
System.out.println("Invalid input. You have now made " + attempts +". This game only allows 4 chances to input the requested number of players.\nYou are allowed to try again.");
} else if(attempts == 3) {
System.out.println("Invalid input. You have now made " + attempts +". This game only allows 4 chances to input the requested number of players.\nYou are allowed to one more time.");
} else if(attempts == 4) {
System.out.println("Invalid input. You have now made " + attempts +". This game only allows 4 chances to input the requested number of players.\n Shutting down the program now.");
System.exit(0);
}
++attempts;
} while(!valid);
Your problem is not quite clear. Let's talk on a code.
What do you think of this ?
int attempts = 0; // is it a good initialization ?
int nbPlayers = 0; // is it a good initialization ?
boolean valid = false; // is it a good initialization ?
String nbPlayersString = "";
do {
// Prompt
try {
nbPlayersString = keyboard.nextLine();
nbPlayers = Integer.parseInt(nbPlayersString);
if(2<= nbPlayers && nbPlayers <= 4) {
valid = true;
}
else {
System.out.println("Bad Attempt " + (attempts + 1) +". Invalid number of players.");
}
}
catch(Exception e) {
nbPlayers=0;
System.out.println("Bad Attempt " + (attempts + 1) +". Wrong input type. ");
}
++attempts;
} while(!valid && attempts < 4);
if(valid)
System.out.println("GOOD JOB!");
else {
System.out.println("You have exhausted all your chances. Program will terminate!");
System.exit(0);
}
Final EDIT
It looks like you also had a cache problem with Scanner.nextInt() after entering an invalid value (string instead of integer). So, in the attempts following, the Scanner cache still had the bad value and considered it.

While loop with JOptionPane returning StringIndexOutOfBounds Exceptions

In my code I have a while loop with 3 IF tests nested in between that have flags triggered by ELSE:
[test1] checks whether the input value has a length of exactly 1 [Prevents users from inputting nothing]
[test2] checks whether the input value at index 0 is a digit [I need a number as an input, but I'm using JSWING]
[test3] checks whether the input value length is greater than 1 [2 Digits (10,11,12,...)
num1= JOptionPane.showInputDialog(null,"Please input Guess #" + (counter+1), "0");
while(exit == false || test1 == false || test2 == false || test3 == false) {
if(num1.length() < 1) {
JOptionPane.showMessageDialog(null,"Input required");
num1= JOptionPane.showInputDialog(null,"Please input Guess #" + (counter+1), "0");
}
else {
test1 = true;
}
if(Character.isDigit(num1.charAt(0)) == false) {
JOptionPane.showMessageDialog(null,"Input has to be a number between 0 - 9.");
num1= JOptionPane.showInputDialog(null,"Please input Guess #" + (counter+1), "0");
}
else {
test2 = true;
}
if(num1.length() > 1) {
JOptionPane.showMessageDialog(null,"Input has to be a number between 0 - 9.");
num1= JOptionPane.showInputDialog(null,"Please input Guess #" + (counter+1), "0");
}
else {
test3 = true;
}
if(test1 == true && test2 == true && test3 == true) {
exit = true;
}
The problem I'm having is somewhere between the first and second test. When I try inputting nothing as a value ["" / or just having an empty box and pressing enter], it detects the error of having nothing and displays "Input required" once, but once it loops, it outputs a StringIndexOutOfBoundsException for the second trial
It works in every other case I've tried (no input -> correct, no-input -> incorrect...) Only sequential no-input cases crash the program.
The error is said to be in this line, but I don't understand where, or how.
if(Character.isDigit(num1.charAt(0)) == false)
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:48)
at java.base/java.lang.String.charAt(String.java:709)
at oof.Lottery_Swing_FIX.main(Lottery_Swing_FIX.java:56)
Fixed Logic
JOptionPane.showMessageDialog(null,"Enter 3 one-digit positive numbers for your 3 guesses");
for(int counter = 0; counter < LIMIT; counter++) {
test = false;
while(exit == false || test == false) {
num1= JOptionPane.showInputDialog(null,"Please input Guess #" + (counter+1), "");
if(num1.length() < 1 || Character.isDigit(num1.charAt(0)) == false || num1.length() > 1) {
JOptionPane.showMessageDialog(null,"Integer between 1-9 required");
}
else {
test = true;
}
if(test == true) {
numberInput = Integer.parseInt(num1);
exit = true;
}
else {
continue;
}
}
Your 'fix' doesn't handle null which will be returned by the JOptionPane.showInputDialog() if the dialog is closed (x) or the cancel Cancel button is selected. You can't play null against the String#length() method as you can with a Null String ("") so, you need to check for this in your code otherwise you can end up with a NullPointerException. You can do this in your very first if statement as a conditional component:
if (num1 == null) {
// The CANCEL or dialog close button was selected.
}
You really don't need those boolean flags in your code. Things are going to happen or they simply will not. You don't really need flags to remind you so close to home (so to speak). If you have the conditions established properly within the if statements and utilize else if then they're not required. With that being said, you don't need these boolean flags within the condition for the while loop either.
The while loop needs to be concerned about one thing...that the prompt is provided valid data. If it isn't then the variable (num1) which holds the prompt data is converted to a null string (""). So in reality:
String num1 = "";
while (num1.equals("")) { .... }
So, for as long as num1 contains a null string ("") we just keep looping thus re-prompting for proper input.
In your code, you want to provide the User with specific details as to why their input failed. There are several ways to do this however whichever way you choose to do it, make sure it doesn't generate any exceptions (errors) that can ultimately halt your application or change its accurate performance. There is nothing wrong with using if and else if statements to carry out this particular task in its current use-case. Following your particular theme:
int LIMIT = 3, numberInput;
int[] guesses = new int[LIMIT];
String errMsg;
String num1;
JOptionPane.showMessageDialog(null, "<html>You will be prompted three times "
+ "to supply<br>a positive <font color=red><b>single digit</b></font> "
+ "number.</html>", "Information", JOptionPane.INFORMATION_MESSAGE);
for (int counter = 0; counter < LIMIT; counter++) {
num1 = "";
while (num1.equals("")) {
errMsg = "";
num1 = JOptionPane.showInputDialog(null, "Please input Guess #" + (counter + 1),
"Guess #" + (counter + 1),JOptionPane.QUESTION_MESSAGE);
// Does num1 contain null?
if (num1 == null) {
if (JOptionPane.showConfirmDialog(null,
"<html>You <font color=blue>canceled</font> your input!<br>"
+ "Do you want to quit?</html>", "Quit",
JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
System.exit(0);
}
num1 = ""; // Set for re-prompt.
continue;
}
// Is nothing supplied?
else if (num1.length() < 1) {
errMsg = "<html><font size=5 color=red><center>Nothing Supplied!"
+ "</center></font><br>You must provide a single Integer "
+ "value between<br>0 and 9 (inclusive).</html>";
}
// Is too much supplied?
else if (num1.length() > 1) {
errMsg = "<html><center><font size=5 color=red>To Much Supplied!</font><br>" +
"<font size=5 color=blue>\"" + num1 + "\"</font></center><br>" +
"You must provide a single Integer value between<br>0 and 9 "
+ "(inclusive).</html>";
}
// Is the supplied character a number?
else if (!Character.isDigit(num1.charAt(0))) {
errMsg = "<html><center><font size=5 color=red>Invalid Digit Supplied!"
+ "</font><br><font size=5 color=blue>\"" + num1 + "\"</font>"
+ "</center><br>You must provide a single Integer value "
+ "between<br>0 and 9 (inclusive).</html>";
}
// Does errMsg actually contain a message? If so display it.
if (!errMsg.equals("")) {
JOptionPane.showMessageDialog(null, errMsg, "Invalid Input!",
JOptionPane.WARNING_MESSAGE);
num1 = ""; // Set for re-prompt.
}
else {
numberInput = Integer.parseInt(num1);
// ... do whatever you want to do with numberInput, for example ....
guesses[counter] = numberInput;
}
}
}
// Display User's LIMITED guesses:
StringBuilder sb = new StringBuilder();
sb.append("<html>The <font color=red><b>").append(LIMIT).
append("</b></font> Guesses supplied by User are:<br><br>");
for (int i = 0; i < guesses.length; i++) {
sb.append("Guess #").append((i + 1)).append(": <font color=blue>").append(guesses[i]).append("</font><br>");
}
sb.append("</html>");
JOptionPane.showMessageDialog(null, sb.toString(), "Guesses Provided",
JOptionPane.INFORMATION_MESSAGE);
As you can see, providing details to a User about input failures requires a lot more code. All this code can be removed if you decide you want just a simple "Invalid Input!" message. This in essence forces the User to read the supplied prompts with more intensity, for example:
int LIMIT = 3;
int numberInput;
int[] guesses = new int[LIMIT];
String num1;
JOptionPane.showMessageDialog(null, "<html>You will be prompted three times "
+ "to supply<br>a positive <font color=red><b>single digit</b></font> "
+ "number.</html>", "Information", JOptionPane.INFORMATION_MESSAGE);
for (int counter = 0; counter < LIMIT; counter++) {
num1 = "";
while (num1.equals("")) {
num1 = JOptionPane.showInputDialog(null, "Please input Guess #" + (counter + 1),
"Guess #" + (counter + 1),JOptionPane.QUESTION_MESSAGE);
// Does num1 contain null?
if (num1 == null){
if (JOptionPane.showConfirmDialog(null,
"<html>You <font color=blue>canceled</font> your input!<br>"
+ "Do you want to quit?</html>", "Quit",
JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
System.exit(0);
}
num1 = ""; // Set for re-prompt.
}
else if (!num1.matches("\\d")) {
JOptionPane.showMessageDialog(null, "<html><center><font size=5 color=red>Invalid Input Supplied!</font><br>" +
"<font size=5 color=blue>\"" + num1 + "\"</font></center><br>" +
"You must provide a single Integer value between<br>0 and 9 "
+ "(inclusive).</html>", "Invalid Input!", JOptionPane.WARNING_MESSAGE);
num1 = "";
}
else {
numberInput = Integer.parseInt(num1);
// ... do whatever you want to do with numberInput, for example ....
guesses[counter] = numberInput;
}
}
}
// Display User's LIMITED guesses:
StringBuilder sb = new StringBuilder();
sb.append("<html>The <font color=red><b>").append(LIMIT).
append("</b></font> Guesses supplied by User are:<br><br>");
for (int i = 0; i < guesses.length; i++) {
sb.append("Guess #").append((i + 1)).append(": <font color=blue>").append(guesses[i]).append("</font><br>");
}
sb.append("</html>");
JOptionPane.showMessageDialog(null, sb.toString(), "Guesses Provided",
JOptionPane.INFORMATION_MESSAGE);
Pay special note to the condition for the else if statement (!num1.matches("\\d)) in the above code. Here the use of the String#matches() method is used with a small Regular Expression, the "\\d" expression. This expression tells the matches() method to see if the string we're matching (in num1) is a single digit string numerical value (like: "5" for example). So, what the else if statement is asking:
else if the string contained in num1 is NOT (!) a single digit string numerical value then run the code in my curly braces ({...}). This basically covers all input failures except null (because we're handling that as a quit option) and the String#matches() method will not accept null.
If you don't want a quit option then then you would only need a single if statement in your code:
if (num1 == null || !num1.matches("\\d")) { ... }

How to get method to recognize else part of if statement? [duplicate]

This question already has answers here:
How can I check for invalid input and loop until the input is valid?
(3 answers)
Closed 5 years ago.
I've made a street craps game and have an error checker in the beginning to make sure the input is valid, I put it in an if statement and then have the rest of the code (for valid inputs) as the else but it isn't recognizing the else part when the user puts in a valid number.
public void play() { //method
System.out.println("Please pick a number.");
guess = scan.nextInt();
if (guess == 7 || guess == 1 || guess == 0 || guess > 12) {
System.out.println("Sorry, that is an invalid input, please choose another number.");
guess = scan.nextInt();
} else {
int roll = dieOne.roll();
int roll2 = dieTwo.roll();
int rollSums = roll + roll2;
System.out.println(roll + "+" + roll2);
while (rollSums != 7) {
if (guess == rollSums) {
System.out.println("Congratulations, you win! Your number was rolled before a seven was rolled!");
rollSums = 7;
guess = 7;
} else {
roll = dieOne.roll();
roll2 = dieTwo.roll();
rollSums = roll + roll2;
System.out.println(roll + "+" + roll2);
}
}
if (rollSums != guess) {
System.out.println("Sorry, your number was not rolled before a seven was rolled.");
}
}
}
I guess you want to execute the if part until the if condition is not satisfied, and then you want to execute the else part. If this is what you want you need to execute the if part as a while loop, and the else part as code after the while loop.
You need a while loop to make sure you get a good input first, and then do the game logic, like this:
int guess = scan.nextInt();
while (guess == 7 || guess == 1 || guess == 0 || guess > 12){
System.out.println("Sorry, that is an invalid input, please choose another number.");
guess = scan.nextInt();
}
//Game Logic (Stuff in else section)

Java: Hangman game, 10 chances, but only 5 lives

I'm creating a little mini game of Hangman. The user has 10 chances to guess, but only 5 lives.
The app works, but will continue after the 5th life, even though, I was hoping it would throw the player out of that loop.
The instantiable class (Hangman.java) is working without problems.
The secret word is "julie" as described in the instantiable class.
My App class:
import javax.swing.JOptionPane;
public class HangmanApp {
public static void main(String args[]) {
String input, secret, result, playAgain;
char guess;
int i, j, k, lives;
Hangman myHangman = new Hangman();
do{
JOptionPane.showMessageDialog(null, "Hello, welcome to Hangman! You have 10 chances but only 5 lives! Best of luck");
lives = 5;
for (j = 10; j > 0; j--) {
while (lives >= 0){
input = JOptionPane.showInputDialog(null, "Please enter a letter");
guess = input.charAt(0);
//process
myHangman.setGuess(guess);
myHangman.compute();
result = myHangman.getResult();
if ((input.charAt(0) == 'j') || (input.charAt(0) == 'u') || (input.charAt(0) == 'l') || (input.charAt(0) == 'i') || (input.charAt(0) == 'e')) {
JOptionPane.showMessageDialog(null, "That letter is in the word! Current correct letters: " + result + ".");
} else {
lives--;
JOptionPane.showMessageDialog(null, "Sorry, that letter is not there. Current correct letters: " + result + ".");
}
//output
//JOptionPane.showMessageDialog(null, "Current correct letters: " + result);
};
lives = -1;
}
result = myHangman.getResult();
secret = myHangman.getSecret();
if (secret.equals(result)) {
JOptionPane.showMessageDialog(null, "Congratulations, you got it!! The word was " + secret + ".");
} else {
JOptionPane.showMessageDialog(null, "Sorry, you didn't get it, better look next time! The word was " + secret + ".");
}
playAgain = JOptionPane.showInputDialog("Do you want to play again? yes/no");
}while (playAgain.equals("yes"));
}
}
Try the following change:
while (lives > 0){
you start at 5 and then go down to 4 3 2 1 AND 0. with the change this will stop at 0
// don't need two nested cycles, you can do it in a single one
// The cycle exits if any one of the conditions fail
// max attempts exhausted or all the lives are lost
// -------------------v v------------------------
for (j = 10, lives=5; j > 0 && lives > 0 ; j--) {
// -------------------------------------^
// j - the number of attempt is decremented for each trial,
// no matter if successful or not
//... the rest of cycle logic, which will decrement the lives
// only in cases of unsuccessful attempts
}

While loop one condition always returning true?

I am trying to make a conditional statement with two "ifs", and it works when I input the correct thing, but when I input an incorrect pokemon and a correct level it still works. I am pretty sure that one of the conditions in my while statement is always true (the first part). Here is the code (sorry about the formatting, just know that it is all formatted correctly in the Java environment):
while ((!(Pokemon.equalsIgnoreCase(Pikachu)) || !(Pokemon.equalsIgnoreCase(Charmander)) || !(Pokemon.equalsIgnoreCase(Squirtle)) || !(Pokemon.equalsIgnoreCase(Bulbasaur))) && !((Level <= 15)&&(Level >= 1 ))) {
System.out.println();
System.out.println("Which one would you like? What level should it be?\n1 to 15 would be best, I think.");
Pokemon = sc.next();
Level = sc.nextInt();
if ((Level <= 15) && (Level >= 1)) {
if ((Pokemon.equalsIgnoreCase(Pikachu)) || (Pokemon.equalsIgnoreCase(Charmander)) || (Pokemon.equalsIgnoreCase(Squirtle)) || (Pokemon.equalsIgnoreCase(Bulbasaur))) {
System.out.print("Added level " + Level + " " + Pokemon + " for " + Trainer + ".");
}
else {
System.out.println("Invalid Pokemon!");
}
}
else {
System.out.println("Invalid Level!");
}
}
Pokeman will always be either not X or not Y, it's basic logic since if it's X, then not-Y is true. If it's Y, then not-X is true. If it's neither then both will be true.
Change || to && and think through your logic on paper.
Should be:
while ((!(Pokemon.equalsIgnoreCase(Pikachu)) &&
!(Pokemon.equalsIgnoreCase(Charmander)) &&
!(Pokemon.equalsIgnoreCase(Squirtle)) &&
!(Pokemon.equalsIgnoreCase(Bulbasaur))) &&
!((Level <= 15)&&(Level >= 1 )))

Categories

Resources