/** This produces randomized bingo cards. The point of this class is not yet necessarily to make the most aesthetic card, but to rigorously and efficiently generate them randomly. You can generate and display a random card using something like: formatTableBoxed[BingoCard.randomCard[]] */ class BingoCard { /** A precalculated array of 5 rows, each with possible combinations of the numbers that could make up each column. The combinations are *not* shuffled nor permuted, but kept in order. The shuffling/permuting is done in randomCard. */ class var cols = BingoCard.initializeCols[] /** Initialize the possible combinations of numbers that can make up each column. */ class initializeCols[] := { cols = new array[[5]] for c = 0 to 4 { start = 15 c + 1 r = array[start to start+14] cols@c = array[r.combinations[5]] } return cols } /** Generate a random card as a two-dimensional array. You can display this using something like: formatTableBoxed[BingoCard.randomCard[]] or, to add a header: card = BingoCard.randomCard[] card.pushFirst[["\u{1f151}", "\u{1f158}", "\u{1f15d}", "\u{1f156}", "\u{1f15e}"]] formatTableBoxed[card] if the optional argument freeText is not the special value undef, this replaces the middle square with that text. The default is a Unicode "BLACK STAR" character. */ class randomCard[freeText = "\u2605"] := { card = new array // This picks a random combination of digits for each column and then // does a Fischer-Yates-Knuth shuffle to permute the column correctly. for c = 0 to 4 card.push[deepCopy[random[cols@c]].shuffle[]] // Replace center with desired symbol if freeText != undef card@2@2 = freeText return card.transpose[] } /** Return a new graphics object with a random card. It can be displayed with its show[] method, for example: BingoCard.graphicCard[].show[] The header should be a five-letter string like "BINGO". If you want to use fancy Unicode letters, you can do something like: "\u{1f171}\u{1f178}\u{1f17d}\u{1f176}\u{1f17e}" If the optional argument freeText is not the special value undef, this replaces the middle square with that text. The default is a Unicode "BLACK STAR" character. */ class graphicCard[header="BINGO", freeText = "\u2605"] := { g = new graphics // Draw "BINGO" header. This is done first so SVG rendering will // select in a predictable order. g.font["SansSerif", "bold", .9] x = 1/2 for h = charList[header] { g.text[h, x, -1/2] x = x + 1 } card = randomCard[freeText] [numRows, numCols] = card.dimensions[] g.font["SansSerif",1/2] for r = 0 to numRows-1 { row = card@r for c = 0 to numCols-1 g.text[row@c, c + 1/2, r + 1/2] } g.color[0,0,0,.5] // Draw horizontal lines for r = 0 to numRows g.line[0, r, numCols, r] // Draw vertical lines for c = 0 to numCols g.line[c, 0, c, numRows] return g } }