View Full Version : [C] lancio dei dadi con vero random
Compsognathus
08-01-2005, 19:31
ciao a tutti, mi serve l'aiuto, x pochi minuti credo, di un programmatore possibilmente di C
vorrei organizzare un gioco di ruolo e strategico online comandato dal lancio dei dadi.
è possibile creare uno scrip in C (ho letto una parte di un manuale ma a livello pratico sono 0) in cui 6 numeri o + possono uscire casualmente veramente??
PS
visto che il gioco deve essere online é possibile far connettere altri giocatori con il mio pc per far si che anche loro possono vedere direttamente il risultato del lancio dei dadi?
LimiT-MaTz
08-01-2005, 19:47
per fare il "lancio" dei dadi
1 + rand() % 6 ;
srand( time( NULL ));
isi isi ...
naturalmente puoi usare un algoritmo di complesso per srandizzare.
Ma credo che questo ti vada + che bene :)
Compsognathus
08-01-2005, 19:51
ma questo si appoggia all'orologio del pc o è un numero pseudocasuale ??
VegetaSSJ5
08-01-2005, 20:15
perchè fai la srand() dopo la rand()???
LimiT-MaTz
08-01-2005, 20:43
si hai ragione la fretta ...
sorry prima fai la srand poi richiami la funzione rand :)
Compsognathus
08-01-2005, 21:45
mi potreste scrivere lo script completo per favore??
mi da un errore sul gcc....
tnk
LimiT-MaTz
08-01-2005, 21:50
scusami come puoi pensare di fare una cosa senza sapere nemmeno da dove iniziare?!?
Prima studia...
#include <stdio.h>
#include <time.h>
int main(){
srand(time(NULL));
int n = 1 + rand() %6;
printf("%d",n);
return 0;
}
Compsognathus
08-01-2005, 22:35
ma nn è un gioco scritto in c
è come dungeon and dragon solo che è online, tramite chat o forum o email
solo che cera il problema dei dadi da tirare....
LimiT-MaTz
08-01-2005, 23:14
ah ok se usate irc perche' non vi fate un scriptino ?!?
non credo sia molto complesso :)
Ziosilvio
09-01-2005, 11:50
Originariamente inviato da LimiT-MaTz
1 + rand() % 6 ;
srand( time( NULL ));
A parte il fatto che la srand inizializza il generatore pseudorandom, quindi va chiamata prima delle rand, e non dopo...
... se usi una congruenza modulare per generare numeri interi a partire dalla rand, viene fuori una cosa tanto più sbilanciata, quanto più il fattore della congruenza è diverso da una potenza di due.
Quello che si fa di solito è definire una frand (rand in virgola mobile) che restituisca valori tra 0 incluso e 1 escluso, ad esempio:
double frand(void)
{
return (double)rand()/(RAND_MAX+1.);
}
A questo punto, una riga di codice che genera un'uscita di lancio di d6 è:
val = (unsigned int)floor(1+6*frand());
(per usare floor devi includere math.h e linkare libm.a).
P.S.: Con un computer deterministico, non puoi avere un generatore "veramente random"; però, puoi avere una cosa che "per quanto riesci a vedere tu, sembra random" --- e che va sicuramente bene per un gioco.
LimiT-MaTz
09-01-2005, 11:58
Originariamente inviato da Ziosilvio
A parte il fatto che la srand inizializza il generatore pseudorandom, quindi va chiamata prima delle rand, e non dopo...
... se usi una congruenza modulare per generare numeri interi a partire dalla rand, viene fuori una cosa tanto più sbilanciata, quanto più il fattore della congruenza è diverso da una potenza di due.
Quello che si fa di solito è definire una frand (rand in virgola mobile) che restituisca valori tra 0 incluso e 1 escluso, ad esempio:
double frand(void)
{
return (double)rand()/(RAND_MAX+1.);
}
A questo punto, una riga di codice che genera un'uscita di lancio di d6 è:
val = (unsigned int)floor(1+6*frand());
(per usare floor devi includere math.h e linkare libm.a).
P.S.: Con un computer deterministico, non puoi avere un generatore "veramente random"; però, puoi avere una cosa che "per quanto riesci a vedere tu, sembra random" --- e che va sicuramente bene per un gioco.
Non riesco a capire che senso abbia fare una rand in virgola mobile compresa tra 0 e 1 ?
puoi spegarlo meglio?
Compsognathus
09-01-2005, 12:04
k ziosilvio
per cortesia potresti fare lo scrip intero ?
x limit matz
uno script su irc per far cosa??
LimiT-MaTz
09-01-2005, 12:48
per simulare il lancio dei dadi e farlo vedere agli altri
Compsognathus
09-01-2005, 13:35
ma prima devo fare l'esecutivo con il c giusto??
l'irc ha un linguaggio suo??
se nn è difficile puoi scrivermolo per favore??
LimiT-MaTz
09-01-2005, 13:43
ok te lo faccio
Compsognathus
09-01-2005, 13:58
grazie in anticipo!!
Ziosilvio
09-01-2005, 14:10
Originariamente inviato da Compsognathus
k ziosilvio
per cortesia potresti fare lo scrip intero ?
No.
Ziosilvio
09-01-2005, 14:17
Originariamente inviato da LimiT-MaTz
Non riesco a capire che senso abbia fare una rand in virgola mobile compresa tra 0 e 1 ?
puoi spegarlo meglio?
Una frand scritta in quel modo, ha il vantaggio di essere uniforme, ossia la probabilità che il risultato cada in un qualsiasi sottoinsieme dell'insieme dei suoi valori, è proporzionale alla misura del sottoinsieme stesso.
Questo non è garantito dall'aritmetica modulare: per esempio, se rand può generare 32768 valori distinti, e tu fai una congruenza modulo 6, allora la probabilità che esca 0 è maggiore della probabilità che esca 5. Questo magari può essere poco importante su pochi lanci; ma è catastrofico se i lanci sono molti, e mi sembra che il caso in esame (gioco di ruolo online) sia proprio questo.
Inoltre, in genere è più facile ricostruire una distribuzione arbitraria a partire da una uniforme (quando è possibile), che non il contrario.
VegetaSSJ5
09-01-2005, 14:34
Originariamente inviato da Ziosilvio
per esempio, se rand può generare 32768 valori distinti, e tu fai una congruenza modulo 6, allora la probabilità che esca 0 è maggiore della probabilità che esca 5.
perchè c'è questa differenza di probabilità??
LimiT-MaTz
09-01-2005, 15:28
Originariamente inviato da VegetaSSJ5
perchè c'è questa differenza di probabilità??
Nemmeno io riesco a capirlo.
per
Compsognathus
/dado /say $chan Dado: $rand(1,6)
scrivitelo negli aliases e basta che digiti /dato in un chan
e avrai come output in quel chan: Dado: "numerorandom"
ciao
Originariamente inviato da VegetaSSJ5
perchè c'è questa differenza di probabilità??
Perche' 32768 non e' divisibile per 6.
VegetaSSJ5
09-01-2005, 16:37
Originariamente inviato da fek
Perche' 32768 non e' divisibile per 6.
se fosse solo questo il motivo allora basterebbe impostare RAND_MAX a 32772 che è divisibile per 6.
Ziosilvio
09-01-2005, 17:14
Originariamente inviato da VegetaSSJ5
se fosse solo questo il motivo allora basterebbe impostare RAND_MAX a 32772 che è divisibile per 6.
RAND_MAX è una costante (definita in stdlib.h o in limits.h, non ricordo) uguale al massimo valore restituito da rand --- la quale, da parte sua, restituisce con uguale probabilità tutti i valori interi tra 0 e RAND_MAX inclusi.
Non puoi ridefinire RAND_MAX senza ridefinire rand, e avere un sistema consistente.
VegetaSSJ5
09-01-2005, 17:31
a lezione è stato detto che era possibile tranquillamente ridefinire RAND_MAX.
Ziosilvio puoi spiegarmi cosa fa la funzione floor()? ho visto la man page di floor() ma sinceramente non mi è stata molto chiara...:confused:
arrotonda il numero all'intero più grande
cia
VegetaSSJ5
09-01-2005, 18:06
Originariamente inviato da NA01
arrotonda il numero all'intero più grande
cia
floor(x) = intero superiore di x, giusto?
dovrebbe, non tocco math.h da un pò ma mi sembra che sia così.
ho di dubbi sull'intero più grande, ma direi di si.
al massimo prova... mal che vada te lo porta al più piccolo
ciao
VegetaSSJ5
09-01-2005, 18:59
Originariamente inviato da NA01
dovrebbe, non tocco math.h da un pò ma mi sembra che sia così.
ho di dubbi sull'intero più grande, ma direi di si.
al massimo prova... mal che vada te lo porta al più piccolo
ciao
infatti è il più piccolo ;) ciao!
Ziosilvio
09-01-2005, 21:01
Originariamente inviato da VegetaSSJ5
a lezione è stato detto che era possibile tranquillamente ridefinire RAND_MAX.
Infatti è possibile. Quello che non si può fare è:
ridefinire RAND_MAX senza ridefinire rand, e avere un sistema consistente
tutto insieme.
Per l'altra domanda: se x è un double, allora floor(x) è un double che ha il valore del più grande intero non maggiore di x.
Per esempio: floor(1.5) è 1.0, ma floor(-1.5) è -2.0.
repne scasb
09-01-2005, 23:31
Ziosilvio
10-01-2005, 11:40
Originariamente inviato da repne scasb
C'e' un limite nel tuo ragionamento.
[CUT]
Simpatico; credo di aver anche capito perché funziona.
Un solo appunto: in C, main deve essere int.
EDIT: inoltre, ha il difetto di operare in tempo O(max_rnd), mentre di solito si vorrebbe un generatore in tempo O(1).
Ziosilvio
10-01-2005, 11:45
Molti generatori pseudorandom sono implementati mediante congruenze modulari iterate, cioè sono una cosa del tipo x_{n+1} = (ax_{n}+b) mod R.
Questo tipo di generatori ha il difetto che le cifre meno significative, hanno proprietà statistiche peggiori delle cifre più significative.
Ora, usare una congruenza modulare in modo brutale, per esempio facendo rand() % 6, significa proprio usare le cifre meno significative.
Convertire in virgola mobile, permette di considerare sempre tutte le cifre anziché solo quelle meno significative: in altre parole, il generatore uniforme fra 0 incluso e 1 escluso dato da (double)rand()/(RAND_MAX+1.), non ha proprietà statistiche peggiori di quelle di rand.
repne scasb
10-01-2005, 12:08
Ziosilvio
10-01-2005, 12:44
Originariamente inviato da repne scasb
Non volevo irritarti
E infatti non mi sono irritato.
Solo che ci ho messo un po' per capire come funzionava la cosa... mea culpa,
Volevo solo "evidenziare" che e' "possibile" distribuire "correttamente" i numeri pseudo-random generati da rand(), utilizzando solo "interi".
E ci sei riuscita.
In effetti, ripensandoci, credo ci sia anche un modo per farlo in tempo O(1) (ma non me lo ricordo).
repne scasb
10-01-2005, 12:56
^TiGeRShArK^
10-01-2005, 14:49
li conosciamo tutti :O
Windows è un generatore di BUG realmente casuali! :asd: ;)
Ziosilvio
10-01-2005, 16:04
Originariamente inviato da repne scasb
Vogliamo invece discutere di generatori "realmente" casuali su PC?
Vi accennavo per l'appunto nel mio primo post di questo thread...
VegetaSSJ5
10-01-2005, 22:53
ragazzi questa discussione sta diventando molto costruttiva, tuttavia non ci siamo, cioè non vi siete ;), messi d'accordo su quella che può essere una funzione random() che sia "veramente" casuale. fino a qualche giorno fa credevo che bastasse semplicemente fare uno srand(time()) e poi rand() ma da come ho visto la cosa è molto più complessa. possiamo tirar fuori da questa discussione una funzione che possa essere utilizzata in maniera standard nel c diventando LA funzione random()?
repne scasb
10-01-2005, 23:34
AnonimoVeneziano
10-01-2005, 23:42
Scusa , posso chiederti che linguaggio stai usando se non è C?
Grazie
Ciao
repne scasb
11-01-2005, 00:24
AnonimoVeneziano
11-01-2005, 00:28
Originariamente inviato da repne scasb
C--
:confused:
VegetaSSJ5
11-01-2005, 00:47
Originariamente inviato da AnonimoVeneziano
:confused:
condivido il tuo :confused:
chetidolanimale
11-01-2005, 04:00
scusate,mi spiegate perchè io faccio
srand(time(NULL));
e chiamando più volte rand()%10000; mi escono in sequenza questi numeri:
2824
2840
2850
2854
2860
2863
2870
3079
3115
e avanti così.....
chetidolanimale
11-01-2005, 04:05
invece se non utilizzo la srand, ogni volta che avvio il programma mi da sempre gli stessi numeri casuali, nello stesso ordine
41
8467
6334
eccetera:confused:
Originariamente inviato da chetidolanimale
scusate,mi spiegate perchè io faccio
srand(time(NULL));
e chiamando più volte rand()%10000; mi escono in sequenza questi numeri:
2824
2840
2850
2854
2860
2863
2870
3079
3115
e avanti così.....
Perchè srand(time(NULL)); lo devi fare solo una volta all'interno di tutto il programma...
repne scasb
11-01-2005, 10:36
VegetaSSJ5
11-01-2005, 11:26
:sbavvv: scusate ma non mi sono trattenuto... cmq tornando IT certo che puoi descriverci il C--.
chetidolanimale
11-01-2005, 13:13
Originariamente inviato da cionci
Perchè srand(time(NULL)); lo devi fare solo una volta all'interno di tutto il programma...
ok,in effetti srand la chiamavo ogni volta appena prima di rand....per curiosità,mi dici anche il motivo? e per l'altra domanda?
p.s.tanto di cappello a repne scasb:eek:
repne scasb
11-01-2005, 14:41
Ziosilvio
11-01-2005, 15:26
Originariamente inviato da chetidolanimale
ok,in effetti srand la chiamavo ogni volta appena prima di rand....per curiosità,mi dici anche il motivo?
Perché la teoria garantisce il "buon" comportamento della sequenza x_{n+1}=f(x_{n}) con x0 scelto arbitrariamente; non quello di x_{n}=f(y_{n}) con y_{n} scelto arbitrariamente per ogni n.
Il primo caso è quello in cui srand viene chiamata solo all'inizio; il secondo, quello in cui srand viene chiamata prima di ogni rand.
VegetaSSJ5
11-01-2005, 18:16
repne scasb sono senza parole...
mi fai venire voglia di cambiare mestiere...:rolleyes:
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.