using System;
using System.Collections.Generic;
using System.Linq;
namespace Game
{
///
/// Provides methods for generating codes with a given number of positions
/// and colors.
///
public class CodeFactory
{
///
/// Gets the number of colors in codes generated by this factory.
///
public int Colors { get; }
///
/// Gets the number of positions in codes generated by this factory.
///
public int Positions { get; }
///
/// Gets the number of distinct codes that this factory can
/// generate.
///
public int Possibilities { get; }
///
/// Initializes a new instance of the CodeFactory class.
///
///
/// The number of positions.
///
///
/// The number of colors.
///
public CodeFactory(int positions, int colors)
{
if (positions < 1)
throw new ArgumentException("A code must contain at least one position");
if (colors < 1)
throw new ArgumentException("A code must contain at least one color");
if (colors > Game.Colors.List.Length)
throw new ArgumentException($"A code can contain no more than {Game.Colors.List.Length} colors");
Positions = positions;
Colors = colors;
Possibilities = (int)Math.Pow(colors, positions);
}
///
/// Creates a specified code.
///
///
/// The number of the code to create from 0 to Possibilities - 1.
///
public Code Create(int number) =>
EnumerateCodes().Skip(number).First();
///
/// Creates a random code using the provided random number generator.
///
///
/// The random number generator.
///
public Code Create(Random random) =>
Create(random.Next(Possibilities));
///
/// Generates a collection of codes containing every code that this
/// factory can create exactly once.
///
public IEnumerable EnumerateCodes()
{
var current = new int[Positions];
var position = default(int);
do
{
yield return new Code(current);
position = 0;
while (position < Positions && ++current[position] == Colors)
current[position++] = 0;
}
while (position < Positions);
}
}
}