Generatoredi Numeri

Come creare un generatore di numeri casuali

Tutorial completo in JavaScript: dalla formula base agli esempi pratici. Nessun framework, solo codice che funziona nel browser.

1. Prerequisiti

Per seguire questo tutorial non serve esperienza avanzata. Sono sufficienti conoscenze base di HTML — sapere cos'è un tag, come si struttura una pagina — e di JavaScript, in particolare come funzionano variabili, funzioni ed eventi. Non è necessario usare framework: tutto il codice proposto funziona in un file HTML con uno script inline, apribile direttamente nel browser senza strumenti aggiuntivi.

2. Il punto di partenza: Math.random()

Tutto parte da una funzione nativa di JavaScript: Math.random(). Chiamandola, restituisce un numero decimale pseudocasuale compreso tra 0 (incluso) e 1 (escluso), e il valore cambia a ogni chiamata. Da sola, però, ha un'utilità limitata: quasi nessuno ha bisogno di un numero tra 0 e 0.99. Serve una formula per trasformare quel valore in un numero intero all'interno di un intervallo specifico.

Math.random(); // es. 0.7341029183
Math.random(); // es. 0.1520934710
Math.random(); // es. 0.9912873400

3. Generare numeri in un intervallo

La formula standard per ottenere un numero intero compreso tra min e max — entrambi inclusi — è questa:

Math.floor(Math.random() * (max - min + 1)) + min

Come funziona passo per passo: Math.random() produce un valore tra 0 e 0.99 che viene moltiplicato per l'ampiezza dell'intervallo (max - min + 1), e questo dà un decimale tra 0 e l'ampiezza. Math.floor() lo arrotonda all'intero inferiore — da 0 a (max - min) — e sommando minsi trasla il risultato nell'intervallo desiderato.

Numeri decimali

Se invece dei numeri interi servono valori con cifre decimali, si omette Math.floor() e si usa toFixed(n) per controllare quante cifre dopo la virgola mostrare.

// Numero decimale tra min e max con 2 cifre
const val = (Math.random() * (max - min) + min).toFixed(2);

4. Generare numeri unici senza ripetizioni

Per estrazioni come il Lotto — 5 numeri distinti da 1 a 90 — i valori non possono ripetersi. Un approccio robusto è l'algoritmo Fisher-Yates: si crea un array con tutti i valori possibili, lo si mescola in modo statisticamente uniforme e si prendono i primi N elementi. L'algoritmo scorre l'array dall'ultimo elemento al primo e, per ciascuno, scambia la posizione con un elemento scelto a caso tra quelli che lo precedono.

function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
  return array;
}

// 5 numeri unici da 1 a 90
const pool = Array.from({ length: 90 }, (_, i) => i + 1);
const result = shuffle(pool).slice(0, 5);

Un'alternativa usa un Set: si generano numeri casuali finché il Set non raggiunge la dimensione richiesta. Per piccoli intervalli e poche estrazioni funziona bene, ma su grandi quantità diventa lenta perché aumenta la probabilità di generare duplicati e rifare il calcolo.

5. Creare l'interfaccia utente

Una struttura HTML minimale richiede un campo input per il minimo, uno per il massimo, un pulsante per avviare la generazione e un contenitore dove mostrare il risultato.

<div class="generator">
  <label>Min: <input type="number" id="min" value="1" /></label>
  <label>Max: <input type="number" id="max" value="100" /></label>
  <button id="btn">Genera</button>
  <div id="result">—</div>
</div>

Per collegare il pulsante alla logica di generazione si usa un event listener che legge i valori degli input, calcola il numero casuale e lo scrive nel div del risultato.

document.getElementById('btn').addEventListener('click', () => {
  const min = parseInt(document.getElementById('min').value);
  const max = parseInt(document.getElementById('max').value);
  const num = Math.floor(Math.random() * (max - min + 1)) + min;
  document.getElementById('result').textContent = num;
});

6. Aggiungere l'effetto animazione

Un semplice effetto slot machine — numeri che scorrono prima del risultato finale — si ottiene con setInterval. L'idea è mostrare valori casuali a intervalli rapidi per una quindicina di frame, poi fermarsi sul risultato definitivo. Il numero di frame e la velocità dell'intervallo controllano quanto l'animazione sembra fluida.

function animateResult(min, max, finalValue, element) {
  let count = 0;
  const totalFrames = 15;
  const interval = setInterval(() => {
    element.textContent = Math.floor(Math.random() * (max - min + 1)) + min;
    count++;
    if (count >= totalFrames) {
      clearInterval(interval);
      element.textContent = finalValue;
    }
  }, 80);
}

Per un effetto più naturale, si aumenta progressivamente il ritardo tra i frame così i numeri rallentano gradualmente fino a fermarsi, simulando l'inerzia di una slot machine fisica.

7. Esempio: generatore per il Lotto

Il Lotto italiano estrae 5 numeri distinti da 1 a 90. Con l'algoritmo Fisher-Yates applicato a un pool di 90 elementi, il codice completo è questo:

function lotto() {
  const pool = Array.from({ length: 90 }, (_, i) => i + 1);
  for (let i = 89; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [pool[i], pool[j]] = [pool[j], pool[i]];
  }
  return pool.slice(0, 5).sort((a, b) => a - b);
}

lotto(); // es. [7, 23, 45, 67, 88]

Il .sort() finale ordina i numeri in modo crescente prima di mostrarli — come avviene nelle schedine fisiche — ma è una scelta di leggibilità, non una necessità algoritmica.

Prova il generatore Lotto completo →

8. Esempio: generatore di password

Una password sicura combina lettere maiuscole e minuscole, numeri e simboli. Tre regole fondamentali nella costruzione: usare Crypto.getRandomValues() invece di Math.random() per avere sicurezza crittografica, forzare almeno un carattere per ogni categoria e mescolare il risultato con Fisher-Yates così i caratteri obbligatori non compaiono sempre nello stesso punto.

function generatePassword(length = 16) {
  const lower   = 'abcdefghijklmnopqrstuvwxyz';
  const upper   = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  const digits  = '0123456789';
  const symbols = '!@#$%^&*()_+-=[]{}|;:,.<>?';
  const all     = lower + upper + digits + symbols;

  const rand = (max) => {
    const arr = new Uint32Array(1);
    crypto.getRandomValues(arr);
    return arr[0] % max;
  };

  let chars = [
    lower[rand(lower.length)],
    upper[rand(upper.length)],
    digits[rand(digits.length)],
    symbols[rand(symbols.length)],
  ];

  while (chars.length < length) {
    chars.push(all[rand(all.length)]);
  }

  for (let i = chars.length - 1; i > 0; i--) {
    const j = rand(i + 1);
    [chars[i], chars[j]] = [chars[j], chars[i]];
  }

  return chars.join('');
}

Prova il generatore di password completo →

9. Esempio: simulatore di dadi

Il dado standard ha 6 facce, ma nei giochi di ruolo si usano dadi poliedrici da 4 a 100 facce. La funzione base è semplice: un parametro per il numero di facce e la formula standard per generare un intero nell'intervallo 1–N.

function rollDice(faces) {
  return Math.floor(Math.random() * faces) + 1;
}

rollDice(6);  // D6: valore tra 1 e 6
rollDice(20); // D20: valore tra 1 e 20

Per la visualizzazione, il dado può essere disegnato in CSS con bordi arrotondati e pallini posizionati in base al valore estratto. Per un effetto realistico si applica una transizione su transform: rotate3d() con un angolo casuale a ogni lancio, così il dado sembra girare prima di mostrare il risultato.

Prova il simulatore di dadi completo →

10. Best practice e sicurezza

Quando usare Crypto.getRandomValues()

Math.random() è adeguato per giochi, animazioni e simulazioni dove la prevedibilità non è un rischio reale. Per qualsiasi dato che protegga informazioni — password, token di accesso, chiavi crittografiche — va sempre usata l'API crittografica del browser. Crypto.getRandomValues() è disponibile in tutti i browser moderni senza librerie esterne e non introduce complessità aggiuntiva nel codice.

Validare sempre gli input

Prima di eseguire qualsiasi calcolo, è necessario validare i valori inseriti dall'utente. Se min è maggiore di max, la formula restituisce risultati errati. Se si chiedono più numeri unici di quanti ne contenga l'intervallo, il ciclo di generazione non termina mai, e un controllo preventivo risolve entrambi i casi con poche righe di codice.

if (min > max) throw new Error('min deve essere minore di max');
if (count > max - min + 1) throw new Error('count supera la dimensione dell\'intervallo');

Esplora tutti i nostri generatori come esempi pratici →