C
C#10mo ago
Mekasu0124

✅ getting length of a list???

In my database file, I have a function that loads all of the ghost items back into a list and returns it
public List<Ghost>? LoadGhosts()
{
var ghostInfo = File.ReadAllText(dbFile);
List<Ghost> ghosts = new List<Ghost>();

foreach (Ghost ghost in ghosts)
{
Ghost g = JsonSerializer.Deserialize<Ghost>(ghostInfo);
ghosts.Add(g);
}

return ghosts;
}
public List<Ghost>? LoadGhosts()
{
var ghostInfo = File.ReadAllText(dbFile);
List<Ghost> ghosts = new List<Ghost>();

foreach (Ghost ghost in ghosts)
{
Ghost g = JsonSerializer.Deserialize<Ghost>(ghostInfo);
ghosts.Add(g);
}

return ghosts;
}
and in my game file, I am obtaining that list and attempting to get the length of it
public static void PlayGame(string selectedDiff, string username, DateTime date)
{
Database db = new Database();
var ghosts = db.LoadGhosts();
int randGhostIndex = Helpers.RandomNumber(0, ghosts.Length);
}
public static void PlayGame(string selectedDiff, string username, DateTime date)
{
Database db = new Database();
var ghosts = db.LoadGhosts();
int randGhostIndex = Helpers.RandomNumber(0, ghosts.Length);
}
I'm passing the length of the list to my random number generator, however, it says that ghosts doesn't have the Length property, so how do I get the length of the ghosts list to pass to my random number generator?
137 Replies
Pobiega
Pobiega10mo ago
a few things one: json serializer can serialize/deserialize a list just fine you don't need to help it. Just JsonSerializer.Deserialize<List<Ghost>>(...) and your code above doesnt really make sense
Mekasu0124
Mekasu012410mo ago
that saved me some code. cool
Pobiega
Pobiega10mo ago
read all the text into a string create an empty list for each item in that empty list deserialize the same string into a single ghost, add it to the list we are currently looping over (not allowed) there are so many things not making sense there looping over an empty list, adding to it while looping over it, deserialzing the same thing several times
Mekasu0124
Mekasu012410mo ago
I changed the load function to deseralize into a list and return it don't have to worry about the loop anymore. I changed the code now I just need to figure out why .Length won't work on the returned list
Pobiega
Pobiega10mo ago
I get that, but you wrote that code and at least somewhat expected it to be correct-ish, no?
Mekasu0124
Mekasu012410mo ago
I thought it was, but I read back over it and saw the mistake.
Pobiega
Pobiega10mo ago
You can't come ask for help on every single method you write for the rest of your life, so its probably good to try to learn well, thats because .Length is for arrays lists have .Count arrays are fixed-size, constant length lists are variable size
Mekasu0124
Mekasu012410mo ago
I'm retaining everything that I can that is told to me, but I can just stop asking. Not being dramatic, but if I'm getting on peoples nerves then I can just stop. thanks for this info. I wasn't aware of this and the tutorial I went through a couple of months ago didn't specify that
Pobiega
Pobiega10mo ago
no no, just you have a way of writing like "oh yeah those four issues you just mentioned dont matter anymore as I changed the code" no, the four issues still matter as you made those mistakes and should try to learn from them. that said, in this particular case the "solution" was to change the code,
Mekasu0124
Mekasu012410mo ago
one: json serializer can serialize/deserialize a list just fine you don't need to help it. Just JsonSerializer.Deserialize<List<Ghost>>(...)
you're not wrong. As soon as you mentioned this, I looked back at the code and saw the problem. It's not that I was avoiding the issue. I saw the issue, understood what I did wrong and just tried to move on to the next problem. It's my fault that I forgot that json can deseralize to a list. That's my bad, but when you said that and I looked back at my code, I saw that I was iterating over an empty list instead of the information read from the file which still would have been wrong anyways.
Pobiega
Pobiega10mo ago
Even so, how would you iterate over a string? also, this is .net 7 right?
Mekasu0124
Mekasu012410mo ago
yes .net 7
Pobiega
Pobiega10mo ago
right, ok nvm then. .NET 8 adds some helper methods to easily pick a random item from a list but in .net 7 you need to write it yourself still, I encourage you to write it like an extension method imagine using it like var randomItem = list.GetRandomItem();
ero
ero10mo ago
If you ever have a programming question, it's a lot faster to just google the question and slap "c#" at the end
Pobiega
Pobiega10mo ago
this is literally the first thing I do for almost every question about coding I have. just briefly scan the top 5-10 hits and see if anything seems relevant
Mekasu0124
Mekasu012410mo ago
ok well after attempting to google, trying to print the type of the variables to the console, and so on, I cannot figure out the type casts for the objects on the left. They're defined in the ghost class on the right, however, when I print the typeof or GetType to console, it only tells me PhasmoTriviaConsole.Ghost.Evidence[] and I have tried List<string>..., List<Ghost>..., and other options and can't figure it out
Pobiega
Pobiega10mo ago
Uhm, Im not sure what you are asking here really I don't see any code for printing anything except the "could not determine..." stuff
Mekasu0124
Mekasu012410mo ago
because I didn't physically type it out.
Pobiega
Pobiega10mo ago
okay so what is the problem? if PhasmoTriviaConsole.Ghost.Evidence[] is being printed, you likely did Console.WriteLine(evidenceArray); you cant just send an array to writeline you probably want to use string.Join to make a suitable string first
Mekasu0124
Mekasu012410mo ago
yes I'm aware of that. that's not what I did.
okay so what is the problem?
having problems determining types.
if PhasmoTriviaConsole.Ghost.Evidence[] is being printed, you likely did Console.WriteLine(evidenceArray);
no I didn't I did Console.WriteLine(typeof(Evidence)) and var evidence = ghost.Evidence; Console.WriteLine(evidence.GetType()) and that's what it gave me.
you can't just send an array to writeline
yes I know this.
you probably want to use string.Join to make a suitable string first
I don't know about this because I cannot figure out the type of the evidence, however, seeing evidenceArray that tells me that it's an array so now I can go google how to type case an array. Thank you
Pobiega
Pobiega10mo ago
at this point I have no idea what you are talking about your screenshot doesnt show anything about a Evidence class
Mekasu0124
Mekasu012410mo ago
thought it did. that's my fault
internal record Evidence(string Name)
{
public static Evidence None = new Evidence("None");
public static Evidence Emf5 = new Evidence("EMF 5");
public static Evidence SpiritBox = new Evidence("Spriit Box");
public static Evidence Writing = new Evidence("Writing");
public static Evidence Dots = new Evidence("DOTs");
public static Evidence Ultraviolet = new Evidence("Ultraviolet");
public static Evidence Freezing = new Evidence("Freezing");
public static Evidence GhostOrbs = new Evidence("Ghost Orbs");

public override string ToString() => Name;
}
internal record Evidence(string Name)
{
public static Evidence None = new Evidence("None");
public static Evidence Emf5 = new Evidence("EMF 5");
public static Evidence SpiritBox = new Evidence("Spriit Box");
public static Evidence Writing = new Evidence("Writing");
public static Evidence Dots = new Evidence("DOTs");
public static Evidence Ultraviolet = new Evidence("Ultraviolet");
public static Evidence Freezing = new Evidence("Freezing");
public static Evidence GhostOrbs = new Evidence("Ghost Orbs");

public override string ToString() => Name;
}
it's an internal record. I know that much
Pobiega
Pobiega10mo ago
Oh okay so its just a "Name" these are not different types, btw they are all just Evidence
Mekasu0124
Mekasu012410mo ago
but when deserializing the json, and trying to type cast it, I'm drawing blanks
Pobiega
Pobiega10mo ago
yup, that will work but there are no types to cast here all your different evidences are all Evidence instances tehy are the same type
Mekasu0124
Mekasu012410mo ago
understandable on that. So this worked Evidence[] evidence = ghost.Evidence; however I still can't print the items to the console.
Pobiega
Pobiega10mo ago
you want to print the names, right?
Mekasu0124
Mekasu012410mo ago
so I'm wanting to learn how to get this result
Console.WriteLine(evidence);
// EMF 5, Writing, Spirit Box
Console.WriteLine(evidence);
// EMF 5, Writing, Spirit Box
Pobiega
Pobiega10mo ago
ye
Mekasu0124
Mekasu012410mo ago
I'm wanting to learn how to get that information like that, but I don't know how to google that
Pobiega
Pobiega10mo ago
you'll need string.join
Pobiega
Pobiega10mo ago
Pobiega
Pobiega10mo ago
there we go 😛 using a loop isn't waht you want thou, since you want it in one line and comma separated much easier to do with string.join, its literally what its for
Mekasu0124
Mekasu012410mo ago
googlin what you showed in your picture, what about Array.ForEach(yourArray, Console.WriteLine); however, I don't want it to print them like that each time but rather put them in a csv string
Pobiega
Pobiega10mo ago
try it, but its not very idiomatic C# and it wouldn't give you the desired result
Mekasu0124
Mekasu012410mo ago
like string evidence = "EMF 5, Writing, Spirit Box"; that would be the wanted result
Pobiega
Pobiega10mo ago
think about what Console.WriteLine does I can say string.Join again if it helps? only did it... 4 times so far? :p
Mekasu0124
Mekasu012410mo ago
just because I haven't physically responded to it doesn't mean I didn't see it or try it. Right now I'm trying to google and work through why string evidence = string.Join(", ", ghost.Evidence); isn't working I figured it out. I had to put the .ToList() on the ghost.Evidence
Pobiega
Pobiega10mo ago
hm, probably better to cast it to IEnumerabe Console.WriteLine(string.Join(", ", (IEnumerable<Evidence>)list));
Mekasu0124
Mekasu012410mo ago
what's the difference?
Pobiega
Pobiega10mo ago
.ToList actually allocates a new list and copies the data from the array in casting just says "eh treat this object as if it was this other type instead"
Mekasu0124
Mekasu012410mo ago
ok that makes more sense
string sanity = string.Join("", (IEnumerable<HuntSanity>)ghost.Sanity);
string speed = string.Join("", (IEnumerable<Speed>)ghost.Speed);
string sanity = string.Join("", (IEnumerable<HuntSanity>)ghost.Sanity);
string speed = string.Join("", (IEnumerable<Speed>)ghost.Speed);
so still trying to get them to a string, these have the following
#region HuntSanity
internal record HuntSanity(int Value)
{
public static HuntSanity ThirtyFive = new HuntSanity(35);
public static HuntSanity Fourty = new HuntSanity(40);
public static HuntSanity Fifty = new HuntSanity(50);
public static HuntSanity Sixty = new HuntSanity(60);
public static HuntSanity SixtyFive = new HuntSanity(65);
public static HuntSanity Seventy = new HuntSanity(70);
public static HuntSanity SeventyFive = new HuntSanity(75);
public static HuntSanity Eighty = new HuntSanity(80);

public override string ToString() => $"{Value}%";
}
#endregion

#region Speeds
internal record Speed(double Value)
{
public static Speed BaseSpeed = new Speed(1.7);

public override string ToString() => $"{Value} m/s";
}
internal record TwoSpeed(double Value, double Value2) : Speed(Value)
{
public override string ToString() => $"{Value} m/s | {Value2} m/s";
}
internal record RangeSpeed(double Value, double Value2) : Speed(Value)
{
public override string ToString() => $"{Value} m/s - {Value2} m/s";
}
#endregion
#region HuntSanity
internal record HuntSanity(int Value)
{
public static HuntSanity ThirtyFive = new HuntSanity(35);
public static HuntSanity Fourty = new HuntSanity(40);
public static HuntSanity Fifty = new HuntSanity(50);
public static HuntSanity Sixty = new HuntSanity(60);
public static HuntSanity SixtyFive = new HuntSanity(65);
public static HuntSanity Seventy = new HuntSanity(70);
public static HuntSanity SeventyFive = new HuntSanity(75);
public static HuntSanity Eighty = new HuntSanity(80);

public override string ToString() => $"{Value}%";
}
#endregion

#region Speeds
internal record Speed(double Value)
{
public static Speed BaseSpeed = new Speed(1.7);

public override string ToString() => $"{Value} m/s";
}
internal record TwoSpeed(double Value, double Value2) : Speed(Value)
{
public override string ToString() => $"{Value} m/s | {Value2} m/s";
}
internal record RangeSpeed(double Value, double Value2) : Speed(Value)
{
public override string ToString() => $"{Value} m/s - {Value2} m/s";
}
#endregion
How would I do these?
Pobiega
Pobiega10mo ago
you only need the cast if the thing is an array
Mekasu0124
Mekasu012410mo ago
understandable. It's not an int and it's not a string so what am I missing?
Pobiega
Pobiega10mo ago
I don't know you haven't shown the Ghost class for one :p
Mekasu0124
Mekasu012410mo ago
internal class Ghost
{
public required string Name { get; init; }
public required Evidence[] Evidence { get; set; }
public required HuntSanity Sanity { get; set; }
public required Speed Speed { get; set; }
public required Tell[] Tells { get; set; }
public required Behavior[] Behaviors { get; set; }
public required HuntSanityBehavior[] HuntSanityBehaviors { get; set; }
public required HuntSpeedBehavior[] HuntSpeedBehaviors { get; set; }
public required Evidence[] GuaranteedEvidence { get; set; }
}
internal class Ghost
{
public required string Name { get; init; }
public required Evidence[] Evidence { get; set; }
public required HuntSanity Sanity { get; set; }
public required Speed Speed { get; set; }
public required Tell[] Tells { get; set; }
public required Behavior[] Behaviors { get; set; }
public required HuntSanityBehavior[] HuntSanityBehaviors { get; set; }
public required HuntSpeedBehavior[] HuntSpeedBehaviors { get; set; }
public required Evidence[] GuaranteedEvidence { get; set; }
}
because it doesn't show the type. Just that it's a public required Speed Speed unless I"m missing it
Pobiega
Pobiega10mo ago
? I mean, that is the type. Speed is the type of the Speed property and thats jsut a wrapper around a double, as far as I can tell so dont use string.Join there, since there is only a single thing in speed its not an array
Mekasu0124
Mekasu012410mo ago
ok I can understand that, but it's not an int, string, or double
Pobiega
Pobiega10mo ago
sure its a Speed
Mekasu0124
Mekasu012410mo ago
and it won't let me double.TryParse
Pobiega
Pobiega10mo ago
what are you trying to do? just print the speed value? Console.WriteLine(ghost.Speed); you've overriden the ToString for Speed so just print it
Mekasu0124
Mekasu012410mo ago
no. I would like to have everything to a string. see how HuntSanity has a public override to put the values in the string? Each one of these has that public override and I'm trying to get the value from the json and return it in that string
Pobiega
Pobiega10mo ago
string speed = ghost.Speed.ToString(); in that case.
Mekasu0124
Mekasu012410mo ago
ohhhhhh. that makes sense casting it to a string causes that override to take place
Pobiega
Pobiega10mo ago
no casts taking place here
Mekasu0124
Mekasu012410mo ago
because it's a ToString override
Pobiega
Pobiega10mo ago
we are just invoking the Tostring method on the Speed object
Mekasu0124
Mekasu012410mo ago
right
Pobiega
Pobiega10mo ago
(string)ghost.Speed would be a cast, and it would crash :p
Mekasu0124
Mekasu012410mo ago
I thought string <- cast speed = ghost.Speed; was a cast
Pobiega
Pobiega10mo ago
nope string speed is just declaring a new variable of type string
Mekasu0124
Mekasu012410mo ago
gotcha now I see the difference. cool
Pobiega
Pobiega10mo ago
you could declare what we call an "implicit operator" to make string x = ghost.Speed; work, but why bother when ToString exists
Mekasu0124
Mekasu012410mo ago
is it better to use ToString?
Pobiega
Pobiega10mo ago
yes explicit is often better than implicit in coding implicit can lead to mistakes, and feels "magic"
Mekasu0124
Mekasu012410mo ago
that makes sense so here's something else I would like to learn. Input validation. I never worked with regex in Python as I never needed to so I have no idea to use it, so how would I validate that a user's input was only the letters of the english alphabet? could I do something like
string alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

foreach (string i in userInput)
{
if (!alphabet.contains(i))
{
//try user input again
}
string alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

foreach (string i in userInput)
{
if (!alphabet.contains(i))
{
//try user input again
}
or is there an easier way to check a whole word at one time instead of each individual letter?
Pobiega
Pobiega10mo ago
not really strings are just char arrays after all
Mekasu0124
Mekasu012410mo ago
so iterate through the string input and check each letter is there maybe a regex I can check it against instead? or would regex even be better in this instance?
Pobiega
Pobiega10mo ago
you could use a regex, it would not be faster. but if you wanted to use it, thats fine like, if your rules were more complicated than "every char has to be one of these letters", you might need regex
Mekasu0124
Mekasu012410mo ago
oh ok. yea no my rule is every letter has to be between Aa and Zz so I'll keep the iteration then
Pobiega
Pobiega10mo ago
Wow you descriminate against scandinavians? 😦 what about ÅÄÖ and other amazing letters 😄
Mekasu0124
Mekasu012410mo ago
lol nothing against them 😛 just using one alphabet type as the ghost names only use the 26-letter english alphabet
Pobiega
Pobiega10mo ago
just joking
Mekasu0124
Mekasu012410mo ago
ok another learning question. When is it better to do
while (someCondition != true)
{
}
while (someCondition != true)
{
}
and
do
{
} while (someCondition != true);
do
{
} while (someCondition != true);
? or what's the difference. We don't have these in python
Pobiega
Pobiega10mo ago
while (...){} runs 0 or more times do {} while() runs 1 or more times thats the major difference
Mekasu0124
Mekasu012410mo ago
the difference is one turn cycle?
Pobiega
Pobiega10mo ago
not a term in familiar with, but sure do runs BEFORE checking the condition. while runs AFTER checking the condition
Mekasu0124
Mekasu012410mo ago
int tries = 5;
int score = 0;
int totalQuestions = ghosts.Count;

string userInput = Console.ReadLine();
userInput = Helpers.ValidateInput(userInput);

do
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine();
} while (tries > 0 && userInput != name);
int tries = 5;
int score = 0;
int totalQuestions = ghosts.Count;

string userInput = Console.ReadLine();
userInput = Helpers.ValidateInput(userInput);

do
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine();
} while (tries > 0 && userInput != name);
ok rephrasing it. Here I'm giving the user 5 tries to get their answer correct. Is a while-loop better or a do-while-loop better and why? so a regular while-loop is better here
Pobiega
Pobiega10mo ago
yeah in general, prefer while over do-while where it doesnt matter
Mekasu0124
Mekasu012410mo ago
gotcha.
Pobiega
Pobiega10mo ago
but when you need the properties of do-while, go ahead and use its
Mekasu0124
Mekasu012410mo ago
cool cool so using a regular while-loop to give the user 5 tries, how would I go about continuing with the rest of my code? What I mean is, if they run out of tries, the score does not increase but if they get it right with at least 1 try remaining, then the score increments by 1?
Pobiega
Pobiega10mo ago
well, you have two exit conditions now tries and guessed right you need to know which one triggered the exit so after the loop, you could test if (tries > 0) to know if they guessed it right or not
Mekasu0124
Mekasu012410mo ago
ok so giving this a shot
public static void PlayGame(string selectedDiff, string username, DateTime date)
{
Database db = new Database();
var ghosts = db.LoadGhosts();

int randGhostIndex = Helpers.RandomNumber(0, ghosts.Count);

var ghost = ghosts[randGhostIndex];

string name = ghost.Name;
string evidence = string.Join(", ", (IEnumerable<Evidence>)ghost.Evidence);
string sanity = ghost.Sanity.ToString();
string speed = ghost.Speed.ToString();
string tells = string.Join("\n", (IEnumerable<Tell>)ghost.Tells);
string behaviors = string.Join("\n", (IEnumerable<Behavior>)ghost.Behaviors);
string huntSanityBehaviors = string.Join("\n", (IEnumerable<HuntSanityBehavior>)ghost.HuntSanityBehaviors);
string huntSpeedBehaviors = string.Join("\n", (IEnumerable<HuntSpeedBehavior>)ghost.HuntSpeedBehaviors);
string guarunteedEvidence = string.Join("\n", (IEnumerable<Evidence>)ghost.GuaranteedEvidence);

List<string> text = new()
{
$"Evidence: {evidence}",
$"Sanity: {sanity}",
$"Speed: {speed}",
$"Tells: {tells}",
$"Behaviors: {behaviors}",
$"Hunt Sanity Behaviors: {huntSanityBehaviors}",
$"Hunt Speed Behaviors: {huntSpeedBehaviors}",
$"Guarunteed Evidence (Nightmare/Insanity Mode): {guarunteedEvidence}"
};

foreach (string line in text)
{
if (line != "None")
{
Console.WriteLine(line);
}
}

int tries = 5;
int score = 0;
int totalQuestions = ghosts.Count;

string userInput = Console.ReadLine();
userInput = Helpers.ValidateInput(userInput);

while (tries > 0 && userInput != name)
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine();

if (tries == 0 || userInput == name)
{
break;
}
};

if (tries > 0 && userInput == name)
{
score++;
}

PlayGame(selectedDiff, username, date);
}
public static void PlayGame(string selectedDiff, string username, DateTime date)
{
Database db = new Database();
var ghosts = db.LoadGhosts();

int randGhostIndex = Helpers.RandomNumber(0, ghosts.Count);

var ghost = ghosts[randGhostIndex];

string name = ghost.Name;
string evidence = string.Join(", ", (IEnumerable<Evidence>)ghost.Evidence);
string sanity = ghost.Sanity.ToString();
string speed = ghost.Speed.ToString();
string tells = string.Join("\n", (IEnumerable<Tell>)ghost.Tells);
string behaviors = string.Join("\n", (IEnumerable<Behavior>)ghost.Behaviors);
string huntSanityBehaviors = string.Join("\n", (IEnumerable<HuntSanityBehavior>)ghost.HuntSanityBehaviors);
string huntSpeedBehaviors = string.Join("\n", (IEnumerable<HuntSpeedBehavior>)ghost.HuntSpeedBehaviors);
string guarunteedEvidence = string.Join("\n", (IEnumerable<Evidence>)ghost.GuaranteedEvidence);

List<string> text = new()
{
$"Evidence: {evidence}",
$"Sanity: {sanity}",
$"Speed: {speed}",
$"Tells: {tells}",
$"Behaviors: {behaviors}",
$"Hunt Sanity Behaviors: {huntSanityBehaviors}",
$"Hunt Speed Behaviors: {huntSpeedBehaviors}",
$"Guarunteed Evidence (Nightmare/Insanity Mode): {guarunteedEvidence}"
};

foreach (string line in text)
{
if (line != "None")
{
Console.WriteLine(line);
}
}

int tries = 5;
int score = 0;
int totalQuestions = ghosts.Count;

string userInput = Console.ReadLine();
userInput = Helpers.ValidateInput(userInput);

while (tries > 0 && userInput != name)
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine();

if (tries == 0 || userInput == name)
{
break;
}
};

if (tries > 0 && userInput == name)
{
score++;
}

PlayGame(selectedDiff, username, date);
}
this is the entire game function. What do you think? oh I messed it up
Pobiega
Pobiega10mo ago
if (line != "None") this is never false You never ask the user to guess the ghost. I guess its implied, but still, I'd want a prompt. Recursion to loop the game instead of a proper loop, bad. score++; maybe also print "you guessed correct, good job"? userInput != name means you are looking for case sensetive match, so Poltergeist and poltergeist wont match
Florian Voß
Florian Voß10mo ago
do Equals() with StringComparison.OrdinalIgnoreCase when you want case insensitive comparisons
Mekasu0124
Mekasu012410mo ago
`if (line != "None") this is never false
I see my mistake there
You never ask the user to guess the ghost. I guess its implied, but still, I'd want a prompt.
string userInput = Console.ReadLine();
userInput = Helpers.ValidateInput(userInput);
string userInput = Console.ReadLine();
userInput = Helpers.ValidateInput(userInput);
I did get user input, but forgot my print statement to prompt for it. I see that mistake too.
Recursion to loop the game instead of a proper loop, bad
I just noticed that I messed it up by not wrapping the game in a loop that iterates for as many ghosts are in the file. I'm working on fixing that now.
score++;
what's wrong here?
maybe also print "you guessed correct, good job"?
I haven't put this in yet. I wanted to get the logic down first, but you're not wrong. I'll add that in now too
userInput != name means you are looking for case sensetive match, so Poltergeist and poltergeist won't match
I didn't notice this before, so another learning point. How can I check for both variations at the same time? I'll put the function in my helpers file as I can reuse it in the other game modes as well so this is that learning point in my last point above. Ok I'll look at the docs that on that. thanks
Pobiega
Pobiega10mo ago
score++; was to show where the comment below belonged to, no issues with that line itself
Florian Voß
Florian Voß10mo ago
could also just call ToUpper() or ToLower() on both strings to make case insensitive but most people consider this kinda hacky and prefer the enum that exists for it 🙂 but good to keep in mind in case you forget about the proper way
Pobiega
Pobiega10mo ago
it is hacky and wont work for some languages, like turkish so prefer StringComparison :p
Florian Voß
Florian Voß10mo ago
didn't know bout cases where its not working but good to know ^^ I guess thats why there is different IgnoreCase enum values for different cultures
Pobiega
Pobiega10mo ago
ah yes, the turkish "dotless i"
Mekasu0124
Mekasu012410mo ago
ok so I've hit a snag
Pobiega
Pobiega10mo ago
yepyep
Mekasu0124
Mekasu012410mo ago
public static void PlayGame(string selectedDiff, string username, DateTime date)
{
Database db = new Database();
var ghosts = db.LoadGhosts();

for (int i = 0; i < ghosts.Count; i++)
{
int randGhostIndex = Helpers.RandomNumber(0, ghosts.Count);

var ghost = ghosts[randGhostIndex];

string name = ghost.Name;
string evidence = string.Join(", ", (IEnumerable<Evidence>)ghost.Evidence);
string sanity = ghost.Sanity.ToString();
string speed = ghost.Speed.ToString();
string tells = string.Join("\n", (IEnumerable<Tell>)ghost.Tells);
string behaviors = string.Join("\n", (IEnumerable<Behavior>)ghost.Behaviors);
string huntSanityBehaviors = string.Join("\n", (IEnumerable<HuntSanityBehavior>)ghost.HuntSanityBehaviors);
string huntSpeedBehaviors = string.Join("\n", (IEnumerable<HuntSpeedBehavior>)ghost.HuntSpeedBehaviors);
string guarunteedEvidence = string.Join("\n", (IEnumerable<Evidence>)ghost.GuaranteedEvidence);

List<string> text = new()
{
$"Evidence: {evidence}",
$"Sanity: {sanity}",
$"Speed: {speed}",
$"Tells: {tells}",
$"Behaviors: {behaviors}",
$"Hunt Sanity Behaviors: {huntSanityBehaviors}",
$"Hunt Speed Behaviors: {huntSpeedBehaviors}",
$"Guarunteed Evidence (Nightmare/Insanity Mode): {guarunteedEvidence}"
};

foreach (string line in text)
{
// this checks that if the line does not equal "None" then it prints that line, otherwise, it ignores that line
if (line != "None")
{
Console.WriteLine(line);
}
}

int tries = 5;
int score = 0;
int totalQuestions = ghosts.Count;

Console.Write("\nWhat Is The Ghost Name: ");
string userInput = Console.ReadLine();
userInput = Helpers.ValidateInput(userInput);

while (tries > 0 && userInput != name)
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine();

if (tries == 0 || userInput == name)
{
break;
}
};

if (tries > 0 && userInput == name)
{
Console.WriteLine("You Got It Right!");
Console.WriteLine($"Ghost Type: {name}");
Console.WriteLine($"Score: {score}/{totalQuestions}");
score++;
}
}
}
public static void PlayGame(string selectedDiff, string username, DateTime date)
{
Database db = new Database();
var ghosts = db.LoadGhosts();

for (int i = 0; i < ghosts.Count; i++)
{
int randGhostIndex = Helpers.RandomNumber(0, ghosts.Count);

var ghost = ghosts[randGhostIndex];

string name = ghost.Name;
string evidence = string.Join(", ", (IEnumerable<Evidence>)ghost.Evidence);
string sanity = ghost.Sanity.ToString();
string speed = ghost.Speed.ToString();
string tells = string.Join("\n", (IEnumerable<Tell>)ghost.Tells);
string behaviors = string.Join("\n", (IEnumerable<Behavior>)ghost.Behaviors);
string huntSanityBehaviors = string.Join("\n", (IEnumerable<HuntSanityBehavior>)ghost.HuntSanityBehaviors);
string huntSpeedBehaviors = string.Join("\n", (IEnumerable<HuntSpeedBehavior>)ghost.HuntSpeedBehaviors);
string guarunteedEvidence = string.Join("\n", (IEnumerable<Evidence>)ghost.GuaranteedEvidence);

List<string> text = new()
{
$"Evidence: {evidence}",
$"Sanity: {sanity}",
$"Speed: {speed}",
$"Tells: {tells}",
$"Behaviors: {behaviors}",
$"Hunt Sanity Behaviors: {huntSanityBehaviors}",
$"Hunt Speed Behaviors: {huntSpeedBehaviors}",
$"Guarunteed Evidence (Nightmare/Insanity Mode): {guarunteedEvidence}"
};

foreach (string line in text)
{
// this checks that if the line does not equal "None" then it prints that line, otherwise, it ignores that line
if (line != "None")
{
Console.WriteLine(line);
}
}

int tries = 5;
int score = 0;
int totalQuestions = ghosts.Count;

Console.Write("\nWhat Is The Ghost Name: ");
string userInput = Console.ReadLine();
userInput = Helpers.ValidateInput(userInput);

while (tries > 0 && userInput != name)
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine();

if (tries == 0 || userInput == name)
{
break;
}
};

if (tries > 0 && userInput == name)
{
Console.WriteLine("You Got It Right!");
Console.WriteLine($"Ghost Type: {name}");
Console.WriteLine($"Score: {score}/{totalQuestions}");
score++;
}
}
}
I wrapped it in a while loop so that the questions repeat for the number of times that there are ghosts, however, I do not know how to get it to not pick the same ghost twice. How can I learn how to do that?
Florian Voß
Florian Voß10mo ago
remember the randomGhostIndexes you have generated and keep generating when you already had that ghost or remove ghosts from the list once you are done with them
Mekasu0124
Mekasu012410mo ago
I didn't realize that I was regenerating it on each iteration, however, it's how I pull a new random index on each iteration too to get a new ghost type. So having the list set to a variable var ghosts = db.LoadGhosts(); and using something like the Pop() method on it, won't erase it from the json file? so like I could something at the bottom like
if (tries > 0 && userInput == name)
{
score++;
ghosts.Remove(ghost);
...
}
if (tries > 0 && userInput == name)
{
score++;
ghosts.Remove(ghost);
...
}
? and doing the case match checking, would I do something like this https://stackoverflow.com/questions/6371150/comparing-two-strings-ignoring-case-in-c-sharp#:~:text=string.Equals(val%2C%20%22astringvalue%22%2C%20StringComparison.OrdinalIgnoreCase) ? I just decided to put .ToLower() on the name and userInput variables to make it easier
public static void PlayGame(string selectedDiff, string username, DateTime date)
{
Database db = new Database();
var ghosts = db.LoadGhosts();
int ghostCount = ghosts.Count;
int tries = 5;
int score = 0;

for (int i = 0; i < ghostCount; i++)
{
int randGhostIndex = Helpers.RandomNumber(0, ghosts.Count);

var ghost = ghosts[randGhostIndex];

string name = ghost.Name.ToLower();
string evidence = string.Join(", ", (IEnumerable<Evidence>)ghost.Evidence);
string sanity = ghost.Sanity.ToString();
string speed = ghost.Speed.ToString();
string tells = string.Join("\n", (IEnumerable<Tell>)ghost.Tells);
string behaviors = string.Join("\n", (IEnumerable<Behavior>)ghost.Behaviors);
string huntSanityBehaviors = string.Join("\n", (IEnumerable<HuntSanityBehavior>)ghost.HuntSanityBehaviors);
string huntSpeedBehaviors = string.Join("\n", (IEnumerable<HuntSpeedBehavior>)ghost.HuntSpeedBehaviors);
string guarunteedEvidence = string.Join("\n", (IEnumerable<Evidence>)ghost.GuaranteedEvidence);

List<string> info = new()
{
evidence,
sanity,
speed,
tells,
behaviors,
huntSanityBehaviors,
huntSpeedBehaviors,
guarunteedEvidence
};

Helpers.PrintGhostInfo(info);

Console.Write("What Is The Ghost Name: ");
string userInput = Console.ReadLine().ToLower();
userInput = Helpers.ValidateInput(userInput);

while (tries > 0 && userInput != name)
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine();

if (tries == 0 || userInput == name)
{
break;
}
};

if (tries > 0 && userInput == name)
{
score++;
ghosts.Remove(ghost);
Console.WriteLine("You Got It Right!");
Console.WriteLine($"Ghost Name: {name}");
Console.WriteLine($"Score: {score}/{ghostCount}");
Console.WriteLine("Showing Next Question");

Thread.Sleep(6000);
Console.Clear();
}
}
}
public static void PlayGame(string selectedDiff, string username, DateTime date)
{
Database db = new Database();
var ghosts = db.LoadGhosts();
int ghostCount = ghosts.Count;
int tries = 5;
int score = 0;

for (int i = 0; i < ghostCount; i++)
{
int randGhostIndex = Helpers.RandomNumber(0, ghosts.Count);

var ghost = ghosts[randGhostIndex];

string name = ghost.Name.ToLower();
string evidence = string.Join(", ", (IEnumerable<Evidence>)ghost.Evidence);
string sanity = ghost.Sanity.ToString();
string speed = ghost.Speed.ToString();
string tells = string.Join("\n", (IEnumerable<Tell>)ghost.Tells);
string behaviors = string.Join("\n", (IEnumerable<Behavior>)ghost.Behaviors);
string huntSanityBehaviors = string.Join("\n", (IEnumerable<HuntSanityBehavior>)ghost.HuntSanityBehaviors);
string huntSpeedBehaviors = string.Join("\n", (IEnumerable<HuntSpeedBehavior>)ghost.HuntSpeedBehaviors);
string guarunteedEvidence = string.Join("\n", (IEnumerable<Evidence>)ghost.GuaranteedEvidence);

List<string> info = new()
{
evidence,
sanity,
speed,
tells,
behaviors,
huntSanityBehaviors,
huntSpeedBehaviors,
guarunteedEvidence
};

Helpers.PrintGhostInfo(info);

Console.Write("What Is The Ghost Name: ");
string userInput = Console.ReadLine().ToLower();
userInput = Helpers.ValidateInput(userInput);

while (tries > 0 && userInput != name)
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine();

if (tries == 0 || userInput == name)
{
break;
}
};

if (tries > 0 && userInput == name)
{
score++;
ghosts.Remove(ghost);
Console.WriteLine("You Got It Right!");
Console.WriteLine($"Ghost Name: {name}");
Console.WriteLine($"Score: {score}/{ghostCount}");
Console.WriteLine("Showing Next Question");

Thread.Sleep(6000);
Console.Clear();
}
}
}
ok I've hit a problem while playing the game and testing it. There are two ghost types that have a space in their names. The Twins and The Mimic. How can I get the check to do correctly because right now, regardless to what I input eg: The Twins, thetwins, the twins, twins it doesn't accept the answer. So how can I get my check to accept both The Twins/The Mimic and Twins/Mimic as an input and check for the capitolization match at the same time?
Pobiega
Pobiega10mo ago
The easiest way would be to add a new field to your ghost class where you can have NormalizedName or something which would always be lowercase and without the so twins or poltergeist etc granted, that wont allow you to guess the ... so you'd perhaps need a special case for that too, by stripping the from any guess ¯\_(ツ)_/¯ many options note that you only use toLower on the initial guess you dont do that on userInput = Console.ReadLine();
Mekasu0124
Mekasu012410mo ago
true ok so where and how would I check if the exists in the user's input and remove it if it does? I added in the normalized name to the ghost class and added in their names to just one word and all lowercase so that negated using .ToLower() on string username = ghost.NormalizedName;
Pobiega
Pobiega10mo ago
Sounds like its time to make some utility methods comparing the guessed name to the real name would be a good one, as you do it in two places and its about to get complicated
Mekasu0124
Mekasu012410mo ago
Console.Write("What Is The Ghost Name: ");
string userInput = Console.ReadLine().ToLower();
userInput = Helpers.ValidateInput(userInput);

if (userInput.Contains("the") || userInput.Contains("The"))
{
userInput = userInput.Split(" ")[1];
}

while (tries > 0 && userInput != name)
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine().ToLower();

if (userInput.Contains("the") || userInput.Contains("The"))
{
userInput = userInput.Split(" ")[1];
}

if (tries == 0 || userInput == name)
{
break;
}
};
Console.Write("What Is The Ghost Name: ");
string userInput = Console.ReadLine().ToLower();
userInput = Helpers.ValidateInput(userInput);

if (userInput.Contains("the") || userInput.Contains("The"))
{
userInput = userInput.Split(" ")[1];
}

while (tries > 0 && userInput != name)
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine().ToLower();

if (userInput.Contains("the") || userInput.Contains("The"))
{
userInput = userInput.Split(" ")[1];
}

if (tries == 0 || userInput == name)
{
break;
}
};
what about this?
Pobiega
Pobiega10mo ago
thats a start but like I said, stick that in a method
Mekasu0124
Mekasu012410mo ago
I replaced calling the ghost.Name with ghost.NormalizedName so that the game only uses the normalized name
Pobiega
Pobiega10mo ago
thats good, but what if the user guesses the twins? that wouldnt match the normalized name
Mekasu0124
Mekasu012410mo ago
Console.Write("What Is The Ghost Name: ");
string userInput = Console.ReadLine().ToLower();
userInput = Helpers.ValidateInput(userInput);
userInput = Helpers.CheckForThe(userInput);

while (tries > 0 && userInput != name)
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine().ToLower();
userInput = Helpers.ValidateInput(userInput);
userInput = Helpers.CheckForThe(userInput);

if (tries == 0 || userInput == name)
{
break;
}
};
Console.Write("What Is The Ghost Name: ");
string userInput = Console.ReadLine().ToLower();
userInput = Helpers.ValidateInput(userInput);
userInput = Helpers.CheckForThe(userInput);

while (tries > 0 && userInput != name)
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine().ToLower();
userInput = Helpers.ValidateInput(userInput);
userInput = Helpers.CheckForThe(userInput);

if (tries == 0 || userInput == name)
{
break;
}
};
ok what about this?
internal static string? CheckForThe(string input)
{
if (input.Contains("the") || input.Contains("The"))
{
input = input.Split(" ")[1];
}

return input;
}
internal static string? CheckForThe(string input)
{
if (input.Contains("the") || input.Contains("The"))
{
input = input.Split(" ")[1];
}

return input;
}
Pobiega
Pobiega10mo ago
notice how much repetition you have
Mekasu0124
Mekasu012410mo ago
right which is why I'm removing The/the from the users input
Pobiega
Pobiega10mo ago
string userInput = Console.ReadLine().ToLower();
userInput = Helpers.ValidateInput(userInput);
userInput = Helpers.CheckForThe(userInput);
string userInput = Console.ReadLine().ToLower();
userInput = Helpers.ValidateInput(userInput);
userInput = Helpers.CheckForThe(userInput);
and
userInput = Console.ReadLine().ToLower();
userInput = Helpers.ValidateInput(userInput);
userInput = Helpers.CheckForThe(userInput);
userInput = Console.ReadLine().ToLower();
userInput = Helpers.ValidateInput(userInput);
userInput = Helpers.CheckForThe(userInput);
Mekasu0124
Mekasu012410mo ago
so put it all in the same method?
Pobiega
Pobiega10mo ago
maybe combine those in a method of its own?
Mekasu0124
Mekasu012410mo ago
but I can't put them in one
Pobiega
Pobiega10mo ago
you can public static string GetValidatedNormalizedInput() 😄 you can just run those three methods in that method and then return the result tada, less repetition
Mekasu0124
Mekasu012410mo ago
internal static string? CheckForThe(string input)
{
if (input.Contains("the") || input.Contains("The"))
{
input = input.Split(" ")[1];
}

return input;
}

internal static string? ValidateInput(string input)
{
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

foreach (char letter in input)
{
while (!alphabet.Contains(letter))
{
Console.WriteLine("\nInvalid Input. Enter Your Guess Using The 26-Letter English Alphabet\n");
input = Console.ReadLine();
}
}

return input;
}
internal static string? CheckForThe(string input)
{
if (input.Contains("the") || input.Contains("The"))
{
input = input.Split(" ")[1];
}

return input;
}

internal static string? ValidateInput(string input)
{
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

foreach (char letter in input)
{
while (!alphabet.Contains(letter))
{
Console.WriteLine("\nInvalid Input. Enter Your Guess Using The 26-Letter English Alphabet\n");
input = Console.ReadLine();
}
}

return input;
}
one checks for the word The/the and the other checks that each letter is a character of the 26 letter alphabet. ok you caught my interest here thinkWarp I don't need to remove The/the from every user input. Only when they're guessing the ghost's name.
Pobiega
Pobiega10mo ago
so only use that method when taking in ghost guesses thats still in two places of your code currently
Mekasu0124
Mekasu012410mo ago
ok I"m a bit lost on what you mean. sorry
Pobiega
Pobiega10mo ago
you can call your own methods from other methods so just do that?
Mekasu0124
Mekasu012410mo ago
so call ValidateInput inside of CheckForThe?
Pobiega
Pobiega10mo ago
no, make a new method that combines all of these is what I was going for also, that the check is kinda... not great :p it uses Contains so it would trigger on "hello hello the" => "hello the" StartsWith sems more reasonable here
Mekasu0124
Mekasu012410mo ago
not a bad idea. ok so what about
string userInput = Console.ReadLine().ToLower();
userInput = Helpers.CheckForThe(userInput);

while (tries > 0 && userInput != name)
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine().ToLower();
userInput = Helpers.CheckForThe(userInput);

if (tries == 0 || userInput == name)
{
break;
}
};
internal static string? ValidateInput(string input)
{
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

foreach (char letter in input)
{
while (!alphabet.Contains(letter))
{
Console.WriteLine("\nInvalid Input. Enter Your Guess Using The 26-Letter English Alphabet\n");
input = Console.ReadLine();
}
}

return input;
}

internal static string? CheckForThe(string input)
{
input = ValidateInput(input);

if (input.StartsWith("the") || input.StartsWith("The"))
{
input = input.Split(" ")[1];
}

return input;
}
string userInput = Console.ReadLine().ToLower();
userInput = Helpers.CheckForThe(userInput);

while (tries > 0 && userInput != name)
{
tries--;
Console.WriteLine($"Incorrect Ghost Type. Try Again! Tries Remaining: {tries}");
userInput = Console.ReadLine().ToLower();
userInput = Helpers.CheckForThe(userInput);

if (tries == 0 || userInput == name)
{
break;
}
};
internal static string? ValidateInput(string input)
{
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

foreach (char letter in input)
{
while (!alphabet.Contains(letter))
{
Console.WriteLine("\nInvalid Input. Enter Your Guess Using The 26-Letter English Alphabet\n");
input = Console.ReadLine();
}
}

return input;
}

internal static string? CheckForThe(string input)
{
input = ValidateInput(input);

if (input.StartsWith("the") || input.StartsWith("The"))
{
input = input.Split(" ")[1];
}

return input;
}
I know you said to make a function incorporating both, but my brain fried on trying to do that
Pobiega
Pobiega10mo ago
.. really?
public static string GetValidatedNormalizedInput()
{
var input = Console.ReadLine();
input = Helper.ValidateInput(input);
input = Helper.CheckForThe(input);
return input;
}
public static string GetValidatedNormalizedInput()
{
var input = Console.ReadLine();
input = Helper.ValidateInput(input);
input = Helper.CheckForThe(input);
return input;
}
also, test "the best friend" in your "the" checker
Mekasu0124
Mekasu012410mo ago
oh it should be input = input.Split(" ")[1:input.Length] shouldn't it to remove the word "The" or "the" but return the rest or input = input.Remove(0,4); -execute
string text = "Some Words Here";
text.Remove(0,4);
Console.WriteLine(text);
string text = "Some Words Here";
text.Remove(0,4);
Console.WriteLine(text);
MODiX
MODiX10mo ago
Mekasu0124
Decompile Result
Failed
Code
string text = "Some Words Here";
text.Remove(0,4);
Console.WriteLine(text);
string text = "Some Words Here";
text.Remove(0,4);
Console.WriteLine(text);
Result:
Emit Failed
'Code.Main()': not all code paths return a value
Emit Failed
'Code.Main()': not all code paths return a value
React with ❌ to remove this embed.
MODiX
MODiX10mo ago
Mekasu0124
Decompile Result
Failed
Code
string text = "Some Words Here";
string newText = text.Remove(0,4);
Console.WriteLine(newText);
string text = "Some Words Here";
string newText = text.Remove(0,4);
Console.WriteLine(newText);
Result:
Emit Failed
'Code.Main()': not all code paths return a value
Emit Failed
'Code.Main()': not all code paths return a value
React with ❌ to remove this embed.
Pobiega
Pobiega10mo ago
uhm, use !e
MODiX
MODiX10mo ago
Pobiega
REPL Result: Success
string text = "Some Words Here";
string newText = text.Remove(0,4);
Console.WriteLine(newText);
string text = "Some Words Here";
string newText = text.Remove(0,4);
Console.WriteLine(newText);
Console Output
Words Here
Words Here
Compile: 613.815ms | Execution: 29.461ms | React with ❌ to remove this embed.
Mekasu0124
Mekasu012410mo ago
so use the remove method instead of splitting and indexing
Pobiega
Pobiega10mo ago
or TrimStart
Mekasu0124
Mekasu012410mo ago
trim start?
Pobiega
Pobiega10mo ago
eh, yeah that doesnt seem to work very well
Mekasu0124
Mekasu012410mo ago
I like the remove method
Pobiega
Pobiega10mo ago
probably nicer with return input[4..]; just straight remove the first 4 characters
MODiX
MODiX10mo ago
Mekasu0124
REPL Result: Success
string text = "The Mimic";
text = text[4..].ToLower();
Console.WriteLine(text);
string text = "The Mimic";
text = text[4..].ToLower();
Console.WriteLine(text);
Console Output
mimic
mimic
Compile: 655.392ms | Execution: 98.836ms | React with ❌ to remove this embed.
Mekasu0124
Mekasu012410mo ago
ok thank you for all your help. It's 5:15am my time and I've been working on this for nearly 13 hours now 😂 I'm going to close this help thread. Thank you all that helped I actually have one more question. To create a save method in my database file that saves the games to the user.json when the game is over.
public class GameModel
{
public string UserName { get; set; }
public string GameType { get; set; }
public DateTime Date { get; set; }
public int Score { get; set; }
public int TotalQuestions { get; set; }
}
public class GameModel
{
public string UserName { get; set; }
public string GameType { get; set; }
public DateTime Date { get; set; }
public int Score { get; set; }
public int TotalQuestions { get; set; }
}
this is my Game Model for the game results.
// Database.cs
public void SaveGame(GameModel info)
{
var content = JsonSerializer.Serialize(into);
}
// Database.cs
public void SaveGame(GameModel info)
{
var content = JsonSerializer.Serialize(into);
}
how would I add to my json file? I currently have in it
{
"Username": "",
"Email": "",
"Password": ""
}
{
"Username": "",
"Email": "",
"Password": ""
}
and I want to make a new field that gets add to the file instead of overwriting it and erasing the user's profile like this
{
"Username": "",
"Email": "",
"Password": "",
"Games": {}
}
{
"Username": "",
"Email": "",
"Password": "",
"Games": {}
}
and the "Games": {} is where the saved games gets added to but never overwrites the file
Pobiega
Pobiega10mo ago
your model needs to have all the fields you wish to save in it then you simply serialize the model and write that string to a file so you'd probably take your existing UserInfo model and add a GameModel Games property on it
Mekasu0124
Mekasu012410mo ago
// UserModel.cs
public class User
{
public string Username { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public GameModel Games { get; set; }
}

// GameModel.cs
public class GameModel
{
public string GameType { get; set; }
public DateTime Date { get; set; }
public int Score { get; set; }
public int TotalQuestions { get; set; }
}

// game.cs
public static PlayGame(string selectedDiff, string username, DateTime date)
{
// instantiations
for (int i = 0; i < ghostCount; i++)
{
// game code here
}
GameModel gameInfo = new()
{
GameType = selectedDiff,
Date = date,
Score = score,
TotalQuestions = ghostCount
}

db.SaveGame(gameInfo);
// UserModel.cs
public class User
{
public string Username { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public GameModel Games { get; set; }
}

// GameModel.cs
public class GameModel
{
public string GameType { get; set; }
public DateTime Date { get; set; }
public int Score { get; set; }
public int TotalQuestions { get; set; }
}

// game.cs
public static PlayGame(string selectedDiff, string username, DateTime date)
{
// instantiations
for (int i = 0; i < ghostCount; i++)
{
// game code here
}
GameModel gameInfo = new()
{
GameType = selectedDiff,
Date = date,
Score = score,
TotalQuestions = ghostCount
}

db.SaveGame(gameInfo);
am I doign this right so far?
Pobiega
Pobiega10mo ago
almost how is your SaveGame method defined? since your top level model is User, thats what you need to save
Mekasu0124
Mekasu012410mo ago
sorry. I totally zoned out in working on the game. I've gotten that part figured out shortly after I posted that question. Thank you for your help