
Programação Gráfica em Java, parte I: Caixas de Diálogo
Programação gráfica em Java, GUI e 2D: Introdução
Vamos dar início em nossa apostila online ao uso de elementos gráficos em Java, e vamos iniciar com as tão famosas caixas de diálogo,
que são aquelas caixinhas com mensagens e botões, que geralmente vemos com algum aviso de erro ou alerta.
Programação Gráfica, GUI e desenhos 2D em Java
Quando pensamos em programar logo pensamos em criar um jogo em 3D super moderno que exige o máximo de uma placa de vídeo ou em criar um sistema operacional bem seguro.
Mas não importa a linguagem que estudemos, sempre começamos com algumas 'bobagens' básicas e não vemos nada gráfico, só janelas pretas (MS-DOS ou Terminal-Linux) ou aquela janelinha onde aparecem o resultado dos programas nas IDEs, como no NetBeans ou no Eclipse.
Isso não é à toa ou por conta de cursos ou livros mal feitos. Faz parte.
Tem que começar por essas coisas mais simples mesmo, como fizemos em nosso curso Java Progressivo.
Para criar aplicações com menus, botões e janelas tem que começar por coisas mais simples e muitas vezes tidas como 'bobas' e inúteis.
Porém, se chegou aqui, já está na hora de ver algumas ferramentas gráficas em ação. De fazer algumas janelas, ver alguns botões e caixas de diálogo. Ao longo do curso você verá mais dos chamados elementos GUI - Graphics User Interface, ou interface gráficas do usuário.
Mas não se engane. Isso é somente uma 'facilidade' para o usuário.
Na verdade, para o programador, isso só complica. Vai ter que programar do mesmo jeito, imaginar as besteiras que usuário pode fazer e tentar minimizar esses problemas além de prever os possíveis atos do cliente.
Verá que por trás de um clique existe um grande esquema de código que irá tratar o evento,
que pode ser um clique, ou algum botão que foi pressionado. E existem muitos botões e muitos locais que podem ser clicados.
Exibindo mensagens através das caixas de diálogo
Caixas de diálogo, ou Dialog Box, são os elementos gráficos mais simples. Mas não menos importantes, e certamente os mais comuns que vemos. São vistos como mensagens de erros e de alertas nos sistemas operacionais.
Vamos mostrar como declarar e exibir mensagens através das dialog boxes.
Caixas de diálogo em Java
Para usarmos as caixas de diálogo precisamos importar uma classe do pacote (package) javax.swing,
que é um pacote que usaremos bastante em nossas aplicações gráficas Java.
Essa classe é estática e se chama JOptionPane.
Se acostume com esses nomes começados com J: JLabel, JButton, JTextField...
A importação, portanto, é: import javax.swing.JOptionPane;
Exibindo mensagens nas caixas de diálogos
Para exibir mensagens em uma dialog box, usaremos o método showMessageDialog, que recebe dois argumentos.
O primeiro se refere à posição da caixa de diálogo (por hora, não nos preocuparemos com ele e enviaremos o argumento 'null')
e o segundo é a string que será exibida.
Um exemplo completo de seu primeiro programa gráfico em Java é:
import javax.swing.JOptionPane; public class grafico { public static void main(String[] args){ JOptionPane.showMessageDialog(null,"Meu primeiro programa gráfico!\n Obrigado, Curso Java Progressivo!"); } }
Note que não precisamos declarar um objeto da classe JOptionPane, pois a classe é static.
Mais a frente, quando explicarmos melhor Orientação a Objetos e classes, saberá melhor o que isso quer dizer.
Note que podemos exibir uma string tanto do jeito que foi mostrado no programa, ou declarando uma variável do tipo String 'mensagem' e usando:
JOptionPane.showMessageDialog(null,mensagem);
Por exemplo, para o usuário entrar com uma string através de um objeto 'entrada' da classe 'Scanner', usamos o comando:
mensagem = entrada.nextLine();
Então, um aplicativo que recebe uma string do usuário e mostra na caixa de diálogo ficaria:
import javax.swing.JOptionPane; import java.util.Scanner; public class caixasDeTexto { public static void main(String[] args){ String mensagem; Scanner entrada = new Scanner(System.in); System.out.print("Digite a mensagem a ser exibida na caixa de diálogo: "); mensagem = entrada.nextLine(); JOptionPane.showMessageDialog(null,mensagem); } }
Note que, por padrão, nesses exemplos mais simples o Java mostra um botão de 'OK' e as opções de minimizar e fechar, além de um ícone do Java e outro de exclamação.
Tudo isso com pouquíssimo código.
Isso é uma vantagem do Java, a programação gráfica. Podemos facilmente alterar esses ícones e colocar mais botões e funções, como veremos ao longo do curso.
Recebendo dados do usuário através das caixas de diálogo
Vimos no artigo passado que as caixas de diálogo - ou dialog box - são muito usadas para exibir mensagens (principalmente de erros e alertas), e mostramos como fazer isso. Porém, também podem ser usadas (e vamos mostrar como fazer isso) para receber dados do usuário, através de uma interface mais amigável e gráfica :)
Como usar as caixas de diálogo para receber dados do usuário em Java
Para usarmos as caixas de diálogo precisamos importar uma classe do pacote (package) javax.swing,
que é um pacote que usaremos bastante em nossas aplicações gráficas Java.
Essa classe é estática e se chama JOptionPane.
Se acostume com esses nomes começados com J: JLabel, JButton, JTextField...
A importação, portanto, é:
import javax.swing.JOptionPane;
Recebendo informações do usuário através das caixas de diálogo
É uma espécie de classe 'Scanner', onde o usuário irá digitar algo e essa informação será atribuída a uma string.
Quando mostramos informações, usamos o método showMessageDialog.
Agora usaremos o método showInputDialog.
Note que não faz sentido simplesmente aparecer uma caixa de diálogo que recebe dados do usuário. É preciso que essa Dialog Box exiba alguma informação, como 'Qual seu nome?', 'Login', 'Senha' etc.
No caso do método showInputDialog, ele irá receber uma string (digitada pelo usuário) e exibirá uma mensagem na caixa de diálogo, essa mensagem será digitada entre parênteses do método showInputDialog e tudo que será digitado pelo usuário será armazenado na string 'nome', pois iremos perguntar o nome do usuário.
Logo após, iremos exibir o nome do usuário. Como exibir?
Ora, através de uma caixa de diálogo que exiba um texto, isso já aprendemos na aula passada.
Nosso aplicativo que pergunta o nome do cliente e exibe uma mensagem gentil é:
import javax.swing.JOptionPane; public class recebe_dados { public static void main(String[] args){ String nome; nome = JOptionPane.showInputDialog("Digite seu nome, caro usuário."); JOptionPane.showMessageDialog(null,nome +"???\nNossa, que nome feio! \nPelo menos sabe programar em Java!"); } }
Um método útil da classe String é o format, que formata a string, ou seja, altera, muda a string para o jeito que você quiser.
No nosso caso, seria útil usar esse método assim:
nome = String.format(nome +"???\nNossa, que nome feio! \nPelo menos sabe programar em Java!");
E usar a string 'nome' na JOptionPane.showMessageDialog assim:
JOptionPane.showMessageDialog(null,nome);
No próximo artigo mostraremos como transformar as informações, que são do tipo String, em tipos inteiro, float, double etc.
Como passar variáveis do tipo String para int, float e double
Nos dois artigos passados aprendemos como exibir mensagens e receber dados a partir das caixas de diálogos.
Porém, notamos que as caixas de diálogos fazem tudo isso através do tipo String.
Mas palma, palma, palma. Não criemos cânico. Pois podemos transformar o que foi digitado como string em inteiro, float, double...
Transformando string em inteiro em Java
Suponha que, através do método showInputDialog visto no artigo passado, tenhamos pedido um número ao usuário.
Ok. O usuário pediu, mas este foi armazenado numa String 'numeroString'.
Para passar essa string para inteiro, vamos usar o método da classe String chamado parseInt, da classe estática Integer.
Suponha que vamos armazenar esse valor inteiro em 'numInteiro', ficaria assim:
numInteiro = Integer.parseInt(numeroString);
Como exemplo, vamos criar um aplicativo que peça dois inteiros ao usuário e mostre a soma como resultado:
import javax.swing.JOptionPane; public class somaGrafica { public static void main(String[] args){ String valor, resultado; int num1, num2; valor = JOptionPane.showInputDialog("Digite o primeiro valor inteiro"); num1 = Integer.parseInt(valor.trim()); valor = JOptionPane.showInputDialog("Digite o segundo valor inteiro"); num2 = Integer.parseInt(valor.trim()); resultado=String.format("Resultado: %d", num1+num2); JOptionPane.showMessageDialog(null,resultado); } }
A maioria dos cursos, tutoriais e livros por aí simplesmente se daria por satisfeito em ensinar como:
num1 = Integer.parseInt(valor);
Sem esse '.trim()'
Faça um teste. Digite '1 ', isso mesmo, com um espaço antes ou depois.
Você terá um baita erro. E aí?
'Que programa ruim!'
Pensaria qualquer usuário que, sem querer, colocasse um espaço e visse essa mensagem de erro.
O curso Java Progressivo tem por objetivo ensinar você a criar aplicações reais, coisas que aprendi na prática e nenhum site me disse nem vi nos livros.
Esse '.trim()' retira os espaços de uma string, pois ESPAÇOS NÃO INTERESSAM EM UM NÚMERO!
Com o .trim() você deixa seu aplicativo mais robusto, à prova de bobagens dos usuários! E acredite, eles são bem criativos!
Transformando string em float
numFloat = Float.parseFloat(numeroString);
Transformando string em double
numDouble = Double.parseDouble(numeroString);
Exercício:
Propus e fiz um aplicativo que recebe os coeficientes de uma equação do segundo grau e retorna suas raízes, até as complexas, confira:
http://www.javaprogressivo.net/2012/08/aplicativo-determina-as-raizes-de-uma.html
Depois propus, nos exercícios de métodos, que fizesse o mesmo, mas quebrando ele em métodos, pra ficar reutilizável:
http://www.javaprogressivo.net/2012/09/questoes-envolvendo-metodos-java.html
Agora faça o mesmo. Um programa que receba os coeficientes de uma equação do segundo grau e retorne suas raízes, mesmo as complexas, mas através de caixas de diálogos.
Note que esse é realmente um programa útil.
Na próxima seção vamos ensinar como fazer seus aplicativos se tornarem 'executáveis' para que você possa mandar programas (gráficos, claro) para seus amigos!
Aplicativo gráfico:
mostra as raízes de uma equação do segundo grau
Exercício:
Faça um programa que receba os coeficientes de uma equação do segundo grau e retorne suas raízes, mesmo as complexas, através de caixas de diálogo.
Programa em Java
Passo 1:
Primeiro o programa recebe os dados do usuário, que são os 3 coeficientes da equação, 'a', 'b' e 'c':
ax² + bx + c = 0
Passo 2:
Uma equação do 2o grau só é do segundo grau se 'a' for diferente de 0.
Caso o usuário entre com o valor 0 o programa entrará em um loop até que o usuário entre com um valor diferente de 0.
Passo 3:
Se delta for maior ou igual a 0 as raízes serão reais e são facilmente calculadas pela fórmula de Bháskara.
Passo 4:
Caso não seja, as raízes serão complexas.
Para calcular as raízes complexas fazemos delta ser positivo (-delta), tiramos sua raiz e calculamos separadamente a parte real e a parte imaginária.
xxx
import javax.swing.JOptionPane; public class bhaskara_dialogBoxes { public static float delta(float a, float b, float c){ return (b*b - 4*a*c); } public static void main(String[] args){ String valor, raizes; float a=0, b, c, //coeficientes delta, //delta sqrtdelta, //raiz quadrada de delta raiz1,raiz2; //raízes //PASSO 1: recebe os coeficientes valor = JOptionPane.showInputDialog("Digite o valor de a"); a = Float.parseFloat(valor.trim()); valor = JOptionPane.showInputDialog("Digite o valor de b"); b = Float.parseFloat(valor.trim()); valor = JOptionPane.showInputDialog("Digite o valor de c"); c = Float.parseFloat(valor.trim()); //PASSO 2: checa se 'a' não é 0 while(a==0){ if(a==0){ valor = JOptionPane.showInputDialog("'a' não pode ser 0. Insira outro valor"); a = Float.parseFloat(valor.trim()); } } //PASSO 3: checa se o delta é positivo. Se for, mostra as raízes reais if(delta(a,b,c)>=0){ raiz1 = (-b + (float)Math.sqrt(delta(a,b,c)))/(2*a); raiz2 = (-b - (float)Math.sqrt(delta(a,b,c)))/(2*a); raizes = String.format("As raízes são: %.2f e %.2f", raiz1,raiz2); JOptionPane.showMessageDialog(null,raizes); //PASSO 4: caso seja negativo, devemos formatar para a exibição para números complexos } else { raizes = String.format("As raízes são:\n" + "%.2f + %.2fi\n" + "%.2f - %.2fi",(-b/(2*a)), ( (float)Math.sqrt(-delta(a,b,c) ) / (2*a) ) ,(-b/(2*a)), ( (float)Math.sqrt(-delta(a,b,c) ) / (2*a) ) ); JOptionPane.showMessageDialog(null,raizes); } } }
Construindo (build) seu projeto Java no NetBeans
Ok, você criou sua aplicação gráfica, já sabe fazer vários aplicativos e tal. Mas você quer mostrar ao mundo seus programas, como fazer?
Vai mandar a pasta como o projeto pros outros? Vai mandar eles baixarem o NetBeans pra rodarem seus programas em Java? Claro que não. Você tem que fazer o build e enviar o seu programa prontinho pra ser usado para o mundo.
Transformando seu programa em Java em executável
Já notou que sempre vai criar um projeto no NetBeans você escolhe um local e um nome, no campo 'Project Location'?
Já teve a curiosidade de ir lá e dar uma fuçada nos arquivos que existem e são criados pro funcionamento de seus aplicativos Java?
Sabia que, diariamente, você usa dezenas de aplicativos Java? E quantas vezes viu essas pastas e arquivos com extensão .java, .xml e .class?
Ora, se nunca precisou usar, não vai precisar ficar mandando isso pros outros.
Vou mostrar agora uma, das várias maneiras, de uma pessoa, sem NetBeans, rodar seus aplicativos Java.
Clean and Build Project no NetBeans
Abra seu projeto. Por exemplo, o aplicativo do exemplo passado, que calcula pra você as raízes de uma equação do segundo grau de modo totalmente gráfico. Perfeito pra mandar pros seus colegas ou irmão. Sabe o botão de play que você clica para rodar os programas que você aqui do curso Java Progressivo? Já se perguntou para que serve para aqueles outros botões ao redor?
Pois é, vamos usar o da 'vassoura' com 'martelo', que fica ao lado, na esquerda: Essa opção vai 'limpar' e 'construir' seu aplicativo (Clean and Build Main Project), ou seja, vai ajeitar, juntar as classes, figuras e tudo mais que você tenha usado em sua aplicação e colocar tudo em um único arquivo de extensão .jar
Provavelmente você já viu arquivos com extensão .jar quando baixou jogos ou aplicativos para celular. São os mesmos, mas agora você vai criar um :) Dentro desse arquivo, vão estar todos os aparatos para uma pessoa que tenha o JRE possa rodar seu aplicativo Java. Esse arquivo estará localizado dentro da pasta/diretório 'dist' que foi criado durante o processo de building. Vá lá e clique no .jar, isso deve fazer com que seu programa rode sem o NetBeans. Agora mande e venda seus aplicativos, fique rico e não esqueça do Java Progressivo :)
Estrutura de Dados, parte I: Array e ArrayList
Introdução aos tipos de Estrutura de Dados em Java
Até o momento, em nossa apostila online Java Progressivo, vinhamos declarando os tipos um por um, notou?
Talvez não, pois é algo normal para você.
Imagine a seguinte situação: você foi contratado para criar um aplicativo Java para um colégio, de mais de 2mil alunos.
Entre outras coisas, vai ter que criar tipos - float, provavelmente - , para armazenar as notas dos alunos, inteiros para armazenar as faltas, strings para os nomes etc.
E aí, vai declarar milhares de variáveis? Uma por uma?
Não! Aprenda estrutura de dados.
Estrutura de dados em Java
Uma das grandes utilidades dos programas, em Java por exemplo, é poder tratar grandes quantidades de informações.
Já imaginou quantos floats, inteiros e strings são declarados nos softwares do governo brasileiro?
Milhões? Claro que não. Milhões é só o número de habitantes.
Cada habitante tem seu nome, cpf, RG, endereço, impostos, ficha criminal, de saúde, de emprego etc etc.
Já pensou como manipular tudo isso?
Até o momento, no curso Java Progressivo, estávamos declarando variável por variável.
Obviamente que em uma aplicação como a do governo isso é humanamente impossível.
Aliás, nem precisa ser de um governo.
Os dados de uma empresa de médio porte já são grandes o suficiente para não ser possível a criação de cada variável 'manualmente'.
Para isso, usamos meios especiais, as estrutura de dados,
como os arrays (também conhecidos como vetores), arraylists, listas, filas e pilhas.
Estrutura de dados em Java: Array e ArrayList
Nesta seção de estrutura de dados, vamos dar uma introdução as tão importantes ferramentas para se trabalhar com muitos dados e informações.
De uma maneira simples, podemos definir os Array - ou vetor- e ArrayList como um conjunto de variáveis do mesmo tipo.
Em vez de declarar um tijolo por vez, vamos usar Arrays para declarar uma parede, com vários blocos de tijolos iguais, uma única vez.
Por exemplo, em vez de declararmos vários inteiros, um por um, até termos declarado 50 variáveis inteiras, vamos usar Array para declarar um bloco de 50 variáveis, todas do mesmo tipo e enumeradas de forma seqüencial.
Array é simplesmente isso. Um bloco de variáveis do mesmo tipo enumeradas em seqüência.
ArrayList são Arrays mais potentes, ou seja, são Arrays mas com utilidades (e complexidade) a mais.
Não entraremos mais em detalhes sobre Array e ArrayList pois esta seção é dedicada ao seu estudo.
Vamos falar um pouco sobre as outras estruturas de dados, que serão tratadas ao longo do curso, em outras seções do site:
Estrutura de dados em Java: Lista
Imagine uma lista, uma lista qualquer. A lista telefônica, por exemplo.
Ela é um registro (e que registro) de dados.
Como funciona? Como você usa?
Não há meio certo para se usar. Você pode usar o começo da lista, o meio ou fim, ir e voltar.
É simplesmente uma lista, uma exposição de informação ao seu dispor.
Assim será em Java.
Estrutura de dados em Java: Fila
Imagine uma fila de banco.
Como ela funciona? (Na verdade, como ela deveria funcionar)
De qualquer jeito, como uma 'lista'?
Claro que não. Na fila, quem estiver na frente é atendido primeiro.
Assim será na programação Java para estrutura de dados.
Quando seus dados estiverem sob essa estrutura, as informações que estão na cabeça da fila serão tratadas primeiro,
assim como as pessoas que estão na cabeça de uma fila de banco seriam atendidas primeiro.
Estrutura de dados em Java: Pilha
Agora imagine uma pilha de pratos.
Você comeu uma lasanha, e guardou o prato.
Depois uma macarronada, e guardou o prato.
Por fim, você comeu uma salada e guardou o prato.
Agora você tem uma fila de pratos, que vai levar para a pia para lavar.
Qual prato vai lavar primeiro? O primeiro, o da lasanha?
Não! O último, o da salada, que está no topo da pilha.
Assim será em seus aplicativos em Java: nas informações sob estrutura de pilha, as últimas informações (último prato) que chegaram -
ou seja, as mais recentes-, serão os primeiros a serem tratadas (primeiros a serem lavados).
Ou seja, é o oposto das filas. Aqui, os últimos que chegaram serão atendidos. Nas filas, os primeiros que chegaram é que são atendidos.
Com isso, você já tem uma noção sobre estrutura de dados em Java e que há várias maneiras de se ver e de se tratar informações.
Arrays: como declarar, usar e acessar os elementos de um array
Nesse artigo introdutório de Arrays de nossa apostila Java Progressivo, você irá aprender como declarar e usar os Arrays, ou vetores, em Java.
Aprenderá, também, a importante notação dos colchetes, [], que vamos usar para tratar dos membros de um Array, bem como acessar os elementos através desses colchetes.
Declarando Arrays(vetores) em Java
A sintaxe da declaração e criação do array é a seguinte:
tipo[] nome_do_array = new tipo[numero_de_elementos];
Ou:
tipo[] nome_do_array = { valor1, valor2, ...,valorx};
Nesse último caso, o tamanho o array é o tamanho de elementos entre chaves {}.
Por exemplo, se em uma sala de aula tiver 20 alunos e você quiser declarar 20 variáveis do tipo float usando array, ficaria assim:
float[] nota = new int[20];
float[] nota = {1,2,3,4,5,6,7,8,90.1,10.02,-11,12.9,13.7,14.5,15.7,16.0,17.5,19.3,20.2};
(lembre-se que float, ou decimais, são escritos com ponto, e não com vírgula, como fazemos no Brasil).
E o nome dos alunos, armazenaríamos em Strings:
String[] nome = new String[20];
Se notar bem, estamos usando a palavra 'new', que é a mesma que usamos na classe Scanner, para criar um objeto.
Aqui não é diferente. Estamos criando um objeto de arrays também.
Duas informações importantes:
1. Quando declaramos variáveis numéricas usando array e não inicializamos com valores, estes serão automaticamente nulos (0 ou 0.0).
Se forem Strings, serão 'null' e vazias caso sejam caracteres (char).
2. O tamanho de um array é constante. Uma vez declarado seu valor, não poderá ser mudado.
Se declarou 5 inteiros, o array terá sempre tamanho 5.
Se quiser saber o tamanho de um array, use o método 'length', que está em todo objeto do tipo array e retorna um inteiro com o número de elementos em cada cada array: nome.length, nota.length etc
A ordem de numeração dos elementos
Vamos mostrar agora uma importante informação, não só de Java, mas de programação.
Em nosso dia-a-dia contamos: 1, 2, 3...
Não fazemos contagem usando o 0.
Em programação,porém, obviamente isso inclui Java, SEMPRE começamos contando em 0!
Por exemplo, se declaramos um array com o nome 'teste', de 3 elementos, seus elementos serão identificados por:
teste[0]
teste[1]
teste[2]
Logo, sempre que declaramos um array de 'n' índices, o índice desses valores vão de 0 até n-1.
Guarde isso, é importante e usaremos sempre de agora em diante.
Como usar os elementos de um array em Java
Pronto, você declarou um array/vetor. Tem elementos do tipo float. Mas usou só um nome, 'nota'.
Como representar 20 variáveis com um só nome?
A resposta é simples: usando números, ou índices.
'nota' é um Array de Floats.
Se quiser usar um tipo float, use a seguinte sintaxe: nome[indice]
Então, suas variáveis, de forma independente, são chamadas de: nota[0]. nota[1], nota[10] etc.
Esses serão seus nomes. Você pode usar como usaria as variáveis, por exemplo:
Armazenar a nota de um aluno que tirou 10
nota[10]= 10.0 //esse, provavelmente, é programador Java
Somar a nota de dois alunos:
float soma = nota[3] + nota[4];
Incrementar:
nota[5]++;
Enfim, pode fazer tudo. São variáveis do tipo float normais.
A diferença é que os nomes das variáveis tem números, que são chamados, em programação, de índice, que são criados automaticamente quando você declara um bloco de vários elementos.
Exemplos de código Java usando Array
Exemplo 1: Faça um programa que peça 3 números inteiros ao usuário, armazene em um Array,
depois mostre o valor de cada elemento do array, assim como seu índice.
Passo 1: Primeiro declaramos um array de inteiros, contendo 3 elementos:
int[] nota = new int[3];
Depois o objeto 'entrada', do tipo Scanner, para receber os valores do usuário.
Passo 2: Armazenar os valores no array
Note que, você é programador e sabe que os índices vão de 0 até 2.
Mas o usuário não. Pro leigo, é número 1, número 2 e número 3, não inicia no 0.
No laço for, o nosso 'indice' vai de 0 até 2.
Porém, ao recebermos o valor de índice 'indice', estamos pedindo ao cliente o valor do número 'indice+1'.
Por exemplo, para armazenar um valor no 'nota[0]', vamos pedir o número '0+1' ao cliente.
Para armazenar um valor no 'nota[1]', vamos pedir o número '1+1' ao cliente.
Para armazenar um valor no 'nota[2]', vamos pedir o número '2+1' ao cliente.
Passo 3: exibindo os valores pro usuário
Usaremos outro laço for para exibir o valor dos índices, que variam de 0 até 2.
Porém, novamente, temos que mostrar 1 ao 3 pro cliente, pois pra ele não faz sentido 'número 0 -> valor 10 ' e sim 'número 1 -> valor 10'.
Então, nosso código Java ilustrando o uso de Arrays será:
import java.util.Scanner; public class arrayTeste { public static void main(String[] args){ int[] nota = new int[3]; Scanner entrada = new Scanner(System.in); //recebendo os números for(int indice=0 ; indice < 3 ; indice++){ System.out.print("\nEntre com o número " + (indice+1) + ": "); nota[indice] = entrada.nextInt(); } //exibindo os números for(int indice=0 ; indice < 3 ; indice++){ System.out.printf("Número %d -> Valor armazenado: %d\n",indice+1, nota[indice]); } } }
Exemplo 2: Faça um aplicativo Java que peça o nome do aluno, receba duas notas e depois retorne todas essas informações junto com a média dele.
Vamos usar, nesse exemplo, um array de floats com 3 elementos.
Dois elementos para armazenar os valores da nota e o terceiro vai armazenar a média.
O resto, não tem segredo. Veja como ficou nosso código Java:
import java.util.Scanner; public class arrayTeste2 { public static void main(String[] args){ float[] nota = new float[3]; String nome; Scanner entrada = new Scanner(System.in); System.out.print("Nome do aluno: "); nome = entrada.nextLine(); System.out.print("Primeira nota: "); nota[0] = entrada.nextFloat(); System.out.print("Segunda nota: "); nota[1] = entrada.nextFloat(); //média nota[2] = (nota[0] + nota[1])/2; System.out.printf("O aluno %s tirou %.1f e %.1f, obtendo média final %.2f",nome,nota[0],nota[1],nota[2]); } }
O laço for para Arrays: o laço For each
Em toda sua vida de programador Java, será comum você usar o laço for para percorrer todos os elementos de um Array.
Se isso é tão utilizado e importante, poderia ter um atalho ou meio mais fácil de fazer isso, não?
É, e tem.
Sem contar que, com Arrays e o laço for convencional, é bem fácil de se enrolar e cometer erros.
Aprenda uma maneira especial de usar o laço for e pare de ter problemas: é laço foreach
Fazendo o for percorrer todo o Array/Vetor
A utilização é bem simples e direta. Vamos usar essa variante do for que percorre sempre, do começo ao fim, todos os elementos de um Array.
É bem útil, também, em termos de precaução e organização, pois alguns programadores não gostam de usar o índice 0, usam direto o índice 1 do array, ou as vezes nos confundimos e passamos (durante as iterações) do limite do array. Isso pode ser facilmente evitado usando o laço for modificado para percorrer os elementos de um array.
A sintaxe do for each é a seguinte:
for ( tipo variavel_do_tipo_do_seuArray : seuArray){
//seu código
}
Se o 'seuArray' for de inteiro, ficaria:
for (int count : seuArray){
...
}
Como podemos interpretar esse laço foreach?
Muito simples, o inteiro 'count' vai receber, a cada iteração, todos os valores de 'seuArray'.
Ou seja, ele vai percorrer todo o seu Array e receber seus valores, na ordem (do começo para o fim), um por vez. E com esses valores você vai fazer o que desejar.
Por exemplo, suponha que as notas de cada aluno de uma escola é armazenada em um Array.
Como para calcular a média você precisará sempre percorrer todo o Array/Vetor, pode, e deve-se, usar esse laço for especial.
Pois ele foi feito para isso, para facilitar nossa vida.
Programadores não devem perder tempo. Devem fazer as coisas sempre da maneira mais simples e prática possível.
Não tente fazer arte ou gambiarra. Se o próprio Java lhe fornece as opções e ferramentas, use-as.
É uma arma 'especial' que não se vê por aí, em qualquer linguagem de programação.
Se você já programa ou programou em outra linguagem deve estar percebendo como Java é cheio dessas ferramentas e pormenores.
Se estudar tudo direitinho, irá se tornar um eficiente programador, pois o Java realmente foi feito para facilitar a vida de desenvolvedores, é realmente uma linguagem voltada para o trabalho.
Exemplo de uso do foreach em Java:
Crie um aplicativo em Java que peça 5 números ao usuário.
Depois, mostre o resultado da soma desses números;
Passo 1:
Vamos declarar o vetor de inteiro e o inteiro 'soma' para receber a soma dos resultados que o usuário fornecer.
Usamos um laço for, convencional, para percorrer o array.
Note que usamos 'numero.length', que é uma boa prática.
Passo 2:
Agora temos que percorrer o array inteiro, e já que temos que fazer isso, vamos fazer usando o laço for modificado que percorre um array inteiro recebendo seus valores.
Como o inteiro 'cont' vai receber os dados de todos os elementos do array 'numero', vamos somar o valor de 'cont' a cada iteração na variável 'soma'.
O código Java de nossa aplicação ficará:
import java.util.Scanner; public class forParaArray { public static void main(String[] args){ int[] numero = new int[5]; int soma=0; Scanner entrada = new Scanner(System.in); for(int cont=0 ; cont< numero.length ; cont++){ System.out.print("Entre com o número "+(cont+1)+": "); numero[cont]=entrada.nextInt(); } //exibindo e somando for(int cont : numero){ soma += cont; } System.out.println("A soma dos números que você digitou é "+soma); } }
Array Multidimensional ou Matriz: Array de arrays
Já vimos no capítulo passado de nossa apostila que um array é um conjunto de variáveis do mesmo tipo.
Porém, poderíamos também declarar um conjunto de arrays. Nesse caso, teríamos um array multidimensional ou vetor multidimensional, também conhecido por matrizes.
Matrizes ou Vetores multidimensionais: Conjunto de vetores ou arrays em Java
Imagine a situação que vinhamos usando como em exemplo em nossa apostila online Java Progressivo, o exemplo dos dados dos alunos de uma escola.
Ora, um aluno faz várias provas todos os anos.
Vamos supor que ele faz 10 provas por ano. Como você já é um sábio programador Java, não vai declarar 10 floats para armazenar as 10 notas. Vai declarar um array de 10 elementos floats.
Porém, existem várias matérias no colégio: Matemáticas, Física, Química, Biologia etc.
Vamos supor que existam 10.
E aí, vai declarar 10 vetores/arrays ?
Claro que não, isso seria muito cansativo.
Declare um array de arrays.
Arrays de uma ou mais dimensões em Java
Nos exemplos passados, declaramos apenas um bloco de variáveis. Dizemos que esse vetor é unidimensional, pois é somente um bloco.
Veja tal array/vetor apenas como uma linha, assim terá a noção de dimensão.
Por exemplo, vamos declarar um array unidimensional com 5 notas de Matemática:
int[] notas = {8.0 , 7.5, 8.5 , 9.0 , 8.0};
Essa nota pode ser representada por uma matriz 1x5, ou seja, uma linha e 5 colunas:
8.07.58.59.08.0
Agora vamos representar as notas em Física, abaixo das de Matemática. Teremos uma matriz 2x5, ou seja, uma matriz de duas linhas e 5 colunas:
8.07.58.59.08.0
8.99.08.68.48.0
Agora vamos representar as notas de Química, abaixo das notas de Física.
Teremos uma matriz 3x5, ou seja, uma matriz de três linhas e 5 colunas:
8.07.58.59.08.0
8.99.08.68.48.0
6.87.17.07.66.5
Matrizes: declarando vetores/arrays multidimensionais em Java
A sintaxe é exatamente a mesma do array normal, a diferença está no número de colchetes '[]' que irmos usar.
No caso, usamos um par para cada dimensão.
Por exemplo, para declarar a matriz 2x5 do exemplo anterior:
float[][] notas = new float[2][5];
Ou
float[][] notas = { {8.0, 7.5, 8.5, 9.0, 8.0 }, {8.9, 9.0, 8.6, 8.4, 8.0 } };
Para declarar a matriz 3x5 do exemplo anterior:
float[][] notas = new float[3][5];
Ou
float[][] notas = { {8.0, 7.5, 8.5, 9.0, 8.0 }, {8.9, 9.0, 8.6, 8.4, 8.0 }, {6.8, 7.1, 7.0, 7.6, 6.5 } };
Note que notas[0] se refere ao array de notas de Matemática.
Note que notas[1] se refere ao array de notas de Física.
Note que notas[2] se refere ao array de notas de Química.
Por exemplo: qual foi a quarta nota de Física do aluno?
Ora, o vetor de Física é notas[1], e a quarta nota é o elemento [3] desse array.
Então a quarta nota de Física do aluno está armazenada em: nota[1][3], que é 8.4
Exemplos de códigos:
Como de costume, em nossa apostila do curso Java Progressivo, vamos apresentar dois exemplos de como usar os arrays dimensionais, ou matrizes, em Java.
Exemplo 1: Crie um aplicativo em Java que peça ao usuário para preencher uma matriz 3x3 com valores inteiros e depois exiba essa matriz.
A grande novidade, e importância, nesse tipo de aplicativo são os laços for aninhados, ou seja, um dentro do outro.
Primeiro criamos um laço que vai percorrer todas as linhas da matriz. Podemos, e devemos, ver cada linha como um vetor de 3 elementos.
Dentro de cada linha, temos que percorrer cada elemento do array e fornecer seu valor. Fazemos isso através de outro laço for, que ficará responsável pelas 'colunas', formando nossos laços aninhados.
Para imprimir, o esquema é exatamente o mesmo. Imprimimos linha por linha, e em cada linha, imprimimos coluna por coluna.
import java.util.Scanner; public class matrizTeste { public static void main(String[] args){ int[][] matriz = new int[3][3]; Scanner entrada = new Scanner(System.in); System.out.println("Matriz M[3][3]\n"); for(int linha=0 ; linha < 3 ; linha++){ for(int coluna = 0; coluna < 3 ; coluna ++){ System.out.printf("Insira o elemento M[%d][%d]: ",linha+1,coluna+1); matriz[linha][coluna]=entrada.nextInt(); } } System.out.println("\nA Matriz ficou: \n"); for(int linha=0 ; linha < 3 ; linha++){ for(int coluna = 0; coluna < 3 ; coluna ++){ System.out.printf("\t %d \t",matriz[linha][coluna]); } System.out.println(); } } }
Exemplo 2: Crie um aplicativo em Java que peça ao usuário para preencher uma matriz 3x2 com valores inteiros e depois exiba essa matriz.
No exemplo passado, o número de linhas era igual ao número de colunas, da matriz. Vamos usar um exemplo diferente, para você fixar seu conhecimento em arrays multidimensionais.
Como dito no começo, uma matriz, array multidimensional ou vetor multidimensional nada mais é que um conjunto de arrays ou conjunto de vetores, array de arrays.
Quando fazemos: int[5] para declarar um array de inteiros, estamos declarando 5 variáveis do tipo inteiro.
Quando fazemos: int[10][5], estamos declarando 10 arrays, e em cada array desses existem 5 inteiros. Ou seja, 10 arrays do tipo do exemplo passado. Logo, o tamanho desse array – length – é 10.
Você pode obter isso com o comando: array.length
Assim, uma matriz 3x2 tem tamanho 3.
Uma 4x3 tem tamanho 4, uma 10x123123 tem tamanho 10 etc.
Ou seja, o length de arrays multidimensionais é o número de linhas.
Vamos usar esse fato nos laços:
import java.util.Scanner; public class matrizTeste2 { public static void main(String[] args){ int[][] matriz = new int[3][2]; Scanner entrada = new Scanner(System.in); System.out.println("Matriz M[3][2]\n"); for(int linha=0 ; linha < 3 ; linha++){ for(int coluna = 0; coluna < 2 ; coluna ++){ System.out.printf("Insira o elemento M[%d][%d]: ",linha+1,coluna+1); matriz[linha][coluna]=entrada.nextInt(); } } System.out.println("\nA Matriz ficou: \n"); for(int linha=0 ; linha < 3 ; linha++){ for(int coluna = 0; coluna < 2 ; coluna ++){ System.out.printf("\t %d \t",matriz[linha][coluna]); } System.out.println(); } } }
Arrays em métodos: passagem por valor e passagem por referência
Vimos em nosso curso de Java uma seção só para métodos, e estamos em outra seção da apostila só para arrays.
São duas coisas importantes, e a interação entre elas também é importante.
Porém, há alguns detalhes que precisam ser esclarecidos e comentados, que veremos agora neste artigo.
Passando arrays/vetores para methods/métodos
Para chamar os métodos usando arrays como argumentos, não há segredo.
Faça como sempre:
nome_do_metodo(nome_da_variavel);
Não se preocupe com o tipo e com os colchetes, [], pois os métodos já estão preparados e sabem que o que você está mandando é um array e não um tipo comum.
Para declarar, porém, é que há a diferença:
public static tipo_do_retorno nomeDoMetodo(tipo_do_parametro[] nome_da_variavel);
Por exemplo, vamos usar o exemplo do código do artigo passadode nosso curso para criar um método chamado 'exibeMatriz' que exibe uma matriz.
Esse método exibe uma matriz 3x3 de inteiros.
public static void exibeMatriz(int[][] Mat){
//codigo
}
Note que nossa matriz tem duas dimensões, então usamos dois pares de colchetes.
Colocando o código que exibe dentre deste método e fazendo o chamado dentro da main, nosso exemplo ficará assim:
Código Java: Preenche e exibe uma Matriz 3x3
import java.util.Scanner; public class arrayPraMetodo { public static void exibeMatriz(int[][] Mat){ System.out.println("\nA Matriz ficou: \n"); for(int linha=0 ; linha < 3 ; linha++){ for(int coluna = 0; coluna < 3 ; coluna ++){ System.out.printf("\t %d \t",Mat[linha][coluna]); } System.out.println(); } } public static void main(String[] args){ int[][] matriz = new int[3][3]; Scanner entrada = new Scanner(System.in); System.out.println("Matriz M[3][3]\n"); for(int linha=0 ; linha < 3 ; linha++){ for(int coluna = 0; coluna < 3 ; coluna ++){ System.out.printf("Insira o elemento M[%d][%d]: ",linha+1,coluna+1); matriz[linha][coluna]=entrada.nextInt(); } } exibeMatriz(matriz); } }
Passagem por valor e passagem por referência
Se você já estudou outras linguagens, como C ou C++ sabe o que são esse tipo de passagem e sua importância, assim como sua confusão.
Muitas vezes queremos passar um valor pro método para que este valor seja alterado. Neste caso, estamos passando por referência, ou seja, é como se estivéssemos passando realmente a própria variável pra ser modificada e receber outro valor dentro do método.
Quando passamos por valor, é como se o método tirasse uma 'xerox' ou uma cópia de nossa variável e trabalhasse com essa cópia, e não alterasse nossa variável. Altera e trabalha apenas com a cópia, deixando a nossa original intacta.
Ambos tipos de passagem são úteis e tem suas funcionalidades dependendo do que se queira fazer.
Porém, na linguagem de programação Java, a passagem é sempre, SEMPRE, feita por valor.
Sempre que criamos uma variável de um tipo, passamos uma cópia de seu valor para o método.
Veja este exemplo, onde definimos um numero de valor 2112, dobramos ele no método e imprimimos de novo. Seu valor não se altera:
Código Java: demonstrativo da passagem por valor, o valor não se altera no método
public class passagemPorValor {
public static int dobra(int num){
return num*2;
}
public static void main(String[] args){
int numero=2112;
System.out.println("O valor de numero é: " + numero);
System.out.println("Dobrando seu valor.");
dobra(numero);
System.out.println("Agora o valor de número é: " + numero);
}
}
A variável 'num', do método 'dobra()' é uma cópia da 'numero' do método 'main'.
O valor do 'numero' não é tocado nem visto pelo method 'dobra()'.
Os tipos de referência em Java
Existem tipos em Java que são chamados de 'tipos de referência, que são variáveis que, por natureza, recebem uma referência, ou seja, elas apontam para outro valor (mais especificamente, elas não armazenam o valor na memória, elas armazenam um endereço de outro bloco de memória - ou seja, tem uma refêrencia desse outro endereço de memória).
Como exemplo, sabemos que o Java trata objetos, de uma maneira geral, e os nosso tema atual de estudo, os arrays, por referência.
Logo, as classes e nossos arrays são tipo referência.
Quando declaramos um objeto por exemplo, com o nome 'meuObjeto', na verdade esse 'meuObjeto' vai guardar uma referência do objeto real. Ou seja, em Java, os tipos referências não armazenam na memória o valor, e sim um endereço - quem já tiver estudado C pode pensar logo em ponteiro!
Isso tudo se deve ao fato que objetos e arrays não possuírem tamanhos definidos, como os tipos primitivos. Então fica mais 'complicado' pro Java tratar esse tipo de dado, pois eles não tem um tamanho exato.
Então, ao invés de lidar com seus valores exatos (value), ele trata eles por referência (reference).
A confusão reside no fato de que, quando passamos esses tipos de variáveis para os métodos, elas mudam de valor! Mas peraí, por quê?
Como assim? Mas, em Java, a passagem não é sempre por valor?
Na verdade, há dois tipos de chamadas: os que usam cópia dos tipos primitivos e os que usam cópias da referência de objetos. Porém, como o assunto é um pouco avançado e não vimos objetos, darei uma explicação simplificada.
Nos valores do tipo 'primitivo', uma cópia é gerada no método e todas as alterações são feita nessa cópia, ok?
Nos valores do tipo 'referência' o mesmo, pois Java só passa por valor! Ok?
Então, no método, é criada outra cópia do objeto!
Ou seja, temos outra referência apontando pro mesmo local na memória. Nada demais até aqui.
Na passagem do tipo por 'referência', essa segunda cópia, dentro do método, altera a referência. Mas a referência aponta pra um local na memória! Então, alteramos o local na memória quando mudamos a referência!
Ora, se as duas variáveis apontam pro mesmo local e uma delas muda esse local, o local fica mudado para as duas, ué. Esse é o truque!
Exemplo de como funciona a passagem dos tipo referência
Se eu declaro o meu tipo referência original com o valor 'x', na verdade essa minha variável aponta pra memória onde esse valor realmente está.
Quando mando pro método, o método cria uma cópia dessa variável do tipo referência, porém a danada dessa cópia também aponta pro mesmo local da memória. Logo, temos duas variáveis apontando pra um mesmo local da memória, o local onde está o 'x'.
Mas o método prossegue e altera o valor 'x' dessa cópia. Na verdade ele alterou foi o valor 'x' na memória. Agora esse valor 'x' é 'x+1', e o método acabou.
De volta pra onde o método foi chamado, minha variável do tipo referência original ainda aponta pro mesmíssimo local da memória. Porém, nesse local não existe mais 'x' e sim 'x+1' e temos a falsa impressão que passamos um valor por referência. Mas passamos sim, por valor!
Veja um exemplo, onde criamos um método que calcula o traço de uma matriz 3x3.
Traço é a soma dos elementos da diagonal principal da matriz, ou seja, os elementos cujo número da linha é igual ao número da coluna:
Código Java: Aplicativo que calcula o traço de uma Matriz
import java.util.Scanner; public class traco{ public static void exibeMatriz(int[][] Mat){ System.out.println("\nA Matriz ficou: \n"); for(int linha=0 ; linha < 3 ; linha++){ for(int coluna = 0; coluna < 3 ; coluna ++){ System.out.printf("\t %d \t",Mat[linha][coluna]); } System.out.println(); } } public static int traco(int[][] Mat){ int soma=0; for(int linha=0 ; linha<Mat.length ; linha++){ soma += Mat[linha][linha]; } return soma; } public static void main(String[] args){ int[][] matriz = new int[3][3]; Scanner entrada = new Scanner(System.in); System.out.println("Matriz M[3][3]\n"); for(int linha=0 ; linha < 3 ; linha++){ for(int coluna = 0; coluna < 3 ; coluna ++){ System.out.printf("Insira o elemento M[%d][%d]: ",linha+1,coluna+1); matriz[linha][coluna]=entrada.nextInt(); } } exibeMatriz(matriz); System.out.println("\nO traço da Matriz é: "+ traco(matriz)); } }
Exemplo de passagem do tipo referência na vida real
Vamos supor que eu anotei um endereço em um papel, o endereço de um prédio.
Em suma: eu tenho uma referência desse prédio.
O papel é minha variável do tipo referência. Ou seja, ela não tem o prédio. Ela tem o endereço dele (referência). Bem claro agora, não?
Agora vamos fazer um 'método'. Ou seja, vamos tirar uma cópia desse papel e dar a um homem-bomba.
Ok, agora o homem bomba tem um papel com a referência também!
Os dois papéis apontam pro mesmo local: o prédio.
É isso que o método faz. Cria uma cópia da referência - por isso é passagem por valor, pois trabalha com a cópia.
Então, agora nosso homem-bomba irá trabalhar com essa cópia (como o método faz).
Ele vai lá e explode o prédio.
Ele mexeu no meu papel? Não, continua intacto, como prediz a passagem por valor.
Porém, ele alterou o lugar para onde meu papel fazia referência.
Ele alterou isso baseado no papel dele. Mas o papel dele tinha o mesmo endereço do meu!
Então, se ele alterou pra onde apontava - pra onde fazia referência - essa mudança vai acontecer pra mim também, pois minha referência também apontava pro prédio!
Em suma, se ficou confuso, aqui vai um resumo do que nos interessa neste ponto do curso:
- se passar tipos primitivos (int, float, double etc), eles não serão alterados pelo métodos
- se passar arrays, eles serão alterados pelos métodos. Bem como todo tipo de Classes
Classe Arrays (Arrays Class):
aprenda a manusear (copiar, ordenar, buscar e manipular) Arrays
Uma das grandes vantagens de se programar em Java é que ele nos fornece uma quantidade enorme de APIs.
Ou seja, o Java já vem com diversas classes e métodos prontos para serem usados.
Nesse tutorial de nosso curso de Java iremos aprender a usar a Classe Arrays bem como seus principais métodos,
que ordenam, comparam, buscam, colocam elementos nos Arrays/vetores dentre outras séries de utilidades.
Como usar a Arrays Class
Para importar, coloque no início de seu código:
import java.util.Arrays;
Diferente de outras classes, não vamos declarar diretamente os objetos: Arrays nome_do_objeto;
Na verdade, quando criamos um Array, automaticamente já podemos usar os métodos da classe Arrays nesse vetor(array).
No exemplo a seguir, vamos mostrar como usar os métodos da classe Arrays.
Ordenando e buscando um elemento em um Array no Java
Nesse exemplo de código deste tutorial de java, iremos usar o método 'sort', que significa ordenar em inglês e o método 'binarySearch',
que faz uma busca por um determinado elemento e retorna sua localização no Array.
Inicialmente definimos um Array de inteiros quaisquer.
Para exibir os elementos de um Array, em Java, como uma string, usamos o método:
Arrays.toString( array );
que recebe um array como argumento.
Depois vamos usar o método 'sort', que ordena o Array de ordem crescente.
Ou seja, vai trocar a posição dos elementos de modo que estejam organizados do menor para o maior.
Para usar o método sort em Java fazemos:
Arrays.sort( array );
Depois, mostramos o array novamente, mas na forma de string para você ver como ficou a organização do array depois do método sort ter entrado em ação.
Depois, vamos armazenar em um inteiro, 'posicao', a posição do elemento '2112' no array:
Arrays.binarySearch(array, numero_que_estamos_procurando) ;
IMPORTANTE: esse método só funciona se o array estiver na ordem crescente! Ou seja, só use o 'binarySearch' após usar o 'sort', pois a Binary Search é um tipo de busca inteligente (ele não sai simplesmente procurando os elementos, um por um, seu algoritmo se baseia na ordenação).
import java.util.Arrays; public class arraysClass{ public static void main(String[] args){ int[] numeros={1, 4, 0, -13, 2112, 14, 17}; int posicao; System.out.println("Os elementos do array são: "+ Arrays.toString(numeros)); System.out.println("Ordenando..."); Arrays.sort(numeros); System.out.println("Array ordenado: "+Arrays.toString(numeros)); posicao=Arrays.binarySearch(numeros, 2112); System.out.println("Posição do elemento '2112': "+ posicao); } }
Métodos da classe Arrays (Array class methods):
Dependendo dos métodos, podemos usar inteiros, float, double, char, short, List, Object etc.
Para saber exatamente se existe um método para aplicar no que você deseja usar, olhe a documentação da classe Arrays em:
http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html
Arrays.binarySearch:
Serve para encontrar um elemento específico dentro do array. Retorna a posição no array (inteiro).
Caso passe como argumento um array e um valor, a busca é feita em todo o array.
Podemos também passar um intervalo de busca. Por exemplo, para procurar o elemento 'x', no Array 'vetor', a partir do elemento 'daqui' até o elemento 'ate_aqui', faça:
Arrays.binarySearch( vetor, daqui, ate_aqui, x);
Arrays.copyOf:
Esse método copia um array e retorna outro. Esse que ele retorna é uma cópia do primeiro.
Se receber dois argumentos - um array e um valor, esse array que você passa é aquele que você deseja copiar e o valor é o número de elementos que você deseja copiar (ou o número de elementos que você quer que seu novo array tenha. Caso deseje ter um array maior, esse método preenche com 0 ou nulls):
novoArray[] = Arrays.copyOf( arrayOriginal, numero_de_elementos_a_serem_copiados);
Você também pode especificar uma faixa de valores:
novoArray[] = Arrays.copyOf( arrayOriginal, daqui, ate_aqui);
Arrays.equals:
Recebe dois arrays. Retorna true caso sejam iguais e false caso contrário.
Arrays.fill:
Vai preencher os valores de um array com determinado valor.
Caso deseje que todos os elementos de 'array' tenham o valor 'valor':
Arrays.fill(array, valor);
Para preencher só determinada faixa de valores:
Arrays.fill(array, daqui, ate_aqui, valor);
Arrays.sort:
Ordena os elementos em ordem crescente:
Arrays.sort(array);
Para ordenar uma faixa de valores:
Arrays.sort(array, daqui, ate_aqui);
Arrays.toString:
Retorna todos os elementos de um array na forma de string:
Arrays.toString(array);
Como usar ArrayList em Java: principais métodos
Até o momento, nessa seção de Estrutura de Dados de nosso curso de Java, vimos o quão útil são os arrays
e as operações que podemos fazer com esses arrays, também conhecidos por vetores.
Porém, há um grande problema neles: são estáticos. Ou seja, tem tamanho definido, não podemos adicionar nem excluir nada neles, o que é bastante incômodo e faz com que arrays em Java sejam limitados.
E por que arrays não são muito úteis?
Porque na vida real as coisas não são assim estáticas, elas mudam. O número de funcionários de um empresa tendem a crescer, em uma faculdade alunos se formam e outros se matriculam, em um jogo de RPG vamos colecionando ítens no decorrer do jogo, ao passo que vamos usando outros.
Agora, nesse tutorial do curso Java Progressivo, vamos aprender como usar os ArrayList, que são arrays mais 'flexíveis', ou dinâmicos, já que podemos adicionar ou retirar elementos, além de fazer outras coisas que não são possíveis com os Arrays.
O que são ArrayList em Java
O Java, por padrão, possui uma série de recursos prontos (APIs) para que possamos tratar de estrutura de dados, também chamados de coleções (collections). Podemos dizer que ArrayList é uma classe para coleções. Uma classe genérica (generic classes), para ser mais exato.
Coleções mesmo, de qualquer tipo de 'coisa', desde que seja um objeto.
Você pode criar seus objetos - através de uma classe - e agrupá-los através de ArrayList e realizar, nessa coleção, várias operações, como: adicionar e retirar elementos, ordená-los, procurar por um elemento específico, apagar um elemento específico, limpar o ArrayList dentre outras possibilidades.
Como declarar e usar ArrayList em Java
Importe:
import java.util.ArrayList;
Por ser um tipo diferente, sua sintaxe é um pouco diferente do que você já viu até então:
ArrayList< Objeto > nomeDoArrayList = new ArrayList< Objeto >();
No exemplo a seguir, vamos usar um ArrayList de String para trabalhar com o nome de várias Bandas de música:
ArrayList<String> bandas = new ArrayList<String> ();
Exemplo de uso do ArrayList
Após declarar a ArrayList 'bandas' que armazenará Strings, vamos adicionar alguns nomes.
Primeiro adicionamos a banda "Rush":
bandas.add("Rush");
Existe um método do ArrayList chamado 'toArray()' que coloca todos os elementos de um ArrayList em um Array.
Ou seja:
bandas.toArray() é um Array!
Porém, já vimos que existe um método 'toString' da classe Arrays que retorna uma String com os elementos de um Array. Vamos usar esse método parar exibir todos os elementos do ArrayList, que transformamos em Array através do método 'toArray()':
Arrays.toString( bandas.toArray() );
Vamos adicionar a segunda banda, "Beatles" e imprimir, usando o mesmo método.
Note que quando usamos 'add', sempre adicionamos o elemento pro fim da ArrayList.
Confirme isso agora, vendo que a banda "Iron Maiden" ficará depois de "Beatles".
Vamos pegar o primeiro elemento, o elemento '0', através do método 'get':
bandas.get(0);
Note que é a banda "Rush", pois ela foi a primeira a ser adicionada.
Vamos adicionar o "Tiririca" na posição do "Rush", ou seja, na posição '0':
bandas.add(0,"Tiririca");
ou
bandas.add( bandas.indexOf("Rush"), "Tiririca");
Pois o método 'indexOf' retorna o índice em que ocorre "Rush".
Para saber o tamanho que tem seu ArrayList, basta usar o método 'size()':
bandas.size();
Feito isso, rapidamente remova o "Tiririca", pois alguém pode ver.
Para tal, use o método 'remove':
bandas.remove("Tiririca");
Ok. Não quer mais brincar de ArrayList? Remova tudo
bandas.clear();
import java.util.ArrayList; import java.util.Arrays; public class arrayLists{ public static void main(String[] args){ ArrayList<String> bandas = new ArrayList<String> (); bandas.add("Rush"); System.out.print( "Adicionando a banda Rush: " ); System.out.println( Arrays.toString( bandas.toArray() ) ); bandas.add("Beatles"); System.out.print( "Adicionando a banda Beatles: " ); System.out.println( Arrays.toString( bandas.toArray() ) ); bandas.add("Iron Maiden"); System.out.print( "Adicionando a banda Iron Maiden: " ); System.out.println( Arrays.toString( bandas.toArray() ) ); System.out.print( "Quem está na índice 0: " ); System.out.println( bandas.get(0) ); System.out.print( "Adicionando Tiririca onde estava o Rush: " ); bandas.add( bandas.indexOf("Rush"), "Tiririca"); System.out.println( Arrays.toString( bandas.toArray() ) ); System.out.print( "Número de elementos na lista: " ); System.out.println( bandas.size() ); System.out.print( "Removendo o Tiririca: " ); bandas.remove("Tiririca"); System.out.println( Arrays.toString( bandas.toArray() ) ); System.out.print( "Removendo tudo: " ); bandas.clear(); System.out.println( Arrays.toString( bandas.toArray() ) ); } }
Saída:
Adicionando a banda Rush: [Rush] Adicionando a banda Beatles: [Rush, Beatles] Adicionando a banda Iron Maiden: [Rush, Beatles, Iron Maiden] Quem está na índice 0: Rush Adicionando Tiririca onde estava o Rush: [Tiririca, Rush, Beatles, Iron Maiden] Número de elementos na lista: 4 Removendo o Tiririca: [Rush, Beatles, Iron Maiden] Removendo tudo: []
Para saber mais métodos e mais opções de parâmetros/argumentos, consulte a documentação sobre ArrayList em Java, no site da Oracle:
http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
Se em vez de de Strings, quiser trabalhar com números, use as classes Wrappers:
ArrayList<Integer>, ArrayList<Float>, ArrayList<Double>, ArrayList<Long> etc.
Jogo: Batalha Naval em Java
Agora que aprendemos como passar arrays (de qualquer dimensão) para métodos, já podemos fazer algo mais útil. Vamos fazer o famoso batalha naval, no modo texto.
Usaremos tudo que aprendemos até o momento em nosso curso de Java: if else, laço do while, laço for, métodos, números aleatórios, arrays, arrays multidimensionais e muita criatividade.
Regras do Jogo Batalha Naval em Java
Há um tabuleiro de 5x5, ou seja, 25 blocos. Há 3 navios escondidos (um em cada bloco).
O objetivo do jogar é descobrir onde estão estes navios e acertá-los.
A cada tiro dado é dito se você acertou algum navio. Caso tenha errado, é dito quantos navios existem naquela linha e naquela coluna.
O jogo só acaba quando você descobrir e afundar os 3 navios.
Legenda pro usuário:
~ : água no bloco. Ainda não foi dado tiro.
* : tiro dado, não há nada ali.
X : tiro dado, havia um navio ali.
Como jogar:
A cada rodada, entre com dois números: o número da linha e o número da coluna onde quer dar o tiro.
Depois é só esperar pra ver se acertou, ou a dica.
Para os programadores Java:
O tabuleiro 5x5 é de inteiros. Ele é inicializado com valores '-1'.
A cada tiro ele é atualizado, dependendo se o usuário acertou ou errou. Esses números servirão para exibir '~', '*' ou 'X' para o usuário.
Também servirão para exibir as dicas.
Legenda do tabuleiro:
-1 : nenhum tiro foi dado naquele bloco (~)
0 : o tiro foi dado e não havia nada (*)
1 : o usuário atirou e tinha um navio lá (X)
Métodos:
-
void inicializaTabuleiro(int[][] tabuleiro) - inicialmente coloca o valor -1 em todas as partes do tabuleiro
-
void mostraTabuleiro(int[][] tabuleiro) - recebe o tabuleiro de inteiros e os exibe
-
void iniciaNavios(int[][] navios) - esse método sorteia 3 pares de inteiros, que são a localização dos 3 navios
-
void darTiro(int[] tiro) - recebe um tiro (linha e coluna) do usuário, e armazena na variável tiro[]
-
boolean acertou(int[] tiro, int[][] navios) - checa se o tiro dado acertou um navio
-
void dica(int[] tiro, int[][] navios, int tentativa) - dá a dica de quantos navios existem naquela linha e naquela coluna onde o tiro foi dado
-
void alteraTabuleiro(int[] tiro, int[][] navios, int[][] tabuleiro) - após o tiro ser dado, o tabuleiro é alterado, mostrando o tiro que foi dado(se acertou ou errou)
Lógica do problema
Inicialmente, são criadas as variáveis 'tabuleiro[5][5]', que vai armazenar o tabuleiro do jogo, a variável 'navios[3][2]', que vai armazenar a posição (linha e coluna) dos 3 navios que estão escondidos no tabuleiro, a variável 'tiro[2]' que vai armazenar a posição (linha e coluna) do tiro que o jogador vai dar a cada rodada, além da variável 'tentativa', que vai armazenar o número de tentativas que o jogador fez até acertar os 3 navios e, por fim, a variável 'acertos' que contabiliza o número de navios que você acertou.
O método 'inicializaTabuleiro()' é acionado, pra criar o tabuleiro com o número '-1' em todas as posições.
Depois é o método 'iniciaNavios()', que vai sortear a posição de 3 navios (linha e coluna).
Esse método sorteia dois números, entre 0 e 4. Depois ele checa se esse número já saiu, pois não podem existir dois barcos na mesma posição.
Caso já tenha saído, entra num laço do...while que fica sorteando números, e só sai quando sorteia outro par de números que ainda não é a localização de um navio.
Após isso, na main(), vamos iniciar o jogo.
Os jogos geralmente se iniciam através de um laço do...while. No caso, a condição do while é 'acertos!=3'. Ou seja, enquanto você não acertar os 3 navios, o jogo não para.
A primeira coisa que ocorre no laço é mostrar o tabuleiro, através do laço 'mostraTabuleiro()'.
Esse método checa cada posição o 'tabuleiro'. Se for -1 ele exibe água, '~'. Se for 0, ele exibe o tiro que foi dado e errou '*', e se for 1, ele exibe 'X' que indica que você acertou um navio naquela posição.
Após mostrar o tabuleiro, você vai dar seu tiro, através do método 'darTiro()', que recebe dois inteiros.
Note que, o usuário vai digitar números de 1 até 5, pois ele conta de 1 até 5.
Você, como programador Java é que conta de 0 até 4.
Portanto, quando o usuário entrar com a linha e com a coluna, SUBTRAIA 1 de cada valor desses.
Ou seja, se usuário entrou com (1,1), no seu tabuleiro Java 5x5 isso representa a posição (0,0).
Após o tiro ser dado, nosso jogo em Java vai checar se esse tiro acertou algum navio. Isso é feito com o método 'acertou()', que retorna 'true' caso acerte e 'false' caso erre.
No método, ele simplesmente checa se esse par de valores - 'tiro[2]' - que definem seu tiro, batem com algum dos valores que definem a posição dos navios - navios[3][2].
Caso acerte, o valor de 'acertos' aumenta.
Acertando ou errando, 'tentativas' aumenta, pois uma tentativa foi feita.
Acertando ou errando, uma dica também é exibida. Essa dica é exibida através do método 'dica()', que vai olhar o seu 'tiro[2]', e olha se na linha e na coluna que você tentou existe mais algum navio, catando na 'navios[3][2]'.
Note que, a linha do seu tiro é 'tiro[0]' e a coluna é 'tiro[1]'.
A linha de cada navio é 'navios[x][0]' e a coluna de cada navio é 'navios[x][1]', onde 'x' é o número dos navios. No nosso caso, são 3 navios, ou seja, vai de 0 até 2.
Acertando ou errando, o tabuleiro vai ser alterado. O tiro que você deu vai alterar aquele local do tabuleiro, vai aparecer tiro dado '*' ou tiro que acertou 'X'.
Vamos fazer isso através do método 'alteraTabuleiro()'.
Aqui, usamos um método dentro do outro. Coisa que já explicamos em nosso curso de Java.
Checamos se o tiro dado 'tiro[2]' acertou através do método, que já usamos e explicamos, 'acertou'.
Caso acerte, a posição do tabuleiro referente ao tiro que você deu vai mudar de '-1' para '1'.
Caso erre, a posição do tabuleiro referente ao tiro que você deu vai mudar de '-1' para '0'.
Assim, quando o tabuleiro for exibido, já vai exibir com '*' ou 'X' no lugar desse antigo '~'.
import java.util.Random; import java.util.Scanner; public class batalhaNaval { public static void main(String[] args) { int[][] tabuleiro = new int[5][5]; int[][] navios = new int[3][2]; int[] tiro = new int[2]; int tentativas=0, acertos=0; inicializaTabuleiro(tabuleiro); iniciaNavios(navios); System.out.println(); do{ mostraTabuleiro(tabuleiro); darTiro(tiro); tentativas++; if(acertou(tiro,navios)){ dica(tiro,navios,tentativas); acertos++; } else dica(tiro,navios,tentativas); alteraTabuleiro(tiro,navios,tabuleiro); }while(acertos!=3); System.out.println("\n\n\nJogo terminado. Você acertou os 3 navios em "+tentativas+" tentativas"); mostraTabuleiro(tabuleiro); } public static void inicializaTabuleiro(int[][] tabuleiro){ for(int linha=0 ; linha < 5 ; linha++ ) for(int coluna=0 ; coluna < 5 ; coluna++ ) tabuleiro[linha][coluna]=-1; } public static void mostraTabuleiro(int[][] tabuleiro){ System.out.println("\t1 \t2 \t3 \t4 \t5"); System.out.println(); for(int linha=0 ; linha < 5 ; linha++ ){ System.out.print((linha+1)+""); for(int coluna=0 ; coluna < 5 ; coluna++ ){ if(tabuleiro[linha][coluna]==-1){ System.out.print("\t"+"~"); }else if(tabuleiro[linha][coluna]==0){ System.out.print("\t"+"*"); }else if(tabuleiro[linha][coluna]==1){ System.out.print("\t"+"X"); } } System.out.println(); } } public static void iniciaNavios(int[][] navios){ Random sorteio = new Random(); for(int navio=0 ; navio < 3 ; navio++){ navios[navio][0]=sorteio.nextInt(5); navios[navio][1]=sorteio.nextInt(5); //agora vamos checar se esse par não foi sorteado //se foi, so sai do do...while enquanto sortear um diferente for(int anterior=0 ; anterior < navio ; anterior++){ if( (navios[navio][0] == navios[anterior][0])&&(navios[navio][1] == navios[anterior][1]) ) do{ navios[navio][0]=sorteio.nextInt(5); navios[navio][1]=sorteio.nextInt(5); }while( (navios[navio][0] == navios[anterior][0])&&(navios[navio][1] == navios[anterior][1]) ); } } } public static void darTiro(int[] tiro){ Scanner entrada = new Scanner(System.in); System.out.print("Linha: "); tiro[0] = entrada.nextInt(); tiro[0]--; System.out.print("Coluna: "); tiro[1] = entrada.nextInt(); tiro[1]--; } public static boolean acertou(int[] tiro, int[][] navios){ for(int navio=0 ; navio<navios.length ; navio++){ if( tiro[0]==navios[navio][0] && tiro[1]==navios[navio][1]){ System.out.printf("Você acertou o tiro (%d,%d)\n",tiro[0]+1,tiro[1]+1); return true; } } return false; } public static void dica(int[] tiro, int[][] navios, int tentativa){ int linha=0, coluna=0; for(int fila=0 ; fila < navios.length ; fila++){ if(navios[fila][0]==tiro[0]) linha++; if(navios[fila][1]==tiro[1]) coluna++; } System.out.printf("\nDica %d: \nlinha %d -> %d navios\n" + "coluna %d -> %d navios\n",tentativa,tiro[0]+1,linha,tiro[1]+1,coluna); } public static void alteraTabuleiro(int[] tiro, int[][] navios, int[][] tabuleiro){ if(acertou(tiro,navios)) tabuleiro[tiro[0]][tiro[1]]=1; else tabuleiro[tiro[0]][tiro[1]]=0; } }
Fica como desafio você fazer um jogo Batalha Naval, mas humano x humano. Faça assim, primeiro um dos jogadores preenche onde quer colocar seus navios.
Depois o outro.
O jogo será por turnos. Crie uma variável chamada 'turno' que é incrementada a cada rodada, e use o resto da divisão por 2 pra saber de quem é a vez.
Por exemplo, se
turno=1 -> turno%2 = 1 -> vez do jogador 1
turno=2 -> turno%2 = 0 -> vez do jogador 2
turno=3 -> turno%2 = 1 -> vez do jogador 1
turno=4 -> turno%2 = 0 -> vez do jogador 2
...
Crie duas variáveis 'tabuleiro', duas 'tentativas', duas 'navios' e duas 'acertos', para armazenar em variáveis diferentes os dados de cada usuário.
O jogo termina quando uma das variáveis 'acertos' é 3.
Ou você pode alterar o tamanho do tabuleiro, o número de navios, a dica etc...sua criatividade é que conta.
Jogos com programação gráfica em Java
Já fizemos um exemplo de jogo em Java usando caixas de diálogo, assim como fizemos o mesmo em modo texto.
Você viu que, a lógica é a mesma, e é, de longe, a parte mais importante.
Entendendo e fazendo o jogo Batalha Naval em Java em modo texto, você saberá como funciona a lógica do game. A parte gráfica usará a mesma lógica. Você irá, simplesmente, colocar alguns recursos visuais/gráficos (GUI - Graphic User Interface) nessa sua aplicação Java.
Muitas pessoas pensam que programar jogos é apenas a parte visual.
Porém, essa é apenas uma parte. Geralmente não é difícil, não é a mais importante nem a que dá mais trabalho.
Programar Jogos é, primeiro, programar. Aprenda antes a linguagem, a lógica, a sintaxe.
Depois, ao longo do curso, você aprenderá a usar os recursos gráficos do Java, como menus, janelas e botões, e iremos ensinar como usar para fazer esse mesmo jogo em uma maneira gráfica, para você enviar para seus amigos :)
Por hora, estude a lógica e tenha calma.
Programar é uma profissão. Não se cria um game ou se aprende a programar em Java em poucas semanas ou meses. Continue estudando...
