8 Replies - 339 Views - Last Post: 02 September 2012 - 05:30 AM Rate Topic: -----

#1 pharylon  Icon User is offline

  • D.I.C Head

Reputation: 39
  • View blog
  • Posts: 80
  • Joined: 01-September 12

Variable Values Not Clearing Even Between Functions?

Posted 01 September 2012 - 02:52 PM

I'm still learning to program. This is the first practical application I've tried to write outside of copying from my textbook. I thought it'd be something easy and within my ability, but it's turning out not so much.

I'ts a simple command line "dice roller" where two people roll 2 six sided dice each and compare the result (with some wrinkles, but those haven't been programmed in yet).

Here's a slimmed down version so you can see what I'm doing.

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

namespace ConsoleApplication1
{
    class Program
    {


        static int GenericAttack()
        {
            Random myRandom = new Random();
            int die1 = myRandom.Next(1, 6);
            int die2 = myRandom.Next(1, 6);
            int attackTotal = die1 + die2;
            Console.WriteLine("The attacking character rolls a {0} and {1} for a total of {2}", die1, die2, attackTotal);
            return attackTotal;
        }

        static int GenericDefend()
        {
            Random myRandom = new Random();
            int die1 = myRandom.Next(1, 6), die2 = myRandom.Next(1, 6);
            int attackTotal = die1 + die2;
            Console.WriteLine("The defending character rolls a {0} and {1} for a total of {2}", die1, die2, attackTotal);
            return attackTotal;
        }

        static int Fight()
        {
            int attackTotal = 0, defendTotal = 0;

            attackTotal = GenericAttack();

            defendTotal = GenericDefend();

            if (attackTotal > defendTotal)
                return 1;
            else if (attackTotal < defendTotal)
                return 2;
            else
                return 0;
        }

        static void Main(string[] args)
        {
            Random myRandom = new Random();
            Console.WriteLine("Let's Fight!");

            int winner = 0;

            while (winner == 0)
            {
                winner = Fight();
            }

            if (winner == 1)
                Console.WriteLine("The attacking Character wins!");
            else if (winner == 2)
                Console.WriteLine("The defending Character wins!");
            else
                Console.WriteLine("Something went horribly wrong!");

            Console.ReadKey();

        }
    }
}



What I'm getting as an output, though, is something like:

Let's Fight!
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 1 and 4 for a total of 5
The attacking character rolls a 1 and 4 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 3 and 2 for a total of 5
The defending character rolls a 3 and 2 for a total of 5
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 2 and 4 for a total of 6
The attacking character rolls a 2 and 4 for a total of 6
The defending character rolls a 4 and 3 for a total of 7
The defending Character wins!



So, at first I thought somehow the die1 and die2 variables were carrying over between functions, even though they shouldn't. But renaming the variables didn't help. Nor did renaming the myRandom methods to something like attackRandom and defendRandom.

It also never happens when I try to Step Into the functions while debugging (though it always happens when I step over). Grrrr. Can someone tell me what's going wrong? Thanks!

Is This A Good Question/Topic? 0
  • +

Replies To: Variable Values Not Clearing Even Between Functions?

#2 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 2035
  • View blog
  • Posts: 6,058
  • Joined: 05-May 12

Re: Variable Values Not Clearing Even Between Functions?

Posted 01 September 2012 - 03:00 PM

Mods: This is C# code, not C/C++ code.
Was This Post Helpful? 0
  • +
  • -

#3 pharylon  Icon User is offline

  • D.I.C Head

Reputation: 39
  • View blog
  • Posts: 80
  • Joined: 01-September 12

Re: Variable Values Not Clearing Even Between Functions?

Posted 01 September 2012 - 03:01 PM

Whoops! Yes, it is. Is there a way to delete this one so I can put it in the right place? I'm not seeing the option.
Was This Post Helpful? 0
  • +
  • -

#4 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 2035
  • View blog
  • Posts: 6,058
  • Joined: 05-May 12

Re: Variable Values Not Clearing Even Between Functions?

Posted 01 September 2012 - 03:06 PM

Anyway, to answer your question, the reason is because you keep on constructing a brand new Random instance. If you read the MSDN documentation for the constructor that takes no parameters:
http://msdn.microsof...y/h343ddh9.aspx
you'll note that the default is time based. With modern processors, things are fast enough that almost all your calls are within the same time unit used by the randomizer as a seed, so you essentially get the same sequence of random numbers. The reason why you are getting different values when stepping in with the debugger is that now you are putting in enough delay (as opposed to stepping over which is not causing the delay).

The correct way to work around this is to have a single instance of the Random object that is created only once the first time you need a random number, and then you just keep using that instance until your program ends.

This post has been edited by Skydiver: 01 September 2012 - 03:07 PM

Was This Post Helpful? 2
  • +
  • -

#5 pharylon  Icon User is offline

  • D.I.C Head

Reputation: 39
  • View blog
  • Posts: 80
  • Joined: 01-September 12

Re: Variable Values Not Clearing Even Between Functions?

Posted 01 September 2012 - 03:14 PM

That makes sense, and it's what I tried at first: instantiating myRandom under the Program class.

But when I try to access it from my function, I get the error "Error 1 An object reference is required for the non-static field, method, or property..."

Apparently the issue is I'm calling it form a static function, but as ultimately it has to get back to Main, and Main *has* to be static, I don't know how to call it.
Was This Post Helpful? 0
  • +
  • -

#6 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 2035
  • View blog
  • Posts: 6,058
  • Joined: 05-May 12

Re: Variable Values Not Clearing Even Between Functions?

Posted 01 September 2012 - 03:43 PM

The way I usually deal with this in a quick and dirty program is:
class Program
{
    Random _random;

    void Run()
    {
        _random = new Random();
        :
    }

    static void Main()
    {
        new Program().Run();
    }
}



I do this because I hate typing in "static" as much as I hate typing in "private".

But in well designed application, what you should really be doing is:
class Program
{
    static void Main()
    {
        IRandomNumberGenerator random = new BuiltInRandomNumberGenerator();
#if DEBUG
        random = new LoggingRandomNumberGenerator(random);
#endif
        FightGame game = new FightGame(random);
        game.Run();
    }
}

interface IRandomNumberGenerator
{
    int Next(int min, int max);
}

class BuiltInRandomNumberGenerator : IRandomNumberGenerator
{
    Random _random = new Random();

    public int Next(int min, int max)
    {
        return _random.Next(min, max);
    }
}

class LoggingRandomNumberGenerator : IRandomNumberGenerator
{
    IRandomNumberGenerator _random;

    public LoggingRandomNumberGenerator(IRandomNumberGenerator random)
    {
        _random = random;
    }

    public int Next(int min, int max)
    {
        int result = _random.Next(min, max);
        Log.WriteLine("Next({0}-{1}) -> {2}", min, max, result);
        return result;
    }
}

class FightGame
{
    IRandomNumberGenerater _random;

    public FightGame(IRandomNumerGenerator random)
    {
        _random = random;
    }

    :
}



The logging is when I'm debugging and need to see what was being generated. The interface lets me do the wrapper above, as well as write another implementation that will let me hard code a specific sequence of numbers when I write my unit tests.

This post has been edited by Skydiver: 01 September 2012 - 04:10 PM

Was This Post Helpful? 3
  • +
  • -

#7 pharylon  Icon User is offline

  • D.I.C Head

Reputation: 39
  • View blog
  • Posts: 80
  • Joined: 01-September 12

Re: Variable Values Not Clearing Even Between Functions?

Posted 01 September 2012 - 04:00 PM

Thank you soooooo much!
Was This Post Helpful? 0
  • +
  • -

#8 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 4949
  • View blog
  • Posts: 11,356
  • Joined: 16-October 07

Re: Variable Values Not Clearing Even Between Functions?

Posted 01 September 2012 - 06:15 PM

Also, if you find yourself doing the same thing more than once, consider a method.

e.g.
private int GetRoll() { return myRandom.Next(1, 6); }


Look for patterns and repetition:
class Program {
	private Random myRandom;
	public Program() { myRandom = new Random(); }
	
	private int GetRoll() { return myRandom.Next(1, 6); }
	
	int GenericRoll(string roller) {
		int die1 = GetRoll();
		int die2 = GetRoll();
		int total = die1 + die2;
		Console.WriteLine(roller + "rolls a {0} and {1} for a total of {2}", die1, die2, total);
		return total;
	}

	private int GenericAttack() { return GenericRoll("The attacking character"); }
	
	private int GenericDefend() { return GenericRoll("The defending character"); }
	
	public int Fight() {
		int attackTotal = GenericAttack();
		int defendTotal = GenericDefend();
		if (attackTotal == defendTotal) { return 0; }
		return (attackTotal > defendTotal) ? 1 : 2;
	}



Hope this helps.
Was This Post Helpful? 1
  • +
  • -

#9 pharylon  Icon User is offline

  • D.I.C Head

Reputation: 39
  • View blog
  • Posts: 80
  • Joined: 01-September 12

Re: Variable Values Not Clearing Even Between Functions?

Posted 02 September 2012 - 05:30 AM

Skydiver, I see you changed your answer a bit to use interfaces. I'm still really new to programming, and I don't know how to use them. I ended up using your original answer of doing:

    class Program
    {
        static void Main()
        {
            FightGame game = new FightGame();
            game.Run();
        }

    }

    class FightGame
    {
       Run ()
       {
        //What used to be in Main()
       }
    }




However, I plan to revisit this program once I learn interfaces. I've bookmarked your answer, and I'll be looking back at this thread then to see how I can improve my simple little program.

Baavgai,

Thanks for the advice. I just used some of your advice to improve things!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1