Stack overflow exception with instances of classes - c#

In my Main Menu class, I have a switch statement that calls the DisplaySellMenu method in the sell menu class(instance of the sell menu class was created in main menu class) when the user types the number to go to the sell menu. I then created a new instance of the Main menu class in the Sell Menu class, below you can see the switch statement I made so that when the user selects to exit to the Main Menu it calls the DisplayMainMenu method in the MainMenu class so the user can go back to the MainMenu. This is causing a stack overflow exception between the instances of the classes. How do I stop this from happening while still allowing the user to exit back to the main menu?
Main menu class:
class MainMenu
{
public BuyMenu buyMenu = new BuyMenu();
public SellMenu sellMenu = new SellMenu();
public ShipGarage shipGarage = new ShipGarage();
int Exit = 0;
public void DisplayMenu()
{
Console.WriteLine("Whatcha tryin to do yo?");
Console.WriteLine("Type 1 to buy");
Console.WriteLine("Type 2 to sell");
Console.WriteLine("Type 3 for SpaceShip Upgrade ");
Console.WriteLine("Type 4 to quit game");
int userSelection = int.Parse(Console.ReadLine());
do
{
switch (userSelection)
{
case 1:
buyMenu.DisplayInventory(buyMenu);
DisplayMenu();
break;
case 2:
sellMenu.SoldItems();
DisplayMenu();
break;
case 3:
shipGarage.DisplayGarage(shipGarage);
DisplayMenu();
break;
case 4:
Exit += 1;
break;
default:
Console.WriteLine("Invalid Input");
break;
}
} while (Exit == 1);
}
}
Sell menu class:
class SellMenu
{
static Random rnd = new Random();
MoneyMath Money = new MoneyMath();
MainMenu MainMenu = new MainMenu();
int goldPrice = rnd.Next(100, 1001);
int silverPrice = rnd.Next(100, 1001);
int titaniumPrice = rnd.Next(100, 1001);
int Exit = 0;
public string DisplayInventory()
{
Console.WriteLine("What would you like to sell?");
Console.WriteLine("Type 1 for Gold");
Console.WriteLine("Type 2 for Silver");
Console.WriteLine("Type 3 for Titanium");
Console.WriteLine("Type 4 for Main Menu");
string itemList = "Gold" + " " + "$" + (goldPrice) + "\n" +
"Silver" + " " + "$" + (silverPrice) + "\n" +
"Titanium" + " " + "$" + (titaniumPrice);
Console.WriteLine(itemList);
return itemList;
}
public void SoldItems()
{
do
{
DisplayInventory();
int userSelection = int.Parse(Console.ReadLine());
switch (userSelection)
{
case 1:
Money.MoneyAddition(goldPrice, 1);
Console.WriteLine(Money.userMoney);
break;
case 2:
Money.MoneyAddition(silverPrice, 1);
Console.WriteLine(Money.userMoney);
break;
case 3:
Money.MoneyAddition(titaniumPrice, 1);
Console.WriteLine(Money.userMoney);
break;
case 4:
Exit += 1;
MainMenu.DisplayMenu();
break;
default:
Console.WriteLine("Invalid Input");
break;
}
} while (Exit == 1);
}
}

It seems to me that your SoldItems() case 4 should simply be this:
case 4:
return;
You're already calling SoldItems() from DisplayMenu() in MainMenu, so all you need to do is return to the DisplayMenu() switch statement and continue its loop.
Having an Exit variable is unnecessary here because return will leave the entire method body, terminating the while loop. The same applies to DisplayMenu()'s Exit variable, too.
Complete code for SoldItems():
public void SoldItems()
{
do
{
DisplayInventory();
int userSelection = int.Parse(Console.ReadLine());
switch (userSelection)
{
case 1:
Money.MoneyAddition(goldPrice, 1);
Console.WriteLine(Money.userMoney);
break;
case 2:
Money.MoneyAddition(silverPrice, 1);
Console.WriteLine(Money.userMoney);
break;
case 3:
Money.MoneyAddition(titaniumPrice, 1);
Console.WriteLine(Money.userMoney);
break;
case 4:
return;
default:
Console.WriteLine("Invalid Input");
break;
}
}
while (true);
}
Explanation of StackoverflowException:
This exception is caused when the stack gets full. Imagine you have three methods:
public void A() { B(); }
public void B() { C(); }
public void C() { }
When A calls B, an extra layer is pushed onto the stack. The same happens when B calls C. When C returns to B, that layer is pushed off the stack, and then the same then B returns to A.
The .NET stack has a finite size, so you can't infinitely call methods. This is typically big enough for any code you write, except recursive functions can be a little dangerous. Imagine this code:
public void A() { A(); }
It calls itself recursively forever. This code is doomed to experience a Stackoverflow exception. When you write code like this, you need to place a limitation on it to ensure that it only goes so deep. Example:
public void A(int maxDepth = 0) { if (maxDepth < 5) { A(++maxDepth); } }
You can read more about the stack and this exception here.
Obligatory Google Easter egg

Related

goto - not within scope (C#)

I am very new to code. Can anyone in a simple way explain why I cant use the goto statement like this, to make the code start over again? Or, how this could have been done in the correct way? And also, why I get an error message on the use of "static".
**
"No such label "Start" within the scope of the goto statmenet"
"The modifier static is not valid for this item"
using System;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
Start:
Random numberGenerator = new Random();
int num1 = numberGenerator.Next(1,11);
int num2 = numberGenerator.Next(1, 4);
Console.WriteLine("What is " + num1 + " times " + num2 + "?");
int svar = Convert.ToInt32(Console.ReadLine());
if (svar == num1 * num2)
{
Console.WriteLine("well done!");
}
else
{
int responseIndex = numberGenerator.Next(1, 4);
switch (responseIndex)
{
case 1:
Console.WriteLine("Wrong, try again? [Y or N]");
AskUser();
break;
case 2:
Console.WriteLine("The answer was incorrect");
AskUser();
break;
default:
Console.WriteLine("You can do better than that");
AskUser();
break;
}
static void AskUser() {
string jaellernei = Console.ReadLine().ToUpper();
if (jaellernei == "Y")
{
goto Start;
} else
{
return;
} }
}
}
}
}
Firstly, your AskUser method is incorrectly nested inside the other method - move it out.
Secondly: goto is only valid within a single method; you can jump around a single stack frame - you cannot jump between stack frames.
Thirdly: the number of times you should be using goto... well, it isn't quite zero, but it asymptotically approaches zero.
Don't use goto unless you MUST to !
and As #Marc Gravell said, it's valid within a single method.
Alternatively : you can make a method of the code u used in the Main method, and then call it from both, main method and the other method where you used goto statement.
Like :
using System;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
someFunction();
}
static void someFunction()
{
Random numberGenerator = new Random();
int num1 = numberGenerator.Next(1, 11);
int num2 = numberGenerator.Next(1, 4);
Console.WriteLine("What is " + num1 + " times " + num2 + "?");
int svar = Convert.ToInt32(Console.ReadLine());
if (svar == num1 * num2)
{
Console.WriteLine("well done!");
}
else
{
int responseIndex = numberGenerator.Next(1, 4);
switch (responseIndex)
{
case 1:
Console.WriteLine("Wrong, try again? [Y or N]");
AskUser();
break;
case 2:
Console.WriteLine("The answer was incorrect");
AskUser();
break;
default:
Console.WriteLine("You can do better than that");
AskUser();
break;
}
}
}
static void AskUser()
{
string jaellernei = Console.ReadLine().ToUpper();
if (jaellernei == "Y")
{
someFunction();
}
else
{
return;
}
}
}
}
You could do it like this
public static Random randd = new Random();
public static void FlachCards()
{
Start:
if (AskAUser() == "Y")
{
goto Start;
}
}
public static String AskAUser()
{
Console.WriteLine("Enter Y to play again");
return Console.ReadLine();
}

Return to a specific block of code in my application

I am fairly new to C# and currently building a simple ATM app. I am attempting to write code to return the user to the main menu according to his/her entry of the letter M. The break, continue, goto or return keywords do not seem to work in my scenario; perhaps I used them incorrectly. The statement directly below is where I would like to jump to.
Console.WriteLine("Select an option? \n VIEW BALANCE (B1) checking, (B2) saving \n DEPOSIT (C1) checking, (C2) saving \n WITHDRAW (W1) checking, (W2) saving");
I would like to jump from the line JUMP (below) within the else if statement nested within the switch statement into the section of code above. How can I achieve this? any help is appreciated...thanks!
switch (response)
{
case "C1":
Console.WriteLine("How much would you like to deposit to your checking account?");
string depositEntry = Console.ReadLine();
double checkingBalance = Convert.ToInt32(depositEntry) + currentCheckingBalance;
currentCheckingBalance += checkingBalance;
Console.WriteLine("Your current checking balance is " + checkingBalance + "\n (X) Exit, (M) Main Menu" );
string selection = Console.ReadLine().ToUpper();
if (selection == "X")
{
return;
}
else if (selection == "M")
{
***JUMP***
}
else
{
Console.WriteLine("Your entry was invalid");
}
break;
case "C2":
break;
case "W1":
Using a jump statement usually indicates the flow of logic is jumbled. I try to avoid any kind of jumps if necessary. The code below prints out a main menu and if the user types “x” the program will quit. If the user selects one of the other options, a message is simply printed out indicating what the user selected. After the user presses any key, the console clears and the main menu is re-displayed.
In the main menu, if the user does not type one of the selections, then the selection is ignored, the console is cleared, and the menu is reprinted. No error is displayed indicating invalid selections.
This does not require the user to type “m” to go back to the main menu. After a selection is made for Deposit/withdraw/… after the method is finished the code will automatically return to the main menu.
I am guessing this may be what you are looking for. Hope this helps.
static void Main(string[] args) {
string userInput = "";
while ((userInput = GetMainSelection()) != "x") {
switch (userInput) {
case "c1":
Console.WriteLine("C1 Deposit Checking method");
break;
case "c2":
Console.WriteLine("C2 Deposit Savings method");
break;
case "b1":
Console.WriteLine("B1 View Balance Checking method");
break;
case "b2":
Console.WriteLine("B2 View Balance Savings method");
break;
case "w1":
Console.WriteLine("W1 Withdraw Checking method");
break;
case "w2":
Console.WriteLine("W2 withdraw Savings method");
break;
}
Console.WriteLine("Press Any Key to continue"); // <-- show what method was just used
Console.ReadKey();
Console.Clear();
}
Console.Write("Press any key to exit the program");
Console.ReadKey();
}
private static string GetMainSelection() {
string userInput = "";
while (true) {
Console.WriteLine("Select an option? \n VIEW BALANCE (B1) checking, (B2) saving \n DEPOSIT (C1) checking, (C2) saving \n WITHDRAW (W1) checking, (W2) saving. (X) to EXit");
userInput = Console.ReadLine().ToLower();
if (userInput == "b1" || userInput == "b2" || userInput == "c1" || userInput == "c2" || userInput == "w1" || userInput == "w2" || userInput == "x") {
return userInput;
}
else {
Console.Clear();
}
}
}
Put the JUMP code in a function and return.
public void MainMenu() {
// Show the main menu
}
public void Response(string response) {
switch (response)
{
case "C1":
Console.WriteLine("How much would you like to deposit to your checking account?");
string depositEntry = Console.ReadLine();
double checkingBalance = Convert.ToInt32(depositEntry) + currentCheckingBalance;
currentCheckingBalance += checkingBalance;
Console.WriteLine("Your current checking balance is " + checkingBalance + "\n (X) Exit, (M) Main Menu" );
string selection = Console.ReadLine().ToUpper();
if (selection == "X")
{
return;
}
else if (selection == "M")
{
***JUMP***
MainMenu();
return;
}
else
{
Console.WriteLine("Your entry was invalid");
}
break;
case "C2":
break;
case "W1":
}
}
Similar to the already given answer, I suggest breaking this out. Here's an example:
The Main method:
static void Main(string[] args) {
string input = null;
do {
input = Console.ReadLine();
ParseInput(input);
} while (input != "X");
}
ParseInput:
static void ParseInput(string input) {
switch (input) {
case "X": //from Main(), this will close the app
return;
case "M":
MainMenu();
break;
case "C1":
ShowAccount("C1"); //move your deposit/withdraw logic into a method and call with the selected account
return;
//other accounts
default:
break; //error message?
}
}
and MainMenu:
static void MainMenu() {
Console.WriteLine("Select an option? \n VIEW BALANCE (B1) checking, (B2) saving \n DEPOSIT (C1) checking, (C2) saving \n WITHDRAW (W1) checking, (W2) saving");
}
This should let you read the input in a loop and the ParseInput function can handle your individual cases. You may also want to call MainMenu() at the start, so it shows from the beginning.
It works like this:
Get input from the user
Pass the input to ParseInput() which decides where to go next.
Any functions hit in ParseInput() will execute, writing to the console or asking for further input
Once that function returns, while (input != "X") evaluates. If input != "X", goto 1, else exit.
I suggest you use goto C# reference.
static void Main()
{
int x = 200, y = 4;
int count = 0;
string[,] array = new string[x, y];
// Initialize the array:
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
array[i, j] = (++count).ToString();
// Read input:
Console.Write("Enter the number to search for: ");
// Input a string:
string myNumber = Console.ReadLine();
// Search:
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
if (array[i, j].Equals(myNumber))
{
goto Found;
}
}
}
Console.WriteLine("The number {0} was not found.", myNumber);
goto Finish;
Found:
Console.WriteLine("The number {0} is found.", myNumber);
Finish:
Console.WriteLine("End of search.");
// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
Output for the Input 44 would be:
Enter the number to search for: 44
The number 44 is found.
End of search.
See here for the MSDN reference.

How to transfer the control of goto statement in C#

I'm beginner in programming and I'm trying this simple program of getting user name and sorting it and so on.
class Program
{
static void Main(string[] args)
{
int number;
dynamic y;
string[] answer = new string[10];
cases:
Console.WriteLine("Enter the options given below 1.Add students\n 2.View all details\n 3.Sorting\n 4.Exit\n");
int input = Convert.ToInt16(Console.ReadLine());
switch (input)
{
case 1:
Console.WriteLine("Enter the Number of Students to be added to the List");
number = Convert.ToInt16(Console.ReadLine());
for (int i = 0; i < number; i++)
{
answer[i] = Console.ReadLine();
}
case 2:
foreach (var item in answer)
{
Console.WriteLine(item.ToString());
}
break;
case 3:
Array.Sort(answer);
foreach (var item in answer)
{
Console.WriteLine(item.ToString());
}
break;
case 4:
Console.WriteLine("Are you sure you want to exit");
Console.WriteLine("1 for Yes and N for No");
y = (char)Console.Read();
if ((y == 1))
{
goto cases;
}
else
{
goto thankyou;
}
thankyou:
Console.WriteLine("thank you");
break;
}
Console.WriteLine("Are you sure you want to exit");
Console.WriteLine("Y for Yes and 1 for No");
y = (char)Console.Read();
if ((y == 1))
{
goto cases;
}
else
{
goto thankyou;
}
}
}
My problem is that after every operation I have ask whether it should continue or not. I have added go-to statements but when pressed No its shows an exception for input variable that I have declared.
Can I use the go-to method or Is there any way we can do this ?
Any suggestions what is wrong here??
If you want a loop in your program you should use one of the loop constructs in C#. In this case a while loop would work:
bool keepPrompting = true;
while(keepPrompting) {
Console.WriteLine("Enter the options given below 1.Add students\n 2.View all details\n 3.Sorting\n 4.Exit\n");
int input = Convert.ToInt16(Console.ReadLine());
// The case statement on input goes here
Console.WriteLine("Are you sure you want to exit");
Console.WriteLine("Y for Yes and 1 for No");
var y = (char)Console.Read();
if (y != 'y')
keepPrompting = false;
}
Console.WriteLine("thank you");
goto is almost never used in C# (or any other language) for that matter because it's hard to follow a program that can jump around to almost any location while a loop has a defined flow.
You shouldn't do this with goto. You should always avoid goto entirely. If you think for some reason that you need to use goto, you should find a way to do it without goto. Here's an example of how to do this while avoiding goto.
class Program
{
static void Main(string[] args)
{
int number;
dynamic y;
string[] answer = new string[10];
bool result = false;
while(!result) {
Console.WriteLine("Enter the options given below 1.Add students\n 2.View all details\n 3.Sorting\n 4.Exit\n");
int input = Convert.ToInt16(Console.ReadLine());
switch (input)
{
case 1:
Console.WriteLine("Enter the Number of Students to be added to the List");
number = Convert.ToInt16(Console.ReadLine());
for (int i = 0; i < number; i++)
{
answer[i] = Console.ReadLine();
}
break;
case 2:
foreach (var item in answer)
{
Console.WriteLine(item.ToString());
}
break;
case 3:
Array.Sort(answer);
foreach (var item in answer)
{
Console.WriteLine(item.ToString());
}
break;
case 4:
Console.WriteLine("Are you sure you want to exit");
Console.WriteLine("1 for Yes and N for No");
result = ((char)Console.Read()) == 'y';
break;
}
}
Console.WriteLine("thank you");
}
}
}
static void Main(string[] args)
{
// First you need a few loops, avoid goto's at all costs they make code much harder to read
// There are better ways to do this but this will get it done
// List<string> answer = new List<string>(); would be better here because it resizes automatically when adding
// I left it like this because it looks like a school project
List<string> answer = new List<string>(); // create variable before loops so it is not recreated on each iteration
bool exit = false; // create bool variable and use it to exit infinite loop by setting it to true when user chooses option 4
for (;;) // create outer infinit loop to so the code will execute until you want you break; when option 4 is entered
{
int option;
for (;;)// create infinite loop to get user input for which option they want
{
Console.Clear();
Console.WriteLine("Enter the options given below\n1.Add students\n2.View all details\n3.Sorting\n4.Exit\n");
if (int.TryParse(Console.ReadLine(), out option) && option >= 1 && option <= 4)
{ break; /*user entered valid option so we break from this infinit loop*/ }
else
{ Console.Clear(); /*User did not enter a valid option so clear the console window*/ }
}
switch (option) // switch cases to handle each of the possible options entered
{
case 1:
// user chose option 1
int number = 0;
while (number <= 0)
{
Console.Clear();
Console.WriteLine("Enter the number of students to add.");
int.TryParse(Console.ReadLine(), out number);
// Because "answer" is now a list it does not have to be sized
for(int i=0;i<number;i++)
{
Console.Clear();
Console.WriteLine("Enter Name: ");
// with a list, the previous list of students are not wiped out
// we also don't have to be carefull about writing outside array bounds because of the add method
answer.Add(Console.ReadLine());
}
}
break; // break out of case 1
case 2:
// user chose option 2
break;// break out of case 2
case 3:
// user chose option 3
if (answer.Count > 0)
{
Console.Clear();
Console.WriteLine("Sorted student names:");
answer.Sort(); // List<string> have a Sort member method
Console.WriteLine(string.Join("\n", answer));
}
else
{ Console.WriteLine("No students exist to sort or list."); }
Console.ReadLine(); // pause screen for reading
break;// break out of case 3
case 4:
// user chose option 4
while (true) // loop until a Y or 1 is entered
{
Console.WriteLine("Are you sure you want to exit\nY for YES and 1 for NO");
char y = (char)Console.Read();
if (y == 'Y' || y == 'y')
{ exit = true; break; /*user is sure they want to exit*/ }
else if (y == '1')
{ Console.Clear(); break; /*user decided not to exit*/ }
else
{ Console.Clear(); }
}
break; // break out of case 4
}
if (exit) break; // if exit variable true then break out of outer infinite loop
}
}
static void Main(string[] args)
{
// First you need a few loops, avoid goto's at all costs they make code much harder to read
// There are better ways to do this but this will get it done
// List<string> answer = new List<string>(); would be better here because it resizes automatically when adding
// I left it like this because it looks like a school project
string[] answer = new string[0]; // create variable before loops so it is not recreated on each iteration
bool exit = false; // create bool variable and use it to exit infinite loop by setting it to true when user chooses option 4
for (;;) // create outer infinit loop to so the code will execute until you want you break; when option 4 is entered
{
int option;
for (;;)// create infinite loop to get user input for which option they want
{
Console.Clear();
Console.WriteLine("Enter the options given below\n1.Add students\n2.View all details\n3.Sorting\n4.Exit\n");
if (int.TryParse(Console.ReadLine(), out option) && option >= 1 && option <= 4)
{ break; /*user entered valid option so we break from this infinit loop*/ }
else
{ Console.Clear(); /*User did not enter a valid option so clear the console window*/ }
}
switch (option) // switch cases to handle each of the possible options entered
{
case 1:
// user chose option 1
int number = 0;
while (number <= 0)
{
Console.Clear();
Console.WriteLine("Enter the number of students to add.");
int.TryParse(Console.ReadLine(), out number);
answer = new string[number]; // re-initize number of students to add
for(int i=0;i<number;i++)
{
Console.Clear();
Console.WriteLine("Enter Name: ");
answer[i] = Console.ReadLine();
}
}
break; // break out of case 1
case 2:
// user chose option 2
break;// break out of case 2
case 3:
// user chose option 3
if (answer.Length > 0)
{
Console.Clear();
Console.WriteLine("Sorted student names:");
Array.Sort(answer);
Console.WriteLine(string.Join("\n", answer));
Console.ReadLine(); // pause screen for reading
}
break;// break out of case 3
case 4:
// user chose option 4
while (true) // loop until a Y or 1 is entered
{
Console.WriteLine("Are you sure you want to exit\nY for YES and 1 for NO");
char y = (char)Console.Read();
if (y == 'Y' || y == 'y')
{ exit = true; break; /*user is sure they want to exit*/ }
else if (y == '1')
{ Console.Clear(); break; /*user decided not to exit*/ }
else
{ Console.Clear(); }
}
break; // break out of case 4
}
if (exit) break; // if exit variable true then break out of outer infinite loop
}
}

First C# program with two Classes. Confused

pretty new to programming and I'm a bit stuck. This is the first program I've written with two classes (in two seperate class files). I'll include all the code below. It's a program to play a dice game called Craps. My task is too create a method in the CrapsGame class that allows me to play the game over and over again until I decide to stop. But I'm having a little trouble working out how to correctly call the manyPlay() method. I'm not really sure what I'm doing. The program will play the game once by calling myCraps.play() but then won't go any further. If anyone else notices anything wrong with the code or anything that's bad practice then please point it out as I am very keen to learn. Thanks to anyone that takes the time to answer.
using System;
namespace Task4_7
{
public class CrapsGame
{
string replay;
private Craps myCraps;
private CrapsGame newGame;
public static void Main()
{
CrapsGame newGame = new CrapsGame();
Craps myCraps = new Craps ();
myCraps.play ();
newGame.manyPlay ();
}
public void manyPlay() {
string input; // declare local variable
do {
myCraps.play();
replay:
Console.Write("Would you like to play again? y/n");
input = Console.ReadLine();
if (input == "y") {
replay = input;
}
else if (input == "n") {
replay = "n";
}
else {
Console.WriteLine("\n Erroneous input. Please enter y (yes) or n (no)");
goto replay;
}
}
while(replay != "n");
}
}
}
using System;
namespace Task4_7
{
public class Craps
{
private Random randy; // define randy as a Random class
public Craps() {
this.randy = new Random ();
}
public int oneThrow() {
return randy.Next(6) + 1; // pick a number from 1 to 6 and return this
}
public int throw2Dice() {
int a, b, c;
a = oneThrow ();
b = oneThrow ();
c = a + b;
Console.WriteLine ("You threw a " + a + " and a " + b + " making " + c);
return c;
}
public void play() {
int result = throw2Dice ();
switch (result) {
case 2:
Console.WriteLine ("You lose! End of game!");
break;
case 3:
Console.WriteLine ("You lose! End of game!");
break;
case 12:
Console.WriteLine ("You lose! End of game!");
break;
case 7:
Console.WriteLine ("You win! End of game!");
break;
case 11:
Console.WriteLine ("You win! End of game!");
break;
case 4:
Console.WriteLine ("Your point! Rolling again!");
throwPoint (result);
break;
case 5:
Console.WriteLine ("Your point! Rolling again!");
throwPoint (result);
break;
case 6:
Console.WriteLine ("Your point! Rolling again!");
throwPoint (result);
break;
case 8:
Console.WriteLine ("Your point! Rolling again!");
throwPoint (result);
break;
case 9:
Console.WriteLine ("Your point! Rolling again!");
throwPoint (result);
break;
default:
Console.WriteLine ("Your point! Rolling again!");
throwPoint (result);
break;
}
}
public void throwPoint(int result) {
Throw:
int a = throw2Dice();
if (a == result) {
Console.WriteLine ("You rolled the same score! You win!");
} else if (a == 7) {
Console.WriteLine ("You rolled a 7! You loose!");
} else {
Console.WriteLine ("You rolled a " + a + ". Rolling again!");
goto Throw;
}
}
}
}
This is your problem:
Craps myCraps = new Craps();
You are hiding variable of class CrapsGame with a local variable of Main method. Simply change it to
myCraps = new Craps();
and it should work.
EDIT
and change myCraps declaration to static, of course.
EDIT2
Scope of variables: C# variable scoping not consistent?
My first suggestion is put your Main method in a seperate file.For example you can use three files: Program.cs, CrapsGame.cs, Craps.cs. To do this just add a new class file,and move your main method to new Class file. Second, never use goto.Instead use while loop like this,
public void throwPoint(int result) {
while(true)
{
int a = throw2Dice();
if (a == result) {
Console.WriteLine ("You rolled the same score! You win!");
break;
} else if (a == 7) {
Console.WriteLine ("You rolled a 7! You loose!");
break;
} else {
Console.WriteLine ("You rolled a " + a + ". Rolling again!");
}
}
}
Many play method:
public void manyPlay() {
string input; // declare local variable
myCraps.play();
while(true) {
Console.Write("Would you like to play again? y/n");
input = Console.ReadLine();
if (input == "y") {
myCraps.play();
}
else if (input == "n") {
break;
}
else {
Console.WriteLine("\n Erroneous input. Please enter y (yes) or n (no)");
}
}
}
The problem looks like you where creating a game for use by the game iterator, but it needs to create a game for each iteration. So I delete some code: all the class variables have to go, variables should be as local as possible.
using System;
namespace Task4_7
{
public class CrapsGame
{
public static void Main()
{
new Craps ().play ();
new CrapsGame().manyPlay ();
}
public void manyPlay() {
string replay;
string input; // declare local variable
do {
new Craps().play();
replay:
Console.Write("Would you like to play again? y/n");
input = Console.ReadLine();
if (input == "y") {
replay = input;
}
else if (input == "n") {
replay = "n";
}
else {
Console.WriteLine("\n Erroneous input. Please enter y (yes) or n (no)");
goto replay;
}
}
while(replay != "n");
}
}
}
Now fix that loop: no gotos. You need a loop in a loop, as you have but don't build your own loops.
Then if Craps.play() returned a score. You could add a class variable to accumulate the score.
Change replay to boolean and make set it to true if input is y and false if input is n.
Then change your main method.
public static void Main()
{
CrapsGame newGame = new CrapsGame();
Craps myCraps = new Craps ();
while (replay == true) {
myCraps.play ();
newGame.manyPlay ();
}
}

New to C#, not all code paths return a value, Bottle counting program, switch statement

Hello I've reached a stump that I cannot pull out.
My program records the number of bottles collected by four rooms. The program should prompt me to enter a room number and then how many bottles that room has collected. When ever the user types in "quit" the program will spit out the bottles collected by each room and calculate the room with the most bottles collected. I should be able to add bottles to each room as long as I haven't typed in quit.
I cannot get my GetRoom (int room) working, that is the method that does not return a value.
How would I find the room with the most bottles collected? Math.Max?
I cannot use LINQ or arrays. Its part of the assignment rules.
Heres is my code:
namespace BottleDrive1
{
class Program
{//Initialize 4 rooms.
int room1 = 0;
int room2 = 0;
int room3 = 0;
int room4 = 0;
static void Main(string[] args)
{
//Start of while loop to ask what room your adding into.
while (true)
{
Console.Write("Enter the room you're in: ");
//If user enters quit at anytime, the code will jump out of while statement and enter for loop below
string quit = Console.ReadLine();
if (quit == "quit")
//Break statement allows quit to jump out of loop
break;
}
}
private void SetRoom(int room, int value)
{
switch (room)
{
case 1:
room1 = value;
break;
case 2:
room2 = value;
break;
case 3:
room3 = value;
break;
case 4:
room4 = value;
break;
}
}
public void GetRoom(int room)
{
int count = int.Parse(Console.ReadLine());
switch (room)
{
case 1:
room1 += count;
break;
case 2:
room2 += count;
break;
case 3:
room3 += count;
break;
case 4:
room4 += count;
break;
default:
throw new ArgumentException();
}
}
}
}
You need to make sure your function returns something. Have you tried compiling this code? It has a compile error that would fix your method.
And Math.Max is a good way to find the max.
The problem is that your GetRoom method is defined to return an int and hence it must do so on every code path. This particular example doesn't return a value on any path.
Based on the logic within the GetRoom method though it seems like you're modifying rooms instead of returning one. If that's the case simply switch the method to return void
public void GetRoom() {
...
}
The GetRoom method does not return a value. Either provide a default value in a switch statement or and a return statement after that. Also, you can raise an exception in these cases.
Example:
public int GetRoom(int room)
{
int count = int.Parse(Console.ReadLine());
switch (room)
{
case 1:
room1 += count;
break;
case 2:
room2 += count;
break;
case 3:
room3 += count;
break;
case 4:
room4 += count;
break;
default:
throw new ArgumentException(); //either this
}
throw new ArgumentException(); //or this
}
BTW, you can use an array of 4 elements instead of 4 different variables, that will simplify your existing code and save you some time writing new. For example, GetRoom will look like this:
public int GetRoom(int room)
{
int count = int.Parse(Console.ReadLine());
rooms[room] += count;
//return what you need to return here
}
Here's an example that uses a Class to hold the information for each room. The reason for using a class is so that if your program needs to change in the future to collect more information, you won't have to track yet another array, you can just add properties to the class.
The individual rooms are now held in a list instead of an array just to show a different construct.
Here is the new Room class:
public class Room
{
public int Number { get; set; }
public int BottleCount { get; set; }
public Room(int wNumber)
{
Number = wNumber;
}
}
And here is the new version of the program. Note that additional checking of the values entered by the end user has been added in order to prevent exceptions when trying to get the current room or parse to an int the value entered by the user:
static void Main(string[] args)
{
const int MAX_ROOMS = 4;
var cRooms = new System.Collections.Generic.List<Room>();
for (int nI = 0; nI < MAX_ROOMS; nI++)
{
// The room number is 1 to 4
cRooms.Add(new Room(nI + 1));
}
// Initializes the room that wins
//Start of while loop to ask what room your adding into.
while (true)
{
Console.Write("Enter the room you're in: ");
//If user enters quit at anytime, the code will jump out of while statement and enter for loop below
string roomNumber = Console.ReadLine();
if (roomNumber == "quit")
{
//Break statement allows quit to jump out of loop
break;
}
int room = 0;
if (int.TryParse(roomNumber, out room) && (room < MAX_ROOMS) && (room >= 0)) {
Room currentRoom;
currentRoom = cRooms[room];
Console.Write("Bottles collected in room {0}: ", currentRoom.Number);
int wBottleCount = 0;
if (int.TryParse(Console.ReadLine(), out wBottleCount) && (wBottleCount >= 0))
{
// This line adds the count of bottles and records it so you can continuously count the bottles collected.
currentRoom.BottleCount += wBottleCount;
}
else
{
Console.WriteLine("Invalid bottle count; value must be greater than 0");
}
}
else
{
Console.WriteLine("Invalid room number; value must be between 1 and " + MAX_ROOMS.ToString());
}
}
Room maxRoom = null;
foreach (Room currentRoom in cRooms) //This loop goes through the array of rooms (4)
{
// This assumes that the bottle count can never be decreased in a room
if ((maxRoom == null) || (maxRoom.BottleCount < currentRoom.BottleCount))
{
maxRoom = currentRoom;
}
Console.WriteLine("Bottles collected in room {0} = {1}", currentRoom.Number, currentRoom.BottleCount);
}
//Outputs winner
Console.WriteLine("And the Winner is room " + maxRoom.Number + "!!!");
}
You are not returning anything from your function at all. Try something like this, store your result in a temporary variable then when you exit the function return it.
public int GetRoom(int room)
{
int count = int.Parse(Console.ReadLine());
int temp = 0;
switch (room)
{
case 1:
room1 += count;
temp = room1;
break;
case 2:
room2 += count;
temp = room2;
break;
case 3:
room3 += count;
temp = room3;
break;
case 4:
room4 += count;
temp = room4;
break;
default:
throw new ArgumentException();
}
return temp;
}

Categories