Issue with number guessing game c#
I keep getting a stackOverflow error (no pun intended):" An unhandled exception of type 'System.StackOverflowException' occurred in NumberGuessingGame.exe "
I'm guessing it would help if you saw my code and alswo where its ocurring:
Source - testClass:
namespace NumberGuessingGame_08029490
{
public class testClass : Form1
{
public bool _gameWon;
public bool _gameRunning;
public int _number;
public int _guessesRemaining;
public int guessesRemaining
{
get { return _guessesRemaining; }
}
public bool gameEnded
{
get { return !_gameRunning; }
}
public bool gameWon
{
get { return _gameWon; }
}
public testClass()
{
_gameRunning = false;
_gameWon = false;
}
public void saveNewTestGame(int numberGuesses)
{
if (numberGuessesComboBox.SelectedIndex == 0)
{
numberGuesses = 1;
}
if (numberGuessesComboBox.SelectedIndex == 1)
{
numberGuesses = 3;
}
if (numberGuessesComboBox.SelectedIndex == 2)
{
numberGuesses = 5;
}
_guessesRemaining = numberGuesses;
_gameRunning = true;
}
public bool makeGuess(int guessNumber)
{
if (_gameRunning)
{
_guessesRemaining--;
if (_guessesRemaining <= 0)
{
_gameWon = false;
_gameRunning = false;
return false;
}
if (guessNumber == _number)
{
_gameWon = true;
return true;
}
if (guessNumber > _number)
{
guessResultTextBox.Text = "Your Guess is too high, try again";
_gameWon = false;
return false;
}
if (guessNumber < _number)
{
guessResultTextBox.Text = "Your Guess is too low, try again";
_gameWon = false;
return false;
}
else
{
return false;
}
}
else
{
throw new Exception("The game is not running. Call newGame() before making a guess.");
}
}
}
}
Source - gameClass:
namespace NumberGuessingGame_08029490
{
public class gameClass : Form1
{
public bool _gameWon;
public bool _gameRunning;
public static Random randomNum = new Random();
public int _number;
public int _guessesRemaining;
public int guessesRemaining
{
get { return _guessesRemaining; }
}
public bool gameEnded
{
get { return !_gameRunning; }
}
public bool gameWon
{
get { return _gameWon; }
}
public gameClass()
{
_gameRunning = false;
_gameWon = false;
}
public void saveNewGame(int numberGuesses)
{
if (numberGuessesComboBox.SelectedIndex == 0)
{
numberGuesses = 1;
}
if (numberGuessesComboBox.SelectedIndex == 1)
{
numberGuesses = 3;
}
if (numberGuessesComboBox.SelectedIndex == 2)
{
numberGuesses = 5;
}
if (rangeNumbersComboBox.SelectedIndex == 0)
{
int randomNumFive = randomNum.Next(1, 5);
randomNumFive = _number;
}
if (rangeNumbersComboBox.SelectedIndex == 1)
{
int randomNumTen = randomNum.Next(1, 10);
randomNumTen = _number;
}
if (rangeNumbersComboBox.SelectedIndex == 2)
{
int randomNumTwenty = randomNum.Next(1, 20);
randomNumTwenty = _number;
}
_guessesRemaining = numberGuesses;
_gameRunning = true;
}
public bool makeGuess(int guessNumber)
{
if (_gameRunning)
{
_guessesRemaining--;
if (_guessesRemaining <= 0)
{
_gameWon = false;
_gameRunning = false;
return false;
}
if (guessNumber == _number)
{
_gameWon = true;
return true;
}
if (guessNumber > _number)
{
guessResultTextBox.Text = "Your Guess is too high, try again";
_gameWon = false;
return false;
}
if (guessNumber < _number)
{
guessResultTextBox.Text = "Your Guess is too low, try again";
_gameWon = false;
return false;
}
else
{
return false;
}
}
else
{
throw new Exception("The game is not running. Call newGame() before making a guess.");
}
}
}
}
Source - form1:
namespace NumberGuessingGame_08029490
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
testClass newTest = new testClass();
gameClass newGame = new gameClass();
private void saveButton_Click(object sender, EventArgs e)
{
if (testCheckBox.Checked == true)
{
int numberGuesses = Convert.ToInt32(numberGuessesComboBox.SelectedIndex);
int _number = Convert.ToInt32(testNumberTextBox.Text);
newTest.saveNewTestGame(numberGuesses);
}
if (testCheckBox.Checked == false)
{
int numberGuesses = Convert.ToInt32(numberGuessesComboBox.SelectedIndex);
int _number = Convert.ToInt32(rangeNumbersComboBox.SelectedIndex);
newGame.saveNewGame(numberGuesses);
}
}
private void guessButton_Click(object sender, EventArgs e)
{
if (testCheckBox.Checked == true)
{
int guessNumber = Convert.ToInt32(guessNumberTextBox.Text);
bool correctAnswer = newTest.makeGuess(guessNumber);
if (correctAnswer)
开发者_开发百科 {
MessageBox.Show("Weldone, you Won!!");
}
// if (game.GameEnded)
// {
// disable guess button, show loss label
// }
}
if (testCheckBox.Checked == false)
{
int guessNumber = Convert.ToInt32(guessNumberTextBox.Text);
bool correctAnswer = newGame.makeGuess(guessNumber);
if (correctAnswer)
{
MessageBox.Show("Weldone, you Won!!");
}
// if (game.GameEnded)
// {
// disable guess button, show loss label
// }
}
}
}
}
EDIT: No more StackOverflowException, code errors:
Thank you everyone for your help <3
Having removed the "Form 1" from the top It seems to have solved the issue for now, but now that the combobox, textbox variables are no longer inheriting I cant use them in the code, so I can't test to see if the solution has worked, any ideas as to how they could be used?
Error 1 The name 'numberGuessesComboBox' does not exist in the current context E:\Projects\NumberGuessingGame\NumberGuessingGame\testClass.cs 46 17 NumberGuessingGame
Error 7 The name 'rangeNumbersComboBox' does not exist in the current context E:\Projects\NumberGuessingGame_08029490\NumberGuessingGame_08029490\gameClass.cs 58 17 NumberGuessingGame_08029490
Error 10 The name 'guessResultTextBox' does not exist in the current context E:\Projects\NumberGuessingGame_08029490\NumberGuessingGame_08029490\testClass.cs 84 21 NumberGuessingGame_08029490
Stack overflow is almost always because you're recursing infinitely. In other words, a function calls itself with no break in that cycle, so it calls a zillion times until the stack overflows. Sometimes function A calls function B which calls A, but the effect is the same. Search your code for that loop, or look at the stack trace the debugger provides and see what the loop is.
EDIT: I scanned through the code you posted but I don't see it. What action do you take to get the error? Is it as soon as you click a button, or upon loading the program, or what?
EDIT2: It's probably incorrect and probably related that you inherited your utility classes from Form1:
public class testClass : Form1
should almost definitely just be
public class testClass
EDIT3 (answering new question edited into original post): To test Form1, your class testClass can have a member variable of type Form1 and do its testing via public methods and properties of Form1. Form1 can even create the testClass instance (though this is considered sloppy) and pass itself to the constructor of testClass:
// Inside Form1()
private TestClass m_testClass;
Form1()
{
m_testClass = new testClass(this);
....
}
// Inside testClass
private Form1 m_testForm;
testClass(Form1 formToTest)
{
m_testForm = formToTest;
}
void DoTest()
{
// use m_testForm here...
}
Not related to your StackOverflow exception but some general notes on improving your code:
- Why all the SelectedIndex if-statements, how about using SelectedValue?
- Try to use the else if statement. If SelIndex == 0, it's useless to check for SelIndex == 1
- Can I suggest classes and properties to start in uppercase?
- Try to isolate repetitive code (place it into a separate method or ..)
- Use (variable) and (!variable) instead of (variable == true) or (variable == false) for regular booleans
- Booleans are already initialized with false
EDIT: The Form1 inheritance is causing an endless loop (and therefor the StackOverflowException
The Form1 class has two fields: testClass and gameClass.
However testClass and gameClass ARE both inheriting Form1.
So every testClass has two fields: testClass and gameClass.
And every gameClass has two fields: testClass and gameClass.
See the loop in that?
I'm sorry to say, but please read some of the C# principles and Object Oriented programming, because this looks a bit like you've got no clue what your doing. I don't say this to demotivate you, but it's way easier and more fun, when you understand the concepts behind the code.
- There are no loops in your code, so I've eliminated the fact that it is being a recursive issue or an issue where you are looping over and over with no end
- I thought you were missing code as I did not see a main but then realized this is a form application (so ignore the comment at the top)
Why are you declaring a class and then inheriting the form to that class ? In addition:
public class testClass : Form1
Since its just a class get rid of the : Form1
You have infinite recursion in the constructors.
Get rid of the : Form1
from your testClass
and gameClass
.
As it is, because they inherit from Form1 each of them are instantiating their own copies of another testClass+gameClass due to the lines:
testClass newTest = new testClass();
gameClass newGame = new gameClass();
Edit: Just to be clear what's happening here: testClass and gameClass, by inheriting from Form1, also inherit all the the member variables, including the members newText and newGame. From the msdn article on C# fields: "A field can be given an initial value by using the assignment operator when the field is declared...Fields are initialized immediately before the constructor for the object instance is called."
So, when a new Form1 is initially instantiated, it first tries to assign initial values to its newTest and newGame members.
In creating that new testClass, before the testClass even gets to its constructor, it will try to provide the initial values to its own newTest and newGame members.
Repeat ad nauseum and voila! Stack Overflow.
精彩评论