JavaScript (ES6), 133132 bytes
f=N=>(F=n=>n<30F=n=>N?n<30?F[k=n%5]^(F[k]|=1<<(v=Math.random()*15))?(nn++-17?"BINGO"[n]||k*15"_BINGO"[n]||k*15-~v:'free')+`
`[k>>2]+F(n+1n):F(n):--N?`
`+f(N-1):'')(0n)``
f = N => ( // outer function taking the number N of grids
F = n => // inner function taking a counter n
N ? // if there's still a grid to process:
n < 30 ? // if n is less than 30:
F[k = n % 5] // k is the column index in [0..4]
^ ^ // if F[k] is not equal to its updated value
( F[k] |= 1 << ( // where the floor(v)-th bit is set
v = v = // where v is
Math.random() // randomly picked in [0,15[
* 15 //
) //
) ? // then:
( nn++ - 17 ? // if this is not the center cell:
"BINGO"[n] || "_BINGO"[n] // append either a BINGO letter (if n <<= 5)
|| // or
k * 15 - ~v // or append the number k * 15 + floor(v + 1)
: : // else:
'free' 'free' // append the word 'free'
) + ) + //
` \n`[k >> 2] + // append a line-feed if k = 4,
// or a space otherwise
F(n) + 1) // append the result of a recursive call to F
: // with n + 1
: // else:
F(n) // try again with ntry unchangedagain
: // else: --N ? // decrement N; if it's not 0else:
`\n` + // append a line-feed followed by
f(N) - 1) // the result of a recursive call to f
: : // else:
n '' // stop the recursion
)(0)`` // initial call to F with n = 0zero'ish
JavaScript (ES6), 133 bytes
f=N=>(F=n=>n<30?F[k=n%5]^(F[k]|=1<<(v=Math.random()*15))?(n-17?"BINGO"[n]||k*15-~v:'free')+`
`[k>>2]+F(n+1):F(n):--N?`
`+f(N):'')(0)
f = N => ( // outer function taking the number N of grids
F = n => // inner function taking a counter n
n < 30 ? // if n is less than 30:
F[k = n % 5] // k is the column index in [0..4]
^ // if F[k] is not equal to its updated value
( F[k] |= 1 << ( // where the v-th bit is set
v = // where v is
Math.random() // randomly picked in [0,15[
* 15 //
) //
) ? // then:
( n - 17 ? // if this is not the center cell:
"BINGO"[n] || // append a BINGO letter (if n < 5)
k * 15 - ~v // or append k * 15 + floor(v + 1)
: // else:
'free' // append the word 'free'
) + //
` \n`[k >> 2] + // append a line-feed if k = 4,
// or a space otherwise
F(n + 1) // append the result of a recursive call to F
// with n + 1
: // else:
F(n) // try again with n unchanged
: // else: --N ? // decrement N; if it's not 0:
`\n` + // append a line-feed followed by
f(N) // the result of a recursive call to f
: // else:
'' // stop the recursion
)(0) // initial call to F with n = 0
JavaScript (ES6), 132 bytes
f=N=>(F=n=>N?n<30?F[k=n%5]^(F[k]|=1<<(v=Math.random()*15))?(n++-17?"_BINGO"[n]||k*15-~v:'free')+`
`[k>>2]+F(n):F(n):`
`+f(N-1):n)``
f = N => ( // outer function taking the number N of grids
F = n => // inner function taking a counter n
N ? // if there's still a grid to process:
n < 30 ? // if n is less than 30:
F[k = n % 5] // k is the column index in [0..4]
^ // if F[k] is not equal to its updated value
( F[k] |= 1 << ( // where the floor(v)-th bit is set
v = // where v is
Math.random() // randomly picked in [0,15[
* 15 //
)) ? // then:
( n++ - 17 ? // if this is not the center cell:
"_BINGO"[n] // append either a BINGO letter (if n <= 5)
|| // or
k * 15 - ~v // the number k * 15 + floor(v + 1)
: // else:
'free' // append the word 'free'
) + //
` \n`[k >> 2] + // append a line-feed if k = 4,
// or a space otherwise
F(n) // append the result of a recursive call to F
: // else:
F(n) // try again
: // else:
`\n` + // append a line-feed followed by
f(N - 1) // the result of a recursive call to f
: // else:
n // stop the recursion
)`` // initial call to F with n zero'ish
Commented
f = N => ( // outer function taking the number N of grids
F = n => // inner function taking a counter n
n < 30 ? // if n is less than 30:
F[k = n % 5] // k is the column index in [0..4]
^ // if F[k] is not equal to its updated value
( F[k] |= 1 << ( // where the v-th bit is set
v = // where v is
Math.random() // randomly picked in [0,15[
* 15 //
) //
) ? // then:
( n - 17 ? // if this is not the center cell:
"BINGO"[n] || // append a BINGO letter (if n < 5)
k * 15 - ~v // or append k * 15 + floor(v + 1)
: // else:
'free' // append the word 'free'
) + //
` \n`[k >> 2] + // append a line-feed if k = 4,
// or a space otherwise
F(n + 1) // append the result of a recursive call to F
// with n + 1
: // else:
F(n) // try again with n unchanged
: // else:
--N ? // decrement N; if it's not 0:
`\n` + // append a line-feed followed by
f(N) // the result of a recursive call to f
: // else:
'' // stop the recursion
)(0) // initial call to F with n = 0
Commented
f = N => ( // outer function taking the number N of grids
F = n => // inner function taking a counter n
n < 30 ? // if n is less than 30:
F[k = n % 5] // k is the column index in [0..4]
^ // if F[k] is not equal to its updated value
( F[k] |= 1 << ( // where the v-th bit is set
v = // where v is
Math.random() // randomly picked in [0,15[
* 15 //
) //
) ? // then:
( n - 17 ? // if this is not the center cell:
"BINGO"[n] || // append a BINGO letter (if n < 5)
k * 15 - ~v // or append k * 15 + floor(v + 1)
: // else:
'free' // append the word 'free'
) + //
` \n`[k >> 2] + // append a line-feed if k = 4,
// or a space otherwise
F(n + 1) // append the result of a recursive call to F
// with n + 1
: // else:
F(n) // try again with n unchanged
: // else:
--N ? // decrement N; if it's not 0:
`\n` + // append a line-feed followed by
f(N) // the result of a recursive call to f
: // else:
'' // stop the recursion
)(0) // initial call to F with n = 0
JavaScript (ES6), 139133 bytes
f=N=>(F=n=>n<30?(g=_=>F[k=n%5]^F[k=n%5]^(F[k]|=1<<(v=Math.random()*15))?(n-17?"BINGO"[n]||k*15-~v:'free':g())()+`
`[k>>2]+F(n+1):F(n):--N?`
`+f(N):'')(0)
JavaScript (ES6), 139 bytes
f=N=>(F=n=>n<30?(g=_=>F[k=n%5]^(F[k]|=1<<(v=Math.random()*15))?n-17?"BINGO"[n]||k*15-~v:'free':g())()+`
`[k>>2]+F(n+1):--N?`
`+f(N):'')(0)
JavaScript (ES6), 133 bytes
f=N=>(F=n=>n<30?F[k=n%5]^(F[k]|=1<<(v=Math.random()*15))?(n-17?"BINGO"[n]||k*15-~v:'free')+`
`[k>>2]+F(n+1):F(n):--N?`
`+f(N):'')(0)