• Post Reply Bookmark Topic Watch Topic
  • New Topic

Creating a leaderboard.  RSS feed

 
Grace Loughran
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm in the process of building an algorithm for a leaderboard for my game, but now I'm stuck.

- It is a two-player game.
- The leaderboard is supposed to display the top 5 players.
- Scores will be saved to an external .txt file as a reference.

Also, may I add that I still cannot decide if I should only consider the winner's score for the leaderboard, or also the loser's.

For example:
Player 1 is Juliet.
Player 2 is Romeo.
At the end of the match, Juliet's score is greater than Romeo's.

Should I only evaluate Juliet's score for the leaderboard, or both of their scores? As of now my algorithm considers only the winner's score.

As of the moment I'm also only thinking of using JLabel to display the scores, but I'm not sure if this is the most efficient way to do it. I'm considering JTable.

So here's my current algorithm:

1) When the user starts a new match/returns to menu/exits game: (I provided 4 options: new game (scores remain but the board is reset), new match (everything is reset), menu, and exit.)



2) Save the name & score in Leaderboard class:



3) The next step which is I'm highly unsure of is to create an ArrayList for the scores (I'm missing the part about the player's name because well I'm not sure as well how I will approach it) and then sort it, but the problem after that would be how to make the score agree with the player's name, if you get what I mean.

Like for example the scores are:

Anna = 1

Pamela = 5

Gabby = 3

Sorted: 5, 3, 1
Pamela has the highest score, but how will I be able to display her name together with her score?

4) I have a checker which determines if the ArrayList of scores is empty, and if it is, it will automatically display the player's name and score (this is for the first pair of players).

It's something like this:


There's a whole lot of buzz going on in my head and now I don't know how I should proceed.

This is obviously a beginner's question and probably needs a 'big' answer, but I'm simply asking for a few hints/suggestions.

** Cross-posting: I have tried to ask this question on stackoverflow and I did get some response, but I am also looking forward to more opinions/ideas from other programmers.
 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch

Nothing needs a “big” answer. Maybe lots of small answers. And that is how you should proceed. Lots of small steps. Start by working out how you can tell who has won the most games/points/whatever to be top of the leader board. To do that there are a few preliminaries: get pencil paper and eraser. And turn your computer off.

This doesn't seem to be a GUI topic, so I shall move this discussion.
 
Paweł Baczyński
Bartender
Posts: 2087
44
Firefox Browser IntelliJ IDE Java Linux Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
One idea is to create PlayerScore class that implements Comparable<PlayerScore >.
In compareTo method you could write logic that determines which score is "bigger" that other.
 
Grace Loughran
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:Welcome to the Ranch

Nothing needs a “big” answer. Maybe lots of small answers. And that is how you should proceed. Lots of small steps. Start by working out how you can tell who has won the most games/points/whatever to be top of the leader board. To do that there are a few preliminaries: get pencil paper and eraser. And turn your computer off.

This doesn't seem to be a GUI topic, so I shall move this discussion.


Thank you! I'm actually doing that at the moment, pencil and paper thing, but I haven't worked on the logic yet of who has the most points, and now I will. And yes perhaps you are right about this not being a GUI topic, to be honest I just wasn't sure in which forum it would fit better but okay thanks again.
 
Grace Loughran
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Pawel Pawlowicz wrote:One idea is to create PlayerScore class that implements Comparable<PlayerScore >.
In compareTo method you could write logic that determines which score is "bigger" that other.


Okay thank you! But do you think I should just modify the Leaderboard class to implement the Comparable interface? Since it's the class where I'm planning anyway to write the code to evaluate the scores for the leaderboard.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Grace Loughran wrote:And yes perhaps you are right about this not being a GUI topic...

Unless you actually want to know how to paint things, or show panels and buttons and have them interact with each other, it almost never is.

GUI is all about presentation. You, on the other hand, have a problem to solve, namely: How to get the "leaders" out of a collection of items.

There are myriad ways of doing this, but using a TreeSet might be the simplest.

Winston
 
Grace Loughran
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
Grace Loughran wrote:And yes perhaps you are right about this not being a GUI topic...

Unless you actually want to know how to paint things, or show panels and buttons and have them interact with each other, it almost never is.

GUI is all about presentation. You, on the other hand, have a problem to solve, namely: How to get the "leaders" out of a collection of items.

There are myriad ways of doing this, but using a TreeSet might be the simplest.

Winston


Thanks. I'm a beginner and the data structures I'm familiar to so far are only Arrays, Stacks and Linked Lists and a bit of ArrayList, so I guess for now I'll stick to implementing Comparable . Can you perhaps, only if it's okay, give another suggestion on how I can approach this in an easier way?
 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Will a TreeSet cope with several players with the same scores?
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:Will a TreeSet cope with several players with the same scores?

Ah. Good point. Not directly.

Grace Loughran wrote:Can you perhaps, only if it's okay, give another suggestion on how I can approach this in an easier way?

Sure. Put your items in a List (eg, an ArrayList) and sort it (have a look at Collections.sort()), then take the first/last 10 (or whatever). It's not wildly fast, but it's dead simple. And do you really need the speed? We're likely talking about fractions of seconds anyway.

Winston

PS: I broke up those enormous comment lines of yours. Please DontWriteLongLines. Thanks.
 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can iterate the List 5× and pick out the largest score not yet found. That does mean, however, that 5th‑equal scores may be treated incorrectly.
 
Grace Loughran
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Grace Loughran wrote:Can you perhaps, only if it's okay, give another suggestion on how I can approach this in an easier way?

Sure. Put your items in a List (eg, an ArrayList) and sort it (have a look at Collections.sort()), then take the first/last 10 (or whatever). It's not wildly fast, but it's dead simple. And do you really need the speed? We're likely talking about fractions of seconds anyway.

Winston

PS: I broke up those enormous comment lines of yours. Please DontWriteLongLines. Thanks.


Thanks! I'll give it a try. And sorry bout the comment lines, didnt realize they were going too far. Thanks again!
 
Grace Loughran
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator



- Am I correct with my algorithm: Load the info first from the .txt file, add them up together with the current players' info, sort them all, overwrite the .txt file with the new info, then display them (only the top 5 though)?

- As of now this bunch of code only gathers up data from the txt file, adds up the info from the winner of the current game (which in the current code the name is String and the score is 40), and overwrites the .txt file with both the old& new info. I'm now about to work on how to sort all the stuff, but I'm not sure how I will add up altogether the info from the file and the info from the current players and add them into a single list to be sorted. I probably should get rid of the two ArrayLists but again I'm not sure how I will proceed from that.

- Wow I'm a mess, my head is about to explode and help would be hugely appreciated right now
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Grace Loughran wrote: - Am I correct with my algorithm: Load the info first from the .txt file, add them up together with the current players' info, sort them all, overwrite the .txt file with the new info, then display them (only the top 5 though)?

Basically. However, there is more than one "part" to this problem. Specifically, the business of reading and writing to a text file are completely separate from the business of keeping scores and displaying the "top 5", so the latter portion of your solution shouldn't care whether it gets its information from a file, a List (or array), or simply by a user typing it in through the keyboard.

My advice: You've got loadScores() and writeScores() methods, which seems substantially correct, but you're loading a List for each field. Why not just load a single ArrayList<Player> instead? And if you're doing that, why not call them loadPlayers() and writePlayers()?

Wow I'm a mess, my head is about to explode

Because you're trying to think about too much at once. Forget about leaderboards and scores and sorting for the moment and simply concentrate on writing your load() and write() methods. And don't write anything else until you KNOW they work. Every single time.

Another tip: Avoid writing methods that "return" void if you can help it, because they tend to lead to tightly coupled logic, which is generally a bad thing.

What does your loadPlayers() method need to do? I'd say this:
1. It needs to take a file name (or path).
2. It needs to load the Players contained in the file into a List (forget about sorting etc, and just concentrate on getting the Players from the file for now).
3. It needs to return that List, so that other things can use it.
So, it should probably look something like this:
private static final List<Player> loadPlayers(String filename) { ...

Why private? Because it's only really needed by your Player class. You're unlikely to want anything outside it to be running that method, so don't allow it. If you find it's too restrictive you can always change it later, but you can't change a public method to anything else without possibly breaking existing code, so be very careful which methods you make public.

Now, what does writePlayers() need to do?
1. It needs to take a List of Players AND a file name (or path) to write to.
2. It needs to write all the Players in the List out to the specified file.
3. It doesn't really need to return anything, but it might be useful for it to return the PrintWriter object that it wrote to (a useful tip to remember: just because a method returns something doesn't mean that you have to use it).
So you get:
private static final PrintWriter writePlayers(List<Player> players, String filename) { ...

Now, my advice: Code those methods; and don't even THINK about leaderboards until you've got them working.

Programming is about breaking down problems. Right now you're all over the place because you're trying to do too much at once.

I should add that the above is only one way of doing it, but even if you decide to code it differently, concentrate on one thing at a time, and don't move onto the next until you know it works.

HIH

Winston
 
Grace Loughran
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:

Programming is about breaking down problems. Right now you're all over the place because you're trying to do too much at once.

I should add that the above is only one way of doing it, but even if you decide to code it differently, concentrate on one thing at a time, and don't move onto the next until you know it works.

Thank you so much for this Winston!
You're quite right about the don't try to solve everything all at once thing. I didn't see your response right away so I continued to solve it on my own, and thankfully I was able to, though I know it's not highly efficient but I'm not worrying about that at the moment.

Now I have another problem:
I need to output the top 5 from the list to a JTextArea and I've made some attempts.

I copied the sorted list (List) to another ArrayList because whenever I passed it to the GUI class using List I get an error saying there's a conflict between util and awt.



A method of the Player class will call the Leaderboard class (which takes two parameters: winner's name and score.


I have a menu bar and the leaderboard can be accessed through there.

But the problem is my program will update the leaderboard each and every time the player begins a new match, returns to menu, or exit the game. If I write the code to display the leaderboard in the Player class, doesn't that mean it will pop up each and every time the player starts a new match, returns to menu, or exits the game?

My other attempt was to create a method that will take the sorted list as its parameter, but I get an IndexOutOfBoundsException Index: 0, Size: 0



In the Player class:

Is it probably because the program was already trying to access the list to display what it contains before it could even add the passed list?

Also I'm thinking of how I will be able to add both the players' info and not only the winner's but I'm stuck in the getName and getScore method. Should I also create separate getName and getScore methods for the winner and loser if you get what I mean?
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Grace Loughran wrote:Thank you so much for this Winston!

You're most welcome.

Now I have another problem:...

And I hate to say, but it looks to me as if you've tried to solve it again by coding, which is almost always the WRONG way to do things.

Java is your tool, not a knowledgebase. Even if you had the best carpenter's tools in the world, would you try to make a table without some kind of blueprint? Code is your hammer and chisel, NOT a CAD app.

I need to output the top 5 from the list to a JTextArea and I've made some attempts.
I copied the sorted list (List) to another ArrayList because whenever I passed it to the GUI class using List I get an error saying there's a conflict between util and awt.

So you've changed your code? That's a terrible reason to redesign.

GUI (which includes 'awt') is solely concerned with DISPLAYING (and maybe gathering) data, so if something in it causes your information design to be changed - choose another GUI.

GUI is glitz. It's shiny buttons and bouncing balls and scrollable text; it is NOT the heart of your project, it's the "chrome-plating".
I can (and have) designed entire information systems without it, so if you run into problems when using one, it's almost certainly because you don't understand what the GUI requires, which should be completely separate from how your information is structured. It's a glorified parrot.

And the first thing I see with your Leaderboard class is that it includes references to a 'textarea' (which I suspect is a GUI component).
DON'T.

The business of a Leaderboard is to return the "top" (or "bottom") n items of whatever list of "things" you hand it (ie, probably another List). It has nothing to do with display, or text areas, or buttons, or anything else to do with your screen.

Again: One thing at a time. Create a Leaderboard class that does exactly what I described. Worry about how you're going to display what it returns later.

HIH

Winston
 
Grace Loughran
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
So you've changed your code? That's a terrible reason to redesign.

GUI (which includes 'awt') is solely concerned with DISPLAYING (and maybe gathering) data, so if something in it causes your information design to be changed - choose another GUI.

GUI is glitz. It's shiny buttons and bouncing balls and scrollable text; it is NOT the heart of your project, it's the "chrome-plating".
I can (and have) designed entire information systems without it, so if you run into problems when using one, it's almost certainly because you don't understand what the GUI requires, which should be completely separate from how your information is structured. It's a glorified parrot.

And the first thing I see with your Leaderboard class is that it includes references to a 'textarea' (which I suspect is a GUI component).
DON'T.

The business of a Leaderboard is to return the "top" (or "bottom") n items of whatever list of "things" you hand it (ie, probably another List). It has nothing to do with display, or text areas, or buttons, or anything else to do with your screen.

Again: One thing at a time. Create a Leaderboard class that does exactly what I described. Worry about how you're going to display what it returns later.

HIH

Winston

Really sorry, I hope you'll bear with me. Thank you for all the tips, really. About the GUI part, I'm quite confused though, are you simply implying that I stop using GUI or? Because I am building a game with GUI, and not simply console-based. And you suggested for me to choose another GUI, but I'm only familiar to awt and Swing and some functions don't work without awt like LayoutManager, BorderLayout, Color which I all use for the GUI.

(By the way the Leaderboard class is the GUI class to show the leaderboard and the Player is the class which has the logic for the leaderboard. Sorry if I didn't mention that).

Everything is up and running now. The leaderboard works and displays what it is expected to display. My code is probably not the most efficient but I'll get to that later. I'm probably asking a lot of favors and questions, but I've made attempts and I'm still stuck and don't know who else to ask.

As you can see from my code, it only takes two parameters: One for the name, the other for the score. As of now, my program only considers the winner's score, but what I'm trying to do is for it to also consider the loser's.

Here:



Here's what I've tried so far, but I'm stuck with the getName() and getScore(). Basically it works only for one player; will I have to duplicate them for the other player?



And from the Game class which calls it:


Suggestions/tips?
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Grace Loughran wrote:Really sorry, I hope you'll bear with me. Thank you for all the tips, really. About the GUI part, I'm quite confused though, are you simply implying that I stop using GUI...

Not at all. I'm simply saying that the GUI is something completely separate from your game.

And you suggested for me to choose another GUI...

Yeah, that was a bit of hyperbole. Sorry if it confused you.
All I'm trying to say is that AWT (or Swing) is solely concerned with display, so you shouldn't alter your game logic to accommodate it.

It's far more likely that you're just unfamiliar with how to do what you want with the GUI, so maybe I should have said "do a bit more reading".

(By the way the Leaderboard class is the GUI class to show the leaderboard and the Player is the class which has the logic for the leaderboard.

So maybe that's where the problem lies. To me, a "Leaderboard" is simple a piece of logic (possibly even just a method) that takes a bunch of items and returns the "top" or "bottom" ones. A GUI component that displays those items? I don't know, but I think I'd be tempted to call it JLeaderboard, although I'd care to bet that it's really just a glorified JTable.

I'm also not sure about having the leaderboard logic in your Player class. 'Player' is singular, so I would expect it to hold the information about one Player (a very good idea, BTW) - 'Players' (or 'Participants'), on the other hand, sounds much more like a class that would hold all the people playing the game.

It's actually quite normal to have two separate classes - a singular one and a 'collective' - for situations like that. A classic example is StockItemStock (or Inventory).

Suggestions/tips?

Give me a little while to look it over, and I'll get back to you.

And once again, sorry if I caused you any confusion.

Winston

PS: You've gone back to writing ENORMOUS lines again.
Please don't, because it makes your thread very hard to read.
I'll let you break them up this time. Just use the 'Edit' key.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Grace Loughran wrote:Suggestions/tips?

Yes, a couple of which I put in my previous post, but I'll add them again here:

1. Separate your GUI from your game completely.

2. Keep your Player class for stuff to do with a single Player. Add another one to deal with all of them.

3. Your Game class appears to be an ActionListener, which is normally a GUI-type object. My advice: DON'T.

Imagine that you were creating a new Deep Blue program to play chess, and you wanted to make it really good. One possible way to go might be to have two "computer players" play millions of games against each other, analyse the results, and learn from their mistakes.

Now, do two computers need a GUI in order to play each other? Of course not. They can just whir away in the background, playing and analysing gazillions of games over sockets using data streams. However, a computer DOES need to know how to play the game (ie, its rules) in order for that to happen.
And that's why I say: the game of chess (or your "game") has NOTHING to do with how it's displayed (your GUI).

GUIs are for us puny humans.

HIH

Winston
 
Grace Loughran
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
1. Separate your GUI from your game completely.

By 'completely' what do you really mean? Because so far the code to perform the logical stuff and the code to deal with the GUI stuff are in separate classes.

Winston Gutkowski wrote:
2. Keep your Player class for stuff to do with a single Player. Add another one to deal with all of them.

Unfortunately that's actually my problem. It's a two-player game, and I'm not sure how to take info from both of the players.

Winston Gutkowski wrote:
3. Your Game class appears to be an ActionListener, which is normally a GUI-type object. My advice: DON'T.

I'm not sure what you mean, but though may I add that it's not the whole Game class (it contains more complicated-except-not-really stuff because it is the 'main' code of the game), I just included the part which I thought was relevant.


The Leaderboard class which handles all the GUI stuff by the way extends JFrame and contains a JLabel (for the image background) and a JTextArea, that's all. It doesn't implement any interface as well.

What I really need help about now is how to deal with taking information from both of the players.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Grace Loughran wrote:By 'completely' what do you really mean? Because so far the code to perform the logical stuff and the code to deal with the GUI stuff are in separate classes.

Then either it isn't a problem or you haven't shown us your whole program (or at least the bits that count).

Unfortunately that's actually my problem. It's a two-player game, and I'm not sure how to take info from both of the players.

Easy, create a Participants class that handles ALL the Players in the game. A "Player" is not "the Players".

I'm not sure what you mean, but though may I add that it's not the whole Game class (it contains more complicated-except-not-really stuff because it is the 'main' code of the game), I just included the part which I thought was relevant.

But the part that you did include involves GUI components. These are not part of your game. Did not chess or bridge or poker exist long before computers were even a glint in Babbage's eye? The GAME is NOT the GUI, and you need to separate one from the other.

The Leaderboard class which handles all the GUI stuff by the way extends JFrame and contains a JLabel (for the image background) and a JTextArea, that's all. It doesn't implement any interface as well.

And, as I said above, if you are looking at a GUI component, I suspect it should be extending JTable, because you want it to display a list of items (but I'm no GUI expert, so others may have better suggestions).

What I really need help about now is how to deal with taking information from both of the players.

Again, I think you're overthinking this. If you have a Player object that can get the information for ONE player, why not another that holds TWO (or however many you need) and run an input() method for each of its Players?

I think you need to get back to basics and think clearly about WHAT you need to do; not HOW you're going to do it.
And for that, your best friend is pencil and paper, NOT a Java IDE or editor.

(And don't worry; it's a common occurrence, even among us old warhorses. Design is NOT easy).

Winston
 
Grace Loughran
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:

I think you need to get back to basics and think clearly about WHAT you need to do; not HOW you're going to do it.
And for that, your best friend is pencil and paper, NOT a Java IDE or editor.

(And don't worry; it's a common occurrence, even among us old warhorses. Design is NOT easy).

Winston


Thank you for all the tips, time and effort Winston!
I'm able to figure it out on my own and it's kind of ridiculous because all it took was just to add a method that will add Player 2's info, if you get what I'm saying.
It looks like this:



Can't believe I hadn't thought of it before though.
But thanks for all the help, I'm keeping them all in mind!
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Grace Loughran wrote:Can't believe I hadn't thought of it before though.

Perhaps because, as I said above, it seems a bit odd to be "adding a Player" to a Player.
Participants.addPlayer()
on the other hand, make a LOT of sense. Maybe one for next time, though...

Just remember, for future reference, that having singular and collective classes for the same thing is not unusual.

But thanks for all the help, I'm keeping them all in mind!

You're most welcome. Best of luck.

Winston
 
Don't get me started about those stupid light bulbs.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!