5
\$\begingroup\$

Some recent discussions on this site involved the Fizz-Buzz game - I have never actually implemented this, but for the record this is what I put together:

public class FizzBuzzConverter
{
    private readonly int _fizz;
    private readonly int _buzz;

    public FizzBuzzConverter(int fizz, int buzz)
    {
        _fizz = fizz;
        _buzz = buzz;
    }

    public string Convert(int value)
    {
        if (value % (_fizz*_buzz) == 0) return "FizzBuzz";
        if (value % _buzz == 0) return "Buzz";
        if (value % _fizz == 0) return "Fizz";
        return value.ToString();
    }
}

When people implement , they tend to run a loop going from 1 to 100 and outputting the results to some console. According to Wikipedia, that's not how the game plays:

Players generally sit in a circle. The player designated to go first says the number "1", and each player thenceforth counts one number in turn. However, any number divisible by three is replaced by the word fizz and any divisible by five by the word buzz. Numbers divisible by both become fizz buzz. A player who hesitates or makes a mistake is eliminated from the game.

So I'm thinking of going that way - and since I've never actually coded anything remotely resembling AI since I tweaked some Duke Nukem 3D configuration files in 1997, I'd like to get some feedback and refactoring thoughts about this:

public class PseudoBrain
{
    private readonly FizzBuzzConverter _converter;
    public PseudoBrain(FizzBuzzConverter converter)
    {
        _converter = converter;
    }

    public virtual string Think(string lastResult, int value)
    {
        var random = new Random();
        var ai = random.Next(0, 99);

        var result = _converter.Convert(value);

        if (ai < 85)
        {
            // thinks straight most of the time.
            return result;
        }
        else
        {
            Hesitate();
            if (ai < 95) return result;

            // could be right, could be wrong. hesitant anyway.
            return lastResult == "fizz" ? value.ToString() : "buzz";
        }
    }

    private void Hesitate()
    {
        Thread.Sleep(500);
    }
}

This brain works, ..it's just a little too hesitant:

enter image description here

Still, it's not too dumb:

enter image description here

I'm sure I could tweak the percentages to come up to something decently smart enough to implement a game with 5-6 of those "brains" playing against a human player, who would win if all the brains fried before his.

How's this PseudoBrain class doing? Don't Hesitate(), just say what you Think()!

\$\endgroup\$
  • 1
    \$\begingroup\$ According to Jeff, it is how you write FizzBuzz. \$\endgroup\$ – svick Dec 6 '13 at 10:45
  • \$\begingroup\$ Also, if you wanted to have a human-like AI, you would need to factor in how difficult computing the modulo is for a human. \$\endgroup\$ – svick Dec 6 '13 at 10:48
4
\$\begingroup\$

I'd first create an interface that your FizzBuzzConverter class can implement:

public interface IConverter
{
    string Convert(int value);
}

public class FizzBuzzConverter : IConverter
{
    // ...
}

Then the PseudoBrain can have any implementation of the interface injected into it:

public class PseudoBrain
{
    private readonly IConverter _converter;

    public PseudoBrain(IConverter converter)
    {
        _converter = converter;
    }

    // ...
}

This will allow for easier unit testing via mocking or writing and using new Converters.

Lastly, I have a bit of a squicky feeling when I see random number generators created over and over (as Think() will be called repeatedly). So I put that at the class level:

public class PseudoBrain
{
    private readonly Random _random = new Random();
    private readonly IConverter _converter;

    public PseudoBrain(IConverter converter)
    {
        _converter = converter;
    }

    public virtual string Think(string lastResult, int value)
    {
        var ai = _random.Next(0, 99);

        // ...
    }

    // ...
}
\$\endgroup\$

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.