views:

261

answers:

4

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
+4  A: 

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...
}
Scott Stafford
Well the error occurs as soon as I Debug, But I looked at the stack trace and it happens on testClass newTest = new testClass(); in the form1 code and public testClass() in the testclass code. If I remove newTest = new testClass(); the same problem will occur with the next line gameClass newGame = new gameClass();:/
Samantha Silva
A: 
  1. 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
  2. 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)
  3. 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

JonH
uppon removing the inheritance it no longer accepts me using parts of the form on the class like the comboboxes and some text boxes
Samantha Silva
@Samantha the : Form1 needs to be removed from both of your class modules the test class and the game class.
JonH
@JonH: While getting rid of Form1 does solve the problem, it -is- a recursive issue - just not a typical one.
Tanzelax
@Tanzelax - -1 to you for negating me for no reason. The issue I was describing was stating from the original poster in that there is no looping to cause a recursive issue. Then negating me on it was pretty bad of you.
JonH
@JonH: I didn't -1 you, I just pointed out that it was a recursive issue because you mentioned that you "eliminated... it being a recursive issue"
Tanzelax
A: 

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.

Tanzelax
I think you might be right, I need to edit my combobox and textboxes because as its not inheriting it no longer accepts them in the class, so I'll have to edit that before I can see if it works or not
Samantha Silva
@Samantha Silva, that is precisely what I answered 13 minutes ago...
JonH
@JonH: and what I answered 47 minutes ago (which if I'm doing the relative-time math right, is 7 minutes before you. :)
Scott Stafford
@JonH and @Scott Stafford: Neither of you mentioned why the stack overflow was happening, just the fix.
Tanzelax
-1 @ Tanzelax, negating me was pretty low of you considering you took my answer.
JonH
I didn't -1 you, just commented. I didn't -1 anyone except the -- guy in this thread, because you did provide the correct answers...
Tanzelax
@Tanzelax: True enough, +1. ;)
Scott Stafford
+1  A: 

Not related to your StackOverflow exception but some general notes on improving your code:

  1. Why all the SelectedIndex if-statements, how about using SelectedValue?
  2. Try to use the else if statement. If SelIndex == 0, it's useless to check for SelIndex == 1
  3. Can I suggest classes and properties to start in uppercase?
  4. Try to isolate repetitive code (place it into a separate method or ..)
  5. Use (variable) and (!variable) instead of (variable == true) or (variable == false) for regular booleans
  6. 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.

Zyphrax
Thank you for your advice, I will definitely take it into conideration, I'm new with C#.
Samantha Silva
@Samantha: your code won't compiled because you are referring to Form controls from another class. Sorry we can't help you make the whole application ;)
Zyphrax