From a0ab77f2e8f21a7096dc9b0828907d6e4e34fc2d Mon Sep 17 00:00:00 2001 From: JP Appel Date: Wed, 11 Sep 2024 22:27:00 -0400 Subject: Start work on bingo functionality Created a simple struct for game state. Started work on board generators and their seeds. --- bingo/tiles.go | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 bingo/tiles.go (limited to 'bingo/tiles.go') diff --git a/bingo/tiles.go b/bingo/tiles.go new file mode 100644 index 0000000..81e945f --- /dev/null +++ b/bingo/tiles.go @@ -0,0 +1,101 @@ +package bingo + +import ( + "iter" + "math/rand" + "slices" +) + +type TilePool map[string][]string + +func (pool TilePool) All() iter.Seq[string] { + return func(yield func(string) bool) { + for _, list := range pool { + for _, tile := range list { + if !yield(tile) { + return + } + } + } + } +} + +type TilePicker interface { + All() iter.Seq[string] // provides an iterator over an entire TilePool + Iter(int) iter.Seq2[string, string] // provides an iterator over n elements of a TilePool + Reset() // reset the internal state of a TilePicker +} + +type RandomTilePicker struct { + ChosenTags []string + tilePool TilePool + rand rand.Rand +} + +func NewRandomTilePicker(tiles TilePool, r rand.Rand) *RandomTilePicker { + tp := new(RandomTilePicker) + tp.tilePool = tiles + tp.rand = r + + return tp +} + +// Iterate over all elements of a TilePool in a random order +func (tp RandomTilePicker) All() iter.Seq[string] { + return func(yield func(string) bool) { + tiles := slices.Collect(tp.tilePool.All()) + if len(tiles) == 0 { + return + } + + tp.rand.Shuffle(len(tiles), func(i int, j int) { + tiles[i], tiles[j] = tiles[j], tiles[i] + }) + + for _, tile := range tiles { + if !yield(tile) { + return + } + } + } +} + +// Iterator over a TilePool by choosing one tile per tag until pool is exhausted or size tiles have been yielded +func (tp RandomTilePicker) Iter(size int) iter.Seq2[string, string] { + return func(yield func(string, string) bool) { + if len(tp.tilePool) == 0 { + return + } + + tags := make([]string, len(tp.tilePool)) + for tag := range tp.tilePool { + tags = append(tags, tag) + } + tp.rand.Shuffle(len(tags), func(i int, j int) { + tags[i], tags[j] = tags[j], tags[i] + }) + + yielded := 0 + for _, tag := range tags { + if yielded == size { + return + } + + list := tp.tilePool[tag] + if len(list) == 0 { + continue + } + + tile := list[tp.rand.Intn(len(list))] + if !yield(tag, tile) { + return + } + yielded++ + } + + } +} + +func (tp RandomTilePicker) Reset() { + tp.ChosenTags = make([]string, len(tp.ChosenTags)) +} -- cgit v1.2.3