Puzzle + Grid Instantiate - Random

Hey guys, the script below works fine, but I’m wondering how I could add more control in the way things are created randomly.

Script:
The script below instantiates GameObjects per an X and Y grid. In the instantiation process, a random number is selected from the puzzleGridArray.length., which then assigns it a X and Y coordinate to go to. Pretty straightforward instantiate coding.

Problem:
Sometimes the same prefab is created 3 times in a row, which is what I’d like to avoid when the board is created. The point of the game is to eliminate objects, so when this happens, the 3 destroy themselves immediately when the game starts. I’d like to even take this one step further where the prefab will not instantiate itself vertically in 3s as well (Which I think is even harder).

Question: How can I add layers of control to where if Random picks the same object 3 times in a row, it switches to another one instead and continues on its merry way?

#pragma strict
//Grid Script

//Inspector Variables
var gridPrefab		: Transform;

var gridX			: int = 8;
var gridY			: int = 10;

var puzzleX			: int = 8;
var puzzleY			: int = 5;

var gridArray 		: Transform[,] = new Transform[gridX, gridY];
var puzzleArray 	: Transform[,] = new Transform[puzzleX, puzzleY]; 

var puzzleTypeArray	: GameObject[];

function Start () 
{
	SpawnGrid();
	SpawnPuzzlePieces();
}

function SpawnGrid()
{
	for(var i = 0; i < gridX; i++)
	{
		for(var j = 0; j < gridY; j++)
		{
			Instantiate(gridPrefab, Vector3(j, i, transform.position.z), Quaternion.identity);
		}
	}	
}

function SpawnPuzzlePieces()
{	
	for(var i = 0; i < puzzleX; i++)
	{
		for(var j = 0; j < puzzleY; j++)
		{
			Instantiate(puzzleTypeArray[Random.Range(0, puzzleTypeArray.Length)], Vector3(j, i, transform.position.z), Quaternion.identity);
		}
	}
}

http://docs.unity3d.com/Documentation/Manual/RandomNumbers.html

You can use [weighted random numbers][1] instead of purely random ones (see accepted answer in link).

The pseudocode explains the principle. For a dynamic version, you would initialize all weights to 1 (not 0!) and replace the return i with:

if(...){
    for(int j=0; j<num_choices; j++)
        choice_weight[j]++;          // increase weight of all numbers, to increase chance they'll be picked the next turn...
    choice_weight_=0; // ...but *reset* the weight of our current number, so it won't be picked again_

return i;
}
EDIT:
This ensures that:
- the same number won’t be picked twice in a row
- numbers just picked recently have lower probabilities to be picked again
- numbers not picked increase their chances to be picked the next turn
- it is much more likely that all numbers are picked relatively evenly distributed with much fewer samples, as opposed to a purely random approach
You can even influence the probability for certain numbers, for example by initializing then with a value >1 (but then you’d have to handle the code pictured above differently, because it will override the initial weights over time.
[1]: c++ - Weighted random numbers - Stack Overflow