Has puesto $NroTarjeta = rand(100,999); fuera del bucle por lo que siempre sera el mismo numero. Simplemente ponlo dentro para que cada vez que se recorra el bucle asigne otro valor a $NroTarjeta
Si tiene que ser obligatoriamente no repetido, ve añadiendo todos los numeros generados a un array y despues haces un blucle para comprobar si no esta en el array.
Código PHP:
$NrosGen = new Array();
// matriz
for ($contador = 1; $contador <= 20; $contador++)
{
do $NroTarjeta = rand(100,999); // obtengo un numero aleatorio
while (!in_array($NrosGen)); // comprueba si ya ha sido usado
$NrosGen[] = $NroTarjeta; // Añade al siguiente valor disponible del array el numero generado.
$Z = ($NroTarjeta + 1);
$n = pow($NroTarjeta,(1/3));
$nRnd = ceil($n); // redondeo el valor de n
$ValorLetra = ($nRnd * $Z); // cada letra vale n redondeado por z
$ValorLetraRed = substr($ValorLetra,2); // reduzco la cantidad de caracteres a 2
$NroChar = strlen($ValorLetraRed); // obtengo el numero de caracteres de la cadena
if ($NroChar == "1") // si es igual a 1 osea 1 digito
{
echo "arreglado <br>";
$NroCharFix = ($ValorLetraRed + 10); // sumo 10 para subirlo a 2 digitos
echo "valor final = " .$NroCharFix. "<br>";
} else {
echo "valor final = " .$ValorLetraRed. "<br>";
}
}
Tampoco entiendo porque haces tantas operaciones, pero será para algo que necesites.