Unity Display Highest 10 Scores - arrays

I am trying to make like a Scoreboard but for a single player. I want to save my best 10 scores to the board and display it to the MainMenu. So far I know how to save and display only one result. The code is as follows:
[SerializeField] private int score;
void Update()
{
if (score > PlayerPrefs.GetInt("highestScore"))
{
PlayerPrefs.SetInt("highestScore", score);
}
}
And I am displaying as follows in my MainMenu scene
void Start()
{
highScore.text = PlayerPrefs.GetInt("highestScore").ToString();
}
Is it possible if you help me to save my last 10 best scores and display them? I couldn't find any tutorial on how to do that. I guess I should you array of Ints and loop through that array and then save it to PlayerPrefs but I have no idea how to do that. Hope you will be able to help me and thank you in advance!!

You could use ArrayPrefs2 to store as an array (http://wiki.unity3d.com/index.php/ArrayPrefs2), then update using:
static void UpdateHighScores(int newScore)
{
var highScores = PlayerPrefsX.GetIntArray("highScores");
if (newScore > highScores[0]) {
highScores[0] = newScore;
Array.Sort(highScores);
PlayerPrefsX.SetIntArray("highScores", highScores);
}
}
After initializing the PlayerPrefs key "highScores" somewhere else with:
PlayerPrefsX.SetIntArray("highScores", new Array[10]);
Note that this produces an array with the lowest high score first and the true highest score last in the array.

You can definitely save more keys,
PlayerPrefs
takes parameters one is a key and the second is a value
you can set it up like
PlayerPrefs.SetInt("highScore_1", value);
PlayerPrefs.SetInt("highScore_2", value);
PlayerPrefs.SetInt("highScore_3", value);
PlayerPrefs.SetInt("highScore_4", value);
PlayerPrefs.SetInt("highScore_5", value);
So when some one scores more than one of the previous highest score, what you'll do is
int newScore = 50;
for(int i=1; i <= 5; i++){
if(newScore > PlayerPrefs.GetInt("highScore_"+i)){
for(int x = 5; x > i; x--){
int value = PlayerPrefs.GetInt("highScore_"+(x-1));
PlayerPrefs.setInt("highScore_"+x, value);
}
break;
}
}
Let me know if it works.

Related

JavaFX - Getting the index when clicking something inside a 2d Array

I've built a 2d array of ImageViews, and I want to be able to print out the indices of the ImageView when I click it (and use that information to change the pictures).
I've got the following code right now, but I don't know how to get it to print the x and y values of its location in the 2d array.
ImageView[][] mainGrid = new ImageView[8][8];
...
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
mainGrid[x][y] = new ImageView(image);
mainGrid[x][y].setOnMouseClicked(createMouseHandler());
}
}
...
private EventHandler<? super MouseEvent> createMouseHandler() {
return event -> {
System.out.println("Clicked");
}
}
Any help is greatly appreciated! Thank you!
The most general solution to this problem is to use the getProperties() method of the Node class. You can use that to store any user information in a node you like and then later retrieve that if you need it. In your case store the indices and then retrieve them in your mouse handler.

How do I efficiently replace a storage array in Solidity?

I have the following function in Solidity which takes as arguments 2 arrays, an array of shareholder addresses and an array of their stakes. I'm keeping an array of shareholders in storage, together with a map to their stakes.
If the updated array is the same size, it's simple, just overwrite each position with the new values. If they are different sizes however, I first go through the entire array and delete each element, and then insert the new ones. I feel this is not very efficient and it could be done better.
PS: I am a complete beginner to Solidity and this is my first contract, so please feel free to let me know if I'm doing anything stupid or inefficiently.
Thanks !
function setShareholders(address[] _shareholders, uint256[] _stakes) public onlyCEO {
require(_shareholders.length > 0);
require(_shareholders.length == _stakes.length);
uint256 accummulator = 0;
for(uint8 x = 0; x < _stakes.length; x++){
require(_addressNotNull(_shareholders[x]));
require(_stakes[x] > 0 && _stakes[x] <= 100);
accummulator = SafeMath.add(accummulator, _stakes[x]);
}
if(accummulator == 100){ // stakes need to add up to 100%
_setShareholders(_shareholders, _stakes);
}
}
function _setShareholders(address[] _shareholders, uint256[] _stakes) private {
if(_shareholders.length == shareholders.length){
for(uint8 x = 0; x < shareholders.length; x++) {
shareholders[x] = _shareholders[x];
shareholderToStake[_shareholders[x]] = _stakes[x];
}
}
else {
for(x = 0; x < shareholders.length; x++) {
delete shareholders[x];
shareholders.length--;
delete shareholderToStake[shareholders[x]];
}
for(x = 0; x < _shareholders.length; x++) {
shareholders.push(_shareholders[x]);
shareholderToStake[_shareholders[x]] = _stakes[x];
}
}
}
In theory, this would work...unfortunately in solidity, managing arrays is a costly nightmare. Doing any array manipulation, on not just one but 2 arrays, is not recommended at all.
You could keep your array of shareholders...but from there, I'd recommend creating a mapping of address->structure. This way you can loop through your mapped structure and contain all necessary data within that.
So something like this for your refactor:
address[] public shareholders;
struct ShareHolder {
uint stake;
// ...other awesome data here
}
mapping (address => ShareHolder) public shareholderData;
This way, you have your shareholders list. And you can directly access a shareholder with shareholderData[<SHAREHOLDER ADDRESS>].

Array throwing exception

I can't seem to put my finger on this and why the array is not being initialized.
Basically I am coding a 2d top down spaceship game and the ship is going to be fully customizable. The ship has several allocated slots for certain "Modules" (ie weapons, electronic systems) and these are stored in an array as follows:
protected Array<Weapon> weaponMount;
Upon creating the ship none of the module arrays are initialized, since some ships might have 1 weapon slot, while others have 4.
So when I code new ships, like this example:
public RookieShip(World world, Vector2 position) {
this.width = 35;
this.height = 15;
// Setup ships model
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(position);
body = world.createBody(bodyDef);
chassis.setAsBox(width / GameScreen.WORLD_TO_BOX_WIDTH, height / GameScreen.WORLD_TO_BOX_HEIGHT);
fixtureDef.shape = chassis;
fixtureDef.friction = 0.225f;
fixtureDef.density = 0.85f;
fixture = body.createFixture(fixtureDef);
sprite = new Sprite(new Texture(Gdx.files.internal("img/TestShip.png")));
body.setUserData(sprite);
chassis.dispose();
// Ship module properties
setShipName("Rookie Ship");
setCpu(50);
setPower(25);
setFuel(500);
setWeaponMounts(2, world);
setDefenseSlots(1);
addModule(new BasicEngine(), this);
addModule(new BasicBlaster(), this);
// Add hp
setHullHP(50);
setArmorHP(125);
setShieldHP(125);
}
#Override
public void addModule(Module module, Ship currentShip) {
// TODO Auto-generated method stub
super.addModule(module, currentShip);
}
#Override
public void setWeaponMounts(int weaponMounts, World world) {
weaponMount = new Array<Weapon>(weaponMounts);
// super.setWeaponMounts(weaponMounts, world);
}
#Override
public String displayInfo() {
String info = "Everyones first ship, sturdy, reliable and only a little bit shit";
return info;
}
When I set the number of weapon mounts the following method is called:
public void setWeaponMounts(int weaponMounts, World world) {
weaponMount = new Array<Weapon>(weaponMounts);
}
This basically initializes the array with a size (weapon mounts available) to whatever the argument is. Now to me this seems fine but I have setup a hotkey to output the size of the Array, which reports zero. If I try to reference any objects in the array, it throws an outofbounds exception.
The addModule method adds to the array as follows:
public void addModule(Module module, Ship currentShip) {
currentShip.cpu -= module.getCpuUsage();
currentShip.power -= module.getPowerUsage();
if(module instanceof Engine){
engine = (Engine) module;
}else if(module instanceof Weapon){
if(maxWeaponMounts == weaponMount.size){
System.out.println("No more room for weapons!");
}else{
maxWeaponMounts += 1;
weaponMount.add((Weapon)module);
}
}
}
My coding ain't great but heh, better than what I was 2 month ago....
Any ideas?
First of all, You should avoid instanceof. It's not a really big deal performance-wise, but it always points to problems with your general architecture. Implement two different addModule methods. One that takes a Weapon, and one that takes an Engine.
Now back to topic:
else if(module instanceof Weapon){
if (maxWeaponMounts == weaponMount.size) {
System.out.println("No more room for weapons!");
} else{
maxWeaponMounts += 1;
weaponMount.add((Weapon)module);
}
}
It looks like you use maxWeaponMounts as a counter instead of a limit. That's why I assume that it will initially be 0. The same holds for Array.size. It is not the limit, but size also counts how many elements the Array currently holds. Thus you will always have (maxWeaponMounts == weaponMount.size) as 0 == 0 and you will not add the weapon to the array. It will always stay empty and trying to reference any index will end in an OutOfBoundsException.
What you should actually do is using maxWeaponMounts as a fixed limit and not the counter.
public void setWeaponMounts(int weaponMounts, World world) {
weaponMount = new Array<Weapon>(weaponMounts);
maxWeaponMounts = weaponMounts;
}
else if(module instanceof Weapon){
if (weaponMount.size >= maxWeaponMounts) {
System.out.println("No more room for weapons!");
} else{
weaponMount.add((Weapon)module);
}
}

Creating a Map-like structure using Array of ArrayLists

I need to create a Map like data structure using an Array or ArrayLists.
Quick program over view: My map holds objects of Word which is a string and holds a frequency count of how many times the word appears in a next file.
Here is code for MyMap, Program outputs nothing.
List<Word>[] table;
int tableSize;
int index;
public MyMap(int tableSize){
table = new ArrayList[tableSize];
this.tableSize = tableSize;
}
//Problem!!
public void put(Word w){
index = Math.abs(w.hashCode()) % tableSize;
if(table[index].isEmpty()){
table[index].add(w);
}
else{
w.increaseFreq();
table[index].set(index, w);
}
}
public void displayMap(){
for(List<Word> w: table){
System.out.println(w);
}
}
}
How about using either a Generic.Dictionary<string,Word> or a KeyedCollection<string,Word>?
If you use the KeyedCollection then you will need to inherit from it and provide a GetKeyForItem implementation.

Is there any possibility to store all database fields value into one array variable if all fields have same datatype in java?

in this program i have used different array variable for each of
the fields in a
database.In database all fields having the same datatype and now i want to store all
the fields values into one array variable.is it possible???
import java.sql.*;
class ja1
{
public static void main(String ar[])
{
try
{
int x,i,j,k,l;
int a[]=new int[30];
int b[]=new int[30];
int c[]=new int[30];
int d[]=new int[30];
int count[]=new int[10];
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection c1=DriverManager.getConnection("Jdbc:Odbc:ds");
Statement s=c1.createStatement();
ResultSet r=s.executeQuery("select * from pro");
i=0;
j=0;
k=0;
l=0;
x=0;
while(r.next())
{
a[i]=r.getInt(2);
i++;
b[j]=r.getInt(3);
j++;
c[k]=r.getInt(4);
k++;
d[l]=r.getInt(5);
l++;
}
for(i=0;i<6;i++)
System.out.println(""+a[i]);
for(j=0;j<6;j++)
System.out.println(""+b[j]);
System.out.print("\n\n");
for(k=0;k<6;k++)
System.out.println(""+c[k]);
System.out.print("\n\n");
for(l=0;l<6;l++)
System.out.println(""+d[l]);
}
catch(Exception e)
{
System.out.print(e);
}
}
}
Yes, it is possible in several ways :
1) If you want to use only one array then please create an array with size of 120 (4X30) and use 4 counter to arrange your data in range. That means, your first variable would be from index 0 to 29, the 2nd would be from 30 to 69 and so on. This is not good if you don't know the exact size of your array as you are binding them with perfect size of 30.
2) You can create a POJO and have 4 arrays into it, you can use a List instead of array, but it depends on your implementation. So, create a class, put 4 arrays into it, give good variable names and access thru getter/setter methods. This will be a clear code
3) You can use a Map<Integer,Integer[]> or Map<Integer,List<Integer>> and have a single variable/reference which is holding your key value pair.
It all depends on you, if you dont know, why are you using arrays,then please move the Collection
I would define a POJO for the record and then use a generic list to add and iterate the record/s
Try this:
class RecordData
{
public int First;
public int Second;
public int Third;
public int Fourth;
}
class ja1
{
public static void main(String ar[])
{
try
{
List<RecordData> list = new ArrayList<RecordData>;
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection c1=DriverManager.getConnection("Jdbc:Odbc:ds");
Statement s=c1.createStatement();
ResultSet r=s.executeQuery("select * from pro");
while(r.next())
{
RecordData data = new RecordData();
data.First = r.getInt(2);
data.Second = r.getInt(3);
data.Third = r.getInt(4);
data.Fourth = r.getInt(5);
list.add(data);
}
for(RecordData data : list) {
System.out.println(data.First);
System.out.println(data.Second);
System.out.println(data.Third);
System.out.println(data.Fourth);
}
}
catch(Exception e)
{
System.out.print(e);
}
}
}

Resources