Writing a simple text game in java. How to display items picked - java

I am trying to write the ("That's right, you brought: " + threeItems) part so that it specifies each item, and not just a copy of what the input is into the variable 'threeItems'
System.out.println("What items did you bring with again? (pick 3)");
System.out.println("(Crowbar, pistol, knife, key, flask, dynamite, flint, quill & parchment, devilishly good looks");
String threeItems = s.nextLine();
At this point, I want to display the three items the user picks out without directly printing what the user wrote. I thought about doing an if else statement but the amount of items would cause that part of the code to become extremely nested, which I do not want.
System.out.println("That's right, you brought: " + threeItems);
Thank you everyone for helping me on this! stackoverflow is a great community and I am glad to be a part of it!

You could use a Map to structure your items where the key is the application-specified item name and value a simple boolean which marks an item as being in possession by your character. You would set the boolean flag when the user input is a match to an item in the map.
With this data structure you would then simply iterate through the Map and add any item names that are "in possession" to the threeItems output variable.
How you do the mappings is up to you. Your code currently seems to suggest that the user enter a comma-delimited list of items on a single line and then hits enter. This could work but is error prone and you would have to parse the input.
I would suggest a loop which would ask the user to enter a single item name at a time and provide a way to exit the loop.
Follow up #Krzysztof in response to comment below: I didn't realize you needed to keep the selected list ordered. If you were to stick with the Map then you could use ints instead of booleans where any non-zero value means the item is in possession and the value would be the order of the item. The issue with this solution is that the Map while useful in the earlier scenario now becomes a hindrance.
Now, instead of using a Map I would suggest using Lists or rather, ArrayLists. Others have suggested Lists and arrays but I'll recommend them in a more Java-esque way:
Create a static final ArrayList<String> and populate it with item objects (just the item names really) in a constructor or initialization block. (ArrayList tutorial here.) Create a similar ArrayList for Items in possession which will initially be empty. Populate the list as the user enters the inventory of items. The index of the item +1 in the list is it's place in possession. Don't get cute with 1st, 2nd, 3rd etc. Use KISS: Item 1: ... Item 2: ... etc.

There are many possible options for this that really depend on how you want to work with the data.
The items could be an enum and then use something like an EnumSet to keep track of what you have in your inventory.
You could just store the items in a String array. Or an List of Strings (ArrayList or LinkedList), or Set of Strings (HashSet, TreeSet).
You could have each item be its own class and object. Use annotations to specify which item in the inventory it is and then annotations (but this is an implementation detail). And then you could put the verbs available on the items.
The options are really limitless and depend quite a bit on how you want to have the program work with the items and the inventory. For this, you really do need to think through the problem and the design of the game a bit more.

It depends on how the user enters the information. If they input "knife, pistol, key" you would interpret that differently than "knife pistol key."
If you would like to do it that way, look into using the split function. So, if you wanted to split the first way, it would go something like this:
String[] items = threeItems.split(", ");
where items[0] = "knife", the first thing they wrote, items[1] would equals "pistol", etc.
However, it might be better to clarify how the user should enter the input so you don't need to deal with a bunch of edge cases on how the user might format their input. You could have a new line for each item, like this:
System.out.print("First Item: ");
String first = s.next();
System.out.println();
System.out.print("Second Item: ");
String first = s.next();
System.out.println();
System.out.print("Third Item: ");
String first = s.next();
System.out.println();
The user enters an item on each line, and now you have their inputs in three seperate variables. This reduces the variability on how the user may enter information and allow for a cleaner, less-error prone game.

Related

Custom Sorting Algorithm in Java?

Hey guys so I want to write a small Java Program that helps me sort a list. Imagine the list looks like this:
Apples, Grapefruit, Bananas, Pineapples, Coconuts
Now I don't want to sort alphabetically or anything like that but for example by what fruit I like the most, so the sorted list could look like this: Coconuts, Bananas, Apples, Pineapples, Grapefruit
My idea so far was that it could kinda go like that: Apples is written into the list. Then Grapefruit and apple is compared and the user says what he likes more (here Apples) so Grapefruits move under Apples. Then it compares Bananas with eg Apples and the user tells the program he likes Bananas more so it goes above Apples and doesnt have to compare with Grapefruit anymore which saves a lot of time. The Program should handle a few hundred entries and comparisions in the end so saving time by asking fewer questions will save a lot of time. Am I on the right track? Also what would be the best way to input the list, an array, an arraylist, or...?
How should this be implemented? Is there a fitting sorting Algorithm? Thanks in advance!
You should build a Binary Search Tree.
As you're inserting new fruits, you ask the user which they like best, to find where to insert the new fruit node. To keep the number of questions down, keep the tree Balanced.
Once the "preference tree" has been built, you can iterate the tree depth-first, assigning incremental "preference values" to each fruit, and build a Map<String, Integer>, so you can quickly lookup any fruits preference values, aka sort sequence number.
The simplest way is to use Collections.sort with a custom comparator that asks for user input.
Scanner sc = new Scanner(System.in);
Collections.sort(fruits, (a, b) -> {
System.out.println("Do you prefer " + a + " or " + b + "?");
String preference = sc.next();
return preference.equals(a) ? -1 : preference.equals(b) ? 1 : 0;
});
The accepted answer is fine, but consider also this alternative:
You could store the fruits in a max-heap, which can be done with an ArrayList (when you don't know the number of fruits beforehand) or a plain array.
When you insert a new fruit, it is appended at the end of the array, and as you let it sift up (according to the heap algorithm), you ask the user for the result of the comparison(s), until the fruit is considered less liked than the one compared with (or it becomes the root -- at index 0).
As post processing, you need to pull out all elements from the top of the heap, again using the appropriate heap algorithm. They will come out in sorted order.

Can array contain text as a name of something and in same way number as a value?

I'm creating app that shows you name of google search and you press higher or lower button to answer it. But right now i don't know exactly how to do it so i came to idea to make array and put a name as a question and number of searches as a number or value. I did search on google but nothing shows me the right method to do this. If it's not possible can you explain what is better way to make this possible.
You can use a Map<String, Integer> where the key is a question and the value is number of searches.
Map reference
Another option is to use 2 lists with synced indexes, one List will hold the questions and the second list for number of searches.
Correct me if I'm wrong, but what you are asking is how to have an array of both a string and number?
If I am correct in understanding what you are wanting to do, you can't do this with just one array (See ronginats' answer for a solution which is close to this). I would make two parallel arrays, one which stores the google search and the other storing the number, but both values share an index. So you could do something like the following:
String[] searchItems = {"What is stack overflow?", "bing.com", "Does youtube own google?"}; //All of the searches
long[] timesSearched = {5000, 10, 250}; //Times each have been searched
system.out.println(searchItems[0] + " has been searched " + timesSearched[0] + " times.");

How can I set specific item in an ArrayList, without getting the OutOfBounds error?

I am trying to code a Trade plugin for a game. My idea is that a player sends request to another player, and if the other player accepts, then each side has to choose an item to trade.
I have 4 ArrayLists:
To store the requesters, to store the requested, to store requester's chosen item and to store requested's chosen item. The problem is that if multiple players trade at the same time, I can't just add the item to the List, because it can match with somebody else's trade. I tried to do this:
requesterItems.set(requesterIndex, clicked);
Where requesterIndex is the index of the requester in the other list and clicked is the item that's selected.
I know why there is an error, but I can't think of a workaround. The problem is that the List is empty and there is no element at this index. How can I add an element there without touching other spots in the list?
I would avoid to work with concrete indexes if possible and work with objects instead.
As already mentioned in the comments, I would recommend an own class with a HashMap. Heres a bit of code like I would do it (!Not tested!):
private HashMap<YourPlayerClass, List<YourItemClass>> playerItemMap = new HashMap<>();
private void tradeItems(YourPlayerClass p_player1, YourPlayerClass p_player2,
YourItemClass p_itemOfPlayer1, YourItemClass p_itemOfPlayer2)
{
List<YourItemClass> itemsOfPlayer1 = playerItemMap.get(p_player1);
List<YourItemClass> itemsOfPlayer2 = playerItemMap.get(p_player2);
//Carry out the trade for player 1
itemsOfPlayer1.remove(p_itemOfPlayer1);
itemsOfPlayer1.add(p_itemOfPlayer2);
playerItemMap.put(p_player1, itemsOfPlayer1); //Not sure if this put is necessary
//Carry out the trade for player 2
itemsOfPlayer2.remove(p_itemOfPlayer2);
itemsOfPlayer2.add(p_itemOfPlayer1);
playerItemMap.put(p_player2, itemsOfPlayer2); //Not sure if this put is necessary
}
So theres a HashMap with the player as key and his/her items as List-value.
The code example isn't failure safe. I would recommend to add some check if the items are really in this list to avoid errors. Like:
if(itemsOfPlayer1.contains(p_itemOfPlayer1))
{
//Carry out the trade
}
else
System.err.println("Player 1 tried to trade an item which wasn't in his/her inventory! Shouldn't be possible!");
I hope this helps a bit to solve your problem, let me know if I've got you wrong! Good luck!

Hash items in a 2d array, but only on one index

So, I have a 2d array (really, a List of Lists) that I need to squish down and remove any duplicates, but only for a specific field.
The basic layout is a list of Matches, with each Match having an ID number and a date. I need to remove all duplicates such that each ID only appears once. If an ID appears multiple times in the List of Matches, then I want to take the Match with the most recent date.
My current solution has me taking the List of Matches, adding it to a HashSet, and then converting that back to an ArrayList. However all that does is remove any exact Match duplicates, which still leaves me with the same ID appearing multiple times if they have different dates.
Set<Match> deDupedMatches = new HashSet<Match>();
deDupedMatches.addAll(originalListOfMatches);
List<Match> finalList = new ArrayList<Match>(deDupedMatches)
If my original data coming in is
{(1, 1-1-1999),(1, 2-2-1999),(1, 1-1-1999),(2, 3-3-2000)}
then what I get back is
{(1, 1-1-1999),(1, 2-2-1999),(2, 3-3-2000)}
But what I am really looking for is a solution that would give me
{(1, 2-2-1999),(2, 3-3-2000)}
I had some vague idea of hashing the original list in the same basic way, but only using the IDs. Basically I would end up with "buckets" based on the ID that I could iterate over, and any bucket that had more than one Match in it I could choose the correct one for. The thing that is hanging me up is the actual hashing. I am just not sure how or if I can get the Matches broken up in the way that I am thinking of.
If I understand your question correctly you want to take distinct IDs from a list with the latest date by which it occurs.
Because your Match is a class it is not as easy to compare with each other because of the fields not being looked at by Set.
What I would do to get around this problem is use a HashMap which allows distinct keys and values to be linked.
Keys cannot be repeated, values can.
I would do something like this while looping through:
if(map.putIfAbsent(match.getID(), match) != null &&
map.get(match.getID()).getDate() < match.getDate()){
map.replace(match.getID(),match);
}
So what that does is it loops through your matches.
Put the current Match with its ID in if that ID doesn't exist yet.
.putIfAbsent returns the old value which is null if it did not exist.
You then check if there was an item in the map at that ID using the putIfAbsent (2 birds with one stone).
after that it is safe to compare the two dates (one in map and one from iteration - the < is an exams for your comparison method)
if the new one is later then replace the current Match.
And finally in order to get your list you use .getValues()
This will remove duplicate IDs and leave only the latest ones.
Apologies for typos or code errors, this was done on a phone. Please notify me of any errors in the comments.
Java 7 does not have the .putIfAbsent and .replace functionality, but they can be substitued for .contains and .put

Auto-correcting an inputted String value, in java

I have a simple application that asks the user for a search term, and then performs a search for that term.
I want to give it the ability to "auto correct" the entered term. This is just for a few terms, that are easy to enter incorrectly. For example, if someone searches for "BestBuy", and what I have in my array to be searched is "Best Buy", I want to automatically convert "BestBuy" into "Best Buy" before the search. I intend to have a list of these in a text file.
What's the best way to do this? Can I have in my text file, every line be something like bestbuy, Best Buy the first item being the entered term and the second one being what it gets autocorrected into? What should I use to store this data? A hashmap?
Edit: Just to clarify, I'm not trying to make an actual auto-correct system. That's way, way beyond the scope of this project. This is just to simply replace certain inputs with "corrected" versions to match what is in the array being searched.
Autocorrect, generally has a harder solution than a hashmap, because you cannot predict the user input, so no point of making a hashmap, though you can use it as a key-existence store.
One possible way: http://en.wikipedia.org/wiki/Levenshtein_distance with the words you have in your map/dictionary, and then selecting the nearest
you could use HashMap, create a method that translate all different types of input into the correct one. You method takes input like bestbuy, best buy, BestBuy,etc and return only Best Buy. The result Best Buy will be the HashMap key.
This is bit tricky. To give a high level idea, you need to maintain a hashMap, with string without spaces as key, and the corrected value as value. when user enters a string, trim() it, check with your map' keyset, and replace with value if found matching entry.

Categories

Resources