Thread: Scoreboard saved in .txt file?

  1. #1
    Registered User
    Join Date
    Mar 2011
    Posts
    21

    Scoreboard saved in .txt file?

    Hello,

    I've been sort of making a tiny game to learn the basics in C programming where the computer generates an array of four unique, random numbers and then the player tries to guess those four numbers.

    I'm pretty much done with the game itself, but i also need a scoreboard for it, that saves your name and what score you received. I'm guessing this should be saved to a .txt file that can later on be read and displayed through the game.

    I'll paste what i've done so far unto pastebin, so you can see what im talking about... Translated all the variable names to english, wrote them in swedish at first, but i think i got all of them.

    One of the requirements is that the function control() must look like it does now:

    void control(Secret secretNumber, Secret Guess, char help[])

    What im having problems with is that i dont really know how to make the scoreboard...

    In the function "control" it checks if your guess is correct and if it is it will call the function "addToScoreboard" which will recieve the number of guesses you've made, ask for your name and then write the name and number of guesses to a .txt file...

    I have basic understanding of how to write to a textfile, but i dont really know how to use it to create a scoreboard. After an entry with name and points has been made, how can i retrieve it if i want to show the top 10 entries on the scoreboard for example?

    I also need to sort the scoreboard with the bubblesort so that the person with the best score is at the top.

    I made a typedef struct for a "Player", with points and name as variables as im guessing this is what i'll need to use when creating the scoreboard?

    I'll paste the code on pastebin, im guessing thats better than pasting it all here...

    http://pastebin.com/pJng7vDK

    Im not surprised if you find some of the coding confusing, just remember im still learning!
    Last edited by Newklear; 03-14-2011 at 10:11 AM. Reason: forgot pastebin link

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Your instincts are right. You'll have an array of Player structs. Every player's scores will be kept in a text file that your program will read, sort, and display, when requested.

    If the name is a new one, then a new struct will be written to the score file, if the score is high enough to warrant keeping. If the name is not new, and the score is high enough to be in the list of top scores you keep, then the high score will be updated for that player, ONLY IF the score is better than his previous score.

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    21
    Okay, so the function that adds entries to the scoreboard looks like this:

    Code:
    void addToScoreboard(int numberOfGuesses)
    {
        FILE *scoreboardFile = fopen("scoreboard.txt", "a");
        char name[20];
        Player player;
    
        player.points = numberOfGuesses;
    
        printf("\n\nGive name: ");
        scanf("%s", name);
        strcpy(player.name, name);
    
        fprintf(scoreboardFile, "Name: %s \nPoints: %d\n\n\n", player.name, player.points);
        fclose(scoreboardFile);
    
    }
    I've used the struct i made to enter the names and points, but how do i get them back out of the textfile??

    EDIT: i also realized i wrote "Player player", is that right or should i do "Player player[SIZE]"?
    Do i have to make it an array?

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Opening the file in append mode is correct. When a player, or the program, needs to see the top (or all) scores and who made them, etc. (in other words, the scorecard), then you will want to use an array of player structs.

    Player or player should be whatever you named your struct. C is case sensitive, so use the right upper or lower case p.

    To read from your file, you can use fscanf() if you like. Imagine you need to show the top 10 scores of the game:

    declare an int high[] array, and rewind(filePointerName) the file pointer to get it back to the start of the file.

    Then, while((fscanf(filePointerName,blah,blah)) > 0) , read in your data, into a local array of player structs

    When you're done with reading all the file data, you will sort the records, according to their scores, and display the top group.

    I'll show you how to do that, using an index array. It makes it a lot easier.

    Code:
    #include <stdio.h>
    #define SIZE 5
    
    typedef struct {
      char name[20];
      int score;
      int level;
    }player;
    
    int main() {
      int i, j, temp;
      int index[SIZE];
      player p[SIZE]={
      {"Abbey",187, 4},
      {"Dane", 194, 5},
      {"Christene", 190, 5},
      {"Zack", 210, 6},
      {"Mary", 208, 6}};
    
      printf("\n\n");
    
      for(i=0;i<SIZE;i++)  //simple initialization for the index array
        index[i] = i;
    
      //simple substitution sort, using the index
      for(i=0;i<SIZE-1;i++) {
        for(j=i+1;j<SIZE;j++) {
          if(p[index[i]].score < p[index[j]].score) { //compare thru the index
            temp=index[i];    //and swap only the indices
            index[i] = index[j];
            index[j] = temp;
          }
        }
      }
      //show the order of the actual data:
      printf("Players in unsorted order: \n\n");
      for(i=0;i<SIZE;i++) {
        printf("%20s  %3d  %2d\n", p[i].name,p[i].score,p[i].level);
      }
      //show the sorted order of the data:
      printf("\nPlayers sorted by scores: \n\n");
      for(i=0;i<SIZE;i++) {
        printf("%20s  %3d  %2d\n", p[index[i]].name,p[index[i]].score,p[index[i]].level);
      }
      printf("\n\n\t\t\t     press enter when ready");
      (void) getchar(); 
      return 0;
    }
    Last edited by Adak; 03-14-2011 at 02:38 PM.

  5. #5
    Registered User
    Join Date
    Mar 2011
    Posts
    21
    Okay, so i've tried the fprintf and fscanf out a little and printing to the scoreboard textfile works, and reading from it works halfway... I can read the entries on the scoreboard, but it reads one step to far and fills the last entry, that doesnt actually exist, with garbage...

    It doesnt sort the entries either, i tried the bubblesort and i got it to sort the points just like i want, but the names didnt follow... I must have changed something, though, cause its not working anymore >.<

    I made a function called showScoreboard to read and show the entries...

    Code:
    void showScoreboard(Player player[])
    {
        FILE *scoreboardfile = fopen("scoreboard.txt", "r");
        int i;
    
        /*system("CLS");*/
    
        for(i=0; i<MAX && !feof(scoreboardfile); i++)
        {
            fscanf(scoreboardfile, "%s %d", player[i].name, &player[i].points);
            printf("name: %s, points: %d\n\n", player[i].name, player[i].points);
        }
        printf("\n\n\n");
        system("pause");
    
        fclose(scoreboardfile);
    }
    I also made the function sortScoreboard...

    Code:
    void sortScoreboard(Spelare player[])
    {
        int i, j, tempPoints;
        char tempName[20];
        int howMany=0;
        FILE *scoreboardfile = fopen("scoreboard.txt", "r");
        FILE *scoreboardfile2 = fopen("scoreboard.txt", "w");
    
        for(i=0; i<MAX && !feof(scoreboardfile); i++)
        {
            fscanf(scoreboardfile, "%s %d", player[i].name, &player[i].points);
            /*printf("name: %s, points: %d\n\n", player[i].name, player[i].points);*/
    
            howMany++;
        }
        printf("\n\n\nhowMany: %d\n\n\n",howMany);
        for(i=0; i<howMany; i++)
        {
            for(j=0; j<howMany-1; j++)
            {
                if(player[i].points > player[i+1].points)
                {
                    tempPoints = player[i].points;
                    /*tempName = player[i].name;*/
    
                    player[i].points = player[i+1].points;
                    /*player[i].name = player[i+1].name;*/
    
                    player[i+1].points = tempPoints;
                    /*player[i+1].name = tempName;*/
                }
            }
        }
    
        for(i=0; i<howMany; i++)
        {
            printf("%s %d\n", player[i].name, player[i].points);
            fprintf(scoreboardfile2, "%s %d\n", player[i].name, player[i].points);
        }
    
        fclose(scoreboardfile);
        fclose(scoreboardfile2);
    }
    I open the file with two file pointers, one for reading and one for writing, then its supposed to read the entries on the scoreboard, sort it with bubblesort, and then print them unto the scoreboard again, overwriting the old one... It doesnt completely work though.

    I also changed the addToScoreboard function to make use of the struct Player...

    Code:
    void addToScoreboard(int numberOfGuesses)
    {
        FILE *scoreboardfile = fopen("scoreboard.txt", "a");
        Player player;
    
        printf("\n\nName: ");
        scanf("%s", player.name);
        player.points = numberOfGuesses;
    
        fprintf(scoreboardfile, "%s %d\n", player.name, player.points);
        fclose(scoreboardfile);
    
    }
    So, whatever help that can be given is very much appreciated!

    Quote Originally Posted by Adak View Post
    When you're done with reading all the file data, you will sort the records, according to their scores, and display the top group.

    I'll show you how to do that, using an index array. It makes it a lot easier.
    One of the requirements is that the scoreboard must be sorted with bubblesort though, so im kind of restricted :S

    EDIT: Hmm, i tried out the code again now and it's completely messed up now... :S

    All the sortScoreboard function does is write garbage to the scoreboard!
    Last edited by Newklear; 03-16-2011 at 08:42 AM.

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    OK, forget the index sort. Good idea, but not what you need for your assignment.

    Try swapping the entire Player struct in your bubblesort. (Yes, as a single unit), in your array of structs. Then write out the sorted array of structs, to your high score file.

    So:
    1) Add your current score to the file, if there is one not in there.
    2) rewind() the file
    3) read in all the scores into your array of structs
    4) sort the structs according to score, using Bubble sort, as required.
    5) close the score file.
    6) open the file in write mode "w", instead of append mode, and write out your sorted structs.
    7) close the file

    If you have all the structs already in your array, then you can skip 1,2 & 3 steps, above.

    Done!

    I'll be back to see how you're doing, in 3 hours.

  7. #7
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    This is how to sort structs, using a bubble sort.

    Code:
    #include <stdio.h>
    #define SIZE 5
    
    typedef struct {
      char name[20];
      int score;
      int level;
    }player;
    
    int main() {
      int i, j, sorted;
      player temp;
      player p[SIZE]={
      {"Abbey",187, 4},
      {"Dane", 194, 5},
      {"Christene", 190, 5},
      {"Zack", 210, 6},
      {"Mary", 208, 6}};
    
      printf("\n\n");
    
      //simple bubble sort
      sorted=0;        //set up the while loop to start and to
      while(!sorted) {
        sorted = 1;    //detect when no more swaps are being made
        for(i=0;i<SIZE-1;i++) {
          if(p[i].score < p[i+1].score) { 
            sorted = 0;   //not sorted yet
            temp=p[i];    //out of order, so swap structs
            p[i] = p[i+1];
            p[i+1] = temp;
          }
        }
      }
      //show the order of the actual data:
      printf("Players in sorted order: \n\n");
      for(i=0;i<SIZE;i++) {
        printf("%20s  %3d  %2d\n", p[i].name,p[i].score,p[i].level);
      }
      printf("\n\n\t\t\t     press enter when ready");
      (void) getchar(); 
      return 0;
    }

  8. #8
    Registered User
    Join Date
    Mar 2011
    Posts
    21
    Okay, have had alot to do so havent been able to program alot, but i tried it out again today, with no result...

    I tried following your 1-7 steps, but failed obviously.

    Heres the two functions that i need help with, the first one is for reading from the textfile and showing it on the screen, the second one is for reading from the textfile and sorting the data and then writing the sorted data back to the textfile... Something in them is wrong but i cant figure it out.

    Heres the pastebin link as usual... http://pastebin.com/Ehp8gBs5

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Code:
    void showScoreboard(Player player[])
    {
        FILE *scoreboardFile = fopen("scoreboard.txt", "r");
        int i, num;
    
        /*system("CLS");*/
    
        /*READ SCORES FROM TEXTFILE*/
    /*
    You need to test if the file is being opened, and feof() will repeat the last value in some conditions, so let's remove it, and test for the return from fscanf(), which will ALWAYS tell us how many items have been scanned and stored.
    */
    
        if(scoreboardFile==NULL) {  //open file OK?
          printf("\nError opening scoreboard data file - returning\n");
          return;      //if not, return
        }
    
        for(i=0; i<MAX; i++)
        {
            num = fscanf(scoreboardFile, "%s %d", player[i].name, &player[i].points);
    
            if(num < 2)  //correct last data record, and break out of the loop
              player[i].name[0]='\0'; 
              player[i].points=0;
              break;
            }
            printf("name: %s, points: %d\n\n\n", player[i].name, player[i].points);
        }
        printf("\n\n\n");
        system("pause");
    
        fclose(scoreboardFile);
    }
    See if that works better

    Any other errors, tell me EXACTLY what they are. "It didn't work", doesn't work for me.
    Last edited by Adak; 03-20-2011 at 08:33 PM.

  10. #10
    Registered User
    Join Date
    Mar 2011
    Posts
    21
    I'm not able to test the code at the moment, but i was looking through it and am now wondering what that "num" variable is...

    You can store both the player.name and player.points in the same "int num" variable?

    And i had problems with the sorting of the struct as well, it didnt sort any of the results, even though i've written the bubblesort like i thought it should be written... Any possible help with that?

  11. #11
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by Newklear View Post
    I'm not able to test the code at the moment, but i was looking through it and am now wondering what that "num" variable is...

    You can store both the player.name and player.points in the same "int num" variable?

    And i had problems with the sorting of the struct as well, it didnt sort any of the results, even though i've written the bubblesort like i thought it should be written... Any possible help with that?
    The num variable is not for data, it's the return of the number of items that fscanf() has scanned, and successfully stored.

    Don't write up a bubble sort that you think is OK. Use the one I gave you in post #7. Sorting logic is one of those things that has to be just right, and is sometimes difficult to see the logic of it.

    If you have a problem, post up your most recent code, in a program that shows the problem, including input and the output you need. Details are very important - can't help you much without them.

  12. #12
    Registered User
    Join Date
    Mar 2011
    Posts
    21
    Ahh okay, didnt know that was the return value of fscanf.

    Alright, so the function showScoreboard works great now, but the sortScoreboard is still kind of messed up... I tried adding the same code to it, the if-statement with the num variable controlling if it has reached the end, but that made it change the last entry in the scoreboard to 0 points instead every time i ran the program...
    So if i have three entries with the scores 5, 3 and 1, the first time i call the sortScoreboard function, it changes the last entry to 0 points, making it 5, 3 and 0... The next time it changes the second entry, making it 5, 0 and 0 etc...

    I'll put up the whole code again, to show what i changed...

    The code you added is at line 171 and 197...

    With the code, the problem is that it changes entries to points=0, without that code it keeps adding extra lines and fills them with garbage...

    EDIT: i changed from
    Code:
           
     if(num < 2){     /*correct last data record, and break out of the loop*/
                  player[i].name[0]='\0';
                  player[i].points=0;
                  break;
            }
    to

    Code:
           
     if(num < 2){     /*correct last data record, and break out of the loop*/
                  player[i+1].name[0]='\0';
                  player[i+1].points=0;
                  break;
            }
    and tried it again and it seems that the first time you press 2 in the menu to show the scoreboard, it shows it correctly, but if you try to view it again without shutting down the program it will start changing the entries to 0... So is it some variable that needs to be returned to 0 at the end of the loop or something?

    EDIT again: im editing alot today :P I did the same change as above to both the if-statements and it seems to be working now, it's showing the right results without changing any of the entries...

    EDIT: had to edit again... The bubblesort seems to function halfway... Its sorting one of the entries every time i show the scoreboard... If i have entries with points
    5, 4, 3, 2, 1
    it would only change it to 4, 3, 2, 1, 5 the first time i call the sortScoreboard function...

    Something is obviously wrong with the first for-loop, but it should work, shouldnt it!?
    Last edited by Newklear; 03-21-2011 at 11:08 AM.

  13. #13
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    I'll have to study your code a bit. The code I posted worked in VERY limited testing, so it might have a bug. TBhonest, I haven't written a bubble sort in years, since I use a simple substitution sort for little sorting jobs.

    I'll post back when I know what's the problem.

    Well, my first question is WTHELL didn't you use the bubble sort code I gave you? What you have is obviously wrong.

    GRrrrr!

    Try this:
    Code:
    void sortScoreboard(Player player[])
    {
        int i,j;
        Player temp;
        char tempName[20];
        int howMany=0;
        FILE *scoreboardFile = fopen("scoreboard.txt", "r");
    
        /*READ SCORES FROM TEXTFILE*/
        for(i=0; i<MAX && !feof(datafil) ; i++)
        {
            fscanf(scoreboardFile, "%s %d%*c", player[i].name, &player[i].points);
            printf("name: %s, points: %d\n", player[i].name, player[i].points);
            howMany++;
        }
        printf("\n\n\nhow many: %d\n\n\n",howMany);
    
        /*SORT WITH BUBBLESORT*/
        for(i=0; i<howMany; i++)
        {
            for(j=0; j<howMany-1; j++)
            {
                if(player[j].points > player[j+1].points)
                {
                    temp = player[j];
                    player[j] = player[j+1];
                    player[j+1] = temp;
                }
            }
        }
    
        fclose(scoreboardFile);
        FILE *scoreboardFile2 = fopen("scoreboard.txt", "w");
        void rewind ( FILE * scoreboardFile2 );
    
        /*WRITE SORTED SCORES TO TEXTFILE*/
        for(i=0; i<howmany; i++)
        {
            printf("%s %d\n", player[i].name, player[i].points);
            fprintf(scoreboardFile2, "%s %d\n", player[i].name, player[i].points);
        }
    
        fclose(scoreboardFile2);
    }
    If you want to run off the reservation on this code, enjoy the run. I'm getting very frustrated here.

    In fscanf(), I added %*c which means a char will be scanned, but nothing will be stored, to handle 1 newline char. I removed the other two newlines you were adding to the file output - don't add multiple newlines to output, as a rule - just one.

    As stated previously, feof() is known to fail on the last entry in the file (it causes it to repeat). Whether it fails on your data file depends on whether the last row of data has a newline after it, or not AFAIK. Your data file will have one there, so it should fail, but only a test will tell. You should have left that as I had it for you.

    I changed the sort to simply compare points, but swap the entire struct as one unit.

    I'll test the sort, and make any corrections in it right here, working with my data. I can't test it with your data.

    Sorting code is VERY touchy stuff. That's why I memorized the simple Substitution sort, and have used it ever since for small jobs - I like Quicksort for the big stuff.

    OK, it works fine for me, now. You may have it fail because your howMany is off, because the feof() has given you an extra value that it shouldn't have, but you know what to do to fix it.

    P.S. You don't need to rewind() for a file you just opened, in "w" mode. Only "a" mode, or any mode AFTER you've written some data out to it, and need to move the file pointer back to the beginning of the file.
    Last edited by Adak; 03-21-2011 at 12:39 PM.

  14. #14
    Registered User
    Join Date
    Mar 2011
    Posts
    21
    Alright, its all working now, lots and lots of thanks to you, you've really been a great help

    And thanks for taking the time to actually explain what i was doing wrong... Hopefully i've never have to touch bubblesort again, what a gods forsaken deathtrap that is... Removed the feof-part as well, i thought it was needed, but nope!

    Got some commenting to do, and then the game is finished, w00t!

  15. #15
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    You're welcome!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A development process
    By Noir in forum C Programming
    Replies: 37
    Last Post: 07-10-2011, 10:39 PM
  2. Formatting a text file...
    By dagorsul in forum C Programming
    Replies: 12
    Last Post: 05-02-2008, 03:53 AM
  3. Formatting the contents of a text file
    By dagorsul in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2008, 12:36 PM
  4. Inventory records
    By jsbeckton in forum C Programming
    Replies: 23
    Last Post: 06-28-2007, 04:14 AM
  5. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM