-6
public void machine()
{
    Random RandomClass = new Random();

    int a = RandomClass.Next(1,9);
    if(a==1)
    { 
        if (pictureBox1.Image == img0) { pictureBox1.Image = img2; }
    else 
    { 
        machine(); 
    }
}

erreur : Une exception non gérée du type 'System.StackOverflowException' s'est produite dans WindowsFormsApplication2xo.exe

Matt Burland
  • 44,552
  • 18
  • 99
  • 171
  • 4
    can you please translate the error into English? – DrewJordan Jan 20 '16 at 17:15
  • 3
    This is recursion. Not looping. Also, I guess your variable `a` is never 1. Try moving the creation of `Random` outside of the method. – Steve Jan 20 '16 at 17:16
  • 4
    @DrewJordan: It's a `StackOverflowException`, there's not actually much more you need from that. – Matt Burland Jan 20 '16 at 17:16
  • @MattBurland yeah, I just realized that... I asked for the translation when I saw the first two words before reading the whole thing. – DrewJordan Jan 20 '16 at 17:17
  • 2
    You're getting a stack overflow error because the function will call itself infinitely until random number is 1. – joordan831 Jan 20 '16 at 17:17
  • 6
    What are you trying to *achieve* here? Why bother taking the random number if you're only going to proceed when the value is 1? – Jon Skeet Jan 20 '16 at 17:18
  • Does it always give you a `StackOverflowException`? Or only sometimes? – Matt Burland Jan 20 '16 at 17:20
  • thank you sir , but i have to randomise the number again and again – Mohammed Chab Jan 20 '16 at 17:20
  • @MohammedChab who are you even replying to? – user1666620 Jan 20 '16 at 17:21
  • @MohammedChab You should declare `Random` only one time outside of your function. – user1274820 Jan 20 '16 at 17:22
  • i want to create tic tao game "XO" if the block of picture is changer by user the pc will select another picture box – Mohammed Chab Jan 20 '16 at 17:23
  • Do not keep creating `Random` over and over again as you are here. Initialize it _ONCE_, and use `Random.Next(1,9)` over and over. – user1274820 Jan 20 '16 at 17:23
  • there is other condition : if (a==2) .. if(a==9) .. : 9 box – Mohammed Chab Jan 20 '16 at 17:25
  • @MohammedChab recursion is not appropriate for looping, every time you call the "machine" method you add one item to the call stack, and this stack has a limit, eventually you are getting a StackOverflow – PhilHdt Jan 20 '16 at 17:25
  • Isn't this likely just a duplicate of http://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number ? – Lasse V. Karlsen Jan 20 '16 at 17:26
  • *there is other condition*, then handle those depending on the value of `a` in block. No need to recurse or loop at all. (also, `a==9` will never be true) – Matt Burland Jan 20 '16 at 17:27
  • 1
    thank you user1274820 Do not keep creating Random over and over again as you are here. Initialize it ONCE, and use Random.Next(1,9) over and over. – user1274820 1 min ago – Mohammed Chab Jan 20 '16 at 17:28
  • 1
    @MohammedChab if you are going to handle all of the possible cases (`a == 1`, `a == 2`, ... `a == 8` (!) then you don't need the loop at all. So you could have saved everyone a lot of time by making that more clear in the first place :) – CompuChip Jan 20 '16 at 17:39
  • Please note that because the calls are made in quick succession, then there is a good chance that random numbers will be sequences of identical numbers. The seed for `Random` is time based, and the quick succession of initializations will result in identical seeds being used. That is the reason why people are telling you to initialize `RandomClass` only once. – Nathan C Jan 20 '16 at 19:05

4 Answers4

2

Righ now, the probability that your loop exits is only about 10% -- it only happens when the random number between 1 and 9 is exactly 1. In all other cases, you call the function again. If this happens to often, you get the StackOverflowException. Sometimes you will be lucky and the recursion will end before that.

The obvious solution is to remove the recursion. This solves another problem with your code: every time you enter the function, you create a new random number generator. Ideally, you should create and seed it once, and call Next on that single instance every time you need a new random number.

Also, your names are slightly strange to a C# programmer's eye. Usually we name local variables with lower case and functions with upper case:

public void Machine()
{
    Random randomNumberGenerator = new Random();

    int a;
    while(true)
    { 
        a = randomNumberGenerator.Next(1,9);
        if(a == 1)
        {
          if (pictureBox1.Image == img0) { pictureBox1.Image = img2; }
          break;
        }
    }
}

Finally, this loop is not very useful. I am guessing you probably meant to extend the body to handle more numbers, in which case I would suggest a switch instead of this weird nested if-construction.

CompuChip
  • 9,143
  • 4
  • 24
  • 48
  • Removing the recursion is definitely the better approach, but it should still exit once a `1` is rolled. You've removed the condition on `a` altogether and now have an infinite loop. – Matt Burland Jan 20 '16 at 17:26
  • Already noticed and edited. My fault for posting too soon, you guys are quick with the downvotes :) – CompuChip Jan 20 '16 at 17:28
  • problem fixed , thank you every one :)))) – Mohammed Chab Jan 20 '16 at 17:31
  • @MohammedChab it is still not clear to me what you _want_ the code to do though - do you intend to expand the number of cases (`else if(a == 2) ... else if(a == 3) ...`)? Or do you just want to check for 1? Because I just fixed the immediate problem with your code, but in both cases I mentioned there are cleaner ways to code it. – CompuChip Jan 20 '16 at 17:33
1

Since I haven't seen the right answer:

class Program
{
    private static Random rand = new Random();
    static void Main(string[] args)
    {
        machine();
    }
    private static void machine()
    {
        if (rand.Next(1, 9) == 1)
            Console.WriteLine("We did it!");
        else
            machine();
    }
}

Here you can specify a maximum depth so you don't overflow the stack.

Note: You shouldn't need to do this if you initialize your random properly.

private static void machine(int depth)
{
    if (rand.Next(1, 9) == 1 || depth > 1000)
        Console.WriteLine("We did it!");
    else
        machine(++depth);
}
user1274820
  • 7,786
  • 3
  • 37
  • 74
  • Any recursive call will "potentially" overflow a stack. I ran this 1000 times with no issues. – user1274820 Jan 20 '16 at 17:31
  • If you wanted to, you could pass a "depth" to it and leave after a certain depth. – user1274820 Jan 20 '16 at 17:32
  • If you want to keep the function recursive, this is the best way to do it. – user1274820 Jan 20 '16 at 17:35
  • 1
    You are right, did a quick calculation and if you draw the random number _properly_ its expected depth is 8 calls which should not cause a stack overflow, so in that sense my "potentially still overflows the stack" is not really relevant anymore. – CompuChip Jan 20 '16 at 17:37
1

Since you indicate in the comments, that you want to handle all the possible outcomes, you should not be using any kind of recursion or loop at all.

Then the only issue to fix, as pointed out at length, is that you have to re-use the random number generator.

Also note that the upper bound of Random.Next is exclusive:

The exclusive upper bound of the random number returned. Source

So all you need is something like

private Random randomNumberGenerator = new Random();
public void machine()
{
    int boxNumber = RandomClass.Next(1, 9);
    switch(boxNumber)
    { 
        case 1:
            if (pictureBox1.Image == img0) { pictureBox1.Image = img2; }
            // ...
            break;

        case 2:
            if (pictureBox1.Image == img0) { pictureBox1.Image = img2; }
            // ...
            break;

        // ...

        case 8: // a will be at most 8
          // ...
          break;
   }
}
CompuChip
  • 9,143
  • 4
  • 24
  • 48
  • I think you have solved the puzzle of what OP is *actually* trying to do at the end of the day instead of recursively looping through randoms looking for a single condition. – user1274820 Jan 20 '16 at 17:44
0

First off, you have a parentheses mismatch. Are you trying to do:

public void machine()
{
    Random RandomClass = new Random();

    int a = RandomClass.Next(1,9);
    if(a==1)
    { 
        if (pictureBox1.Image == img0) { 
            pictureBox1.Image = img2; 
        }
    }
    else 
    { 
        machine(); 
    }
}

or this:

public void machine()
{
    Random RandomClass = new Random();

    int a = RandomClass.Next(1,9);
    if(a==1)
    { 
        if (pictureBox1.Image == img0) { 
           pictureBox1.Image = img2; 
        }
        else 
        { 
            machine(); 
        }
    }
}

As stated by many users, you don't need to keep creating a new Random object. In fact, you will be much better off with a loop than with recursion in this instance.

Here is an example:

public void machine()
    {
        Random RandomClass = new Random();
        // Not sure what the point of the random is but whatevs
        int a = RandomClass.Next(1,9);
        for (; a != 1; a = RandomClass.Next(1,9));
        if (pictureBox1.Image == img0) { 
            pictureBox1.Image = img2; 
        }
    }

Note: While highly unlikely, there is no guarantee that this function will ever end. However, using a loop rather than recursion will simply cause your computer to respond a little worse and the fan to go nuts rather than throw a Stack Overflow exception.

Hope this helps and good luck!

ohiodoug
  • 1,493
  • 1
  • 9
  • 12