Welcome to Dream.In.Code
Getting C# Help is Easy!

Join 109,157 C# Programmers for FREE! Ask your question and get quick answers from experts. There are 1,024 online right now! We've got more than 500 tutorials and 2,000 snippets. Join and find out why Dream.In.Code is the #1 programming help community on the internet! Registration is fast and FREE... Join Now!



Best methods to condense this code

 
Reply to this topicStart new topic

Best methods to condense this code, lots of repeating code

OliveOyl3471
post 9 Jun, 2008 - 11:38 PM
Post #1


#include<popeye.h>

Group Icon
Joined: 11 Jul, 2007
Posts: 614



Thanked 4 times

Dream Kudos: 25
My Contributions


Here's my game that I made just for fun and to help me learn. There is a lot of similar or repeating code that I would like to use methods for, as I have done for some of it.

Yes, this is pretty sloppy. I probably should have used flags for some (or all?) of the error checking.

And some of the while loops probably could have been for loops, when I used a counter...except that you'd need to break out of the for loop when the user gets the correct answer and I don't know how to do that. How do you do that?

Also, is there a way to keep from having to create different variable names (example: for the user's answer or for their guess)?


So here's my sloppy code:
csharp

using System;
using System.Collections.Generic;
using System.Text;


namespace ConsoleApplication1
{
class Program
{
private static void greeting()
{
//Depending on the current time, print either "Good morning," "Good afternoon," or "Good evening"
DateTime time = new DateTime();

//get the current time
time = DateTime.Now;

//if it is past midnight but before noon, print "Good morning."
if (time.Hour >=0 && time.Hour < 12 )
{
Console.WriteLine("Good morning.");
}
//if it is past noon but before 6PM, print "Good afternoon."
else if (time.Hour >= 12 && time.Hour < 18)
{
Console.WriteLine("Good afternoon.");
}
//if it is past 6PM, print "Good evening."
else if (time.Hour >= 18)
{
Console.WriteLine("Good evening.");
}

}

//method to get answer from user, when asked if they want to know my name
public static void GetAns()
{
string ans = Console.ReadLine();
ans = ans.ToUpper();
if (ans == "Y")
{
Console.WriteLine("Okay. You asked. My name is Tammy.");
greeting();

}
else //if they enter anything other than Y or y, allow them to exit
{
Console.WriteLine("Okay. I will not tell you my name.");
greeting();

}
}
//method called when the user doesn't enter a valid number
public static void GuessError()
{
Console.WriteLine("You must enter a whole number greater than zero.");
}

static void Main(string[] args)

{ //initialize a new instance of the Random class
Random RandomClass = new Random();
//print greeting based on user's current time
greeting();

Console.WriteLine("Welcome to the game.\n");
Console.WriteLine("What shall I call you?");

//assign whatever they type to a property called name, which we will use throughout the game
string name = Console.ReadLine();
Console.WriteLine("Hello {0}!", name);

Console.WriteLine("Would you like to play a game? Type Y for yes or N for no.");
string answer = Console.ReadLine();
answer = answer.ToUpper();

if (answer == "Y")
{
Console.WriteLine("What do you want to play, {0}? Pick one: 1. Harder guessing game 2. Math game 3. Easy guessing game", name);

int game;
//if they didn't enter a number, return 0
int.TryParse(Console.ReadLine(), out game);
//show error if they did not enter a number between 1 and 3
while (game <= 0 || game > 3)
{
Console.WriteLine("You must enter either 1, 2, or 3.");
int.TryParse(Console.ReadLine(), out game);
}
switch (game)
{
case 1: Console.WriteLine("Okay, let's start the harder guessing game!");
Console.WriteLine("I am thinking of a number between one and one hundred.");
Console.WriteLine("Try to guess my number, {0}! Type your first guess now.", name);

//get a random number between one and 100
int myNum = RandomClass.Next(1, 100);

//create property for guesses
int guess;
int.TryParse(Console.ReadLine(), out guess);
//make sure the user entered a valid number
while (guess <=0 || guess >= 101)
{
GuessError();
int.TryParse(Console.ReadLine(), out guess);
}
int countr = 0;
//let them keep guessing until they guess the right number or for 10? tries
while (guess != myNum && countr<9)
{
//give a hint if they are within one number
if (guess == (myNum + 1)|| guess == myNum -1)
{
//put a couple methods in here for repeating code
Console.WriteLine("That's pretty close, {0}, but not right. Guess again!", name);
int.TryParse(Console.ReadLine(), out guess);
}

//if they guess too high, tell them to guess lower
else if (guess > myNum)
{
Console.WriteLine("Lower!");
int.TryParse(Console.ReadLine(), out guess);
}
//if they guess too low, tell them to guess higher
else if (guess < myNum)
{
Console.WriteLine("Higher!");
int.TryParse(Console.ReadLine(), out guess);
}
countr++;
//make sure the user entered a valid number
while (guess <= 0 || guess >= 101)
{
GuessError();
int.TryParse(Console.ReadLine(), out guess);
}
}
if (countr >= 9)
{
Console.WriteLine("Sorry, {0}, the correct answer was " + myNum.ToString(), name);

}

if (guess == myNum)
{
Console.WriteLine("Good guess, {0}! That's my number!", name);
}

Console.WriteLine("Would you like to play again?");
string again = Console.ReadLine();
again = again.ToUpper();

//if they want to play again, repeat the game
if (again == "Y")
{
goto case 1;
}

else//if they enter anything other than Y or y, end the game
Console.WriteLine("Okay. No more games. Shall I tell you my name, {0}?", name);
//call method to get the user's answer
GetAns();

break;

case 2: Console.WriteLine("Let's play a math game. Pick one: 1. addition or 2. subtraction.");
int pick;
//if they didn't enter a number, return 0
int.TryParse(Console.ReadLine(), out pick);
//if they didn't enter either 1 or 2, show error
while (pick <= 0 || pick > 2)
{
Console.WriteLine("You must enter either 1 or 2.");
int.TryParse(Console.ReadLine(), out pick);
}
if (pick == 1)
{
Console.WriteLine("Let's start adding!");
int add1 = RandomClass.Next(1, 100);
int add2 = RandomClass.Next(1, 100);
Console.WriteLine("Add " + add1.ToString() + " and " + add2.ToString() + ".");
Console.WriteLine("Type your answer now.");
int sumGuess;
int.TryParse(Console.ReadLine(), out sumGuess);
//make sure they entered a number
while (sumGuess == 0)
{
GuessError();
int.TryParse(Console.ReadLine(), out sumGuess);
}

int sum = add1 + add2;
int tries = 0;
//let them keep trying until they get it or for 10 tries
while (sumGuess != sum && tries < 9)
{
//if their answer is within one number, give a hint
if (sumGuess == sum + 1 || sumGuess == (sum - 1))
{
Console.WriteLine("That's pretty close, {0}, but not right. Keep guessing!", name);
}
else
{
Console.WriteLine("Keep trying!");
}
//update counter
tries++;
int.TryParse(Console.ReadLine(), out sumGuess);
//show error if they don't enter number or leave blank
while (sumGuess == 0)
{
GuessError();
int.TryParse(Console.ReadLine(), out sumGuess);
}

}
if (tries >= 9)
{ //if they don't get it within 10 tries, tell them the answer
Console.WriteLine("Sorry, {0}, the correct answer is " + sum + ".", name);
}

if (sumGuess == sum)
{
Console.WriteLine("Congratulations! That is the correct answer.");
}

Console.WriteLine("Would you like to play again? Type Y or N.");
string addAgain = Console.ReadLine();
if (addAgain == "Y" || addAgain == "y")
{
goto case 2;
}
else
{
Console.WriteLine("Ok, so you don't want to add any more. Do you want to know my name?");
//call method to get the user's answer
GetAns();
}
}
else if (pick == 2)
{
Console.WriteLine("Let's start subtracting!");
int sub1 = RandomClass.Next(1, 100);
int sub2 = RandomClass.Next(1, 100);
int trys = 0;
//make sure the first number is more than the second one, to avoid negative numbers
//and make sure the two numbers are not equal, so the answer will never be zero
while (sub1 <= sub2)
{ sub1 = RandomClass.Next(1, 100);
sub2 = RandomClass.Next(1, 100);
}
int diff = sub1 - sub2;
Console.WriteLine("Subtract " + sub1 + " minus " + sub2 + ".");
Console.WriteLine("Type your answer now.");
int diffGuess;
int.TryParse(Console.ReadLine(), out diffGuess);

//show error if they didn't enter a number
while (diffGuess == 0)
{
GuessError();
int.TryParse(Console.ReadLine(), out diffGuess);
}
//let them keep trying until they get it or for 10 tries
while (diffGuess != diff && trys < 9)
{
//if their answer is within one number, give a hint
if (diffGuess == diff + 1 || diffGuess == diff - 1)
{
Console.WriteLine("That's pretty close, {0}, but not right. Try again.",name);
}
else
{
Console.WriteLine("Keep trying!");
}
//update counter
trys++;
int.TryParse(Console.ReadLine(), out diffGuess);
//show error if they don't enter number or leave blank
//this code is repeated, can I avoid this?
while (diffGuess == 0)
{
GuessError();
int.TryParse(Console.ReadLine(), out diffGuess);
}

}
if (trys >= 9)
{
Console.WriteLine("Sorry, {0}, the correct answer is " + diff + ".", name);
}

if (diffGuess == diff)
{
Console.WriteLine("Congratulations! That is the correct answer.");
}
Console.WriteLine("Would you like to play again? Type Y or N.");
string subAgain = Console.ReadLine();
if (subAgain == "Y" || subAgain == "y")
{
goto case 2;
}
else
{
Console.WriteLine("Ok, so you don't want to subtract any more. Do you want to know my name?");
//call method to get the user's answer
GetAns();
}
}

break;

case 3: Console.WriteLine("Let's start the easy guessing game!");
Console.WriteLine("I am thinking of a number between one and ten.");
Console.WriteLine("Try to guess my number, {0}! Type your first guess now.", name);

//get a random number between one and ten
myNum = RandomClass.Next(1, 10);

int.TryParse(Console.ReadLine(), out guess);
//make sure the user enters a valid number (1-10)
while(guess <=0||guess>=11)
{
GuessError();
int.TryParse(Console.ReadLine(), out guess);
}
//let them keep guessing until they guess the right number or for 5 tries
int count = 0;
while (guess != myNum && count<4)//count starts at 0, so when it gets to 4, they will have used 5 tries
{

//give a hint if they guess within one number
if (guess == (myNum + 1) || guess == myNum - 1)
{
Console.WriteLine("That's pretty close, {0}, but not right. Guess again!", name);
count++;
int.TryParse(Console.ReadLine(), out guess);

}
else
{
Console.WriteLine("Keep guessing!");

count++;

int.TryParse(Console.ReadLine(), out guess);
}
//make sure the user enters a valid number (1-10)
while (guess <= 0 || guess >= 11)
{
GuessError();
int.TryParse(Console.ReadLine(), out guess);
}
}
//if they use up all their tries, tell them the answer
if (count >= 4)
{
Console.WriteLine("Sorry, {0}, my number was " + myNum + ".", name);
}
//if they get the right answer, let them know
if (guess == myNum)
{
Console.WriteLine("Good guess, {0}! That's my number!", name);
}
//give the user a choice whether to play again
Console.WriteLine("Would you like to play again?");
again = Console.ReadLine();
again = again.ToUpper();

//if they want to play again, repeat the game
if (again == "Y")
{
goto case 3;
}
else//if they enter anything other than Y or y, end the game
Console.WriteLine("Okay. No more games, {0}. Shall I tell you my name?", name);

//call method to get the user's answer
GetAns();
break;
}
}

else //if they enter anything other than Y or y when asked if they want to play a game
{
Console.WriteLine("Okay. No games. Shall I tell you my name, {0}?", name);
//call method to get the user's answer
GetAns();

}
}
}
}




User is offlineProfile CardPM

Go to the top of the page


baavgai
post 10 Jun, 2008 - 04:55 AM
Post #2


Dreaming Coder

Group Icon
Joined: 16 Oct, 2007
Posts: 1,570



Thanked 44 times

Dream Kudos: 325

Expert In: C, C++, Java, C#, ASP.NET, PHP, Perl, Python, Oracle, SQL Server, MySql, HTML, JavaScript, Lua

My Contributions


Don't be afraid of methods, they're good for you. Each distinct section that you have in your massive if case thing can be placed in it's very own method.

Also, a goto is a sign of failure and any instructor is likely to let you know it.

Here's some code to get you going. I didn't write it all, but it should give you an idea.

csharp

using System;
using System.Collections.Generic;
using System.Text;


namespace ConsoleApplication1 {
class Program {
private String userName = null;
private Random RandomClass = new Random();

private void greeting() {
int hour = DateTime.Now.Hour;
if (hour < 12 ) {
Console.WriteLine("Good morning.");
} else if (hour < 18) {
Console.WriteLine("Good afternoon.");
} else {
Console.WriteLine("Good evening.");
}
}


private void Welcome() {
Console.WriteLine("Welcome to the game.\n");
Console.WriteLine("What shall I call you?");
this.userName = Console.ReadLine();
Console.WriteLine("Hello {0}!", userName);
}

// helper function
private bool GetYN(string prompt) {
if (prompt != null) {
Console.WriteLine(prompt);
}
string ans = Console.ReadLine();
return (ans.Trim().ToUpper() == "Y");
}

private bool GetYN() { return GetYN(null); }


//method to get answer from user, when asked if they want to know my name
private void GetAns() {
if (GetYN()) {
Console.WriteLine("Okay. You asked. My name is Tammy.");
} else {
Console.WriteLine("Okay. I will not tell you my name.");
}
greeting();
}

// return true if they want to play again
private bool EasyGame() {
Console.WriteLine("Let's start the easy guessing game!");
Console.WriteLine("I am thinking of a number between one and ten.");
Console.WriteLine("Try to guess my number, {0}! Type your first guess now.", this.userName);

int guess = 0;
int count = 0;
bool done = false;
int myNum = RandomClass.Next(1, 10);

while (!done) {
int.TryParse(Console.ReadLine(), out guess);
if (guess<1 || guess>=11) {
Console.WriteLine("You must enter a whole number greater than zero.");
} else {
count++;
if (guess == myNum) {
Console.WriteLine("Good guess, {0}! That's my number!", this.userName);
done = true;
} else if (count > 5) {
Console.WriteLine("Sorry, {0}, my number was " + myNum + ".", this.userName);
done = true;
} else {
if (guess == (myNum + 1) || guess == myNum - 1) {
Console.WriteLine("That's pretty close, {0}, but not right. Guess again!", this.userName);
} else {
Console.WriteLine("Keep guessing!");
}
}
}
}

return (GetYN("Would you like to play again?"));
}



private bool HarderGame() {
// your code
return false;
}

private bool MathGame() {
// your code
return false;
}

private int GetGameSelection() {
int game;
Console.WriteLine("What do you want to play, {0}? Pick one: 1. Harder guessing game 2. Math game 3. Easy guessing game", name);
//if they didn't enter a number, return 0
int.TryParse(Console.ReadLine(), out game);
//show error if they did not enter a number between 1 and 3
while (game < 1 || game > 3) {
Console.WriteLine("You must enter either 1, 2, or 3.");
int.TryParse(Console.ReadLine(), out game);
}
return game;
}

private void GameSelect() {
switch (GetGameSelection()) {
case 1:
while (HarderGame());
break;

case 2:
while (MathGame());
break;

case 3:
// loop on one game until they're done
while (EasyGame());
break;
}
}

public void Play() {
Welcome();
if (GetYN("Would you like to play a game? Type Y for yes or N for no.")) {
GameSelect()
} else {
Console.WriteLine("Okay. No games. Shall I tell you my name, {0}?", this.userName);
}
// give them the name
GetAns();
}

static void Main(string[] args) {
Program pgm = new Program();
pgm.Play();
}
}
}

User is online!Profile CardPM

Go to the top of the page

OliveOyl3471
post 10 Jun, 2008 - 03:12 PM
Post #3


#include<popeye.h>

Group Icon
Joined: 11 Jul, 2007
Posts: 614



Thanked 4 times

Dream Kudos: 25
My Contributions


Thank you.
Since this is not for a class, I consider you (and other DIC'ers) my instructor at the moment. wink2.gif

So... should I get rid of the case statement completely? Or just don't use goto.
I see why you said it is a sign of failure, since I could not get it to work any other way.

It does make sense that every chunk of code should go into a method, especially if it repeats.

I'll study your revisions to my code. smile.gif
User is offlineProfile CardPM

Go to the top of the page

baavgai
post 10 Jun, 2008 - 04:48 PM
Post #4


Dreaming Coder

Group Icon
Joined: 16 Oct, 2007
Posts: 1,570



Thanked 44 times

Dream Kudos: 325

Expert In: C, C++, Java, C#, ASP.NET, PHP, Perl, Python, Oracle, SQL Server, MySql, HTML, JavaScript, Lua

My Contributions


If code repeats, then a method is often the most efficient way to eliminate the duplication.

I'm not a big fan of case statements. They don't do anything that an if then else construct can't do, and are far more limited. They can make some code look cleaner, but only in specific instances and usually providing that code doesn't grow. Some folks love them, but not I.

Some cleanups will be purely cosmetic, by their nature. Just choose a coding style that appeals to you and be consistent.
User is online!Profile CardPM

Go to the top of the page

OliveOyl3471
post 10 Jun, 2008 - 10:27 PM
Post #5


#include<popeye.h>

Group Icon
Joined: 11 Jul, 2007
Posts: 614



Thanked 4 times

Dream Kudos: 25
My Contributions


This is a flag, is that right? I haven't used them much yet.

csharp

// helper function
private bool GetYN(string prompt) {
if (prompt != null) {
Console.WriteLine(prompt);
}
string ans = Console.ReadLine();
return (ans.Trim().ToUpper() == "Y");
}

private bool GetYN() { return GetYN(null); }


and if I understand it correctly, since it is boolean, it must return either true or false. This line:
return (ans.Trim().ToUpper() == "Y");
will cause GetYN to return true if they enter a y or Y and false otherwise. Is that right?

There are really two different methods here, both named GetYN, but since their parameters differ, you can do that.
When you call GetYN(), it causes GetYN(string prompt) to run, and returns either true or false to GetYN().


This happens first:
CODE

            return (GetYN("Would you like to play again?"));  

and it causes "Would you like to play again?" to be displayed, and then it gets their answer using the two methods above.


This:
CODE

                    while (HarderGame());

causes the game to continue as long as they want to play, because HarderGame is boolean, and the code will run as long as HarderGame() returns true.

What I put in here:
CODE

        private bool HarderGame() {  
            // your code  
            return false;  
        }

in place of //your code, would be code that causes the game to start, that I already have written.
At the end of the game code, I would ask if they want to play again, using your boolean
CODE

            return (GetYN("Would you like to play again?"));

and it works because if they enter Y or y, as stated above, it will return true, otherwise it returns false.

The boolean done, here, just lets them quit playing that game (not the entire program) when they guess the right number or use up all their tries. Otherwise, it lets them keep trying.
CODE

            bool done = false;  
            int myNum = RandomClass.Next(1, 10);  
              
            while (!done) {  
                int.TryParse(Console.ReadLine(), out guess);  
                if (guess<1 || guess>=11) {  
                    Console.WriteLine("You must enter a whole number greater than

zero.");  
                } else {  
                    count++;  
                    if (guess == myNum) {  
                        Console.WriteLine("Good guess, {0}! That's my number!",

this.userName);  
                        done = true;


This game is the most involved thing I've ever done in programming, so far. We never did anything like this in class. (edit--with a couple exeptions in VB)

I really want to be good at this, so thanks again for helping me. I want to make sure I understand why things are done, not just "what" to do. Please tell me if I have not understood any part of this correctly. smile.gif

This post has been edited by OliveOyl3471: 10 Jun, 2008 - 10:30 PM
User is offlineProfile CardPM

Go to the top of the page

OliveOyl3471
post 29 Jun, 2008 - 02:28 PM
Post #6


#include<popeye.h>

Group Icon
Joined: 11 Jul, 2007
Posts: 614



Thanked 4 times

Dream Kudos: 25
My Contributions


I finally got around to testing all of this.

The program runs and for the most part it works as is, but it doesn't ask them if they want to know my name whenever they are done playing the games. It just displays a blank line and if you press enter it will display "Okay. I will not tell you my name." lol.

I would also like to change it so that instead of automatically repeating the same game they can go back to the game choices when asked if they want to play again. You would call GetGameSelection() at that point, wouldn't you? Where would you call it?

I did change it so that they have a choice of adding or subtracting when they want to play again, for the math game.

Here's part of the 'new improved' game (still working on it):

csharp


//Show error message if they don't enter a number
private static void GuessError()
{
Console.WriteLine("That is not a valid number. Please try again.");
}

// return true if they want to play again
private bool EasyGame()
{
//baavgai's improved version of my code here
}

private bool HarderGame()
{

Console.WriteLine("Okay, let's start the harder guessing game!");
Console.WriteLine("I am thinking of a number between one and one hundred.");
Console.WriteLine("Try to guess my number, {0}! Type your first guess now.", this.userName);

int count = 0;
bool done = false;
int myNum = RandomClass.Next(1, 100);
int guess=0;
while (!done)
{
int.TryParse(Console.ReadLine(), out guess);
//make sure the user entered a valid number
while (guess <= 0 || guess >= 101)
{
GuessError();
int.TryParse(Console.ReadLine(), out guess);
}

//let them keep guessing until they guess the right number or for 10? tries
while (guess != myNum && count < 9)
{
//give a hint if they are within one number
if (guess == (myNum + 1) || guess == myNum - 1)
{

Console.WriteLine("That's pretty close, {0}, but not right. Guess again!", this.userName);
int.TryParse(Console.ReadLine(), out guess);
}

//if they guess too high, tell them to guess lower
else if (guess > myNum)
{
Console.WriteLine("Lower!");
int.TryParse(Console.ReadLine(), out guess);
}
//if they guess too low, tell them to guess higher
else if (guess < myNum)
{
Console.WriteLine("Higher!");
int.TryParse(Console.ReadLine(), out guess);
}
count++;
//make sure the user entered a valid number
while (guess <= 0 || guess >= 101)
{
GuessError();
int.TryParse(Console.ReadLine(), out guess);
}
}
if (count >= 9)
{
Console.WriteLine("Sorry, {0}, the correct answer was " + myNum.ToString(), this.userName);
done = true;
}

if (guess == myNum)
{
Console.WriteLine("Good guess, {0}! That's my number!", this.userName);
done = true;
}
}
//if they want to play again, repeat the game
return (GetYN("Would you like to play again?")); //how do you get this to do something else when they enter N?
}

private bool MathGame()
{
//my math game code goes here

return (GetYN("Would you like to play again?"));//lets them play another math game
}

private int GetGameSelection()
{
int game;
Console.WriteLine("What do you want to play, {0}? Pick one: 1. Harder guessing game 2. Math game 3. Easy guessing game", this.userName);
//if they didn't enter an int, return 0
int.TryParse(Console.ReadLine(), out game);
//show error if they did not enter a number between 1 and 3
while (game < 1 || game > 3)
{
Console.WriteLine("You must enter either 1, 2, or 3.");
int.TryParse(Console.ReadLine(), out game);
}
return game;
}

private void GameSelect()
{
switch (GetGameSelection())
{
case 1:
while (HarderGame()) ;
break;

case 2:
while (MathGame()) ;
break;

case 3:
// loop on one game until they're done
while (EasyGame()) ;
break;
}
}

User is offlineProfile CardPM

Go to the top of the page

djkitt
post 30 Jun, 2008 - 06:51 AM
Post #7


D.I.C Head

**
Joined: 22 May, 2008
Posts: 119



Thanked 13 times
My Contributions


QUOTE(OliveOyl3471 @ 10 Jun, 2008 - 01:38 AM) *


And some of the while loops probably could have been for loops, when I used a counter...except that you'd need to break out of the for loop when the user gets the correct answer and I don't know how to do that. How do you do that?


CODE

        private void button9_Click(object sender, EventArgs e)
        {
            string iStr = "";
            for (int i = 0; i < 10; i++)
                if (i == 5)
                {
                    iStr = i.ToString();
                    break; // This is how you break out of a for loop
                }
            MessageBox.Show(iStr);
        }


Hope this helps,

This post has been edited by djkitt: 30 Jun, 2008 - 06:52 AM
User is offlineProfile CardPM

Go to the top of the page

Fast ReplyReply to this topicStart new topic
Time is now: 9/5/08 05:40PM

Live C# Help!

C# Tutorials

Reference Sheets

C# Snippets

Bye Bye Ads

Free DIC T-Shirt

T-Shirt Example

Related Sites

Monthly Drawing

Thumb Drive

Partners

Top Contributors

Top 10 Kudos This Month