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:
- 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, 3);
switch (diffChoice)
{
case 1:
diff = Difficulty.Easy;
break;
case 2:
diff = Difficulty.Medium;
break;
case 3:
diff = Difficulty.Hard;
break;
}
Console.WriteLine();
guessNum = new Random().Next((int)diff)+1;
int remainingGuesses = 5;
bool winner = guessNumber(guessNum, diff, ref remainingGuesses, new List<int>());
if (winner)
{
Console.WriteLine("Winner!! It took you "+(5-remainingGuesses)+" tries!\n");
}
else
{
Console.WriteLine("Loser :( \nThe number was "+guessNum+"!!\n");
}
playAgain = getBool("Would you like to play another game? (Y/N) ", "Y", "N", true);
} while (playAgain);
Console.WriteLine("\nThanks for playing!");
}
public bool guessNumber(int answer, Difficulty diff, ref int triesLeft, List<int> guesses)
{
if(triesLeft == 0){
return false;
}
else
{
if (triesLeft == 1)
{
Console.WriteLine("Last chance!!!\n");
}
else
{
Console.WriteLine(triesLeft+" chances left!\n");
}
int userGuess = getInt("Guess a number from 1 to " + (int)diff+" (inclusive): ", 1, (int)diff);
if (guesses.Contains(userGuess))
{
Console.WriteLine("You've already guessed "+userGuess+"!! Try again\n");
return guessNumber(answer, diff, ref triesLeft, guesses);
}
else
{
Console.WriteLine();
triesLeft--;
guesses.Add(userGuess);
if (userGuess == answer)
{
return true;
}
else
{
if (userGuess > answer)
{
Console.WriteLine("Over!\n");
}
else
{
Console.WriteLine("Under!\n");
}
return guessNumber(answer, diff, ref triesLeft, guesses);
}
}
}
}
public int getInt(string message, int min, int max)
{
bool success = false;
int result;
Console.Write(message);
string input = Console.ReadLine();
success = Int32.TryParse(input, out result);
success = (result >= min && result <= max);
return success ? result : getInt("INVALID INPUT: "+input+"\n"+message, min, max);
}
public bool getBool(string message, string trueResponse, string falseResponse, bool ignoreCase = true)
{
Console.Write(message);
string response = Console.ReadLine();
if (ignoreCase)
{
if (response.ToUpper().Equals(trueResponse.ToUpper()))
{
return true;
}
if (response.ToUpper().Equals(falseResponse.ToUpper()))
{
return false;
}
}
else
{
if (response.Equals(trueResponse))
{
return true;
}
if (response.Equals(falseResponse))
{
return false;
}
}
Console.WriteLine("INVALID INPUT: "+response+"; Expected "+trueResponse+" or "+falseResponse+"\n");
return getBool(message, trueResponse, falseResponse, ignoreCase);
}
}
}
Difficulties.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NumberGuessingGame
{
public enum Difficulty : int
{
Easy = 10,
Medium = 50,
Hard = 100
}
}
Any input would be highly appreciated! I want to focus on becoming a better programmer in any way I can. Don't be afraid to nitpick!