Reputation: 621
I'm trying to create a bingo card which should be set up with the following rules:
So far I've managed to create a card that contains 9 columns and 3 rows and filled the card with unique random numbers but I can't figure out how to achieve 3rd and 4th rules.
In the end, a bingo card should look similar to this:
1 EMPTY 18 EMPTY 12 EMPTY 40 EMPTY 32
EMPTY 2 EMPTY EMPTY 67 33 EMPTY 44 EMPTY
90 EMPTY 79 EMPTY 38 EMPTY 55 EMPTY 71
In my algorithm I don't know how to put EMPTY blocks and avoid repeating them more than twice
My card generator function is:
public GameCard GetCard()
{
//This is the list of all numbers between 1 and 99
var availableNumbers = Enumerable.Range(CARD_NUM_MIN, CARD_NUM_MAX).ToList();
var card = new GameCard();
//looping for 9 columns
for (var col = 0; col < CARD_COL_COUNT; col++)
{
var cardColumn = new CardColumn();
//looping for 3 rows in each column
for (var row = 0; row < CARD_ROW_COUNT; row++)
{
var cardRow = new NumberBlock();
//getting a random number from availableNumbers and removing that number from list to avoid duplicate numbers.
var rand = RandomNumberGenerator.Instance.Next(availableNumbers.Count - 1);
cardRow.Value = availableNumbers[rand];
availableNumbers.RemoveAt(rand);
//I believe somewhere here I should check if there will be more than 5 numbers in a row, or should randomly generate empty blocks? Can't really figure out...
cardColumn.Rows.Add(cardRow);
}
card.Columns.Add(cardColumn);
}
return card;
}
GameCard class:
public class GameCard
{
public string CardId { get; set; }
public List<CardColumn> Columns { get; set; }
public GameCard()
{
Columns = new List<CardColumn>();
}
}
CardColumn class
public class CardColumn
{
public int Count { get; set; }
public List<NumberBlock> Rows { get; set; }
public CardColumn()
{
Rows = new List<NumberBlock>();
}
}
NumberBlock class
public class NumberBlock
{
public int Value { get; set; }
public bool IsBlank { get; set; }
public NumberBlock()
{
IsBlank = false;
}
}
Upvotes: 1
Views: 5674
Reputation: 2951
First do some research - there are 45 possible types of row
91=Number Number Empty Number Number Empty Number Empty Empty
107=Number Number Empty Number Empty Number Number Empty Empty
109=Number Empty Number Number Empty Number Number Empty Empty
155=Number Number Empty Number Number Empty Empty Number Empty
171=Number Number Empty Number Empty Number Empty Number Empty
173=Number Empty Number Number Empty Number Empty Number Empty
179=Number Number Empty Empty Number Number Empty Number Empty
181=Number Empty Number Empty Number Number Empty Number Empty
182=Empty Number Number Empty Number Number Empty Number Empty
203=Number Number Empty Number Empty Empty Number Number Empty
205=Number Empty Number Number Empty Empty Number Number Empty
211=Number Number Empty Empty Number Empty Number Number Empty
213=Number Empty Number Empty Number Empty Number Number Empty
214=Empty Number Number Empty Number Empty Number Number Empty
217=Number Empty Empty Number Number Empty Number Number Empty
218=Empty Number Empty Number Number Empty Number Number Empty
299=Number Number Empty Number Empty Number Empty Empty Number
301=Number Empty Number Number Empty Number Empty Empty Number
307=Number Number Empty Empty Number Number Empty Empty Number
309=Number Empty Number Empty Number Number Empty Empty Number
310=Empty Number Number Empty Number Number Empty Empty Number
331=Number Number Empty Number Empty Empty Number Empty Number
333=Number Empty Number Number Empty Empty Number Empty Number
339=Number Number Empty Empty Number Empty Number Empty Number
341=Number Empty Number Empty Number Empty Number Empty Number
342=Empty Number Number Empty Number Empty Number Empty Number
345=Number Empty Empty Number Number Empty Number Empty Number
346=Empty Number Empty Number Number Empty Number Empty Number
357=Number Empty Number Empty Empty Number Number Empty Number
358=Empty Number Number Empty Empty Number Number Empty Number
361=Number Empty Empty Number Empty Number Number Empty Number
362=Empty Number Empty Number Empty Number Number Empty Number
364=Empty Empty Number Number Empty Number Number Empty Number
403=Number Number Empty Empty Number Empty Empty Number Number
405=Number Empty Number Empty Number Empty Empty Number Number
406=Empty Number Number Empty Number Empty Empty Number Number
409=Number Empty Empty Number Number Empty Empty Number Number
410=Empty Number Empty Number Number Empty Empty Number Number
421=Number Empty Number Empty Empty Number Empty Number Number
422=Empty Number Number Empty Empty Number Empty Number Number
425=Number Empty Empty Number Empty Number Empty Number Number
426=Empty Number Empty Number Empty Number Empty Number Number
428=Empty Empty Number Number Empty Number Empty Number Number
434=Empty Number Empty Empty Number Number Empty Number Number
436=Empty Empty Number Empty Number Number Empty Number Number
The LinqPad script I used to generate this list is:
List<bool []> permutations = new List<bool []>();
void Main()
{
// Generate all possible permutations of 9 items
// 511 is 9 1-bits
for(uint n = 0; n < 512; n++) {
bool [] p = perm(n);
if(valid(p)) {
permutations.Add(p);
Console.Write(" {0}=", n);
for(int i = 0; i < 9; i++)
Console.Write(p[i] ? "Number " : "Empty ");
Console.WriteLine();
}
}
}
// Convert a number into a bit pattern (array of 9 bools)
// Representing number (true) or gap (false)
bool [] perm(uint n) {
bool [] result = new bool[9];
uint m = 1;
for(int i = 0; i < 9; m <<= 1, i++)
result[i] = (n & m) != 0;
return result;
}
// See if a bit pattern satisfies the rules
bool valid(bool [] p) {
int repeat = 0; // Number of trues (numbers) or falses (gaps)
int count = 0; // Number of trues (numbers)
bool last = false;
for(int n = 0; n < 9; n++) {
bool current = p[n];
if(current == last) {
// This is the same as the last one (i.e. both numbers or both gaps)
if(++repeat > 2)
return false; // May not have more than 2 of the same together
} else {
repeat = 1;
}
if(current)
count++;
last = current;
}
return count == 5;
}
You could proceed from there - First generate 15 different random numbers from your list, then for each row, randomly choose one of the 25 possibilities, and finally fill the row with numbers.
Far better to do this by row, rather than column, because all your rules apply to rows. If you really need things in columns, switch them round at the end.
Upvotes: 5