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); } } }