Before I post the code there are two things I should mention, 1 there is a text file that works in link with this code that I will post the few details in the post. 2, I'm nearly done with this project of mine so I'm only really focused on the topFive() function and the topWin() function. My issue though is when I try to get the top five players in this function it only prints out one name five times. I'd really appreciate any help, very stumped!
Here are the players.txt file's contents followed by the code.
Peter 100 90
Emma 150 0
Richard 50 10
Abigail 138 128
Jacob 210 100
Anthony 800 -10
Joseph 328 62
Ashley 89 16
Hannah 197 7
Ethan 11 -20
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
typedef struct {
char pl_name[10];
int balance;
int wincount;
} plyr;
plyr pl[10];
plyr top[5];
int psearch(){ // finds the index of the name in the file
int i;
char name[20];//This creates the initial array that searches throughout the array for the users name variable identity.
printf("Enter the user's name. ");
scanf("%s", name); // This will ask the user for the name whos balance they are changing.
for(i=0;i<10;){
if (strcmp(&name, pl[i].pl_name) == 0 ) break;
i++; //This will continue the search.
}
return i;
}
void topBalance(){ // finds the top balance for 5 players
int i;
printf("What is the player name? ");
scanf("%s", pl[i].pl_name); // This basically takes a users name and is ready to edit it.
printf("What's the balance? ");
scanf("%d", &pl[i].balance); // This changes whatever name is enters balance to whatever it wants to change it to.
}
void playGame(){ //Needs correction.
srand(time(0));
char enter = 'i';
int r1, r2, sum, point;
int playerno = psearch();
char again = 'y';
while (playerno == 10) { // This ensures that there are only 10 players that are going to be searched throughout.
printf("Players not found.\n");
playerno = psearch();
}
while(again == 'y'){
for(;;) {
printf("Press enter to roll the dice. ");
getchar(); // This will continue the dice to be rolled past the original point of just one or two rolls
while (enter != '\n')
enter = getchar();
r1 = (rand() % 6) + 1; // This acts as the math of the function and it takes a random integer and divides it by 6 and takes the remainder by 1.
r2 = (rand() % 6) + 1;
sum = r1 + r2;
printf("You got a %d and %d from the roll, the sum is %d. \n", r1, r2, sum);
if(sum == 7 || sum == 11) {
pl[playerno].balance += 10;
pl[playerno].wincount += 10;
printf("Your new balance is %d. \n", pl[playerno].balance);
break;
}
else if(sum == 2 || sum == 3 || sum == 12){
pl[playerno].balance -= 1; // This is anoyher simple way to lose if the sum is only equal to 2 or 3.
pl[playerno].wincount -= 1;
printf("You lose with a balance of %d", pl[playerno].balance);
break; // The basic loss variable in the play game function.
}
else {
point = sum;
printf("Your point is %d. Roll %d without rolling a 7 to win. \n", point, point);
for(;;){
enter = 'i';
printf("Roll the dice.\n");
while (enter != '\n') // This is a while loop that basically makes sure that if the dice is equal to 0 then it can not be submitted.
enter = getchar();
r1 = (rand() % 6) + 1;
r2 = (rand() % 6) + 1;
sum = r1 + r2; // Adds together the first and second random calculation above.
printf("You rolled %d and %d to get %d. \n", r1, r2, sum);
if(sum == point){
pl[playerno].balance += 10;
pl[playerno].wincount += 10;
printf("You win. New Balance is %d. \n", pl[playerno].balance);
break;
}
else if(sum == 7){
pl[playerno].balance -= 1;
pl[playerno].wincount -= 1;
printf("You lose. New Bal is %d. \n", pl[playerno].balance);
break;
}
else
printf("Retry. \n");
}
break;
}
}
printf("Want to play again?");
scanf("%s", &again);
}
}
void topWin(){
int maxM, list, max1;
for(int p = 0; p < 5; p++) {
maxM = 999999; //makes sure that the top maximum variable is a really high number in this loop, basically ensures that this loop will run as long as it doesn't go over 999999
for(int a = 0; a < 10; a++){
list = 0;
for(int t = 0; t < 5; t++){
if(strcmp(top[t].pl_name, pl[a].pl_name) == 0) list = 1;
}
if (pl[a].balance > maxM && !list) {
maxM = pl[a].wincount;
max1 = a;
}
}
top[p] = pl[max1];
}
printf("\n");
for(int a = 0; a < 5; a++) {
printf("%s\t%d\n", top[a].pl_name, top[a].wincount);
}
}
void topFive(){
int maxM, list, max1;
for(int p = 0; p < 5; p++) {
maxM = 999999; //makes sure that the top maximum variable is a really high number in this loop, basically ensures that this loop will run as long as it doesn't go over 999999
for(int a = 0; a < 10; a++){
list = 0;
for(int t = 0; t < 5; t++){
if(strcmp(top[t].pl_name, pl[a].pl_name) == 0) list = 1;
}
if (pl[a].balance > maxM && !list) {
maxM = pl[a].wincount;
max1 = a;
}
}
top[p] = pl[max1];
}
printf("\n");
for(int a = 0; a < 5; a++) {
printf("%s\t%d\n", top[a].pl_name, top[a].wincount);
}
}
int main(){
int i = 0, ch;
FILE *rp;
FILE *wp;
rp = fopen("players.txt", "r");
while(!feof(rp)){
fscanf(rp, "%s\t%d\t%d", pl[i].pl_name, &pl[i].balance, &pl[i].wincount);
i++;
}
char name[10];
srand (time(NULL));
while (ch != 4) {
printf("\n0. Top up your balance ");
printf("\n1. Play Game!!! ");
printf("\n2. Top 5 Players by Balance ");
printf("\n3. Top 5 Winners! ");
printf("\n4. Exit ");
printf("\nWhat do you pick? ");
scanf("%d", &ch);
// From here on, I need to create seperate functions for each of these then tie them into the menu!!
switch(ch) {
case 0:
topBalance();
wp = fopen("players.txt", "w");
for(i = 0; i < 10; i++)
fprintf(wp, "%s\t%d\t%d\n", pl[i].pl_name, pl[i].balance, pl[i].wincount);
fclose(wp);
break;
case 1: // Need to finish this and correct it!
playGame();
wp = fopen("players.txt", "w");
for(i = 0; i < 10; i++)
fprintf(wp, "%s\t%d\t%d\n", pl[i].pl_name, pl[i].balance, pl[i].wincount);
fclose(wp);
break;
case 2: // Segmentation Error
topFive();
break;
case 3:
topWin();
break;
case 4:
break;
break;
}
}
}
One problem I can see with your code is here -
for(int t = 0; t < 5; t++){
if(strcmp(top[t].pl_name, pl[a].pl_name) == 0)
list = 1;
}
You are checking for all the top 5, when only p
of them are set yet. Meaning when you are checking for the second top, you are checking if the present name exists in any of the top 5. But only 1 has been set yet.
This leads to reading memory (in strcmp
) that has not been initialized. Most probably the uninitialized name is not a nul-terminated string and hence it leads to Undefined Behavior.
This is the reason for your Segmentation fault.
A simple fix here would be to change the loop to -
for(int t = 0; t < p; t++){
....
}
Also, there is something seriously wrong with your topBalance
function. You are using pl[i]
. But i
is never set to anything.