HELP: Reusing Code with Iterations

I am making a Bingo game, and am having trouble with reusing code in one area. I am trying to fill the cards.

/* ==================================================================== *
* FillCard *
* ==================================================================== *
* Fills the card with valid values from the number pools. *
* ==================================================================== */
private void FillCard()
{
// WE NEED A RANDOM NUMBER GENERATOR.
Random rndNumber = new Random();

// WE NEED A TEMPORARY PLACE TO STORE THE CURRENT RANDOM NUMBER RETURNED
// FROM THE RANDOM NUMBER GENERATOR.
byte crntNumber = 0;

// 1. GENERATE RANDOM NUMBER BASED ON THE AMOUNT OF NUMBERS LEFT IN THE POOL.
// 2. QUERY NUMBER POOL TO GET THE VALUE AT THE RANDOM NUMBERS LOCATION.
// 3. REMOVE THE NUMBER FROM THE NUMBER POOL SO IT CANNOT BE USED AGAIN.

// B
crntNumber = (byte)rndNumber.Next(bMin, bPool.Count);
B_Row0 = bPool[crntNumber];
bPool.Remove(crntNumber);

crntNumber = (byte)rndNumber.Next(bMin, bPool.Count);
B_Row1 = bPool[crntNumber];
bPool.Remove(crntNumber);

crntNumber = (byte)rndNumber.Next(bMin, bPool.Count);
B_Row3 = bPool[crntNumber];
bPool.Remove(crntNumber);

crntNumber = (byte)rndNumber.Next(bMin, bPool.Count);
B_Row4 = bPool[crntNumber];
bPool.Remove(crntNumber);

// I

// TODO: FINISH GENERATING THE CARD HERE

}

I have a BingoCard object, with several members such as B_Row0 - B_Row4, I_Row0 - I_Row4, etc...

each member will hold a number value during the game, based upon the rules B 0-15, I 16-30, etc. I need to populate each members with a number and as you can see I'm tying similar statements over and over again, generating a number, pulling out the value, and then removing the value. Is there a way I can make this more concise by using an iteration block? Something that will look cleaner in the end?

bMin, bMax are simply const values that store the rules for the game, for example

private const byte bMin = 1;
private const byte bMax = 15;

bPool is a List<byte> which contains all the numbers that can be used for B, for example it contains 1 - 15.

These are the same rules for iMin, iMax, etc... and iPool.

If you need to see more code let me know but there is a lot of standard code (properties, accessors) which I don't think anyone should need.

Thanks.

Edit: I just noticed that my Remove statements need to be replaced with RemoveAt, in case that confuses anyone. I updated the source code already.
[2819 byte] By [DanDandy] at [2007-11-20 9:41:26]
# 1 Re: HELP: Reusing Code with Iterations
As you can see the final source really needs to be cleaned up I think. If I could some how do this same thing with a few lines in an iteration it would be awesome!!

private void FillCard()
{
// WE NEED A RANDOM NUMBER GENERATOR.
Random rndNumber = new Random();

// WE NEED A TEMPORARY PLACE TO STORE THE CURRENT RANDOM NUMBER RETURNED
// FROM THE RANDOM NUMBER GENERATOR.
byte crntNumber = 0;

// 1. GENERATE RANDOM NUMBER BASED ON THE AMOUNT OF NUMBERS LEFT IN THE POOL.
// 2. QUERY NUMBER POOL TO GET THE VALUE AT THE RANDOM NUMBERS LOCATION.
// 3. REMOVE THE NUMBER FROM THE NUMBER POOL SO IT CANNOT BE USED AGAIN.

// B
crntNumber = (byte)rndNumber.Next(bMin, bPool.Count);
B_Row0 = bPool[crntNumber];
bPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(bMin, bPool.Count);
B_Row1 = bPool[crntNumber];
bPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(bMin, bPool.Count);
B_Row3 = bPool[crntNumber];
bPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(bMin, bPool.Count);
B_Row4 = bPool[crntNumber];
bPool.RemoveAt(crntNumber);

// I
crntNumber = (byte)rndNumber.Next(iMin, iPool.Count);
I_Row0 = iPool[crntNumber];
iPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(iMin, iPool.Count);
I_Row1 = iPool[crntNumber];
iPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(iMin, iPool.Count);
I_Row2 = iPool[crntNumber];
iPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(iMin, iPool.Count);
I_Row3 = iPool[crntNumber];
iPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(iMin, iPool.Count);
I_Row4 = iPool[crntNumber];
iPool.RemoveAt(crntNumber);

// N
crntNumber = (byte)rndNumber.Next(nMin, nPool.Count);
N_Row0 = nPool[crntNumber];
nPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(nMin, nPool.Count);
N_Row1 = nPool[crntNumber];
nPool.RemoveAt(crntNumber);

/* NOTICE: N_Row2 IS A FREE SPACE AND WILL ALWAYS HAVE THE SAME VALUE
THEREFORE IT HAS BEEN SKIPPED DURING THIS PROCESS */

crntNumber = (byte)rndNumber.Next(nMin, nPool.Count);
N_Row3 = nPool[crntNumber];
nPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(nMin, nPool.Count);
N_Row4 = nPool[crntNumber];
nPool.RemoveAt(crntNumber);

// G
crntNumber = (byte)rndNumber.Next(gMin, gPool.Count);
G_Row0 = gPool[crntNumber];
gPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(gMin, gPool.Count);
G_Row1 = gPool[crntNumber];
gPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(gMin, gPool.Count);
G_Row2 = gPool[crntNumber];
gPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(gMin, gPool.Count);
G_Row3 = gPool[crntNumber];
gPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(gMin, gPool.Count);
G_Row4 = gPool[crntNumber];
gPool.RemoveAt(crntNumber);

// O
crntNumber = (byte)rndNumber.Next(iMin, iPool.Count);
I_Row0 = iPool[crntNumber];
iPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(iMin, iPool.Count);
I_Row1 = iPool[crntNumber];
iPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(iMin, iPool.Count);
I_Row2 = iPool[crntNumber];
iPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(iMin, iPool.Count);
I_Row3 = iPool[crntNumber];
iPool.RemoveAt(crntNumber);

crntNumber = (byte)rndNumber.Next(iMin, iPool.Count);
I_Row4 = iPool[crntNumber];
iPool.RemoveAt(crntNumber);

}

I just have to watch for row N_Row2 as it is special (its the free space), and always should have the value (byte)255 so my game engine will know how to handle it when it validates bingo cards. :)

The only difference in there is B I N G and O, if I could enumerate those some how I could use an iteration block but I'm not sure how to do it so that the compiler will accept it.
DanDandy at 2007-11-9 11:34:31 >
# 2 Re: HELP: Reusing Code with Iterations
Instead of making each square in your bingo table a seperate variable, just make a rectangular array.

//a 5x4 table could be written as
byte[,] bingoTable = new byte[5,4];

Then you could populate it using a for loop:

for(int i=0; i < 5; i++)
{
for(int j=0; j < 4; j++)
{
bingoTable[i, j] = bPool[crntNumber];
bPool.RemoveAt(crntNumber);
}
}

Or something like that.
Mutant_Fruit at 2007-11-9 11:35:32 >
# 3 Re: HELP: Reusing Code with Iterations
I'm not sure I understand your solution but you are saying I should use 0 - 4 instead of b, i, n, g, and o? So I can pupulate them in a iteration?

I will try to figure it out. If I can do it and still have the code readable.

I was trying to make use OOP so I have a BingoCard, BingoCaller, and Game classes.
DanDandy at 2007-11-9 11:36:31 >
# 4 Re: HELP: Reusing Code with Iterations
There's nothing wrong with making it OO and using classes and suchlike, but by the looks of it you've defined each of the squares in your bingo board as a seperate variable. That is what makes it impossible to fill your grid using an 'iteration'.

I'm not 100% sure how bingo works. But isn't each 'card' basically a grid of squares? If so, you're bingo card should just contain an array representing that grid, not individual variables for each square in the grid.
Mutant_Fruit at 2007-11-9 11:37:36 >
# 5 Re: HELP: Reusing Code with Iterations
ok thanks, i will work on it tomorrow and see what i can come up with. i am starting to design video games and i figured bingo would be an easy one to start with, then i can learn microsofts xna game studio.

each card is kinda like a table, at least thats the way i am going to represent it in code. I figured i would make each "square" on the card a class member, im use to desiging business software.

i will look into your solution in the moring i think it will work, if anyone has more info as well please let me know.

thanks
DanDandy at 2007-11-9 11:38:36 >