Frustração/Nervos com Sorteio em ActionScript

Rexobias

Power Member
Olá malta.

Escrevo isto neste momento muito frustrado. Fiquei em fazer uma pequena aplicação em Flash/ActionScript que consiste num sorteio de 16 equipas por 4 grupos.

A verdade é que pensava terminar isto em pouco tempo, mas a verdade é bem pior. Tenho a certeza que o algoritmo está bem, assim como o código parece-me bem, e não encontro qualquer razão para não trabalhar ... a verdade é que o FlashPlayer tem dado o aviso de ciclo infinito, e não consigo perceber o porque do mesmo.

O programa tem 16 Dynamic Text Box's (cada uma para guardar o nome das equipas que resultam do sorteio, e cada uma com uma var atribuida no respectivo campo - pos1, pos2, etc...), e um botão que é que faz o sorteio começar. Como tal, o botão é o único que tem código, sendo este o seguinte:

----------------------------------------------------------

Código:
on (release){[/FONT][/I]
[i][FONT=Arial] var sort, aleat, ver, i: Number;
 var posicao = new Array();
 var teste = new Array();
 var equipas = new Array();
 
 equipas[0] = "FC Porto";
 equipas[1] = "SL Benfica";
 equipas[2] = "Sporting";
 equipas[3] = "Manchester Utd.";
 equipas[4] = "Arsenal";
 equipas[5] = "Chelsea";
 equipas[6] = "AC Milan";
 equipas[7] = "Inter";
 equipas[8] = "Juventus";
 equipas[9] = "Barcelona";
 equipas[10] = "Real Madrid";
 equipas[11] = "PSG";
 equipas[12] = "O.Lyon";
 equipas[13] = "Bayern Munchen";
 equipas[14] = "Werder Bremen";
 equipas[15] = "Celtic";
 sort = 0;
 i = 0;
 
 while (i < 16)
  {
  teste[i] = 20;
  i = i + 1;
  }
 
 while (sort < 16)
  { 
  ver = 0;
  i = 0;
  aleat = Math.floor(Math.random()*16); 
  teste[sort] = aleat;
  //Verifica se uma equipa já foi anteriormente sorteada
  
  [B]while (i < 16)
   {
   if (aleat == teste[I]){
    {
    ver = ver + 1;
    }
   i = i + 1;
   }
[/I][/B][I]    
 [B] if (ver == 0)
   {
[/B]   posicao[sort] = aleat;
   sort = sort + 1;
  [B] }
  }
[/B] }[/I][/FONT]
[I][FONT=Arial] pos1 = equipas[posicao[0]];
 pos2 = equipas[posicao[1]];
 pos3 = equipas[posicao[2]];
 pos4 = equipas[posicao[3]];
 pos5 = equipas[posicao[4]];
 pos6 = equipas[posicao[5]];
 pos7 = equipas[posicao[6]];
 pos8 = equipas[posicao[7]];
 pos9 = equipas[posicao[8]];
 pos10 = equipas[posicao[9]];
 pos11 = equipas[posicao[10]];
 pos12 = equipas[posicao[11]];
 pos13 = equipas[posicao[12]];
 pos14 = equipas[posicao[13]];
 pos15 = equipas[posicao[14]];
 pos16 = equipas[posicao[15]];
 
}

----------------------------------------------------------

Se retirar o código a negrito, que é responsável por fazer uma verificação ao valor gerado para evitar que uma equipa seja sorteada mais do que uma vez, o sorteio funciona, mas como é óbvio eu preciso de fazer a filtragem.

array teste - guarda os valores gerados para verificar a repetição dos mesmos
pos1, pos2, pos3, etc... - Variáveis atribuidas ás Dynamic Text's
 
Última edição pelo moderador:
Visto não perceber muito de Action Script, não consigo perceber onde é criado o loop infinito;
Não percebi este ciclo, se me puderes explicar:
Código:
while (i < 16)
{
teste[i] = 20;
i = i + 1;
}


No entanto proponho-te uma solução um pouco diferente, mas que funcionará às mil maravilhas:

Crias um segundo array com a mesma dimensão (sorteado[]) para depositar as equipas sorteadas.

Fazes o ciclo para o random, e deposita no array sorteado, a equipa sorteada, colocando de seguida esse índice do array equipas a Null;
Qualquer coisa do género:

Código:
i = 0;
while (i<16)
{
    aleat = random 16;
    if equipes[aleat] != Null
    {
            sorteado[aleat] = equipes[aleat];
            equipes[aleat] = Null;
            i++;
    }
}
(não ligues à sintaxe pois não é action Script, mas é facil de transpores)

Por fim preenches as tuas textboxes com os valores do sorteado[]
Assim condensas tudo na mesma repetição, o teste e a atribuição.

Espero que tenha ajudado.

Bom coding
 
Esse ciclo while que referes era para preencher o array que guarda os valores com os quais vou comparar o valor gerado. Preencho o mesmo para evitar problemas ao comparar registos vazios...de qualquer maneira, esse array teste só está a ocupar espaço pois podia usar o posicao, mas mesmo assim devia funcionar.

Eu que percebo algumca coisa de ActionScript, não apanho de forma alguma o problema, o código parece-me correcto.

Vou exprementar a tua proposta, obrigado pela atenção.
 
Estás correcto.

Faço isso que é para mais tarde quando faço a comparação de valores gerados com os valores do array evitar que aconteçam eventuais erros ao testar com indices vazios.
 
Aqui fica uma actualização do código com lixo eliminado e devidamente comentado ... mas infelizmente o Flash Player continua a avisar sobre um ciclo infinito.

Código:
on (release){
 
//Declaração de variáveis
var sort, ver, i: Number;
var posicao = new Array();
var equipas = new Array();
 
//Iniciação de variáveis
equipas[0] = "FC Porto";
equipas[1] = "SL Benfica";
equipas[2] = "Sporting";
equipas[3] = "Manchester Utd.";
equipas[4] = "Arsenal";
equipas[5] = "Chelsea";
equipas[6] = "AC Milan";
equipas[7] = "Inter";
equipas[8] = "Juventus";
equipas[9] = "Barcelona";
equipas[10] = "Real Madrid";
equipas[11] = "PSG";
equipas[12] = "O.Lyon";
equipas[13] = "Bayern Munchen";
equipas[14] = "Werder Bremen";
equipas[15] = "Celtic";
sort = 0;
i = 0;
 
//Preenche o array posicao com o valor 20 em 16 indices para evitar 
//problemas ao comparar com campos vazios mais tarde. O valor escolhido 
//foi 20 para assim não estar no intervalo que será gerado evitando 
//qualquer problema com os primeiros valores gerados
while (i < 16)
{
posicao[i] = 20;
i = i + 1;
}
 
//Ciclo que gera um valor aleatório para sortear as equipas
//e faz a verificação de equipas repetidas
while (sort < 16)
{ 
ver = 0;
i = 0;
posicao[sort] = Math.floor(Math.random()*16); 
 
//Verifica se uma equipa já foi anteriormente sorteada comparando 
//o índice em análise do array posicao com todos os índices existentes 
//do mesmo array. A variável ver vai registar a quantidade de vezes 
//que a equipa foi encontrada 
while (i < 16)
{
if (posicao[sort] == posicao[i])
{
ver = ver + 1;
}
i = i + 1;
}
 
//Analisa o resultado do contador ver. Se o valor for zero significa 
//que o valor gerado é novo e será registado, incrementando um valor 
//no contador do while, fazendo com que o programa avance um índice. 
//Caso este seja superior, o contador não sofre qualquer aletração 
//obrigando o ciclo a repetir-se e assim gerar outro valor
if (ver == 0)
{
sort = sort + 1;
}
}
//Regista os resultados do array posicao que teoricamente devem ter 
//todos um valor único entre 0 e 15 
pos1 = equipas[posicao[0]];
pos2 = equipas[posicao[1]];
pos3 = equipas[posicao[2]];
pos4 = equipas[posicao[3]];
pos5 = equipas[posicao[4]];
pos6 = equipas[posicao[5]];
pos7 = equipas[posicao[6]];
pos8 = equipas[posicao[7]];
pos9 = equipas[posicao[8]];
pos10 = equipas[posicao[9]];
pos11 = equipas[posicao[10]];
pos12 = equipas[posicao[11]];
pos13 = equipas[posicao[12]];
pos14 = equipas[posicao[13]];
pos15 = equipas[posicao[14]];
pos16 = equipas[posicao[15]];
 
}
Não consigo perceber o que está errado :(

P.S: andre, tentei o teu código mas não compreendi aquilo do Null :( e de qualquer maneira quero saber porque que este não funciona...
 
Última edição pelo moderador:
Baderous, estou a incrementar no final. Só incremento após o valor gerado ter sido introduzido com sucesso. :( Infelizmente ao fazer copy/paste ele retirou as tabulações o que dificulta a leitura do código, mas com os comentários penso que se percebe a lógica.

andre, será que podias passar o pseudocódigo (ou o código bem comentado) para eu tentar perceber, é que sinceramente não percebi antes :(
 
Código:
 i = 0;
while (i<16) //com este while executas o bloco, tantas vezes qtas forem necessárias              //até ele preencher as 16 equipes no novo vector sorteado[]
{
    aleat = random 15; // aqui atribuis à variável aleat, um valor inteiro aleatório de 0 a 15
    if equipes[aleat] != Null //Testa se o índice aleat do array equipes não é um valor vazio
    {
            //Tinha-me enganado no código inicial. repara no vermelho
            sorteado[i] = equipes[aleat]; //atribuis a equipe seleccionada aleatóriamente ao indice [i] do array sorteado
            //Quando uma equipe passa para o array Sorteado, deixa de ter interesse no original, a linha seguinte apaga-a
            //permite também o teste do IF em cima
            equipes[aleat] = Null;
            //Incrementas o indice i, se e só se atribuiste uma equipe ao novo array
            i++;
    }
}

Assim funciona certamente, qq dúvida apita
 
andre, muito obrigado, agora percebi, só há um problema ... não sei usar o Null em ActionScript (nada que ao googlar nao se resolva - edit: já googlei e é como em C).

Se isto funcionar (e parece-me que sim, o código está bem mais optimizado), tenho que te pagar uma cerveja, aliás, mesmo senão funcionar tenho que pagar-te na mesma como agradecimento pelo apoio.

O problema na questão é que não vejo razão para que o código que fiz não funcionar
 
Código:
on (release){
 
//Declaração de variáveis[INDENT] var sort, ver, i: Number;
var posicao = new Array();
var equipas = new Array();
[/INDENT]//Iniciação de variáveis[INDENT] equipas[0] = "FC Porto";
equipas[1] = "SL Benfica";
equipas[2] = "Sporting";
equipas[3] = "Manchester Utd.";
equipas[4] = "Arsenal";
equipas[5] = "Chelsea";
equipas[6] = "AC Milan";
equipas[7] = "Inter";
equipas[8] = "Juventus";
equipas[9] = "Barcelona";
equipas[10] = "Real Madrid";
equipas[11] = "PSG";
equipas[12] = "O.Lyon";
equipas[13] = "Bayern Munchen";
equipas[14] = "Werder Bremen";
equipas[15] = "Celtic";
sort = 0;
i = 0;
[/INDENT]//Preenche o array posicao com o valor 20 em 16 indices para evitar 
//problemas ao comparar com campos vazios mais tarde. O valor escolhido 
//foi 20 para assim não estar no intervalo que será gerado evitando 
//qualquer problema com os primeiros valores gerados[INDENT] while (i < 16) {[INDENT] posicao[i] = 20;
i++;
[/INDENT]}
[/INDENT]//Ciclo que gera um valor aleatório para sortear as equipas
//e faz a verificação de equipas repetidas[INDENT] while (sort < 16) {[INDENT] ver = 0;
i = 0;
posicao[sort] = (int) (Math.random()*16); 
[/INDENT]//Verifica se uma equipa já foi anteriormente sorteada comparando 
//o índice em análise do array posicao com todos os índices existentes 
//do mesmo array. A variável ver vai registar a quantidade de vezes 
//que a equipa foi encontrada[INDENT] while (i < sort) {[INDENT] if (posicao[sort] == posicao[i]) {[INDENT] ver++;
break;
[/INDENT]}
[/INDENT]i++;
}
[/INDENT]//Analisa o resultado do contador ver. Se o valor for zero significa 
//que o valor gerado é novo e será registado, incrementando um valor 
//no contador do while, fazendo com que o programa avance um índice. 
//Caso este seja superior, o contador não sofre qualquer aletração 
//obrigando o ciclo a repetir-se e assim gerar outro valor[INDENT] if (ver == 0) {[INDENT] sort++;
[/INDENT]}
[/INDENT]}
[/INDENT]//Regista os resultados do array posicao que teoricamente devem ter 
//todos um valor único entre 0 e 15[INDENT] pos1 = equipas[posicao[0]];
pos2 = equipas[posicao[1]];
pos3 = equipas[posicao[2]];
pos4 = equipas[posicao[3]];
pos5 = equipas[posicao[4]];
pos6 = equipas[posicao[5]];
pos7 = equipas[posicao[6]];
pos8 = equipas[posicao[7]];
pos9 = equipas[posicao[8]];
pos10 = equipas[posicao[9]];
pos11 = equipas[posicao[10]];
pos12 = equipas[posicao[11]];
pos13 = equipas[posicao[12]];
pos14 = equipas[posicao[13]];
pos15 = equipas[posicao[14]];
pos16 = equipas[posicao[15]];
[/INDENT]}

Nunca usei ActionScript, mas diria que assim deveria funcionar.
PS.: Quando ele vai ver se já existe, não precisa de ver as posições à frente do sort. NEM a do Sort (obviamente vai ser igual e nunca sai!)
Problema resolvido.
ex.: posicao[0] = 10
posicao[0] == posicao[0] ? Obvio que sim, e nunca vai sair do while.
 
Última edição pelo moderador:
anjo2, muito obrigado pela ajuda, mas é ActionScript e não JavaScript :D

andre, apliquei o teu código e nada, dá o mesmo aviso de ciclo infinito. Nesse aviso posso escolher para cancelar ou continuar ... a primeira cancela e se escolher a segunda, bloqueia...

Código:
on (release){
 
 //Declaração de variáveis
 var sort, aleat, i: Number;
 var sorteado = new Array();
 var equipas = new Array();
 
 //Iniciação de variáveis
 equipas[0] = "FC Porto";
 equipas[1] = "SL Benfica";
 equipas[2] = "Sporting";
 equipas[3] = "Manchester Utd.";
 equipas[4] = "Arsenal";
 equipas[5] = "Chelsea";
 equipas[6] = "AC Milan";
 equipas[7] = "Inter";
 equipas[8] = "Juventus";
 equipas[9] = "Barcelona";
 equipas[10] = "Real Madrid";
 equipas[11] = "PSG";
 equipas[12] = "O.Lyon";
 equipas[13] = "Bayern Munchen";
 equipas[14] = "Werder Bremen";
 equipas[15] = "Celtic";
 sort = 0;
 i = 0;
 
 while (i < 16)
  {
  aleat = Math.floor(Math.random()*15); 
     if (equipas[aleat] != null)
      {
            sorteado[i] = equipas[aleat]; 
            equipas[aleat] = null;
            i = i + 1;
      }
  }
 //Regista os resultados do array posicao que teoricamente devem ter 
 //todos um valor único entre 0 e 15 
 pos1 = sorteado[0];
 pos2 = sorteado[1];
 pos3 = sorteado[2];
 pos4 = sorteado[3];
 pos5 = sorteado[4];
 pos6 = sorteado[5];
 pos7 = sorteado[6];
 pos8 = sorteado[7];
 pos9 = sorteado[8];
 pos10 = sorteado[9];
 pos11 = sorteado[10];
 pos12 = sorteado[11];
 pos13 = sorteado[12];
 pos14 = sorteado[13];
 pos15 = sorteado[14];
 pos16 = sorteado[15];
 
}

Tou a começar a pensar que deve ser alguma limitação ou diferença de syntax's no Flash/ActionScript (embora o compilador do Flash dizer que está tudo correcto), pois ambos os algoritmos estão correctos e deviam funcionar.
 
Última edição pelo moderador:
Tens a certeza que isto está correcto???

Código:
aleat = Math.floor(Math.random()*15);

não consigo encontrar nada ali que gere um ciclo infinito. e este random, é o único elemento comum
 
Só um aparte. Quando geras um numero aleatorio, vais ter de comparar com os que já sairam. Não podes tirar 2 vezes a mesma equipa :)

Em relação ao código não conheço muito bem Actionscript, mas eu mudava os While para Ciclos For, pois assim garantes que sais sempre dos ciclos.
 
andre, sim está correcto, pois já testei e foi copiado de um outro trabalho meu :D

anjo2, terei que adaptar e ver, mas se o meu e o do andre não funcionam sem razão aparente. Amanha expremento.

Karski, é isso mesmo que é feito. Em relação aos For, os While vão dar ao mesmo penso eu), mas amanha expremento...
 
Só um aparte. Quando geras um numero aleatorio, vais ter de comparar com os que já sairam. Não podes tirar 2 vezes a mesma equipa :)

Em relação ao código não conheço muito bem Actionscript, mas eu mudava os While para Ciclos For, pois assim garantes que sais sempre dos ciclos.
Não pode, porque se já existir, vai ter que gerar outro e ver de novo se já existe.
 
andre, sim está correcto, pois já testei e foi copiado de um outro trabalho meu :D

anjo2, terei que adaptar e ver, mas se o meu e o do andre não funcionam sem razão aparente. Amanha expremento.

Karski, é isso mesmo que é feito. Em relação aos For, os While vão dar ao mesmo penso eu), mas amanha expremento...
Leste o meu post? Eu disse onde o teu ficava, nem sai da posição 0.
 
Back
Topo