The simplest approach I can think of:
for each tile
based on the surrounding already generated tiles,
generate a random type among those which won't result in 3-in-a-row
And an unoptimized way to do this, assuming just horizontal and vertical matches (not diagonal): (pseudo-code)
for x = 1 to M
for y = 1 to M
do
board[x][y] = randomType()
while ((x >= 3 && board[x-1][y] == board[x-2][y] && board[x-1][y] == board[x][y]) ||
(y >= 3 && board[x][y-1] == board[x][y-2] && board[x][y-1] == board[x][y]))
A way to avoid the repeated generation completely: (assuming types are numbers)
for x = 1 to M
for y = 1 to M
limit = N
horizontal = (x >= 3 && board[x-1][y] == board[x-2][y] && board[x-1][y] == board[x][y])
vertical = (y >= 3 && board[x][y-1] == board[x][y-2] && board[x][y-1] == board[x][y])
if horizontal
limit--
if vertical
limit--
board[x][y] = randomType(limit)
offset = 0
if (vertical && board[x][y] >= board[x][y-1])
offset++
if (horizontal && board[x][y] >= board[x-1][y])
offset++
board[x][y] += offset
The above method works similar to generating numbers in the ranges [0,A-1] and [A+1,B] by generating numbers in the range [0,B-1] and then, if the generated number is A or greater, we increase it by 1.
N
needs to be at least 3, otherwise you may get something like:
..A
..A
BB?
For which the above algorithm will run into an infinite loop.