GUJ Discussões   :   últimos tópicos   |   categorias   |   GUJ Respostas

Erro ao utilizar sequencia de números aleatórios - RESOLVIDO

Boa noite
Comecei a fazer um jogo (spider solitaire) em J2ME. Para tanto, criei um método que gera uma sequencia de números inteiros aleatórios sem repetição (geraSeqAleatoria()). Dentro do método run eu tenho o método inicializaJogo que chama o método geraSeqAleatoria(). Estou usando o NetBeans. O problema é que a lista de aleatórios não é passada de um método para o outro. Se eu faço no eclipse (J2SE) dá certo. Não aparece nenhum erro, simplesmente não é impressa na tela. Tenho a impressão de ser algum problema relacionado à capacidade de memória (me corrijam se eu estiver falando besteira). Já fiz diversas tentativas e nem sei onde atacar.

Se alguém puder testar pra mim, eu envio a imagem do sprite por e-mail (esthercamilo@gmail.com)

Vou postar o código juntamente com toda a configuração que utilizei:

Netbeans 6.7 - J2ME - CLDC 1.1 MIDP - 2.0

ClasseMeuCanvas.java

[code]import java.io.IOException;
import java.util.Random;
import javax.microedition.lcdui.game.;
import javax.microedition.lcdui.
;

public class ClasseMeuCanvas extends GameCanvas implements Runnable {

Thread meuThread;
Graphics meuGrafico = this.getGraphics();
Image baralho;
Sprite[] carta = new Sprite[56];
LayerManager meuLayerManager;

public ClasseMeuCanvas() {
    super(false);
    meuThread = new Thread(this);
    meuThread.start();
}

public void determinaCartas() {
    try {
        baralho = Image.createImage("/images/baralho.png");
         int[] sprite = new int[55];
        for (int i = 0; i <= 54; i++) {
            sprite[i] = i;
        }            for (int j = 0; j <= 5; j++) {

            for (int i = 0; i <= 9; i++) {

                carta[j * 10 + i] = new Sprite(baralho, 15, 20);
                carta[j * 10 + i].setFrameSequence(sprite);
                carta[j * 10 + i].setFrame(j * 10 + i);

                if (j * 10 + i > 52) {
                    break;
                }
            }
        }

    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

public int[] geraSeqAleatoria(int tamanho) {
    Random random = new Random();
    int i = 0;
    int aux = 0;

    int[] seqAleatoria = new int[tamanho]; //array vazia {0,0,0,.....}
    while (i <= tamanho) {
        boolean repete = false;
        aux = random.nextInt(tamanho);   //gera um número aleatório, por ex.  3

        for (int j = 0; j <= tamanho - 1; j++) { //percorre a seqAleatorio pra ver se tem o 3
            if (aux == seqAleatoria[j]) {
                repete = true;
                break;                      // se encontra sai do laço
            } else {
                continue;   //se não encontra percorre a array até o final e repete é false
            }
        }

        if (repete == false) {
            seqAleatoria[i] = aux;
            System.out.println(seqAleatoria[i]);
            i++;
        }

    }
    System.out.println(seqAleatoria);
    return seqAleatoria;
}

public void inicializaJogo() {
    meuLayerManager = new LayerManager();
    meuLayerManager.append(carta[1]);
    carta[1].setPosition(10, 10);
    geraSeqAleatoria(10);

}

public void run() {

    determinaCartas();
    inicializaJogo();

    boolean fimDeJogo = false;
    while (fimDeJogo == false) {
        try {
            meuLayerManager.paint(meuGrafico, 0, 0);
            meuThread.sleep(50);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        } finally {

            flushGraphics();
        }
    }
}

}
[/code]

Midlet.java

[code]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */

import javax.microedition.lcdui.Display;
import javax.microedition.midlet.*;

/**

  • @author Professor
    */
    public class Midlet extends MIDlet {

    Display meuDisplay = Display.getDisplay(this);
    ClasseMeuCanvas meuCanvas = new ClasseMeuCanvas();

    public void startApp() {
    meuDisplay.setCurrent(meuCanvas);
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }
    }
    [/code]

Esse método está extremamente ineficiente. Ele percorre a lista várias vezes, e pode ser que demore muito até sortear um número que não esteja nela, principalmente quando a lista estiver praticamente cheia.

Eis uma versão muitíssimo mais eficiente dele. Nela é garantido que a lista será percorrida exatamente duas vezes:

[code] public int[] geraSeqAleatoria(int tamanho) {
Random random = new Random();

  // Array em ordem
  int[] seqAleatoria = new int[tamanho];
  for (int i = 0; i < tamanho; i++) {
     seqAleatoria[i] = i;
  }

  // Embaralhamos o array
  for (int i = 0; i < tamanho - 1; i++) {
     int max = tamanho - i - 1;
     int ind = random.nextInt(max);

     int aux = seqAleatoria[ind];
     seqAleatoria[ind] = seqAleatoria[max];
     seqAleatoria[max] = aux;
  }
  return seqAleatoria;

}
[/code]

Basicamente a modificação é gerar uma sequencia em ordem e embaralha-la através do seguinte algoritmo:

  1. Sorteie um número do indice 0 até o tamanho da sequencia ordenada-2;
  2. Troque esse número com o do último índice. O do último índice agora está embaralhado;
  3. Repita o passo 1 até a sequencia estar toda embaralhada;

Exemplo: Para a sequencia de 10 números:
[color=brown]0 1 2 3 4 5 6 7 8 9[/color] -> Sorteamos um número de 0 até 9 -> 4
0 1 2 3 [color=red]4[/color] 5 6 7 8 [color=blue]9[/color] -> Trocamos o elemento 4 com o último índice ordenado ( 9 )
0 1 2 3 9 5 6 7 8 [color=green]4[/color] -> O último índice encontra-se embaralhado
[color=brown]0 1 2 3 9 5 6 7 8[/color] 4 -> Sorteamos um número de 0 até 8 -> 1
0 [color=red]1[/color] 2 3 9 5 6 7 [color=blue]8[/color] 4 -> Trocamos o elemento 1 com o último índice ordenado ( 8 )
0 8 2 3 9 5 6 7 [color=green]8 4[/color] -> Os últimos índices encontram-se embaralhados.

Repetimos o processo até percorrermos o array todo. Isso garante muito mais performance e boa distribuição.

Talvez o problema seja que num dispositivo lento, seu método está demorando demais a executar. Tente substituir por essa versão bem mais rápida e teste. Não coloquei dentro do método o println que imprime a sequencia.

então era o problemas de memória mesmo por ineficiência do código. Nem sei como agradecer Vini. Muito obrigada mesmo!

Esther :smiley:

Memória não era, era só velocidade de execução mesmo.

Mas que bom que o problema foi resolvido. :slight_smile: