Alternative to FloatDict

edited October 2017 in Programming Questions

I want to store a high score with a name before, so an example would be "Schotsl 100" where Schotsl is my name and 100 my score. I though the FloatDict would be perfect since I can store one String and value in one set + I can just sort them based of the value which i exactly what i wanted!

Then it turned out I can only use the string once which is my where I run into problems since it means "Schotsl" can only have one high score, Is there another method I could use that would allow me to set create multiple strings with the same name but different high scores and then sort them based of the second value

Answers

    • In order to have more than 1 score, 1st you're gonna need to have some container of float type.
    • However, a FloatDict don't accept any other value datatype but a single float.
    • What isn't clear is what exactly you wanna sort: The values under the same key or among all keys as well?
  • There are many ways to do this.

    One is using an ArrayList of custom class objects:

    ArrayList<Entry> scoreList;
    void setup() {
      scoreList = new ArrayList<Entry>();
      scoreList.add(new Entry("Schotsl", 100));
      for(Entry e : scoreList){
        println(e.name, e.points);
      }
    }
    class Entry {
       String name;
       float points;
       Entry( String name_, float points_ ){
         name = name_;
         points = points_;
       }
    }
    

    Another is to use a Table with TableRows:

    Table scoreList;
    void setup() {
      scoreList = new Table();  
      scoreList.addColumn("name", Table.STRING);
      scoreList.addColumn("points", Table.FLOAT);
    
      TableRow newScore = scoreList.addRow();
      newScore.setString("name", "Schotsl");
      newScore.setFloat("points", 100);
    
      for(TableRow r : scoreList.rows()){
        println(r.getString("name"), r.getFloat("points"));
      }
      saveTable(scoreList, "data/scoreList.csv");
    }
    

    The custom class has slightly more concise code for adding and printing data. However the Table approach comes with saveTable already built-in if you want to save and load your scoreList file between sessions.

  • @GoTo I want to put them in like a top 10 and display them automatically, so it would be perfect to have 10 different object for all of my 10 high scores (which is why I choose FloatDict since I only want one value but 10 different FloatDict 'entries' ) and then each one contains my name and my score (as float like you said) and I want to sort them among all keys

  • edited October 2017
    • I'm still confused about your request. :-??
    • Seems like you don't mind having the same name repeated w/ diff score values, right?
    • If it is so, just use a FloatList in place of FloatDict container: L-)
      https://Processing.org/reference/FloatList.html
  • edited October 2017 Answer ✓

    @schotsl -- If you also want to sort a high score list, I'd go with Table, which already has Table.sort() built in.

    Like this:

    Table scoreList;
    TableRow newScore;
    
    void setup() {
      scoreList = new Table();  
      scoreList.addColumn("name", Table.STRING);
      scoreList.addColumn("points", Table.FLOAT);
    
      newScore = scoreList.addRow();
      newScore.setString("name", "JD");
      newScore.setFloat("points", 50);
    
      newScore = scoreList.addRow();
      newScore.setString("name", "Schotsl");
      newScore.setFloat("points", 100);
    
      newScore = scoreList.addRow();
      newScore.setString("name", "GTL");
      newScore.setFloat("points", 75);
    
      scoreList.sort("points");
    
      for(TableRow r : scoreList.rows()){
        println(r.getFloat("points"), r.getString("name"));
      }
      saveTable(scoreList, "data/scoreList.csv");
    }
    

    If you want the sort results reversed, you can loop through the scores backwards -- or there are two undocumented ways of reversing the sort itself:

    scoreList.sortReverse("points");
    scoreList.sort(1, true); // column number, boolean reverse
    

    Results:

    100.0  Schotsl
    75.0   GTL
    50.0   JD
    

    Final suggestion: perhaps use int for your scores, not float....

  • I want to put them in like a top 10...

    Given the number of scores are fixed at 10, you can even change to a vanilla float[] array: *-:)
    float[] topScores = new float[10];

    Then use Arrays::sort() method to sort that array: :)>-
    http://Docs.Oracle.com/javase/8/docs/api/java/util/Arrays.html#sort-float:A-

    Still I wonder why a float datatype for scores. Can't they be just an int datatype instead? :>

  • it's a name / value pair though, score AND scorer.

    have you never played a video game?

  • edited October 2017 Answer ✓

    Oops, I've ended up forgetting you still need to associate a name to each score. How forgetful I am! #-o

    In this case, the class solution proposed at 1st by @jeremydouglass is the simplest.

    However, it's a good idea to make that class implements Comparable too:
    http://Docs.Oracle.com/javase/8/docs/api/java/lang/Comparable.html

    Then having a List container to store each object of the ScoreEntry class.

    And finally, create a getTop10() helper function which calls Collections::sort() over that List container:
    http://Docs.Oracle.com/javase/8/docs/api/java/util/Collections.html#sort-java.util.List-

    And collect the 10 1st entries after that, returning everything as 1 String, ready to be println(). \m/

    /**
     * Sorted 10 Top Score Entries (v1.0)
     * GoToLoop (2017-Oct-15)
     * Forum.Processing.org/two/discussion/24564/alternative-to-floatdict#Item_8
     */
    
    import java.util.List;
    import java.util.Collections;
    
    static final int TOPS = 10, MAX_SCORE = 100;
    final List<ScoreEntry> topScores = new ArrayList<ScoreEntry>();
    
    void setup() {
      for (int i = 0; i < TOPS; ++i) {
        topScores.add(new ScoreEntry("John", (int) random(1 + MAX_SCORE)));
        topScores.add(new ScoreEntry("Lisa", (int) random(1 + MAX_SCORE)));
        topScores.add(new ScoreEntry("Dave", (int) random(1 + MAX_SCORE)));
      }
    
      println(getTop10(topScores));
      exit();
    }
    
    static final String getTop10(final List<ScoreEntry> list) {
      final StringBuilder sb = new StringBuilder();
    
      Collections.sort(list);
    
      for (int i = 0; i < TOPS; 
        sb.append(nf(i+1, 2)).append(". ").append(list.get(i++)).append(ENTER));
    
      return sb.substring(0, sb.length() - 1);
    }
    
    class ScoreEntry implements Comparable<ScoreEntry> {
      final String name; 
      final int score; 
    
      ScoreEntry(final String entry, final int value) {
        name = entry; 
        score = value;
      }
    
      @ Override int compareTo(final ScoreEntry entry) {
        return entry.score - score;
      }
    
      @ Override String toString() {
        return "Player: " + name + "  -  Score: " + score;
      }
    }
    
  • Thanks for all your help guys! Table seems like the simplest solution since it has everything build in :)

Sign In or Register to comment.