Item List for Text RPG - java

I'm trying to make a simple text-based RPG to keep my skills sharp between semesters. I'm trying to create the different elements separately before bringing them together. Right now, I'm trying to create a basic generic list to hold "Item" objects for the player (things like potions and bombs etc.).
As you can see in the image, I'm trying to tie the index values to the individual items in the list. Since I added the same item to the list three times, it shows up three times (which is what I want), but I'm wondering how I can have this and somehow have the index value represent that actual number of items instead of just the true index value of the objects added.
Essentially, I want to be able to have the player select a number and then use the item that way. I'm sure I'm missing something obvious, I appreciate any insight!

Use a for loop instead of a for-each loop so you have access to a counter.
for (int i = 0; i < playerItems.size(); i++)
{
System.out.println(i + ". " + playerItems.get(i).getName());
}
Or, just use the ctr variable you already have and increment for each item.
for (Item i : playerItems)
{
ctr+=1;
System.out.println(ctr + ". " + playerItems.get(i).getName());
}
Also, you don't need to check if playerItems contains i. You will never get an item in a for-each loop that isn't in the collection.

Related

Complex Loop with limited iterations and IF statement

The loop needs to scan an external file, from the bottom to the top. BUT...
When the loop has scanned 6 items from the external file, it needs to stop.
Then, IF there are less than 6 items to scan from the list on the external file it needs to print all of the those items to the screen.
I know how to do a loop that can scan the file from top to bottom using inFile.hasNext(); etc. I just don't know how to do from bottom to top and then define how many iterations I want the loop to actually do, with an if statement that is something like:
if (number of iterations < 6 print all)
{
JOptionPane.showMessageDialog(iteration1, iteration2, etc...)
}`
else if (number of iterations >= 6 only show the first 6 the loop has scanned)
{
JOptionPane.showMessageDialog(iteration1, iteration2, etc...)
}
Sorry about my awful pseudo code, just really stuck and this is the last part I need to do to finish my system!
any help would be brilliant!
I would recommend using a predefined class for reading backward. As to looping:
for(int i = 0; i < 6 && /* test for more input*/; i++)
{
JOptionPane.showMessageDialog( /*next input*/ );
}
I'd try instantiating an array with 6 empty strings and then concatenate the item you get in each iteration of the loop with the corresponding empty string in your array.
Afterwards you can check for your < 6 condition and depending on the result concatenate the string you want to give to your JOptionPane
You can't read a file from bottom to top. Instead, read the file (top to bottom) keeping the last (up to) 6 items read. When you hit the end if the file, test if you you have 6 items or not and act accordingly.
Use a LinkedList object, which allows removal of the element of the list via removeFist().
You could just store all items and use only the last 6, but that may mean using a lot of memory if the file is very large.

I'm not that experienced with ArrayLists, I need some basic functions for it

I have a 2D ArrayList
List<List<String>> transitionTable = new ArrayList<List<String>>()
If I'm correct, adding "rows" to this would be (correct me if I'm wrong)
transitionTable.add(new ArrayList<String>())
How would I go about adding the equivalent of a column? Use a for loop something like this?:
for (int i = 0; i < transitionTable.get(0).size(); i++)
{
transitionTable.get(i).add("something");
}
edit: Now having trouble figuring out why it stops adding after a certain point, it's always at index
i = anything (depending on how many times I've iterated the loop"
j = 1 (always)
I forgot to mention I'm aiming for a nxn 2d arraylist (a square basically)
This is my code so far:
transitionTable.add(new ArrayList<String>()); //Adds a new row
if (transitionTable.size() == 1)
{
transitionTable.get(0).add("NULL"); //Adds a new column.
}
else
{
for (int i = 0; i < transitionTable.get(0).size(); i++)
{
transitionTable.get(i).add("NULL"); //Adds a new column (needs to iterate for each row to create something like a column)
}
}
At the moment, each iteration will add a value in the first column because they are empty;
After adding three arraylists;
transitionTable
- ArrayList[0] - []
- ArrayList[1] - []
- ArrayList[2] - []
After using your loop;
transitionTable
- ArrayList[0] - [something]
- ArrayList[1] - [something]
- ArrayList[2] - [something]
But when you add more items to each list, you then need to edit the position in the arraylist specifically! As David Wallace said, you are close, I hope the above bit of information helps!
A Java List (and ArrayList is just one implementation) is a way to represent a list of things, such as:
Strings: 〖 "This" "That" "Another string" "Wow" 〗
Integers: 〖 15 208 -632 17 999 5 〗
Other objects, anything you can describe with a class, like Animal or Contact.
Just think of them as lists you have on paper. They have order (but they are not necessarily sorted), new items can be added, items can be removed, and you can access them by index or iterate on them in order.
So what exactly does a List of Lists look like? Basically, something like this:
〖 〖 "This", "That" 〗 〖 "Something" 〗 〖 〗 〖 "A" "Bunch" "Of" "Several" 〗〗
This is a list of four items. Each item is a list of strings. Note something important about it, though: the lists inside it are still lists, and they are independent of one another just like the numbers in the list of Integers. For this reason, each of the lists inside can have a different number of items.
This is important to remember if you want to use a list of lists to represent a table. Tables are objects that have the same number of items in each row. And you have the concept of a column. In Excel, you can copy a column together as one, to somewhere else.
Using a List of Lists doesn't give you the concept of equal-length-rows and separable columns. At least, not directly. If you use it to represent a table, you should probably wrap it in a class that makes sure that every time you extend one row, all the others are extended as well, and allows you to do things like return whole columns or delete whole columns.
It would do so by looping over the rows and performing the operations on each sub-list separately.
You can use a List of Lists as a table even without wrapping it as said, if you don't actually need all those operations and you just need a rudimentary implementation of a table as part of something else. You will still have to take care to fill and retrieve "columns" by looping over the rows and accessing the required column on each of them.
I would suggest using a temporary "reference" ArrayList, like this:
List<List<String>> templist = new ArrayList<List<String>>();
for(List<String> list1 : transitionTable) {
list1.add("String whatever");
templist.add(list1);
}
transitionTable = templist;
Edit: Accidentally posted prematurely.

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

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.

IndexOutOfBoundsException - only sometimes?

I keep getting random java.lang.IndexOutOfBoundsException errors on my program.
What am i doing wrong?
The program runs fine, its a really long for loop, but for some elements i seem to be getting that error and then it continues on to the next element and it works fine.
for (int i = 0; i < response.getSegments().getSegmentInfo().size()-1; i++) {
reservedSeats = response.getSegments().getSegmentInfo().get(i).getCabinSummary().getCabinClass().get(i).getAmountOfResSeat();
usedSeats = response.getSegments().getSegmentInfo().get(i).getCabinSummary().getCabinClass().get(i).getAmountOfUsedSeat();
System.out.println("Reserved Seats: " + reservedSeats);
System.out.println("Used Seats : " + usedSeats);
}
How can i prevent this errors?
For those thinking this is an array, it is more likely a list.
Let me guess, you used to be getting ConcurrentModificationExceptions, so you rewrote the loop to use indexed lookup of elements (avoiding the iterator). Congratulations, you fixed the exception, but not the issue.
You are changing your List while this loop is running. Every now and then, you remove an element. Every now and then you look at the last element size()-1. When the order of operations looks like:
(some thread)
remove an element from response.getSegments().getSegmentInfo()
(some possibly other thread)
lookup up the size()-1 element of the above
You access an element that no longer exists, and will raise an IndexOutOfBoundsException.
You need to fix the logic around this List by controlling access to it such that if you need to check all elements, you don't assume the list will be the same as it crosses all elements, or (the much better solution) freeze the list for the loop.
A simple way of doing the latter is to do a copy of the List (but not the list's elements) and iterate over the copy.
--- Edited as the problem dramatically changed in an edit after the above was written ---
You added a lot of extra code, including a few extra list lookups. You are using the same index for all the list lookups, but there is nothing to indicate that all of the lists are the same size.
Also, you probably don't want to skip across elements, odds are you really want to access all of the cabin classes in a segmentInfo, not just the 3rd cabinClass in the 3rd segmentInfo, etc.
You seem to be using i to index into two entirely separate List objects:
response.getSegments().getSegmentInfo().get(i) // indexing into response.getSegments().getSegmentInfo()
.getCabinSummary().getCabinClass().get(i) // indexing into getCabinSummary().getCabinClass()
.getAmountOfResSeat();
This looks wrong to me. Is this supposed to happen this way? And is the list returned by getCabinClass() guaranteed to be at least as long as the one returned by getSegmentInfo()?
You're using i both as an index for the list of segment infos and for the list of cabin classes. This smells like the source of your problem.
I don't know your domain model but I'd expect that we need two different counters here.
Refactored code to show problem (guessed the types, replace with correct class names)
List<SegmentInfo> segmentInfos = response.getSegments().getSegmentInfo();
for (int i = 0; i < segmentInfos.size()-1; i++) {
// use i to get actual segmentInfo
SegmentInfo segmentInfo = segmentInfos.get(i);
List<CabinClass> cabinClasses = segmentInfo.getCabinSummary.getCabinClass();
// use i again to get actual cabin class ???
CabinClass cabinClass = cabinClasses.get(i);
reservedSeats = cabinClass.getAmountOfResSeat();
usedSeats = cabinClass.getAmountOfUsedSeat();
System.out.println("Reserved Seats: " + reservedSeats);
System.out.println("Used Seats : " + usedSeats);
}
Assuming that response.getSegments().getSegmentInfo() always returns an array of the same size, calling .get(i) on it should be safe, given the loop header (but are you aware that you are skipping the last element?) However, are you sure that .getCabinSummary() will return an array that is as large as the getSegmentInfo() array? It looks suspicious that you are using i to perform lookups in two different arrays.
You could split the first line in the loop body into two separate lines (I'm only guessing the type names here):
List<SegmentInfo> segmentInfo = response.getSegments().getSegmentInfo().get(i);
reservedSeats = segmentInfo.getCabinSummary().get(i).getAmountOfResSeat();
Then you'll see which lookup causes the crash.

Sliding an array in java - algorithm based

I'm writing a program in java where I need to slide the elements of the array and it should be performing as less as possible number of operations as it's inside a double loop and I'm working with length of array ranging from upto 10^8.
Example : A = {1,2,3,4,5,6}
Result : A = {2,3,4,5,6,1} for 1st time
A = {3,4,5,6,1,2} for 2nd time and so on..
Please feel free to suggest any other data structure or any modifications to the array!! Thank you guys!! :D
The simplest way to achieve that effect, is to do a "circular array"; that is, instead of moving the contents of the array, you can simply store the index that marks the beginning of the array.
To get the item at index i, you then do:
Type item = arr[(offset + i) % arr.length];
This way, you get the same properties as you have in an array, and you can perform any rotation in O(1).
In order to make this less of a hassle to use, you could make a simple wrapper class, that simply wraps an array, allowing easy rotation through this method. That way, the code could look clean, while you get efficient rotation.
In order to achieve an O(1) complexity, you could...
use a linked list
wrap your array with a class that stores the start position and let you access the array through "virtual" indexes (wrapped.acces(i) => array[(start + i) % array.length]
"double" your array and slice it in an appropriate way (so you don't have to change the surrounding code)
Otherwise, if you want to stick with your data structure, you need to pay O(n), no matter what.
I'd go with (2), because it is faster to both random access and linear access patterns (arrays have better data locality + O(1) random access complexity wrt O(n) of linked lists).
Use Collections.rotate(Arrays.asList(myArray), myDistance).
If you're not married to the idea of using arrays, then you could make use of the Collections.rotate() method.
List<Integer> list = new ArrayList<Integer>();
for (int i = 1; i <= 6; i++) {
list.add(i-1, new Integer(i));
}
int j = 0;
while (j < 100) {
Collections.rotate(list, -1);
System.out.print("{");
for (Integer integer : list) {
System.out.print(integer + ", ");
}
System.out.println("}");
}
Why do You have to rotate the table ?
Imagin that table is a circle and after that you can walk like this:
Object object = array[(offset + i) % array.length];
This give you O(1) on any access or rotation step;
You can use a simple List for that. If you do this sliding often, a queue would be the best choice.
The thing is, the array doesn't really change, you just start to read at position x and then continue to read at the start of the array length(array)-x elements. This is the fastest Variant.

Categories

Resources