patterncsharpMinor
C#/.Net 4.5 - Number Guessing Game
Viewed 0 times
numbergamenetguessing
Problem
I'm currently enrolled in an introductory C#/.Net 4.5 course and one of the things I want to focus on is the quality of my code.
This is the first assignment our instructor had us do, the ever-popular number guessing game. The requirements our instructor set out for us were:
In addition to these, our instructor challenged me to use as few loops as possible and to use ref or out parameters at least once (we just learned about them in class), because I am already somewhat familiar with C#.
This is what I came up with:
Program.cs:
```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NumberGuessingGame
{
public class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
public void Run()
{
Console.WriteLine("Welcome to the Number Guessing Game!\n");
Difficulty diff = Difficulty.Easy;
bool playAgain = false;
int guessNum;
do
{
int diffChoice = getInt("Your choices of difficulty are:\n1.) Easy (1-10)\n2.) Medium (1-50)\n3.) Hard (1-100)\n\nWhich difficulty would you like to play? ", 1,
This is the first assignment our instructor had us do, the ever-popular number guessing game. The requirements our instructor set out for us were:
- On startup, the program asks the user to select a difficulty (easy, medium, hard).
- Once the difficulty is selected, randomly choose the number and prompt the user to guess.
- The program must validate inputs for the current game (input is numeric and within the possible range of values for that difficulty).
- The program must keep track of values guessed for the current game. Repeated guesses are considered invalid and do not count as an attempt.
- If invalid input is received, inform the user and re-prompt.
- After each guess, tell the user if he was correct, under, or over.
- The number of attempts remaining should be displayed each turn of the game
- The program will ask the user if they want to play again.
In addition to these, our instructor challenged me to use as few loops as possible and to use ref or out parameters at least once (we just learned about them in class), because I am already somewhat familiar with C#.
This is what I came up with:
Program.cs:
```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NumberGuessingGame
{
public class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
public void Run()
{
Console.WriteLine("Welcome to the Number Guessing Game!\n");
Difficulty diff = Difficulty.Easy;
bool playAgain = false;
int guessNum;
do
{
int diffChoice = getInt("Your choices of difficulty are:\n1.) Easy (1-10)\n2.) Medium (1-50)\n3.) Hard (1-100)\n\nWhich difficulty would you like to play? ", 1,
Solution
public enum Difficulty : intThere's no need to specify the type. It's an
int by default. Every enumeration type has an underlying type, which can be any integral type except char. The default underlying type of enumeration elements is int. To declare an enum of another integral type, such as byte, use a colon after the identifier followed by the type, as shown in the following example.
MSDN - enum
A couple of things about your
Main. static void Main(string[] args)
{
Program p = new Program();
p.Run();
}- There's no reason to create a new instance of
Programfrom inside ofProgram. Just makeRunastaticmethod and call it. However...
- You've probably heard that you shouldn't have a bunch of logic in your
Mainroutine, so you created thisRunmethod to call fromMain. Unfortunately, you've missed the point. Instead of stuffing all of the logic intoMain, you've stuffed it intoRun.
Get rid of
Run entirely and move that logic into Main. Then, start extracting methods. By the time you're done, Main should read something like this pseudo code. WelcomeUser();
var play = true;
var isFirstGame = true;
while (play)
{
if (!isFirstGame && !play)
{
var difficulty = PrompUserForDifficulty();
PlayGame(difficulty);
}
play = AskUserToPlayAgain();
}
SayGoodbye();And that's it. 99% of the logic should reside in
PlayGame() or some equivalent. To clarify, Main shouldn't be entirely void of logic. The logic should simply be minimal. You're returning early here, so there's an opportunity to reduce the levels of indentation.
if(triesLeft == 0){
return false;
}
else
{
(if triesLeft == 1)Is equivalent to
if (triesLeft == 0)
{
return false;
}
if (triesLeft == 1)My last point (although more could be said) is that
ref and out params are a bit of a code smell. Rarely are they really needed out in the real world. I won't pick on it too much, because your teacher challenged you to use it, but in reality, if you think you need a ref arg, what you really need is a function, a method that returns a value. If you think you need a bunch out args, what you really need is a struct that formally groups those args into a formally defined and coherently grouped data structure (and obviously a method to return it).Code Snippets
public enum Difficulty : intstatic void Main(string[] args)
{
Program p = new Program();
p.Run();
}WelcomeUser();
var play = true;
var isFirstGame = true;
while (play)
{
if (!isFirstGame && !play)
{
var difficulty = PrompUserForDifficulty();
PlayGame(difficulty);
}
play = AskUserToPlayAgain();
}
SayGoodbye();if(triesLeft == 0){
return false;
}
else
{
(if triesLeft == 1)if (triesLeft == 0)
{
return false;
}
if (triesLeft == 1)Context
StackExchange Code Review Q#86456, answer score: 4
Revisions (0)
No revisions yet.