 |
 |

04-17-2012, 06:51 AM
|
|
Newcomer
|
|
Join Date: Apr 2012
Posts: 7
|
|
High score in game?
|
I made a game with a score. Now i want to save that score in a .txt so it can be displayed later. I want to save the top 5 scores by introducing them in a text box from a form1 and them display them in a form2.
So when the game is over a form pops up asking you to insert your name. This is the form:
-------------
Imports System.Windows.Forms.Form
Imports System.IO
Public Class Highscore
Private Sub bt_Ok_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bt_OK.Click
Dim i As Integer
Dim aryText(5) As String
Dim objWriter As New System.IO.StreamWriter("scor.txt")
aryText(1) = 0
aryText(2) = 0
aryText(3) = 0
aryText(4) = 0
aryText(5) = 0
For i = 1 To 5
If Tetris.Tetris.LblScoreValue.Text > aryText(1) Then
aryText(1) = Tetris.Tetris.LblScoreValue.Text
objWriter.WriteLine(TextBox_Player.Text & " " & aryText(1))
ElseIf Tetris.Tetris.LblScoreValue.Text > aryText(2) Then
aryText(2) = Tetris.Tetris.LblScoreValue.Text
objWriter.WriteLine(TextBox_Player.Text & " " & aryText(2))
ElseIf Tetris.Tetris.LblScoreValue.Text > aryText(3) Then
aryText(3) = Tetris.Tetris.LblScoreValue.Text
objWriter.WriteLine(TextBox_Player.Text & " " & aryText(3))
ElseIf Tetris.Tetris.LblScoreValue.Text > aryText(4) Then
aryText(4) = Tetris.Tetris.LblScoreValue.Text
objWriter.WriteLine(TextBox_Player.Text & " " & aryText(4))
ElseIf Tetris.Tetris.LblScoreValue.Text > aryText(5) Then
aryText(5) = Tetris.Tetris.LblScoreValue.Text
objWriter.WriteLine(TextBox_Player.Text & " " & aryText(5))
End If
Next
objWriter.Close()
Me.Close()
End Sub
------------
Tetris.Tetris.LblScoreValue is the score value made string in a label in the main class.
If score is bigger than arytext(1) =0 , replace 0 with the score and add the name inserted in the textbox.
If i do this, all the 5 names become what i inserted in the textbox along with the same score. I know it's because i put arytext(1) =0, so i need a way to look inside the txt, check each line to see if it's at least bigger that last place arryText(5) and replace it with the new score.
I would also like to increment each line position. For example if place #1 was replaced move all the scores down with one position.
Can somebody please help?? I'm familiar with programming but I'm new to vb.net and maybe I've complicated things too much.
|
|

04-17-2012, 06:55 AM
|
|
Newcomer
|
|
Join Date: Apr 2012
Posts: 7
|
|
|
If i made 200 pts in my game and it's over , after i introduce my name in that form that pops out, for ex "Alex", this is what scor.txt looks like:
Alex 200
Alex 200
Alex 200
Alex 200
Alex 200
If I play again and make 100 points, with name Mark this is the new scor.txt
Mark 100
Mark 100
Mark 100
Mark 100
Mark 100
|
|

04-17-2012, 08:46 AM
|
 |
Fabulous Florist
Forum Leader * Guru *
|
|
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,416
|
|
One way to diagnose a problem is to substitute known values for variables when you read the code. This can shed a lot of light on what's going on. Here's what I mean.
Let's give the following start values:
LblScoreValue.Text = "300"
TextBox_Player.Text = "Rose"
The rest are assigned via code. So we'll take this line:
Code:
aryText(1) = Tetris.Tetris.LblScoreValue.Text
...and consider it like this instead:
Consider these two cases:
Code:
If Tetris.Tetris.LblScoreValue.Text > aryText(1) Then
aryText(1) = Tetris.Tetris.LblScoreValue.Text
objWriter.WriteLine(TextBox_Player.Text & " " & aryText(1))
ElseIf Tetris.Tetris.LblScoreValue.Text > aryText(2) Then
aryText(2) = Tetris.Tetris.LblScoreValue.Text
objWriter.WriteLine(TextBox_Player.Text & " " & aryText(2))
Code:
If "300" > "0" Then
aryText(1) = "300"
objWriter.WriteLine("Rose" & " " & "300")
ElseIf "300" > "0" Then
aryText(2) = "300"
objWriter.WriteLine("Rose" & " " & "300")
This brings up multiple problems, but the most pressing is you don't change which name you're writing. That's why you get the same name each time. Here's some suggestions.
Normally high score logic looks like this:
Code:
1. Read the list of names and scores from the file.
2. Add the current name and score to the appropriate place in the list.
3. Trim the list.
4. Write the list to a file.
Each of those pieces is an interesting discussion in and of itself.
1. Read the list of names and scores.
You're not reading the old high scores file right now; there's not much point to writing it if you don't read it later. You've currently only got an array of scores; that means you'll lose the old names.
2. Add the current name and score to the appropriate place.
If you think through your current logic, you'll replace /every/ score, because if the score is the highest it's automatically greater than all the lower scores. That's why my step 2 involves finding the right place. A simple way to do it if you've got a list that supports insertion:
Code:
1. For each element in the list:
1.1. If score > currentScore Then
1.1.1. Insert the score before this position
1.1.2. Stop searching
2. If no replacement occurred:
2.1. Add the score to the end of the list
3. Trim the List and 4. Write the list to the file
These can be combined. If you want 5 items, only write 5 items to the file. If the last score was lower than any high scores, it'll get dropped.
Give it another shot with these hints in mind and see if you have more success.
|
|

04-17-2012, 08:49 AM
|
 |
Sinecure Expert
Super Moderator * Guru *
|
|
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,714
|
|
|
{edit}: I see AtmaWeapon slipped in. I tried to check to make sure I didn't post if someone else was going to (I saw PlausiblyDamp skipped). I've got to run so can't read Atma's till later, but I'm sure it is good and this post is probably redundant, and less helpful {/edit}
Since you are going to have five scores, when you start your game, you should check to see if you have a scores file.
If you do, then read the five sets of data into your score array.
If you don't, now would be a good time to create a file with five dummy low score values and set your high score array data to that.
Now, when someone finishes the game, you compare their score to the lowest on the list.
If it is not greater, then they don't go on the list, so you don't have to have them input anything.
If it is greater than the lowest score, then replace the lowest score with their score.
Then loop through the four "higher" score positions, and compare the trailing score against that score, and if the trailing score is greater, than swap the entries (i.e. you've written a score in the 5th slot, so starting at the 4th slot, if the 5th score is greater than the 4th, swap the 4th and 5th).
You continue with the next (is 3rd > 4th) and when the answer is no, the scores are sorted.
You would normally just do this in a simple loop, looping backwards until the preceeding score is > than the succeeding score and then exit the loop at that point.
Now, you can write those highscore values out to your save file.
|
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
|

04-17-2012, 09:17 AM
|
 |
Senior Contributor
* Expert *
|
|
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,278
|
|
The array's a bit of an issue because of the player name associated with the score.
For that reason it'd be worth creating a highscore class and using IComparible on your class so that the array can be sorted by score. It's not as daunting as it sounds...
Code:
Public Class HighScore
Implements IComparable(Of HighScore)
' public variables because I can't be bothered typing out the properties
Public PlayerName as String
Public PlayerScore as Integer
Public Sub New(byval name as string, byval score as integer)
Me.Playername = name
me.PlayerScore = score
End Sub
Public Function CompareTo(ByVal other As highscore) As Integer Implements System.IComparable(Of highscore).CompareTo
return Me.PlayerScore.CompareTo(other.PlayerScore)
End Function
Public Overrides Function ToString() As String
Return me.playerName & ": " & me.playerScore.ToString
end sub
End Class
An array of HighScores can now act like an array of integers when calling Array.Sort to get the scores in order.
|
__________________
There are no computers in heaven!
|

04-17-2012, 11:27 AM
|
|
Newcomer
|
|
Join Date: Apr 2012
Posts: 7
|
|
Quote:
Originally Posted by AtmaWeapon
One way to diagnose a problem is to substitute known values for variables when you read the code. This can shed a lot of light on what's going on. Here's what I mean.
Let's give the following start values:
LblScoreValue.Text = "300"
TextBox_Player.Text = "Rose"
The rest are assigned via code. So we'll take this line:
Code:
aryText(1) = Tetris.Tetris.LblScoreValue.Text
...and consider it like this instead:
Consider these two cases:
Code:
If Tetris.Tetris.LblScoreValue.Text > aryText(1) Then
aryText(1) = Tetris.Tetris.LblScoreValue.Text
objWriter.WriteLine(TextBox_Player.Text & " " & aryText(1))
ElseIf Tetris.Tetris.LblScoreValue.Text > aryText(2) Then
aryText(2) = Tetris.Tetris.LblScoreValue.Text
objWriter.WriteLine(TextBox_Player.Text & " " & aryText(2))
Code:
If "300" > "0" Then
aryText(1) = "300"
objWriter.WriteLine("Rose" & " " & "300")
ElseIf "300" > "0" Then
aryText(2) = "300"
objWriter.WriteLine("Rose" & " " & "300")
This brings up multiple problems, but the most pressing is you don't change which name you're writing. That's why you get the same name each time. Here's some suggestions.
Normally high score logic looks like this:
Code:
1. Read the list of names and scores from the file.
2. Add the current name and score to the appropriate place in the list.
3. Trim the list.
4. Write the list to a file.
Each of those pieces is an interesting discussion in and of itself.
1. Read the list of names and scores.
You're not reading the old high scores file right now; there's not much point to writing it if you don't read it later. You've currently only got an array of scores; that means you'll lose the old names.
2. Add the current name and score to the appropriate place.
If you think through your current logic, you'll replace /every/ score, because if the score is the highest it's automatically greater than all the lower scores. That's why my step 2 involves finding the right place. A simple way to do it if you've got a list that supports insertion:
Code:
1. For each element in the list:
1.1. If score > currentScore Then
1.1.1. Insert the score before this position
1.1.2. Stop searching
2. If no replacement occurred:
2.1. Add the score to the end of the list
3. Trim the List and 4. Write the list to the file
These can be combined. If you want 5 items, only write 5 items to the file. If the last score was lower than any high scores, it'll get dropped.
Give it another shot with these hints in mind and see if you have more success.
|
 
Thx for the advices so far.
I'm gonna implement that feature that the form should pop out only if the score is bigger than array 5 later after i sort the writing/reading problem first.
So i have a couple of questions?
1.In the logic of my code if I switch and start from the bottom of the code I get the same thing because if LblScoreValue.Text>aryText(1) but smaller than aryText(2) it's ok. but if LblScoreValue.Text>aryText(2), it's gonna change both aryText(1) and (2) and if it's the biggest it's gonna replace all of them again, so it's gonna be the same result. 5 times the same thing
2.how do i read the names and scores in the file. using Console.ReadLine() or StreamReader. I can't get the sintax right for both of them
So it's like this the score at game over must read the file to see if it's bigger than #5, if it is replace aryText(5) with the new value, but if it's bigger than aryText(4), how to replace first aryText(4) with aryText(5) and then get the new value, so that it seems like the position has dropped one spot.
3. for your :
Quote:
For each element in the list:
1.1. If score > currentScore Then
1.1.1. Insert the score before this position
1.1.2. Stop searching
|
Stop searching should be like a break in C. So what's the equiv in vb.net. End Loop ?
I'm ataching a diagram of what i'm looking to achieve maybe it will make things clearer.
I must certainly be complicating my like too much, there must be an easier way.
|
|

04-17-2012, 03:09 PM
|
|
Newcomer
|
|
Join Date: Apr 2012
Posts: 7
|
|
Am i going in the right direction ?
Ok , so I rewrote the code a bit differently, I made a different string for every player name, i'm not using the same on for every player. Also I'm trying to read first the file and then rewrite it. The problem is that if i try first to read it before writing it for the first time, is says the file doesnt not exists. And I try to write the file first and then read it , it gives me an error like "The process cannot access the file 'C:\....\bin\Debug\scor.txt' because it is being used by another process." So i'm thinking streamreader is in conflict with streamwriter. This is the code:
Code:
Private Sub bt_Ok_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bt_OK.Click
Dim FILE_NAME As String = "scor.txt"
Dim Scor(5) As String
Dim Nume(5) As String
Dim i As Integer
For i = 1 To 5
Dim objreader As New System.IO.StreamReader(FILE_NAME)
Do While objreader.Peek() >= 0
Console.WriteLine(objreader.ReadLine())
Loop
objreader.Close()
Dim objWriter As New System.IO.StreamWriter(FILE_NAME)
If Tetris.Tetris.LblScoreValue.Text > Scor(1) Then
TextBox_Player.Text = Nume(1)
Tetris.Tetris.LblScoreValue.Text = Scor(1)
objWriter.WriteLine(Nume(1) & " " & Scor(1))
objWriter.Close()
ElseIf Tetris.Tetris.LblScoreValue.Text > Scor(2) Then
TextBox_Player.Text = Nume(2)
Tetris.Tetris.LblScoreValue.Text = Scor(2)
objWriter.WriteLine(Nume(2) & " " & Scor(2))
objWriter.Close()
ElseIf Tetris.Tetris.LblScoreValue.Text > Scor(3) Then
TextBox_Player.Text = Nume(3)
Tetris.Tetris.LblScoreValue.Text = Scor(3)
objWriter.WriteLine(Nume(3) & " " & Scor(3))
objWriter.Close()
ElseIf Tetris.Tetris.LblScoreValue.Text > Scor(4) Then
TextBox_Player.Text = Nume(4)
Tetris.Tetris.LblScoreValue.Text = Scor(4)
objWriter.WriteLine(Nume(4) & " " & Scor(4))
objWriter.Close()
ElseIf Tetris.Tetris.LblScoreValue.Text > Scor(5) Then
TextBox_Player.Text = Nume(5)
Tetris.Tetris.LblScoreValue.Text = Scor(5)
objWriter.WriteLine(Nume(5) & " " & Scor(5))
objWriter.Close()
End If
Next
Me.Close()
End Sub
End Class
|
Last edited by passel; 04-17-2012 at 04:46 PM.
Reason: Added [code] tags
|

04-18-2012, 06:43 AM
|
 |
Senior Contributor
* Expert *
|
|
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,278
|
|
You don't need to read and write the file 5 times, which is what your loop will be doing.
It would be far easier to have an array of highscores that when your program starts it reads the current highscores into the array. When someone finishes their game it checks if it's a highscore against the array and if it is it removes the lowest score from the array (if the array contains the maximum number of high scores) and puts the new score into the array and then writes the array out to the file.
That breaks it down into seperate methods to write, where each method has a particular task (this uses the HighScore class I detailed above)...
Code:
Private Sub ReadHighScores(byval filePath as string) as HighScore()
' Read the file and return an array of highscores
End Sub
Private Sub WriteHighScores(byval filePath as string, byval highscores() as HighScore)
' Write the array to the file
End Sub
Private Function IsHighScore(byval newScore as integer, byval highScores() as HighScore) as Boolean
' Check the array to see if newScore is higher than any of the existing highscores
' and return true if it is
End Function
Private Sub AddNewHighScore(byval newScore as HighScore, byval highScores() as HighScore)
' Remove the lowest score from the array if array is at MaxHighScores and add the new score
End Sub
Then, when the game has finished it goes along the lines of...
Code:
' The array containing the highscores.
' In the form load then this is set to the return of ReadHighScores
Dim MyHighScores() as HighScore
Private Sub bt_Ok_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bt_OK.Click
dim userName as string
dim h as highscore
If IsHighScore(cint(Tetris.Tetris.LblScoreValue.Text), MyHighScores) Then
' Get a name for them.
userName = InputBox("Enter name:", "You got a high score")
h = new HighScore(username, cint(Tetris.Tetris.LblScoreValue.Text))
AddNewHighScore(h, MyHighScores)
WriteHighScores([A file to save them to], MyHighScores)
end if
End Sub
It's readable as to what it's doing, each seperate process is fairly easy to write because it only has to achieve a particular task (and it's easy enough to test that it achieves its task) and it's possible to change the logic of a particular step without screwing up anything else.
|
__________________
There are no computers in heaven!
Last edited by DrPunk; 04-18-2012 at 07:49 AM.
|

04-18-2012, 10:50 AM
|
|
Newcomer
|
|
Join Date: Apr 2012
Posts: 7
|
|
|
I'm sorry, I don't understand your methods. I just wanted to understand why my method wasn't working. Not make a whole different logic to the game. I have 3 forms : the main gameform one where the inputform pops put at the end of the game, then i got inputform that needs to check the information in the file.txt and make the necesary changements if it's a highscore and then i got a thirf form Highscoreform that must display the top 5 scores.
I just wanted to modify my code a bit so that it would work, not make a whole new one, because i'm new at vb and I juggling with so many subs and forms is too much for me.
In the gameform i Have,
If GameOver=true Then
'................
If score > highscore.array(5)
Show inputform
End if
'................
In the input form
I have to see if the gameform.score is bigger than 4,3,2,1 ' where does it stop,( so there must be a read function somewhere), after that write the new code over the line which is smaller than it, and decrement the rest of the scores by one line.
in the higscoreform
replace each labelanames and labelscores in the form with the names and the scores that match those names from the file.txt
|
|

04-18-2012, 11:00 AM
|
 |
Senior Contributor
* Expert *
|
|
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,278
|
|
Quote:
|
Not make a whole different logic to the game.
|
Working logic as opposed to not working logic. It's not different. It does what you want it to do.
You're struggling to understand why what you've written doesn't do what you want it to. That suggests it's badly written. I've tried to show you how you could write it so that it's easier to work out what it's doing.
You've taken something that didn't work, you didn't know why it didn't work, then changed it to try and make it work and still don't understand why it doesn't work. On top of that you then want someone else to work out what it's doing in order to tell you why it's not doing what it should be doing.
Maybe someone else would like to do that. I don't. Sorry. But I can see it's reading and writing the file 5 times and it shouldn't be doing that, along with your original code that never worked. It would just be better if it was written well.
|
__________________
There are no computers in heaven!
|

04-18-2012, 11:19 AM
|
|
Newcomer
|
|
Join Date: Apr 2012
Posts: 7
|
|
point taken
I understand your point of view. You're right.
Can you be more specific with your sub then, so i can finally finish this thing?
More clearly, how do i write 5 lines, how to i read and compare those 5 lines with the new score. how do i rewrite it. I know it sound needy, but i've been searching forums and tutorials for the last 4 days and I only got like general methods that i couldn't apply here or other useless stuff.
Code:
Private Sub ReadHighScores(byval filePath as string) as HighScore()
' Read the file and return an array of highscores
End Sub
Private Sub WriteHighScores(byval filePath as string, byval highscores() as HighScore)
' Write the array to the file
End Sub
Private Function IsHighScore(byval newScore as integer, byval highScores() as HighScore) as Boolean
' Check the array to see if newScore is higher than any of the existing highscores
' and return true if it is
End Function
Private Sub AddNewHighScore(byval newScore as HighScore, byval highScores() as HighScore)
' Remove the lowest score from the array if array is at MaxHighScores and add the new score
End Sub
|
|

04-18-2012, 11:30 AM
|
 |
Senior Contributor
* Expert *
|
|
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,278
|
|
Quote:
Originally Posted by qweqwe256
I'm sorry, I don't understand your methods.
|
I should maybe at least answer this.
The method names are pretty self explanatory.
The ReadHighScores one's probably the hardest but the others shouldn't take much effort.
For example...
Code:
Private Function IsHighScore(byval newScore as integer, byval highScores() as HighScore) As Boolean
dim h as HighScore
dim isHigh as boolean = False
' How many high scores are recorded?
if highScores.Length < MAXHIGHSCORES then ' MAXHIGHSCORES is 5 for you, but it's worth making it
' a constant so you can easily change it and refer to it elsewhere
' There is space for new high scores so it must be a high score
isHigh = True
Else
' There are high scores. Look at each high score, order doesn't matter
For each h in highScores
' Is the new score higher than this existing high score?
if newScore > h.PlayerScore then
' It is! This score is a new high score
isHigh = True
' No need to check any more scores
exit for
end if
Next
end if
return isHigh
End Function
Again, it's easy to see what it's doing. Or more importantly if it's not doing what it should be doing, why it isn't.
No doubt the other 3 will be in this thread by the end of the week.
Edit :- I would like to add, that the main point of this is that one of the tasks that you need to complete is working out if a score is a high score or not. How you go about working out it's a high score is your own business. I imagine everyone here would have a different way of doing it. But anyone tackling this problem would have to overcome working out that a new score is a high score. So, stick that calculation into a function. It's the same for the other tasks. They've got to be done. How everyone does them will be different. And they're worth putting in their own methods.
|
__________________
There are no computers in heaven!
Last edited by DrPunk; 04-18-2012 at 11:45 AM.
|

04-18-2012, 11:54 AM
|
 |
Senior Contributor
* Expert *
|
|
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,278
|
|
I'm reluctant to type out all the code.
Rather than always having 5 high scores I've based all this on having no high scores to maxhighscores.
Writing the high scores, you already know about the StreamWriter to use and the IsHighScore that I wrote shows how to loop over every score. The HighScore class has a .ToString function to use to write the properties to the file.
Amending the high scores array, like with the IsHighScore function should first check the length of the array and if there's less than maxhighscores it can just dump it into the highscore array (Redim preserve the array to .GetUpperBound(0) + 1 of the array). If the array is "full" then you want to sort it (using Array.Sort that the IComparable interface of the HighScore class will let you use) then replace the last item (maxhighscores - 1) with the new high score. Obviously it won't be in order any more but it will have replaced the lowest score with the new score.
Reading the high scores, you can read it line by line and split the line by ":" which seperates the username and score in to seperate elements of .ToString. Then use those to create highscore classes and put them into an array. Reading should check if the file exists and create an empty highscores array if there is no file (as far as an empty array goes, you could check if HighScores is nothing in certain places in the code like when the IsHighScores function checks the length of the array an array of nothing would cause an error and so a Is Nothing check should maybe be in there, or you could Redim an array with -1. See -> http://msdn.microsoft.com/en-us/libr...(v=vs.80).aspx for more information on empty arrays).
|
__________________
There are no computers in heaven!
Last edited by DrPunk; 04-18-2012 at 12:04 PM.
|

04-19-2012, 07:07 AM
|
 |
Senior Contributor
* Expert *
|
|
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,278
|
|
I've done the code for the other routines. I've tried it and it appears to be working OK. It uses 2 Buttons (Button1 and Button2) and a NumericUpDown control (NumericUpDown1). Button1 does the high score stuff on the value of NumericUpDown1. Button2 puts the scores into a messagebox on the screen using a new DisplayScores method I've added.
Code:
Public Class Form1
Private Const MAXHIGHSCORES = 5
Private Const SCOREFILE = "C:\Temp\Scores.txt"
Dim MyHighScores() As HighScore
Private Function ReadHighScores(ByVal filePath As String) As HighScore()
' Read the file and return an array of highscores
Dim sr As IO.StreamReader
Dim line As String
Dim params() As String
Dim highScores() As HighScore
Dim h As HighScore
' Initialise the array as empty. If there's no file there will be no scores
ReDim highScores(-1)
' Check that the file exists
If IO.File.Exists(filePath) Then
Try
sr = New IO.StreamReader(filePath)
' read each line of the file creating highscores as we go along
While Not sr.EndOfStream
line = sr.ReadLine
' Check that there's something in the line. Writeline of WriteHighScores
' will leave a blank line at the end
If line.Length > 0 Then
' Split the line into its name and score parameters
params = line.Split(":")
' Use those to create a highscore
h = New HighScore(params(0), CInt(params(1)))
' Increase the size of the array by one and add the high score
ReDim Preserve highScores(highScores.GetUpperBound(0) + 1)
highScores(highScores.GetUpperBound(0)) = h
End If
End While
Catch ex As Exception
Throw
Finally
sr.Close()
sr.Dispose()
End Try
End If
Return highScores
End Function
Private Sub WriteHighScores(ByVal filePath As String, ByVal highscores() As HighScore)
' Write the array to the file
Dim sw As IO.StreamWriter
Dim h As HighScore
' Are there any high scores recorded
If highscores.Length > 0 Then
Try
' Overwrite an existing high score file
sw = New IO.StreamWriter(filePath, False)
' Work through each high score and add it to the file
For Each h In highscores
sw.WriteLine(h.ToString)
Next
Catch ex As Exception
Throw
Finally
sw.Close()
sw.Dispose()
End Try
End If
End Sub
Private Function IsHighScore(ByVal newScore As Integer, ByVal highScores() As HighScore) As Boolean
Dim h As HighScore
Dim isHigh As Boolean = False
' How many high scores are recorded?
If highScores.Length < MAXHIGHSCORES Then ' MAXHIGHSCORES is 5 for you, but it's worth making it
' a constant so you can easily change it and refer to it elsewhere
' There is space for new high scores so it must be a high score
isHigh = True
Else
' There are high scores. Look at each high score, order doesn't matter
For Each h In highScores
' Is the new score higher than this existing high score?
If newScore > h.PlayerScore Then
' It is! This score is a new high score
isHigh = True
' No need to check any more scores
Exit For
End If
Next
End If
Return isHigh
End Function
Private Function AddNewHighScore(ByVal newScore As HighScore, ByVal highScores() As HighScore) As HighScore()
' Remove the lowest score from the array if array is at MaxHighScores and add the new score
' Check to see how many scores are recorded
If highScores.Length < MAXHIGHSCORES Then
' Less than the maximum means increase the size of the array
ReDim Preserve highScores(highScores.GetUpperBound(0) + 1)
Else
' At the maximum means we want to replace the lowest score so get the array in
' order
Array.Sort(highScores)
Array.Reverse(highScores)
End If
' Record the score at the last element. Either empty or the lowest scores
highScores(highScores.GetUpperBound(0)) = newScore
Return highScores
End Function
Private Sub DisplayScores(ByVal highScores() As HighScore)
Dim h As HighScore
Dim scores As String = ""
Array.Sort(highScores)
Array.Reverse(highScores)
For Each h In highScores
scores &= h.ToString & vbCrLf
Next
MessageBox.Show(scores)
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' When the form loads, read the high scores
MyHighScores = ReadHighScores(SCOREFILE)
End Sub
Private Sub bt_Ok_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim userName As String
Dim h As HighScore
If IsHighScore(NumericUpDown1.Value, MyHighScores) Then
' Get a name for them.
userName = InputBox("Enter name:", "You got a high score")
h = New HighScore(userName, NumericUpDown1.Value)
MyHighScores = AddNewHighScore(h, MyHighScores)
WriteHighScores(SCOREFILE, MyHighScores)
End If
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
DisplayScores(MyHighScores)
End Sub
End Class
A couple of things have changed since I tried getting this to work.
My passing on the Array by value to AddNewHighScore was wrong, so AddNewHighScore is now a function and returns the array with the new score in it.
I could've got around the AddNewHighScore problem by having it access MyHighScores instead of passing the array (or could've ByRef'd), but it's quite nice to have methods working on stuff you can pass to it if you can so that it doesn't rely on external stuff if you wanted to use the method elsewhere (like passing SCOREFILE instead of using it in the methods). Ideally for that reason the whole workings of high scores that's in Button1.Click should really be in it's own method and passing the high score to it rather than using a control's value. But hey ho, there's always room for improvement.
The order that the array gets sorted into is Ascending when it really should be descending. Therefore I've gone for reversing the array after sorting it. Not a great technique if the array is large (but it's 5 here so it's hardly cpu breaking). The alternative would be to go and change the CompareTo in the HighScore class so that it compared the numbers the other way round, but I thought I'd go with the simpler option that works with the class I've already posted instead of having to change that class too.
I didn't do much in the way of error handling so that should really be addressed.
As the code stands, it will happily cope with increasing the MAXHIGHSCORES number but will go a bit screwy on decreasing it less than the current number of high scores. It should also be noted that scores of 0 are high scores.
Usernames with a ":" in them will cause the reading of high scores to error.
|
__________________
There are no computers in heaven!
Last edited by DrPunk; 04-19-2012 at 07:31 AM.
|

04-20-2012, 09:43 AM
|
|
Newcomer
|
|
Join Date: Apr 2012
Posts: 7
|
|
Code:
Public Class Form1
Private Const MAXHIGHSCORES = 5
Private Const SCOREFILE = "C:\Temp\Scores.txt"
Dim MyHighScores() As HighScore
Related to my game , what is form1, and in
Code:
Dim MyHighScores() As HighScore
. Who is HighScore. It's asking me to declare it.
|
|

04-20-2012, 10:04 AM
|
 |
Senior Contributor
* Expert *
|
|
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,278
|
|
Quote:
Originally Posted by DrPunk
The array's a bit of an issue because of the player name associated with the score.
For that reason it'd be worth creating a highscore class and using IComparible on your class so that the array can be sorted by score. It's not as daunting as it sounds...
Code:
Public Class HighScore
Implements IComparable(Of HighScore)
' public variables because I can't be bothered typing out the properties
Public PlayerName as String
Public PlayerScore as Integer
Public Sub New(byval name as string, byval score as integer)
Me.Playername = name
me.PlayerScore = score
End Sub
Public Function CompareTo(ByVal other As highscore) As Integer Implements System.IComparable(Of highscore).CompareTo
return Me.PlayerScore.CompareTo(other.PlayerScore)
End Function
Public Overrides Function ToString() As String
Return me.playerName & ": " & me.playerScore.ToString
end sub
End Class
An array of HighScores can now act like an array of integers when calling Array.Sort to get the scores in order.
|
This class that I created earlier in this thread is the HighScore class. The program uses an array of these.
As far as Form1 goes, that's the form of the application.
Create a new project, that will create Form1. When you open the code file for Form1, all the is there until you start adding code is...
Code:
Public Class Form1
End Class
If you want to post the code into an existing form then just copy the bits between the Public Class and End Class parts of the class.
Same with the HighScore class. In the project menu, choose Add Class. It'll ask you for a name, call it HighScore. It'll open the file and you'll just have...
Code:
Public Class HighScore
End Class
... so you can select everything between those parts of the class in this post to copy and paste in between the Public Class and End Class.
If that all makes sense.
|
__________________
There are no computers in heaven!
|
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
|
|
|
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|
|
|
|
 |
|