patterncsharpMinor
Hangman Game in windows forms
Viewed 0 times
formswindowsgamehangman
Problem
today I created a simple hangman game, which has 10 different categories with 10 words each. The words order is being randomized each time you pick a category. You have the chance to pick a wrong letter 8 times, after this it's game over and your progress on the current category is being wiped out. The game also saves all the completed categories in the Settings of the project so you wont loose any progress if you restart the game. There are 3 difficulties - easy, medium, hard. Easy show's you the first and the last letters of the word, medium shows you only the first one and hard shows none. Each one has separate progress completion. This is how the game looks http://prntscr.com/b0hkye you can enter letter by pressing them on your keyboard or by using the alphabet built-in the app. That's pretty much of it now I'm going to quickly go over the code.
The game has a static class which holds some data that will be used over all the forms.
and I also created another static class which holds all the available words
```
public static class Words
{
public static string[] Capitals =
{
"London",
"Tokyo",
"Paris",
"Berlin",
"Ottawa",
"Washington",
"Copenhagen",
"Kabul",
"Sofia",
"Budapest"
};
public static string[] FoodAndDrinks =
{
"Haggis",
"Spaghetti",
"Pizza",
"Salad",
"Fanta",
"Hamburger",
"Steak",
"Eggs",
The game has a static class which holds some data that will be used over all the forms.
public static class GeneralSettings
{
public enum Difficulty
{
Easy,
Medium,
Hard
}
public enum Category
{
Capitals,
FoodAndDrinks,
Animals,
Plants,
Objects,
Movies,
Cities,
Furniture,
Figures,
Sports
}
public static Difficulty GameDifficulty { get; set; }
public static Category GameCategory { get; set; }
public static string[] GameWords { get; set; }
}and I also created another static class which holds all the available words
```
public static class Words
{
public static string[] Capitals =
{
"London",
"Tokyo",
"Paris",
"Berlin",
"Ottawa",
"Washington",
"Copenhagen",
"Kabul",
"Sofia",
"Budapest"
};
public static string[] FoodAndDrinks =
{
"Haggis",
"Spaghetti",
"Pizza",
"Salad",
"Fanta",
"Hamburger",
"Steak",
"Eggs",
Solution
A Single "Difficulty" Event Handler
Extend
More HangEventArgs Goodness
Same idea as above. BONUS: new categories use this handler too.
Data Structure Simplifies Everything
By data structure I mean a class design making the hangman data accessible. You almost got this with the
The big insight to all of this is that there are not "easy difficulty", "medium difficulty", etc. There is just a "difficulty". Likewise with categories. And the
Meanwhile, back at the Category_Click Handler
Back to HangData class
Put the "completed" properties in here too.
At this point I'm not seeing a use for a collection of these flags.
One
You're going to use this in the category click event handler (not shown).
MainGame
I'm not going into the nit-picking of code changes, but note:
The Big Picture
We made a data structure for the more abstract ideas of "difficulty" and "category" (vice "easy capitals" for example). This very dramatically reduced code volume and simplified client code.
Extend
EventArgs so you can pass Difficulty. public class HangEventArgs : EventArgs {
public Difficulty challenge {get; set;}
}
// one handler to rule them all
private void Difficulty_Click(object sender, HangEventArgs e)
{
GameDifficulty = e.challenge;
ChapterSelection cs = new ChapterSelection();
cs.ShowDialog();
}More HangEventArgs Goodness
Same idea as above. BONUS: new categories use this handler too.
public class HangEventArgs : EventArgs {
public Difficulty Challenge {get; set;}
public Category Jeopardy {get; set;}
}
private void Category_Click(object sender, HangEventArgs e)
{
GameWords = Words.Capitals; // this will be dealt with below
GameCategory = e.Jeopardy;
MainGame mg = new MainGame();
mg.ShowDialog();
UpdateEasyCompletedCategories(); // this will be dealt with below
}Data Structure Simplifies Everything
By data structure I mean a class design making the hangman data accessible. You almost got this with the
GeneralSettings class. But we need instances.The big insight to all of this is that there are not "easy difficulty", "medium difficulty", etc. There is just a "difficulty". Likewise with categories. And the
enums say as much.public class HangData {
// moved the enums out
// enums do not need to be inside of a class. They can be
// defined in the namespace.
public Difficulty GameDifficulty { get; protected set; }
public Category GameCategory { get; protected set; }
public string[] GameWords { get; protected set; }
public HangData (Difficulty howHard, Category askWhat) {
GameDifficulty = howHard;
GameCategory = askWhat;
GameWords = GetGameWords();
}
protected string[] GetGameWords() { // do it }
}Meanwhile, back at the Category_Click Handler
private void Category_Click(object sender, HangEventArgs e)
{
MainGame mg = new MainGame( new HangData(e.Challenge, e.Jeopardy));
mg.ShowDialog();
UpdateEasyCompletedCategories(); // this will be dealt with below
}Back to HangData class
Put the "completed" properties in here too.
public class HangData {
public bool CapitalsCompleted {get; set;}
// et cetera
public HangData (Difficulty howHard, Category askWhat) {
// all the earlier stuff, then
SetCategoryCompleteFlags();
}
protected void SetCategoryCompleteFlags() { // whatever it takes }
}At this point I'm not seeing a use for a collection of these flags.
One
UpdateCompletedCategories() methodprivate void UpdateCompletedCategories() {
cbCapitals.Checked = myHangData.CapitalsCompleted;
// et cetera
}You're going to use this in the category click event handler (not shown).
MainGame
I'm not going into the nit-picking of code changes, but note:
- Don't need properties like
categoryWords. It's all neatly encapsulated inHangData
- The matrix of properties and methods named: "hard/med/easy" combined with every category - goes away.
- The
lettersstatic property might best be put intoHangData. Try it out and see how it feels.
The Big Picture
We made a data structure for the more abstract ideas of "difficulty" and "category" (vice "easy capitals" for example). This very dramatically reduced code volume and simplified client code.
Code Snippets
public class HangEventArgs : EventArgs {
public Difficulty challenge {get; set;}
}
// one handler to rule them all
private void Difficulty_Click(object sender, HangEventArgs e)
{
GameDifficulty = e.challenge;
ChapterSelection cs = new ChapterSelection();
cs.ShowDialog();
}public class HangEventArgs : EventArgs {
public Difficulty Challenge {get; set;}
public Category Jeopardy {get; set;}
}
private void Category_Click(object sender, HangEventArgs e)
{
GameWords = Words.Capitals; // this will be dealt with below
GameCategory = e.Jeopardy;
MainGame mg = new MainGame();
mg.ShowDialog();
UpdateEasyCompletedCategories(); // this will be dealt with below
}public class HangData {
// moved the enums out
// enums do not need to be inside of a class. They can be
// defined in the namespace.
public Difficulty GameDifficulty { get; protected set; }
public Category GameCategory { get; protected set; }
public string[] GameWords { get; protected set; }
public HangData (Difficulty howHard, Category askWhat) {
GameDifficulty = howHard;
GameCategory = askWhat;
GameWords = GetGameWords();
}
protected string[] GetGameWords() { // do it }
}private void Category_Click(object sender, HangEventArgs e)
{
MainGame mg = new MainGame( new HangData(e.Challenge, e.Jeopardy));
mg.ShowDialog();
UpdateEasyCompletedCategories(); // this will be dealt with below
}public class HangData {
public bool CapitalsCompleted {get; set;}
// et cetera
public HangData (Difficulty howHard, Category askWhat) {
// all the earlier stuff, then
SetCategoryCompleteFlags();
}
protected void SetCategoryCompleteFlags() { // whatever it takes }
}Context
StackExchange Code Review Q#127558, answer score: 2
Revisions (0)
No revisions yet.