Saving data for a basic leaderboard? - java

I know how to save data pretty easily with the printWriter to a txt file etc.
I have a mineSweeper game that saves the name, boardsize, time taken for completion and how many mines were used; the file looks like this:
name
10x10
00:00:01
20
gap
repeat
but trying to get this to be sorted is going to be a very difficult ordeal as none of this data when saved in a file is technically "related.
Are there any ways of saving this data so they are some what related.
I was thinking of saving it in one big long string with break character at the end and between such as
name + "!!" + boardSize + "!!" + time + "!!" + mines + "!?" < as the end break
any help would be great, thanks.

You can save the data as xml:
<root>
<name>...</name>
<boardsize>...</boardsize>
.
.
.
</root>
This way you will be maintain relationship with your data when extracting it back from file

The easiest way to do this would probably be sqlLite, it's portable and fairly straight forward to use, Tutorial point have a pretty good example of how to set it up and use it - http://www.tutorialspoint.com/sqlite/sqlite_java.htm
Might also be worth looking into joins if you want to store related data in seperare tables - http://www.tutorialspoint.com/sqlite/sqlite_using_joins.htm

Keep it simple, create a model of a game session
define a class of that a serialize it to lets say json
{name:xoce, size:10x10, time:00:00:01, mines:20}
when this step is ready, append every game result to a Txtfile and if you want to sort, then read the file, deserialize it to a json list and sort the list with the anonymous Comparator so you can play with your best sort criteria

How about creating a Game class which will contain all the necessary attributes - name, boardSize, ... - and will implement Serializable and Comparable<T> so you can sort it in an array later.
Then you can simply save it to a file using ObjectOutputStream.
List<Game> gamesList = ...; // I suppose you have a list of games you want to store
ObjectOutputStream oos = new ObjectOutputStream(...);
oos.writeObject(gamesList);
...

Related

Easily save and read basic game data from files in Java?

What is the easiest (simplest) way to read and write game data to a file? Necessary game data is: gameStage(int), playerName (String), playerHealth (int), playerArmour (int), playerInventory (array of 5 Item objects, each has 2 Strings (itemType, itemName) and 1 or 2 ints (itemCount, itemDamage/itemHealing).
The format I would like (so I can easily use Scanner) is:
gameStage
playerName
playerHealth
playerArmour
SLOT1
itemType
itemName
itemCount
itemDamage
END1
SLOT2
... etc
STOP
I'm trying to work with Scanner to read from a file and BufferedWriter (which I'm unfamiliar with) to write to the text file. Everything is being stored in one file, and is being overwritten each time the game is saved.
What I am really asking is: Is there a way to do this using only Scanner and BufferedWriter, and if so, how do I do it?
If not, is there a way to do this without having to spend hours learning new things? I'm pressed for time.
I appreciate any help that I get, I've been using Java in school for a bit over a year and I am decently proficient but file saving has never been a focus of mine.
Thanks!
P.S. I'm new to Stack Overflow.
EDIT: Added one more int, gameStage, which is not attached to my Player object.
I usually use BufferedReader and BufferedWriter. But in this case, I probably use ObjectOutputSream and ObjectInputStram. I think everything you said, they are player's attributes, if I'm correcte, you should use OOS and OIS. Remember to use these classes, "Player" class has to implement Serializable and it has to be imported.

How to Iterate Over Objects to Determine Their Variable Content Depending on How Many Objects There Are in the Class?

I am VERY NEW to Java. I don't even know if I am asking the correct question, however I need help.
So I am trying to set an object's variables depending on what the user inputs. However, I am trying to make my code more efficient (by re-using methods) and this is my problem:
if (Store.product1.productName.equals("")){
Store.product1.setProductName(inputProduct);
Store.product1.setProductDemandRate(productDR);
Store.product1.setProductSetupCost(productSC);
Store.product1.setProductUnitCost(productUC);
Store.product1.setProductInventoryCost(productIC);
Store.product1.setProductSellingCost(productSP);
System.out.println(System.lineSeparator() + "Product " + inputWithCap + " Added Successfully. Returning to Main-Menu" + System.lineSeparator());
displayMenu();
}
So if I have 5 products, does that really mean I have to have that large amount of code 5 times? I can't think of a method that would allow me to just shove in some parameters and it'll do the rest :(
Any help would be GREATLY appreciated!
NB: I'm not allowed to use arrays :(
No you don't need to repeat your code several times. Each time you need a new product you should create one and then add it to the store once the values are set:
Product product = new Product(name);
product.setDemandRate(demandRate);
...
store.add(product);
The store needs to be able to take as many new products as you need. There are plenty of structures other than arrays that you can use to store them.

Java - changing data in array

I'm pretty much a complete newbie to java and programming in general. I was wondering if anyone could help me out.
So I have a .csv that I am reading and storing data from (i think in the form of an array?) by using the following. This works fine and is grabbing all the data from the csv.
fo=new File()
fo.open(filename)
contents = fo.read()
fo.close
The data that I am grabbing from the .csv is in the form of well positions on a plate e.g. A1, B1, C1, D1 etc. Now is there a way that I can make each of the letters worth a particular value?
For example, A=1, B=2 C=3 etc, and then make this new value multiply by the second number e.g. A1 would become 1*1 = 2 and A2 would become 1*2 = 2 and B2 would become 2*2 = 4.
Any help would be greatly appreciated.
Usually the way that files are read follow this structure:
Open File using Reader. (using Scanner, FileReader, etc)
Read data. (Scanner.nextLine() for example)
Close File Reader. (close)
In your case, one possible approach is to read the data and then if you want an array of values, simply use String.split() method, passing the "," as a delimiter because it is comma separated file. Once you have an array, you make w/e changes you want. In your case, you want to iterate over that array and perform transformations.
However, I would also like to clarify something, because it is kind of implied by your question, that updating the array after you read will not update the file. Just wanted to make that clear to avoid confusion.

How to save an array or object to be used in other runs

I'm working with a sensor that taking data and giving it to me whenever I call on it. I want to collect 1 minute of data in an arraylist and then save it to a file or something so that I can analyze it at a different time.
So I have something like this:
ArrayList<DataObject> data = new ArrayList<DataObject>();
public void onUpdate(DataObject d) { //being called by my sensor every second
data.add(d);
}
I want to save the ArrayList data to a file to my computer so that I can later feed it into a different program and use it there.
How do I go about doing this?
If you want to save these as CSV files, they'll be easily exportable and importable, even to Excel (which may be of value for doing further work or passing on results).
Check out OpenCSV and in particular this entry in the FAQ relating to writing the data out.
e.g.
CSVWriter writer = new CSVWriter(new FileWriter("yourfile.csv"), ',');
// feed in your array (or convert your data to an array)
String[] entries = "first#second#third".split("#");
writer.writeNext(entries);
writer.close();
I think you should just output the values to a file with something as a delimiter between the values, then read the files into an array in a new program. To get the array into a file, loop through the array while appending each number to a file when looped through until you reach the end.
If the other program is also based on Java, you could leverage the Java Serializable inferface. Here is a tutorial, Java - Serialization.
it would be best to use ObjectOutputStream for the purpose, since the output of the sensor is a integer or double. using writeObject method method your task can be done.
see the link for a detailed reading:
http://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html

using java to parse a csv then save in 2D array

Okay so i am working on a game based on a Trading card game in java. I Scraped all of the game peices' "information" into a csv file where each row is a game peice and each column is a type of attribute for that peice. I have spent hours upon hours writing code with Buffered reader and etc. trying to extract the information from my csv file into a 2d Array but to no avail. My csv file is linked Here: http://dl.dropbox.com/u/3625527/MonstersFinal.csv I have one year of computer science under my belt but I still cannot figure out how to do this.
So my main question is how do i place this into a 2D array that way i can keep the rows and columns?
Well, as mentioned before, some of your strings contain commas, so initially you're starting from a bad place, but I do have a solution and it's this:
--------- If possible, rescrape the site, but perform a simple encoding operation when you do. You'll want to do something like what you'll notice tends to be done in autogenerated XML files which contain HTML; reserve a 'control character' (a printable character works best, here, for reasons of debugging and... well... sanity) that, once encoded, is never meant to be read directly as an instance of itself. Ampersand is what I like to use because it's uncommon enough but still printable, but really what character you want to use is up to you. What I would do is write the program so that, at every instance of ",", that comma would be replaced by "&c" before being written to the CSV, and at every instance of an actual ampersand on the site, that "&" would be replaced by "&a". That way, you would never have the issue of accidentally separating a single value into two in the CSV, and you could simply decode each value after you've separated them by the method I'm about to outline in...
-------- Assuming you know how many columns will be in each row, you can use the StringTokenizer class (look it up- it's awesome and built into Java. A good place to look for information is, as always, the Java Tutorials) to automatically give you the values you need in the form of an array.
It works by your passing in a string and a delimiter (in this case, the delimiter would be ','), and it spitting out all the substrings which were separated by those commas. If you know how many pieces there are in total from the get-go, you can instantiate a 2D array at the beginning and just plug in each row the StringTokenizer gives them to you. If you don't, it's still okay, because you can use an ArrayList. An ArrayList is nice because it's a higher-level abstraction of an array that automatically asks for more memory such that you can continue adding to it and know that retrieval time will always be constant. However, if you plan on dynamically adding pieces, and doing that more often than retrieving them, you might want to use a LinkedList instead, because it has a linear retrieval time, but a much better relation than an ArrayList for add-remove time. Or, if you're awesome, you could use a SkipList instead. I don't know if they're implemented by default in Java, but they're awesome. Fair warning, though; the cost of speed on retrieval, removal, and placement comes with increased overhead in terms of memory. Skip lists maintain a lot of pointers.
If you know there should be the same number of values in each row, and you want them to be positionally organized, but for whatever reason your scraper doesn't handle the lack of a value for a row, and just doesn't put that value, you've some bad news... it would be easier to rewrite the part of the scraper code that deals with the lack of values than it would be to write a method that interprets varying length arrays and instantiates a Piece object for each array. My suggestion for this would again be to use the control character and fill empty columns with &n (for 'null') to be interpreted later, but then specifics are of course what will individuate your code and coding style so it's not for me to say.
edit: I think the main thing you should focus on is learning the different standard library datatypes available in Java, and maybe learn to implement some of them yourself for practice. I remember implementing a binary search tree- not an AVL tree, but alright. It's fun enough, good coding practice, and, more importantly, necessary if you want to be able to do things quickly and efficiently. I don't know exactly how Java implements arrays, because the definition is "a contiguous section of memory", yet you can allocate memory for them in Java at runtime using variables... but regardless of the specific Java implementation, arrays often aren't the best solution. Also, knowing regular expressions makes everything much easier. For practice, I'd recommend working them into your Java programs, or, if you don't want to have to compile and jar things every time, your bash scripts (if your using *nix) and/or batch scripts (if you're using Windows).
I think the way you've scraped the data makes this problem more difficult than it needs to be. Your scrape seems inconsistent and difficult to work with given that most values are surrounded by quotes inconsistently, some data already has commas in it, and not each card is on its own line.
Try re-scraping the data in a much more consistent format, such as:
R1C1|R1C2|R1C3|R1C4|R1C5|R1C6|R1C7|R1C8
R2C1|R2C2|R2C3|R2C4|R2C5|R2C6|R2C7|R3C8
R3C1|R3C2|R3C3|R3C4|R3C5|R3C6|R3C7|R3C8
R4C1|R4C2|R4C3|R4C4|R4C5|R4C6|R4C7|R4C8
A/D Changer|DREV-EN005|Effect Monster|Light|Warrior|100|100|You can remove from play this card in your Graveyard to select 1 monster on the field. Change its battle position.
Where each line is definitely its own card (As opposed to the example CSV you posted with new lines in odd places) and the delimiter is never used in a data field as something other than a delimiter.
Once you've gotten the input into a consistently readable state, it becomes very simple to parse through it:
BufferedReader br = new BufferedReader(new FileReader(new File("MonstersFinal.csv")));
String line = "";
ArrayList<String[]> cardList = new ArrayList<String[]>(); // Use an arraylist because we might not know how many cards we need to parse.
while((line = br.readLine()) != null) { // Read a single line from the file until there are no more lines to read
StringTokenizer st = new StringTokenizer(line, "|"); // "|" is the delimiter of our input file.
String[] card = new String[8]; // Each card has 8 fields, so we need room for the 8 tokens.
for(int i = 0; i < 8; i++) { // For each token in the line that we've read:
String value = st.nextToken(); // Read the token
card[i] = value; // Place the token into the ith "column"
}
cardList.add(card); // Add the card's info to the list of cards.
}
for(int i = 0; i < cardList.size(); i++) {
for(int x = 0; x < cardList.get(i).length; x++) {
System.out.printf("card[%d][%d]: ", i, x);
System.out.println(cardList.get(i)[x]);
}
}
Which would produce the following output for my given example input:
card[0][0]: R1C1
card[0][1]: R1C2
card[0][2]: R1C3
card[0][3]: R1C4
card[0][4]: R1C5
card[0][5]: R1C6
card[0][6]: R1C7
card[0][7]: R1C8
card[1][0]: R2C1
card[1][1]: R2C2
card[1][2]: R2C3
card[1][3]: R2C4
card[1][4]: R2C5
card[1][5]: R2C6
card[1][6]: R2C7
card[1][7]: R3C8
card[2][0]: R3C1
card[2][1]: R3C2
card[2][2]: R3C3
card[2][3]: R3C4
card[2][4]: R3C5
card[2][5]: R3C6
card[2][6]: R3C7
card[2][7]: R4C8
card[3][0]: R4C1
card[3][1]: R4C2
card[3][2]: R4C3
card[3][3]: R4C4
card[3][4]: R4C5
card[3][5]: R4C6
card[3][6]: R4C7
card[3][7]: R4C8
card[4][0]: A/D Changer
card[4][1]: DREV-EN005
card[4][2]: Effect Monster
card[4][3]: Light
card[4][4]: Warrior
card[4][5]: 100
card[4][6]: 100
card[4][7]: You can remove from play this card in your Graveyard to select 1 monster on the field. Change its battle position.
I hope re-scraping the information is an option here and I hope I haven't misunderstood anything; Good luck!
On a final note, don't forget to take advantage of OOP once you've gotten things worked out. a Card class could make working with the data even simpler.
I'm working on a similar problem for use in machine learning, so let me share what I've been able to do on the topic.
1) If you know before you start parsing the row - whether it's hard-coded into your program or whether you've got some header in your file that gives you this information (highly recommended) - how many attributes per row there will be, you can reasonably split it by comma, for example the first attribute will be RowString.substring(0, RowString.indexOf(',')), the second attribute will be the substring from the first comma to the next comma (writing a function to find the nth instance of a comma, or simply chopping off bits of the string as you go through it, should be fairly trivial), and the last attribute will be RowString.substring(RowString.lastIndexOf(','), RowString.length()). The String class's methods are your friends here.
2) If you are having trouble distinguishing between commas which are meant to separate values, and commas which are part of a string-formatted attribute, then (if the file is small enough to reformat by hand) do what Java does - represent characters with special meaning that are inside of strings with '\,' rather than just ','. That way you can search for the index of ',' and not '\,' so that you will have some way of distinguishing your characters.
3) As an alternative to 2), CSVs (in my opinion) aren't great for strings, which often include commas. There is no real common format to CSVs, so why not make them colon-separated-values, or dash-separated-values, or even triple-ampersand-separated-values? The point of separating values with commas is to make it easy to tell them apart, and if commas don't do the job there's no reason to keep them. Again, this applies only if your file is small enough to edit by hand.
4) Looking at your file for more than just the format, it becomes apparent that you can't do it by hand. Additionally, it would appear that some strings are surrounded by triple double quotes ("""string""") and some are surrounded by single double quotes ("string"). If I had to guess, I would say that anything included in a quotes is a single attribute - there are, for example, no pairs of quotes that start in one attribute and end in another. So I would say that you could:
Make a class with a method to break a string into each comma-separated fields.
Write that method such that it ignores commas preceded by an odd number of double quotes (this way, if the quote-pair hasn't been closed, it knows that it's inside a string and that the comma is not a value separator). This strategy, however, fails if the creator of your file did something like enclose some strings in double double quotes (""string""), so you may need a more comprehensive approach.

Categories

Resources