Fazer download em pdf ou txt
Fazer download em pdf ou txt
Você está na página 1de 119

Luiz Fernando Duarte Júnior

Java para iniciantes

2a edição

Gravataí/RS
Edição do Autor
2017
Copyright © Luiz Fernando Duarte Júnior, 2017
Java para Iniciantes
Luiz Duarte

Duarte, Luiz,
Java para Iniciantes - 2a edição

Luiz Duarte - Gravataí/RS:2017

ISBN 978-65-900538-1-7

1. Programação em Java. 2. Computação, Internet e Mídia Digital.

Reservados todos os direitos.


Sobre o autor
Antes de começar
Para quem é este livro
1 Introdução
Características
Mercado
2 Ambiente de desenvolvimento
Java Development Kit
NetBeans
Olá Mundo
3 Tipos e Variáveis
Declaração de Variáveis
Tipos de dados primitivos
Comentários
4 Operadores e o tipo String
Operadores Aritméticos
Operadores Relacionais
Operadores Lógicos
Operador de Atribuição
O tipo String
5 Estruturas de Controle e Arrays
Estruturas de repetição
Estruturas de desvio de fluxo
Arrays
6 Aplicações Console
Estrutura básica
Saída de Dados
Entrada de Dados
Criando Aplicações
7 Seguindo em Frente
Sobre o autor
Luiz Fernando Duarte Júnior é Bacharel em Ciência da Computação pela
Universidade Luterana do Brasil (ULBRA, 2010) e Especialista em
Desenvolvimento de Aplicações para Dispositivos Móveis pela Universidade
do Vale do Rio dos Sinos (UNISINOS, 2013). Carrega ainda um diploma de
Reparador de Equipamentos Eletrônicos (SENAI, 2005) e duas certificações
Scrum para trabalhar com Métodos Ágeis: Professional Scrum Developer e
Professional Scrum Master (ambas em 2010).

Atuando na área de TI desde 2006, na maior parte do tempo como


desenvolvedor, é apaixonado por Java desde que teve o primeiro contato com
a tecnologia nos primeiros semestres da faculdade, sob indicação de seu
professor, o mestre Rafael Gastão. De lá para cá teve oportunidade de utilizar
Java em em diferentes oportunidades e sistemas, mas principalmente para
dispositivos móveis, incluindo J2ME e, nos últimos anos, apps Android. Foi
amor à primeira vista e a paixão continua acesa!

Trabalhando com Java para Android desenvolveu diversos projetos para


empresas, incluindo grandes marcas como Embelleze, LG, Ford e Renault,
além de ministrar cursos de Android para alunos do curso superior de várias
universidades. Um grande entusiasta da plataforma, espera que com esse
livro possa ajudar ainda mais pessoas a aprenderem a desenvolver softwares
Java e aumentar a competitividade das empresas brasileiras.

Além de desenvolvedor, atua como professor do ensino superior no curso


tecnológico de Análise e Desenvolvimento de Sistemas na Faculdade de
Tecnologia de Porto Alegre (FAQI/RS) e é autor do blog
https://www.luiztools.com.br, onde escreve semanalmente sobre
empreendedorismo e desenvolvimento de software.

Seu trabalho também pode ser visto em mais detalhes em seu perfil no
LinkedIn e na sua página no Facebook.com/luiztools.
Entre em contato, estou sempre disposto a ajudar meus leitores e ouvir suas
críticas e sugestões.

Conheça meus outros livros:

Programação Web com Node.js


Criando apps para empresas com Android
Scrum e Métodos Ágeis: Um Guia Prático
Agile Coaching: Um Guia Prático
MongoDB para Iniciantes
Node.js e Microservices

Conheça meus cursos:

Curso online de Scrum e Métodos Ágeis


Curso online de Node.js e MongoDB
Antes de começar
Antes de começarmos, é bom você ler esta seção para evitar surpresas e até
para saber se este livro é para você.
Para quem é este livro
Primeiramente, este livro vai lhe ensinar a programar em Java, mas não vai
lhe ensinar lógica básica de programação, ele exige que você já saiba isso, ao
menos em um nível básico (metade do primeiro semestre da faculdade de
computação, por exemplo). Coisas como lógica AND/E e lógica OR/OU, por
exemplo, não devem ser coisas completamente estranhas à você.

Segundo, este livro exige que você já tenha conhecimento técnico prévio
sobre computadores, que ao menos saiba mexer em um e que
preferencialmente possua um, bem como conexão com a Internet. Não
importa seu sistema operacional ou requisitos de hardware, se possui um
computador com menos de 7 anos de uso, ele vai dar conta do recado!

Parto do pressuposto que você é ou já foi um estudante de Técnico em


informática, Ciência da Computação, Sistemas de Informação, Análise e
Desenvolvimento de Sistemas ou algum curso semelhante de tecnologia.
Usarei diversos termos técnicos ao longo do livro que são comumente
aprendidos nestes cursos e que não tenho o intuito de explicar aqui.

O foco deste livro é ensinar o básico de programação Java, indo desde a


declaração de variáveis, operadores, estruturas de desvio de fluxo até a
criação de programas interativos no console. Nenhum tópico, intermediário
ou avançado será tratado aqui (como Orientação à Objetos, Banco de Dados
ou Padrões de Projeto) e nenhuma API específica.

Ao término deste livro você estará apto a construir softwares simples para
computadores usando qualquer sistema operacional que suporte a máquina
virtual Java, bem como compreenderá o básico da principal linguagem de
programação para computadores da atualidade, sendo capaz de criar
programas interativos com o usuário e pequenos jogos que estimularão sua
lógica e raciocínio. Além disso, terá uma noção abrangente do mercado de
desenvolvimento Java em que está se inserindo.
1 Introdução
Java é uma linguagem de programação introduzida no mercado na década de
90 pela Sun Microsystems, que provocou grande entusiasmo em
programadores, analistas e projetistas de software na época, graças à
quantidade de inovações que trouxe consigo. No início dos anos 2000, a
empresa Sun foi comprada pela Oracle, fazendo com que o Java mudasse de
dono mas sem perder o seu brilho e importância no mercado.

Mas por que o Java é uma linguagem tão importante de ser aprendida?

Simplesmente porque é o resultado de um trabalho consistente de pesquisa e


desenvolvimento de mais do que uma simples linguagem de programação,
mas de todo um ambiente de desenvolvimento e execução de programas que
exibe as facilidades proporcionadas pela orientação à objetos, pela extrema
portabilidade do código produzido, pelas características de segurança que esta
plataforma oferece e finalmente pela facilidade de sua integração com outros
ambientes, destacando-se a Internet.

Hoje, bilhões de dispositivos ao redor do mundo rodam programas escritos


em Java. Desde dispositivos mais tradicionais como computadores e
smartphones, até dispositivos menos elaborados como receptores de sinal
digital, máquinas industriais, televisores inteligentes e até mesmo
refrigeradores e carros (!!). Obviamente que essa profusão de dispositivos
cria uma demanda incessante por programadores aptos a trabalhar com esta
linguagem para resolver os mais variados desafios de todos os tipos de
mercados.
Características
A linguagem Java exibe importantes características que, em conjunto,
diferenciam-na
de outras linguagens de programação:

Orientada à Objetos
Java é uma linguagem puramente orientada à objetos pois, com exceção de
seus tipos primitivos de dados, tudo em Java são classes ou instância de uma
classe. Java atende todos os requisitos necessários para uma linguagem ser
considerada orientada à objetos que resumidamente são oferecer mecanismos
de abstração, encapsulamento e hereditariedade. Esse é um conceito
intermediário que você deve ouvir falar no futuro, mas que será ignorado
nesta obra para simplificar seu aprendizado.

Independente de Plataforma
Java é uma linguagem independente de plataforma pois os programas Java
são compilados para uma forma intermediária de código denominada
bytecodes que utiliza instruções e tipos primitivos de tamanho fixo,
ordenação big-endian e um biblioteca de classes padronizada. Os bytecodes
são como uma linguagem de máquina destinada a uma única plataforma, a
máquina virtual Java (JVM – Java Virtual Machine), um interpretador de
bytecodes. Pode-se implementar uma JVM para qualquer plataforma assim
temos que um mesmo programa Java pode ser executado em qualquer
arquitetura que disponha de uma JVM.

Se você já mexeu com Delphi sabe como é frustrante não poder desenvolver
softwares para vários sistemas operacionais...Além disso, esse modelo de
máquina virtual foi tão bem sucedido que diversas outras plataformas de
desenvolvimento migraram para esta arquitetura, como a famosa plataforma
.NET da Microsoft, que veio muitos anos depois do Java.

Sem Ponteiros
Java não possui ponteiros, isto é, Java não permite a manipulação direta de
endereços de memória nem exige que o objetos criados sejam destruídos
livrando os programadores de uma tarefa complexa. Além disso a JVM
possui um mecanismo automático de gerenciamento de memória conhecido
como garbage collector (coletor de lixo), que recupera a memória alocada
para objetos não mais referenciados pelo programa.

Se você já programou na linguagem C, sabe do que estou falando! Na


verdade a maioria das linguagens modernas, tidas como de alto nível, nem
mesmo tem permitido ou aconselhado o uso de ponteiros.

Performance
Java foi projetada para ser compacta, independente de plataforma e para
utilização em rede o que levou a decisão de ser interpretada através dos
esquema de bytecodes. Como uma linguagem interpretada a performance é
razoável, não podendo ser comparada a velocidade de execução de código
nativo. Para superar esta limitação várias JVM dispõem de compiladores just
in time (JIT) que compilam os bytecodes para código nativo durante a
execução otimizando a mesma, que nestes casos melhora significativamente a
performance de programas Java.

Isto faz toda a diferença quando você programa grandes aplicações, e um dia
espero que você chegue lá!

Segurança
Considerando a possibilidade de aplicações obtidas através de uma rede, a
linguagem Java possui mecanismos de segurança que podem evitar qualquer
operação no sistema de arquivos da máquina-alvo, minimizando problemas
de segurança. Tal mecanismo é flexível o suficiente para determinar se uma
programa Java é considerado seguro especificando nesta situação diferentes
níveis de acesso ao sistema-alvo.

A máquina virtual Java tem sido alvo de muitos "ataques" e especulações nos
últimos anos no que diz respeito à segurança. No entanto, em todas as
ocasiões foi comprovado que as ditas "brechas" eram culpa de plugins para
navegadores mal construídos ou ainda outros tipos de brechas causadas por
falta de atualização e uso indevido da tecnologia. O Java continua
posicionado como uma das plataformas mais seguras do mundo, sendo
utilizado em sistemas que exigem altíssima segurança, de governos de países
às maiores empresas do mundo listadas na bolsa, incluindo grandes bancos
públicos e privados.
Permite Multithreading
Java oferece recursos para o desenvolvimento de aplicações capazes de
executar múltiplas rotinas concorrentemente bem como dispõe de elementos
para a sincronização destas várias rotinas. Cada um destes fluxos de execução
é o que se denomina thread, um importante recurso de programação de
aplicações mais sofisticadas.

Além disso, o Java é uma linguagem bastante robusta, oferece tipos inteiros e
ponto flutuante compatíveis com as especificações IEEE, suporte para
caracteres UNICODE (isto significa suporte à muitos alfabetos diferentes), é
extensível dinamicamente além de ser naturalmente voltada para o
desenvolvimento de aplicações em rede ou aplicações distribuídas.

Tudo isto (e muito mais que você verá durante seu aprendizado da
linguagem) torna o Java uma linguagem de programação única.
Mercado
O ranking TIOBE mede a popularidade de linguagens de programação
através da Internet, levando em conta videos no Youtube, resultados do
Google, quantidade de tutoriais e materiais sobre as linguagens, etc. O Java
reina em primeiro lugar há diversos anos!

Fonte: http://www.tiobe.com/tiobe-index/

Outro gráfico bem interessante mostra a evolução da popularidade das


linguagens de programação com o passar dos anos. Enquanto diversas
linguagens surgiram (e morreram) nas últimas duas décadas, o Java segue
firme e forte, sempre se mantendo uma excelente opção para desenvolvedores
que buscam um mercado seguro e estável para trabalhar.
Fonte: http://www.tiobe.com/tiobe-index/

Não acredita em minhas fontes?

Que tal conferir este outro gráfico abaixo, organizado segundo pesquisa do
famoso site StackOverflow, a maior fonte de perguntas e respostas para
desenvolvedores do mundo, onde o Java aparece em terceiro lugar, logo atrás
de Javascript e SQL.

Caso não saiba, SQL e Javascript não são exatamente concorrentes da


linguagem Java, uma vez que o primeiro é uma linguagem de consulta de
banco de dados (que você usa geralmente em conjunto com qualquer outra
linguagem de programação, incluindo Java) e o segundo é uma linguagem de
scripting, que você usa em conjunto com outras linguagens para programação
web, incluindo novamente, o Java.

Podemos dizer que as três linguagens no pódio do StackOverflow são usadas


em conjunto para criar sistemas, constituindo um dos mais populares stacks
de tecnologia do mundo.
Fonte: http://stackoverflow.com/research/developer-survey-2016#technology

Muitas, mas muitas empresas e desenvolvedores ao redor do mundo usam


Java. Eu realmente acredito que você deveria usar também.
2 Ambiente de desenvolvimento
Para que seja possível programar com a plataforma Java é necessária a
instalação de alguns softwares visando não apenas o funcionamento, mas
também a produtividade no aprendizado e desenvolvimento dos programas.

Eu realmente poderia começar lhe ensinando com o bloco de notas, mas


tenho quase certeza que você desistiria logo no início. ;)

Para tanto, vamos começar do princípio.


Java Development Kit
A plataforma Java é distribuída pelo seu fabricante, Oracle, em duas versões:
JRE e JDK, o que causa algumas confusões nos iniciantes na linguagem. Isso
porque é muito comum as pessoas possuírem o JRE instalado, o Java
Runtime Environment ou Ambiente de Execução Java, pré-requisito para o
funcionamento de alguns sistemas web seguros, como os "Internet
Bankings". Mas apenas com o JRE instalado não estamos aptos a programar
Java, apenas a executar softwares Java.

O que precisamos neste caso é do JDK, o Java Development Kit ou Kit de


Desenvolvimento Java. Ele é pré-requisito para qualquer tarefa de
desenvolvimento Java, independente do software que escolher para
desenvolver nesta linguagem.

Sendo assim, para deixar o seu computador pronto para desenvolvermos Java
ao longo deste livro será necessário que baixe a versão mais recente do JDK
no link abaixo, que aponta para o site oficial do fabricante:

http://www.oracle.com/technetwork/java/javase/downloads/index.html

A instalação não requer nenhuma instrução especial, apenas avance cada uma
das etapas e aceite o contrato de uso da plataforma. Na data em que escrevo
este livro a Oracle também tem disponibilizado uma versão do NetBeans
(outro software que iremos utilizar) já com o JDK embutido, para facilitar a
instalação. Minha sugestão é que baixe ambos softwares e instale-os em
separado, assim como vou mostrar aqui, para evitar problemas futuros com
outros softwares que possam precisar do JDK.

O JDK é composto basicamente por:


● Um compilador (javac)
● Uma máquina virtual Java (java)
● Bibliotecas de desenvolvimento (os packages java)
● Um programa para composição de documentação (javadoc)
● Um depurador básico de programas (jdb)
● Versão runtime do ambiente de execução (jre)
Deve ser observado que o JDK não é um ambiente visual de
desenvolvimento, embora mesmo assim seja possível o desenvolvimento de
aplicações gráficas complexas apenas com o uso do JDK que é, de fato, o
padrão em termos da tecnologia Java. Vale ressaltar também, que assim como
o próprio Java, o JDK pode ser baixado para qualquer sistema operacional
para computadores.

Compilador? Foi citado anteriormente a existência de um compilador Java.


Se você não está familiarizado com o tema, um compilador é um programa de
computador que traduz o seu código de programação, para linguagem de
máquina, que o computador entende. O ato de compilar nada mais é do que o
ato de traduzir o código que você escreveu em Java, por exemplo, para os
códigos binários que a máquina virtual Java entende.
NetBeans
Ao longo deste livro iremos desenvolver uma série de exemplos de softwares
escritos em Java usando a IDE, Integrated Development Environment ou
Ambiente Integrado de Desenvolvimento, NetBeans, da Oracle. Esta não é a
única opção disponível, mas geralmente é considerada a melhor,
principalmente para iniciantes, uma vez que reduz consideravelmente a curva
de aprendizado com ferramentas visuais e uma experiência fácil e intuitiva.

Outras excelentes ferramentas incluem o Eclipse e o IntelliJ, sendo que a


primeira eu utilizei ativamente durante meus primeiros anos como
programador Java, principalmente em virtude do hardware que eu dispunha à
época que era bem modesto. O NetBeans é uma IDE razoavelmente "pesada"
e caso você tenha um computador muito antigo, talvez tenha problemas em
usá-lo.

Para baixar e instalar o NetBeans, acesse o seguinte link, no site oficial da


ferramenta:

https://netbeans.org/downloads/

Você notará que existem diversas opções para download, isso porque o
NetBeans não é uma IDE exclusiva para o Java, permitindo desenvolvimento
em C/C++, PHP, Web e diversas plataformas Java diferentes, sendo que a
que usaremos aqui é a Java SE (Standard Edition, Edição Padrão). Caso
esteja com espaço em disco sobrando e esteja pensando em programar para
outras plataformas mais adiante, baixe a versão completa (All) mesmo. Da
mesma forma que o Java em si, o NetBeans possui instaladores para os
principais sistemas operacionais do mercado.

Não há nada de especial com a instalação, apenas avance constantemente e


aceite o contrato que aparecer.
Olá Mundo
Vamos verificar se está tudo funcionando corretamente? A melhor maneira
para isso é criando nosso primeiro programa em Java!

Mande executar a ferramenta NetBeans e você verá a tela de boas vindas, que
deve se parecer com essa abaixo, dependendo da versão mais atual da
ferramenta. Chamamos esta tela de Boas Vindas (Welcome Screen).

No menu do topo você deve encontrar a opção File/Arquivo e dentro dela a


sub-opção New Project/Novo Projeto, abrindo o assistente de configuração
de projeto abaixo.
Assim como exemplificado na imagem anterior, selecione a categoria Java e
depois o projeto Aplicação Java.

Na página "Nome e local" do assistente, adote o seguinte procedimento


(como mostrado na figura a seguir):
1. no campo Nome do projeto, digite OlaMundo. (ou nome de sua
preferência).
2. deixe desmarcada a caixa de verificação "Usar pasta dedicada para
armazenar bibliotecas".
3. deixe marcada a caixa de verificação "Criar Classe Principal" e no
nome da classe digite: "olaMundo.OlaMundo".
4. deixe marcada a caixa de verificação "Definir como projeto principal".
Clique em Finalizar.

Esses passos citados acima são sempre os mesmos toda vez que criarmos um
novo projeto Java. Marque essa página para futuras consultas, pois não
descreverei mais estes passos com tantos detalhes mais tarde.

O projeto é criado e aberto no IDE. Agora você deve ver os seguintes


componentes principais:
● A coluna lateral Projetos, que contém uma exibição em árvore dos
componentes do projeto, incluindo arquivos de origem, bibliotecas de
que seu código depende e diversos elementos que você precisará
futuramente.
● A janela "Editor de código-fonte" ao meio, com um arquivo chamado
OlaMundo aberto.

Uma vez que você deixou marcada a caixa de verificação Criar classe
principal no assistente para Novo projeto, a IDE criou um classe básica para
você. Você pode adicionar a mensagem "Olá mundo!" ao código de exemplo
substituindo a linha:

Código 1: disponível em http://www.luiztools.com.br/livro-java-i-fontes

// TODO code applications logic here

pela linha:

Código 2: disponível em http://www.luiztools.com.br/livro-java-i-fontes

System.out.println("Olá Mundo!");

Salve a alteração escolhendo Arquivo > Salvar ou usando o atalho Ctrl + S.

O arquivo deve ter uma aparência semelhante à seguinte amostra de código.

Os demais exemplos não postarei a imagem do código, mas sim apenas o


conteúdo interno do bloco de código main (entre as linhas 14 e 16), assim
como representado acima.

Devido ao recurso Compilar ao salvar do IDE, não é necessário compilar


manualmente o projeto para que seja executado no IDE. Quando um arquivo
de código-fonte Java é salvo, ele é compilado automaticamente pelo IDE.
Para executar o programa escolha Executar > Executar projeto principal (F6).
A figura abaixo mostra o que você deve ver agora, na janela inferior
Saída/Output da IDE, que fica na parte inferior esquerda da mesma.

Parabéns! Seu programa funciona!

Se houver erros de compilação, estes são marcados com marcas vermelhas na


margem esquerda do editor de código-fonte. Você pode passar o mouse sobre
a marca do erro para ver a descrição de tal erro.

Classe?
O Java é uma linguagem da família das linguagens Orientadas à Objetos, o
que quer dizer que seu programa será estruturado em classes, sendo cada
arquivo Java uma classe (class). Cada classe pode ter vários códigos Java
dentro dela. Nossos programas serão básicos, então teremos apenas uma
classe por programa e não se preocupe muito com isso por enquanto.

Vimos que com o uso do comando System.out.println podemos escrever


textos na janela do console do NetBeans. Esta instrução orienta que seja
impresso uma linha (println) na saída (out) do sistema (System), linha essa
que deve estar entre aspas dentro dos parênteses do comando println.

A primeira linha "package olaMundo" indica um pacote a que pertence esta


classe, como se fosse uma pasta do sistema operacional, e servem para
organizar os programa em Java.
O segundo bloco do código descreve um comentário em Java, um trecho de
texto que não será compilado. Vamos ignorar ele por enquanto, é apenas para
guardar instruções e veremos mais disso depois.

Já a linha
Código 3: disponível em http://www.luiztools.com.br/livro-java-i-fontes

public class OlaMundo {

inicia uma definição de classe para o arquivo OlaMundo.

Importante: todo programa Java deve possuir pelo menos uma


classe/arquivo Java que é definida pelo programador. Essa classe possuirá o
bloco principal de código da aplicação, chamado de main. O main é por onde
a aplicação inicia sua execução.

A palavra reservada public indica que esta classe/arquivo é pública, ou seja,


pode ser invocada de qualquer ponto do programa.

A palavra class introduz uma definição de classe em Java, ou seja, define que
aquele código entre as chaves será uma classe. Ela deve possuir o nome da
classe à sua direita, no caso OlaMundo.

A linha

Código 4: disponível em http://www.luiztools.com.br/livro-java-i-fontes

public static void main (String args[]) {

é uma parte recorrente em todo programa de computador Java. Os programas


em Java sempre começam sua execução em um bloco de código main, sendo
que os parênteses depois do main indicam que ele é um bloco de construção
de programa chamado de método.

Para uma classe que seja um programa Java, sempre devemos ter um método
main que deve ser definido tal qual como está na linha descrita anteriormente.
Se o método main não for escrito exatamente daquele jeito, o interpretador do
Java não executará o programa.

A palavra reservada public como já foi dito anteriormente, define o escopo


do código dentro do programa, ou seja, público, qualquer um pode "chamar"
esse código.

A palavra reservada void indica que este método realizará uma tarefa (neste
caso, imprimir a linha de texto na tela) mas NÃO retornará informação
alguma ao seu término.

O termo "String args[]" dentro dos parênteses são argumentos passados para
esse programa e são obrigatórios no main, embora não iremos utilizá-lo aqui.

As chaves esquerda e direita definem o escopo em programas Java, blocos de


código. Uma chave esquerda "{" indica o início do corpo da definição da
classe ou do método. Toda chave que abre deve possuir uma chave que fecha,
"}", caso contrário teremos erro de compilação.

A linha

Código 5: disponível em http://www.luiztools.com.br/livro-java-i-fontes

System.out.println("Olá Mundo!");

instrui o computador a realizar a ação de imprimir o texto contido entre as


aspas duplas na janela de saída da IDE ou em um prompt de comando
(também chamado de console ou terminal) no computador, definido pela
palavra System.out, que significa "saída do sistema".

System.out.println é o comando que imprime a linha que é passada entre


parênteses, que chamamos de parâmetros ou argumentos.

As duas últimas chaves do código do nosso programa são o fechamento do


método main e o fechamento da classe em si.
Cuidado com o ponto-e-vírgula! Com exceção das linhas em branco, linhas
comentadas e linhas que terminem com chaves, todas as demais linhas de
arquivos Java exigem o término com ponto-e-vírgula, para indicar fim de
instrução.

E com isso finalizamos a construção do nosso Olá Mundo em Java, o


primeiro programa que qualquer programador deve criar quando está
aprendendo uma nova linguagem de programação!
3 Tipos e Variáveis
Todo programa Java é um sistema computacional completo e, como tal, é
feito de entrada de dados, processamento e saída de informações. Esses dados
citados são geralmente armazenados para processamento e transporte pela
memória do computador em estruturas que chamamos de variáveis, o menor
elemento de um programa de computador.

Neste capítulo apresentarei a sintaxe da linguagem Java, abordando os


principais tipos de dados existentes, as regras para declaração de variáveis e
as recomendações gerais para nomenclatura. Como será notado por quem já é
programador de outras linguagens, a sintaxe da linguagem Java é muito
semelhante àquela usada pela linguagem C/C++, isso porque tanto o Java
quanto o C# se inspiraram em C/C++.
Declaração de Variáveis
Uma variável é um nome definido pelo programador ao qual pode ser
associado um valor pertencente a um certo tipo de dados. Para que muitas
coisas aconteçam em nossos sistemas, nós precisaremos de variáveis, tal qual
operações aritméticas, armazenamento de dados e mensagens para o usuário,
só para citar alguns exemplos comuns.

Em outras palavras, uma variável é como uma memória, capaz de armazenar


um valor de um certo tipo, para a qual se dá um nome que usualmente
descreve seu significado ou propósito. Desta forma toda variável possui um
nome, um tipo e um conteúdo.

O nome de uma variável em Java pode ser uma sequência de um ou mais


caracteres alfabéticos e numéricos, iniciados por uma letra ou ainda pelos
caracteres ‘_’ (underscore) ou
‘$’ (cifrão). Os nomes não podem conter outros símbolos gráficos,
operadores ou espaços em branco. É importante ressaltar que as letras
minúsculas são consideradas diferentes das letras maiúsculas, ou seja, a
linguagem Java é sensível ao caixa empregado (case sensitive), assim temos
como exemplos válidos:

a total x2 $mine _especial


TOT Maximo ExpData nome meuNumero

Segundo as mesmas regras temos abaixo exemplos inválidos de nomes de


variáveis:

1x Total geral numero-minimo void

A razão destes nomes serem inválidos é simples: o primeiro começa com um


algarismo numérico, o segundo possui um espaço em branco, o terceiro
contém o operador menos, mas por que o quarto nome é inválido?
Porque além das regras de formação do nome em si, uma variável não pode
utilizar como nome uma palavra reservada da linguagem. As palavras
reservadas são os comandos, nomes dos tipos primitivos, especificadores e
modificadores pertencentes a sintaxe de uma linguagem.

As palavras reservadas da linguagem Java, que portanto não podem ser


utilizadas
como nome de variáveis ou outros elementos, são:

abstract boolean break byte case catch


char class continue default do double
else extends false final finally float
for if implements import instanceof int
interface long native new null package
private protected public short static super
switch synchronized this throw throws transient
true try void while const future
generic goto inner operator outer rest
var volatile

As últimas palavras, grifadas em cinza, não são usadas pela linguagem, mas
ainda assim são reservadas, devido à comandos da especificação original da
linguagem Oak, precursora do Java.

Desta forma para declararmos uma variável devemos seguir a seguinte


sintaxe:

TipoDaVariavel nomeDaVariavel;

Ou seja, primeiro indicamos um tipo, depois declaramos a variável,


terminando a declaração com ‘;’ (ponto e vírgula). Exemplos:
int i; byte mascara; double valorMedio;

As variáveis podem ser declaradas individualmente ou em conjunto,


separando variáveis de mesmo tipo apenas por vírgula:

char opcao1, opcao2; float total, preco;

Também é possível definirmos uma valor inicial para uma variável


diretamente em sua declaração como indicado a seguir:

int quantidade = 0; float angulo = 1.57;


boolean ok = false; char letra = ‘c’;

Variáveis podem ser declaradas em qualquer ponto de um programa Java,


sendo válidas em todo o escopo onde foram declaradas e nos escopos
internos à estes. Por escopo entende-se o bloco (conjunto de comandos da
linguagem) onde ocorreu a declaração da variável (geralmente delimitado por
chaves).

Em Java recomenda-se que a declaração de variáveis utilize nomes iniciados


com letras minúsculas. Caso o nome seja composto de mais de uma palavras,
as demais deveriam ser iniciadas com letras maiúsculas tal como nos
exemplos:

contador total sinal


posicaoAbsoluta valorMinimoDesejado mediaGrupoTarefa2
Tipos de dados primitivos
A linguagem Java possui oito tipos básicos de dados, denominados tipos
primitivos, que podem ser divididos nos 3 grupos a seguir:

Grupo 1: Números inteiros


● Byte - representado pela palavra byte;
● Inteiro Curto (Short Integer) - representado como short;
● Inteiro (Integer) - representado como int;
● Inteiro Longo (Long Integer) - representado como long;

Devido ao tamanho de cada um dos tipos de números inteiros, podemos


armazenar uma diferente quantidade de valores em variáveis que possuam os
respectivos tipos, a saber:

Tipo Tamanho Mínimo Máximo


byte 8-bit -128 +127
short 16-bit -32.768 +32.767
int 32-bit -2.147.483.648 +2.147.483.647
long 64-bit -9.223.372.036.854.775.808 +9.223.372.036.854.775.807

Exemplos de variáveis declaradas com estes tipos são dados no trecho de


código Java abaixo. Note que em todos eles eu já atribuí um valor à cada
uma, o que é considerado uma boa prática de desenvolvimento.
Código 6: disponível em http://www.luiztools.com.br/livro-java-i-fontes

byte b = 0;
short s = 20;
int i = 200;
long l = 2000;

Grupo 2: Números com ponto flutuante


● Ponto Flutuante Simples (Float) - representado pela palavra float e
tamanho de 32 bits
● Ponto Flutuante Duplo (Double) - representado pela palavra double e
tamanho de 64 bits

No Java existem duas representações para números em ponto flutuante que se


diferenciam pela precisão oferecida: o tipo float permite representar valores
reais com precisão simples (representação interna de 32 bits) enquanto o tipo
double oferece dupla precisão (representação interna de 64 bits).

Exemplos de variáveis declaradas como tipos de ponto flutuante podem ser


observados abaixo:

Código 7: disponível em http://www.luiztools.com.br/livro-java-i-fontes

float f = 1.5f;
double d = 2000.678;

Note como o valor literal da variável float está sendo atribuído com um ‘f’ no
final. Isso se deve ao fato de que, em Java, valores literais com ponto
flutuante são considerados double por padrão.

Grupo 3: Tipos Não-numéricos

Caractere (Character)

O tipo char permite a representação de caracteres individuais. Como o Java


utiliza uma representação interna no padrão UNICODE, cada caractere ocupa
16 bits (2 bytes) sem sinal, o que permite representar até 32.768 caracteres
diferentes, teoricamente facilitando o trabalho de internacionalização de
aplicações Java.

Alguns caracteres são considerados especiais pois não possuem uma


representação
visual, sendo a maioria caracteres de controle e outros caracteres cujo uso é
reservado pela
linguagem. Tais caracteres podem ser especificados dentro dos programas
como indicado
na tabela abaixo, ou seja, precedidos por uma barra invertida (‘\’):

Representação Significado
‘\n’ quebra de linha
‘\r’ retorno ao início da linha (carriage return)
‘\t’ tabulação (tab)
‘\’’ apóstrofe (também chamado de aspas simples)
‘\"’ aspas (ou aspas duplas)
‘\\’ barra invertida (backslash)

O valor literal de caracteres deve estar delimitado por aspas simples (‘ ’).

Abaixo temos o exemplo de uma variável declarada do tipo char:

Código 8: disponível em http://www.luiztools.com.br/livro-java-i-fontes

char c = 'a';

Booleano (Boolean)

Em Java dispomos do tipo lógico boolean capaz de assumir os valores false


(falso) ou
true (verdadeiro) que equivalem aos estados off (desligado) e on (ligado) ou
no (não) e yes
(sim).

Abaixo temos um exemplo de variável declarada como tipo booleano,


recebendo um dos dois valores possíveis para a mesma:

Código 9: disponível em http://www.luiztools.com.br/livro-java-i-fontes


boolean b = true;

Como pode ser facilmente observado, os tipos primitivos do Java são os


mesmos encontrados na maioria das linguagens de programação e permitem a
representação adequada de diversos valores. Ainda assim, você pode sentir a
falta de outros tipos de dados enquanto estiver desenvolvendo seus
programas, e o Java tem diversos outros tipos que não são considerados
primitivos, mas derivados ou objetos.

A representação de outros tipos de dados utiliza objetos específicos assim


como existem classes denominadas wrappers que encapsulam os tipos
primitivos como objetos da linguagem. O maior exemplo de tipo derivado
que usamos no dia-a-dia é a String, utilizada para representar textos (mais do
que um caractere). Mas falaremos disso mais tarde.
Comentários
Comentários são trechos de texto, usualmente explicativos, inseridos dentro
do programa de forma que não sejam considerados como parte do código, ou
seja, são informações deixadas juntamente com o código para informação de
quem programa.

O Java aceita três tipos de comentários: de uma linha, de múltiplas linhas e de


documentação. O primeiro de uma linha utiliza duas barras (//) para marcar
seu início:

Código 10: disponível em http://www.luiztools.com.br/livro-java-i-fontes

//comentário de uma linha


//tudo após as duas barras é considerado comentário

O segundo usa a combinação /* e */ para delimitar uma ou mais linhas de


comentários:

Código 11: disponível em http://www.luiztools.com.br/livro-java-i-fontes

/* comentário
de múltiplas linhas */

O último tipo é semelhante ao comentário de múltiplas linhas mas tem o


propósito
de documentar o programa:

Código 12: disponível em http://www.luiztools.com.br/livro-java-i-fontes

/** comentário de documentação que também


* podem ter múltiplas linhas
*/
Geralmente o comentário de documentação é posicionado imediatamente
antes do elemento a ser documentado e tem seu conteúdo extraído
automaticamente pelo utilitário javadoc fornecido juntamente com o JDK.
Esta ferramenta gera páginas em formato html contendo os comentário
organizados da mesma forma que a documentação fornecida juntamente com
o JDK.

Mas porque estou falando de comentários agora, logo após falar de


declaração de variáveis? Porque uma excelente maneira de melhorar os seus
estudos é, a cada trecho de código escrito, comentar do que se trata a
respectiva linha de código!

Aproveitando o exemplo de ‘olá mundo’ que fizemos no capítulo anterior,


coloco abaixo o mesmo trecho de código, mas desta vez comentado. Note
como fica mais fácil entender do que se trata cada uma das linhas.

Código 13: disponível em http://www.luiztools.com.br/livro-java-i-fontes

package olaMundo;//nome do pacote

//declaração da classe
public class OlaMundo{
//bloco principal, que inicia a aplicação
public static void main(String[] args){
//diretiva que imprime no console
System.out.println("Olá mundo!");
}
}

Conforme você for avançando e pegando experiência com Java, não precisará
usar mais tantos comentários, provavelmente apenas em blocos de código
complexos, como forma de documentação para uso futuro. Por ora, comente
tudo o que achar conveniente para seus estudos.

Aproveitando que "revisitamos" o ‘olá mundo’, que tal escrever um software


bem simples que apenas imprima na tela o valor que o usuário fornece para
algumas variáveis?

Para fazer isso é bem simples. Primeiro, declare quantas variáveis quiser, de
preferência de tipos diferentes e atribua um valor inicial para cada uma, como
fiz no exemplo abaixo com a variável do tipo int.

Código 14: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int x = 0;

Segundo, peça ao usuário que digite um valor para essa variável, apenas
imprimindo uma mensagem para ele:

Código 15: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int x = 0;
System.out.println("Digite um valor inteiro para x:");

O comando acima apenas "pede" ao usuário que digite um número, mas


como "identificamos" o número que o usuário digitar no teclado? Não é
difícil, na verdade precisa de apenas duas linhas!

Vou falar com mais detalhes delas futuramente, mas por ora, apenas entenda
a primeira linha cria um objeto que simboliza o teclado do computador
(teclado), e a segunda linha lê o primeiro número inteiro que o usuário digitar
no teclado (teclado.nextInt).

Código 16: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int x = 0;
System.out.println("Digite um valor inteiro para x:");

Scanner teclado = new Scanner(System.in);


x = teclado.nextInt();
Uma vez que você tenha uma variável teclado declarada (como fizemos
acima), podemos usá-la para ler diversos valores digitados pelo usuário sem
precisar declarar novamente o teclado, como mostrado no exemplo abaixo,
que não faz parte do programa anterior:

Código 17: disponível em http://www.luiztools.com.br/livro-java-i-fontes

Scanner teclado = new Scanner(System.in);


int x = teclado.nextInt();
float f = teclado.nextFloat();
double d = teclado.nextDouble();
//etc

Depois, para cada variável digitada pelo usuário, digite o comando abaixo,
que imprime o valor da variável logo após a frase "Variável x: ", sendo que
troque ‘x’ pelo nome da sua variável.

Código 18: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int x = 0;
System.out.println("Digite um valor inteiro para x:");

Scanner teclado = new Scanner(System.in);


x = teclado.nextInt();

System.out.println("Variável x:" + x);

Executando este último trecho de código, dentro de um método main, o


NetBeans vai abrir a janela do console e lhe pedir para digitar um número.
Digite um número inteiro qualquer e depois tecle Enter. Até que você tecle
Enter, o programa não prosseguirá, esperando que digite.

Se você digitar o valor 10, por exemplo, o programa vai encerrar com a
seguinte aparência:
Digite um valor inteiro para x:
10
Variável x: 10

Note que quando você coloca o nome de uma variável entre aspas
(consequentemente dentro de um texto), é impresso o nome da mesma no
console. Já quando coloca o nome da variável sem aspas, é impresso o valor
da mesma, neste meu exemplo, o valor numérico 10.

Note também que usamos um sinal de ‘+’ para concatenar (combinar) o texto
"Variável x: " com o valor numérico da variável. Quando mandamos executar
esse bloco de código, o texto combinado é exibido ao invés de suas partes
individuais, o que nos mostra que o operador ‘+’ pode ter efeitos diferentes
do que estamos acostumados, dependendo se estamos lidando com números
ou palavras.

Isso tudo por causa de um tipo especial de objeto, as Strings, que falaremos
mais adiante, no próximo capítulo, juntamente com os operadores!
4 Operadores e o tipo String
A linguagem Java oferece um conjunto bastante amplo de operadores
destinados a realização de operações aritméticas, lógicas, relacionais e de
atribuição. Essas operações servem para processar os dados recebidos em seu
sistema computacional, visando realizar alguma tarefa para o usuário, o
objetivo do seu sistema.

Usamos alguns destes operadores no capítulo anterior, mas sem entrar muito
nos detalhes do seu funcionamento, o que faremos agora.

O tipo String, que também será abordado neste capítulo, é um tipo mais
avançado que os primitivos, falados no capítulo anterior. Ele será abordado
ao término desta unidade.
Operadores Aritméticos
Como na maioria das linguagens de programação, o Java possui vários
operadores aritméticos. Considere nos exemplos que a e b são variáveis
numéricas (int, short, etc).

Operador Significado Exemplo


+ Adição, soma dois valores a+b
- Subtração, subtrai um valor de outro a-b
* Multiplicação, multiplica dois valores a*b
/ Divisão, divide um valor pelo outro e retorna o a/b
resultado da divisão
% Módulo, divide um valor pelo outro e retorna o a%b
resto da divisão
++ Incremento unário, aumenta o valor em 1 a++ ou
++a
-- Decremento unário, diminui o valor em 1 a-- ou --a

Estes operadores aritméticos podem ser combinados para formar expressões,


fazendo uso de parênteses para determinar a ordem específica de avaliação
de cada expressão.
A seguir um exemplo de aplicação que declara algumas variáveis, atribui
valores iniciais e efetua algumas operações imprimindo os resultados obtidos.

Crie um novo projeto no NetBeans (Arquivo > Novo Projeto > Aplicação
Java) e dê o nome de Aritmetica pra ele, sendo que esse será o nome da
classe principal com o main dentro. Em seguida, cole o código abaixo dentro
do bloco main da referida classe/arquivo.

Código 19: disponível em http://www.luiztools.com.br/livro-java-i-fontes


// Declaracao e inicializacao de duas variaveis, troque os valores se quiser
int a = 5;
int b = 2;
// Varios exemplos de operacoes sobre variaveis
System .out.println( "a = " + a);
System .out.println( "b = " + b);
System .out.println( "a + b = " + (a + b));
System .out.println( "a - b = " + (a - b));
System .out.println( "a * b = " + (a * b));
System .out.println( "a / b = " + (a / b));
System .out.println( "(float) a / b = " + (( float )a / b));
System .out.println( "a % b = " + (a % b));
System .out.println( "a++ = " + (a++));
System .out.println( "--b = " + (--b));
System .out.println( "a = " + a);
System .out.println( "b = " + b);

Compilando e executando o código fornecido (basta clicar no botão de play


verde do NetBeans ou com o clique-direito do mouse sobre o arquivo na
opção Executar) teremos o resultado a seguir:

a=6
b=1

Embora o exemplo só tenha utilizado variáveis e valores inteiros, o mesmo


pode ser realizado com variáveis do tipo ponto flutuante (float ou double).
Operadores Relacionais
Além dos operadores aritméticos o Java possui operadores relacionais, isto é,
operadores que permitem comparar valores literais, variáveis ou o resultado
de expressões retornando um resultado do tipo lógico, ou seja, um resultado
falso ou verdadeiro. Os operadores relacionais disponíveis são:

Operador Significado Exemplo


== Igualdade, retorna true se ambos valores forem a == b
iguais
!= Diferença, retorna true se ambos valores não a != b
forem iguais
> Maior que, retorna true se o valor da esquerda for a > b
maior que o da direita
>= Maior ou igual que, retorna true se o valor da a >= b
esquerda for maior ou igual ao da direita
< Menor que, retorna true se o valor da esquerda for a < b
menor que o da direita
<= Menor ou igual que, retorna true se o valor da a <= b
esquerda for menor ou igual que o da direita

Note que o operador igualdade é definido como sendo um duplo sinal de


igual (==) que não deve ser confundido com o operador de atribuição, um
sinal simples de igual (=), que falarei mais tarde. Esse erro é um dos mais
comuns por programadores desatentos.

O operador de desigualdade é semelhante ao existente na linguagem C, ou


seja, é representado por "!=". Os demais são idênticos a grande maioria das
linguagens de
programação em uso.

É importante ressaltar também que os operadores relacionais duplos, isto é,


aqueles definidos através de dois caracteres, não podem conter espaços em
branco.

A seguir um outro exemplo simples de aplicação envolvendo os operadores


relacionais. Como para o exemplo anterior, sugere-se que esta aplicação seja
testada como forma de se observar seu comportamento e os resultados
obtidos. Assim como sugerido anteriormente, crie um novo projeto, desta vez
com o nome de OperadoresRelacionais e cole o código abaixo dentro do
bloco main para realizar esse teste.

Código 20: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int a = 15;
int b = 12;
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("a == b : " + (a == b));
System.out.println("a != b : " + (a != b));
System.out.println("a < b : " + (a < b));
System.out.println("a > b : " + (a > b));
System.out.println("a <= b : " + (a <= b));
System.out.println("a >= b : " + (a >= b));
Operadores Lógicos
Como seria esperado o Java também possui operadores lógicos, isto é,
operadores que permitem conectar logicamente o resultado de diferentes
expressões aritméticas ou relacionais construindo assim uma expressão
resultante composta de várias partes e portanto mais complexa.

Nos exemplos abaixo, a e b não são necessariamente variáveis, mas sim


condições booleanas (true ou false), ou seja, podem ser qualquer tipo de
expressões que retornem true ou false, incluindo variáveis booleanas simples.

Operador Significado Exemplo


&& E lógico (AND), retorna true se ambas expressões a && b
retornarem true
|| Ou lógico (OR), retorna true se ao menos uma a || b
expressão retornar true
! Negação lógica (NOT), retorna o valor oposto ao !a
da expressão

Os operadores lógicos duplos, isto é, definidos por dois caracteres, também


não podem conter espaços em branco.
Operador de Atribuição
Atribuição é a operação que permite definir o valor de uma variável através
de uma constante ou através do resultado de uma expressão envolvendo
operações diversas. Geralmente lemos a expressão ‘a = b’ como ‘a recebe b’
e ‘a = 1’ como ‘a recebe 1’. Note que isto é diferente de ‘a == b’ e ‘a == 1’,
que lemos como ‘a é igual a b’ e ‘a é igual a 1’.

Exemplos de atribuições válidas são mostradas no trecho de código abaixo.

Código 21: disponível em http://www.luiztools.com.br/livro-java-i-fontes

boolean result = false;


i = 0;
y = a*x + b;

Note como podemos fazer uma atribuição no momento que declaramos a


variável, para inicializá-la com algum valor. Também podemos atribuir
valores mais tarde, com valores literais ou como resultado de expressões.

Que tal exercitar o aprendizado de operadores? Use o mesmo programa


criado no trecho de código 15, onde exercitamos a declaração e impressão de
variáveis, e adicione algumas operações na atribuição de variáveis, para
provocar alguns efeitos diferentes, como abaixo:

Código 22: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int i = 0;
int y = i + 2;
System.out.println("Valor do i: " + i);

Realize testes ao menos uma vez com cada operador, para entender na prática
como eles funcionam. Se não conseguir realizar testes com os operadores
lógicos, não tem problema, revisitaremos ele no próximo capítulo: Estruturas
de Controle.
O tipo String
Todos os tipos utilizados na linguagem Java, com exceção dos tipos
primitivos (int, double, char e boolean), são "objetos". O tipo String, com S
maiúsculo, é um dos objetos mais utilizados, isso porque ele é utilizado para
criar variáveis que guardam texto dentro de si, algo muito recorrente em
desenvolvimento de software.

Enquanto que o tipo char permite armazenar apenas um caracter por vez, o
tipo String permite armazenar um número virtualmente infinito de caracteres,
formando palavras, frases, textos, etc. Apesar de todo esse "poder", sua
declaração é tão simples quanto a de qualquer outra variável:

Código 23: disponível em http://www.luiztools.com.br/livro-java-i-fontes

String nome = "Luiz";

Note que a palavra ‘Luiz’ está entre aspas (duplas), logo após a declaração da
variável. Isso porque valores de texto literais devem estar entre aspas (duplas)
para serem considerados Strings.

Também vale prestar atenção que, se não declararmos o valor contido em


uma String em sua inicialização, ela conterá null (nulo). O ideal é sempre
inicializarmos nossas Strings, para não corrermos o risco de termos erros de
execução mais pra frente.

Assim como vimos anteriormente, quando usamos o operador ‘+’ com textos
(que agora chamaremos de Strings), ele não soma os seus valores, mas sim
concatena (junta) eles. Isso vale tanto para Strings literais (textos entre aspas)
quanto para variáveis Strings.

Código 24: disponível em http://www.luiztools.com.br/livro-java-i-fontes

String nome = "Luiz";


String sobrenome = "Duarte";
System.out.println("Prof. " + nome + sobrenome);
O código acima, se colocado dentro de um método main() qualquer em um
projeto do NetBeans deve imprimir o texto Prof. LuizDuarte na janela do
console. Isso porque ele concatenou (juntou) a String literal "Prof. " com as
variáveis nome e sobrenome, resultando em uma nova String, maior e mais
completa "Prof. LuizDuarte", que foi impressa pelo System.out.println.

Outra característica muito interessante das Strings é que qualquer variável


que a gente concatene com uma String, acaba gerando outra String, como
abaixo.

Código 25: disponível em http://www.luiztools.com.br/livro-java-i-fontes

String nome = "Luiz";


int idade = 28;
System.out.println("Prof. " + nome + " tem " + idade + " anos!");

Isso vai imprimir o texto "Prof. Luiz tem 28 anos!", copiando o valor da
variável idade pra dentro da nova String completa. Note que isso não altera o
tipo da variável idade ou seu valor, apenas faz uma cópia dela em forma de
texto, automaticamente.

Legal, não é mesmo?!

Agora vamos criar um programa bem simples, que pede o nome e o peso de
duas pessoas, para exercitar alguns tipos de variáveis que aprendemos até
agora!

Primeiro, vamos declarar as variáveis que precisaremos:

Código 26: disponível em http://www.luiztools.com.br/livro-java-i-fontes

String nome1 = "";//nome vazio


float peso1 = 0f;
String nome2 = "";
float peso2 = 0f;
Agora, vamos pedir ao usuário que digite o primeiro nome, e vamos ler ele.
Anteriormente vimos que podemos criar um objeto teclado que lê valores
digitados pelo usuário, será que podemos aproveitar esse objeto teclado para
ler uma palavra digitada pelo usuário?

Claro que sim, como abaixo!

Código 27: disponível em http://www.luiztools.com.br/livro-java-i-fontes

String nome1 = "";//nome vazio


float peso1 = 0f;
String nome2 = "";
float peso2 = 0f;

Scanner teclado = new Scanner(System.in);


System.out.println("Digite o nome 1:");
nome1 = teclado.next();

O tipo Scanner, que estamos usando para criar nosso objeto teclado, não
possui um método nextString, em analogia ao que ocorre com inteiros
(nextInt) por exemplo. Porém possui dois métodos para ler Strings: next e
nextLine, sendo que o primeiro lê a próxima palavra, e o segundo lê a
próxima linha digitada pelo usuário!

Agora para solicitar e "capturar" os demais valores, basta replicarmos os


conhecimentos que já vimos até aqui!

Código 28: disponível em http://www.luiztools.com.br/livro-java-i-fontes

String nome1 = "";//nome vazio


float peso1 = 0f;
String nome2 = "";
float peso2 = 0f;

Scanner teclado = new Scanner(System.in);


System.out.println("Digite o nome 1:");
nome1 = teclado.next();
System.out.println("Digite o peso 1:");
peso1 = teclado.nextFloat();
System.out.println("Digite o nome 2:");
nome2 = teclado.next();
System.out.println("Digite o peso 2:");
peso2 = teclado.nextFloat();

E para finalizarmos, testando se armazenamos os valores corretamente,


vamos mandar imprimir cada um dos nomes com seus respectivos pesos:

Código 29: disponível em http://www.luiztools.com.br/livro-java-i-fontes

System.out.println("A pessoa " + nome1 + " tem " + peso1 + "kg");


System.out.println("A pessoa " + nome2 + " tem " + peso2 + "kg");

Coloque o código acima no final do código anterior, que solicitava e lia as


variáveis, e mande executar no NetBeans, dentro de um arquivo com o
método main. Isso deve imprimir os nomes e pesos de cada pessoa no
console do NetBeans.

Mas e se quisermos saber quem é a mais pesada das duas pessoas?

Temos operadores para comparações, os operadores relacionais, conforme


vimos no tópico anterior! Ainda falta um conhecimento para poder usar eles
corretamente, que é o de estruturas de controle, que será visitado no próximo
capítulo.

Está começando a ficar mais interessante!


5 Estruturas de Controle e Arrays
Um programa de computador é escrito em uma sequência de instruções
organizadas de forma tal a produzir a solução de um determinado problema.
Naturalmente tais instruções são executadas em sequência, o que se
denomina fluxo sequencial de execução. Esse fluxo normal vai da primeira
instrução do seu programa (mais ao topo), até a última (mais abaixo).

No entanto, em inúmeras circunstâncias é necessário executar as instruções


de um programa em uma ordem diferente da estritamente sequencial. Tais
situações são caracterizadas pela necessidade da repetição de instruções
individuais ou de grupos de instruções e também pelo desvio do fluxo de
execução para outros trechos de código, ou em casos mais avançados, até
para outros arquivos.

As linguagens de programação tipicamente possuem diversas estruturas de


programação destinadas ao controle do fluxo de execução, isto é, estruturas
que permitem a repetição e o desvio do fluxo de execução. Geralmente as
estruturas de controle de execução são divididas em:

Estruturas de repetição: destinadas a repetição de um ou mais comandos,


criando o que se denomina laços. O número de repetições é definido por uma
condição, que pode ser simples como uma comparação numérica, ou
complicado como uma expressão lógica. No Java dispõe-se das diretivas for,
while e do/while.

Estruturas de desvio de fluxo: destinadas a desviar a execução do programa


para uma outra parte, quebrando o fluxo sequencial de execução. O desvio do
fluxo pode ocorrer condicionalmente, quando associado a avaliação de uma
expressão, ou incondicionalmente. No Java dispomos das diretivas if/else e
switch/case.

A imagem abaixo ilustra os três tipos possíveis de fluxos de execução em um


software: o sequencial, que seria o fluxo padrão; um fluxo repetitivo, onde
temos um laço de repetição em determinado momento; e um fluxo com
desvio, cuja "direção" é decidida com base em uma condição lógica.
Agora vamos estudar cada um dos tipos de estruturas de controle básicas que
possuímos no Java.
Estruturas de repetição
Estas estruturas podem ser divididas entre simples e condicionais.
Independente da classificação, elas repetem um ou mais comandos Java
durante um número de vezes definido na sua declaração ou baseado em uma
expressão lógica, como veremos a seguir.

Como repetição simples consideramos um trecho de código, isto é, um


conjunto de diretivas que deve ser repetido um número conhecido e fixo de
vezes. A repetição é uma das tarefas mais comuns da programação utilizada
para efetuarmos contagens, para obtenção de dados, para impressão etc.

Estrutura FOR
Em Java dispomos da diretiva for cuja sintaxe é dada a seguir:

for (inicialização; condição de execução; incremento/decremento)


diretiva;

O for (PARA) possui três campos ou seções, delimitados por um par de


parênteses que efetuam o controle de repetição de uma diretiva individual ou
de um bloco de diretivas (neste caso, circundado por chaves). Cada campo é
separado do outro por um ponto e vírgula.

O primeiro campo é usado para dar valor inicial a uma variável de controle
(um contador). Nele declaramos nossa variável de controle, geralmente um
inteiro, e inicializamos ele, geralmente com 0, como no exemplo abaixo.

for (int i=0; condição de execução; incremento/decremento)


diretiva;

O segundo campo é uma expressão lógica que determina a execução da


diretiva associada ao for, geralmente utilizando a variável de controle e
outros valores. Resumindo: o segundo campo vai determinar quantas vezes a
diretiva do for será executada. Atente ao exemplo abaixo:

for (int i=0; i < 10; incremento/decremento)


diretiva;

O que você consegue abstrair a partir do segundo campo do for?


Considerando que i é a nossa variável de controle, usamos ela em uma
expressão lógica para determinar quantas vezes a diretiva irá ser executada.
Neste caso, enquanto i for menor que 10, executaremos a diretiva (um
comando Java qualquer).

Mas se i = 0, quando que ele será maior ou igual à 10 para o for encerrar a
repetição? Aí que entra o terceiro campo do for: o incremento/decremento.
Neste último campo nós mudamos o valor da variável de comando, para mais
ou para menos. Esse incremento/decremento acontece uma vez a cada
repetição do laço, logo após a execução da diretiva e antes da condição
(segundo campo do for) ser analisada novamente. Isto faz com que, em
determinado momento, o laço pare de se repetir, como no exemplo abaixo.

for (int i=0; i < 10; i++)


diretiva;

Neste caso, a diretiva será executada 10 vezes e sequência, uma vez que a
cada execução o valor de i aumentará em uma unidade até alcançar o valor
10, o que fará com que a condição ‘i < 10’ se torne falsa e o for acabe sua
execução.

Não acredita? Copie o código abaixo, onde substituí a diretiva por um


comando de impressão do Java e execute no NetBeans dentro do main de
algum projeto para ver o resultado:

Código 30: disponível em http://www.luiztools.com.br/livro-java-i-fontes


for (int i=0; i < 10; i++)
System.out.println("i=" + i);

A saída esperada é uma sequência de impressões iniciadas em ‘i=0’ e


terminando em ‘i=9’, pois quando o i for igual a 10, o for será encerrado.

A tradução literal do for é PARA, e lemos o código anterior como "para uma
dada variável i, inicializada com 0, até ela se tornar 10, imprima o valor de i e
incremente-o logo após".

Atenção: você notou a margem usada antes do comando System.out.println?


Ela se chama identação e serve para mostrar que o comando em questão
pertence ao escopo da instrução anterior (for). Isso Não é obrigatório, mas
ajuda enormemente a entender que a diretiva de impressão está aninhada na
estrutura de repetição. Assim, é sempre uma boa prática usar tabulação (tab)
ou uns 3 espaços em diretivas aninhadas.

Caso quiséssemos executar mais de uma instrução dentro do for, repetidas


vezes, basta apenas circundarmos elas com chaves, como no exemplo abaixo:

Código 31: disponível em http://www.luiztools.com.br/livro-java-i-fontes

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


System.out.println("i=" + i);
//outra instrução qualquer, quantas quiser
}

Podemos resumir o funcionamento da estrutura for através do fluxograma


abaixo:
Mas e as estruturas de repetição mais complexas, baseadas em condições?

As estruturas de repetição condicionais são estruturas de repetição cujo


controle de execução é feito pela avaliação de expressões condicionais. Estas
estruturas são adequadas para permitir a execução repetida de um conjunto de
diretivas por um número indeterminado de vezes, isto é, um número que não
é conhecido durante a fase de programação mas que pode ser determinado
durante a execução do programa tal como um valor a ser fornecido pelo
usuário, obtido de um arquivo ou ainda de cálculos realizados com dados
alimentados pelo usuário ou lido de arquivos.

Existem duas estruturas de repetição condicionais: while e do/while.

Estrutura WHILE
O while (ENQUANTO) é o que chamamos de laço condicional, isto é, um
conjunto de instruções que é repetido enquanto o resultado de uma expressão
lógica (uma condição) é avaliado como verdadeiro. Abaixo segue a sintaxe
desta diretiva:

while (expressão_lógica)
diretiva;

Note que a diretiva while avalia o resultado da expressão antes de executar a


diretiva associada, assim é possível que a diretiva nunca seja executada caso
a condição seja inicialmente falsa.

Mas que tipo de expressão lógica usamos geralmente como condição do


while? Abaixo temos um exemplo bem simples:

boolean chave = true;


while(chave == true)
diretiva;

Neste exemplo inicializamos uma variável chave do tipo boolean como true
(verdadeiro) e depois usamos a própria variável como condição de parada do
while. Enquanto chave for true, o while continuará sendo executado (i.e. a
diretiva será executada). No entanto, note que um problema típico
relacionado a avaliação da condição da diretiva while é o seguinte: se a
condição nunca se tornar falsa o laço será repetido indefinidamente.

Para que isso não aconteça, devemos nos certificar de que exista algo na
diretiva que, em dado momento, modifique o valor da condição, como no
exemplo abaixo:

Código 32: disponível em http://www.luiztools.com.br/livro-java-i-fontes

boolean chave = true;


while(chave == true)
chave = false;
Nesse caso, o while executará apenas uma vez e depois será encerrado, pois
na segunda vez que a condição for analisada, a variável chave terá valor false
e ele não executará sua diretiva novamente.

Lemos o trecho de código anterior como "enquanto a variável chave for


verdadeira, troque o valor dela para false".

Claro, esse é um exemplo pouco útil, uma vez que a única instrução existente
é para encerrar o while. O que acontece geralmente é que o while possua
mais de uma diretiva e, assim como for, elas devem ser circundadas por
chaves:

Código 33: disponível em http://www.luiztools.com.br/livro-java-i-fontes

boolean chave = true;


while(chave == true){
//outra instrução qualquer
System.out.println("Imprime!");
chave = false;
}

É possível ainda, usar o while de maneira semelhante ao for, definindo como


condição uma comparação lógico-aritmética:

Código 34: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int i = 0;
while(i < 10){
//outra instrução qualquer
System.out.println("Imprime!");
i++;
}

Nesse caso, o texto "Imprime!" será impresso 10 vezes, assim como seria
possível fazer com um for.

O funcionamento do while pode ser resumido através do fluxograma abaixo:

Estrutura DO/WHILE
O do/while também é um laço condicional, isto é, tal como o while é um
conjunto de instruções que são repetidas enquanto o resultado da condição é
avaliada como verdadeira mas, diferentemente do while, a diretiva associada
é executada antes da avaliação da expressão lógica e assim temos que esta
diretiva é executada pelo menos uma vez.

Por exemplo:
Código 35: disponível em http://www.luiztools.com.br/livro-java-i-fontes

boolean chave = false;


do{
//outra instrução qualquer
System.out.println("Imprime!");
} while(chave == true);
Note que a variável chave foi declarada como false logo na sua inicialização,
ou seja, quando ela for comparada na condição do while ela ainda será false e
consequentemente sairá do while. Porém, como o bloco do é executado
primeiro, teremos a impressão da palavra "Imprime!" na saída do console.

Lemos o código anterior como: "faça (DO) a impressão da palavra imprime,


enquanto (WHILE) a variável chave for verdadeira".

Basicamente esta é a única diferença entre os laços while e do/while. O


do/while sempre executa o laço ao menos uma vez, antes de fazer a
comparação, como ilustrado pelo fluxograma abaixo:

Um exercício que você pode fazer para testar o for, o while e o do/while é o
seguinte: antes de conhecer os laços de repetição, como você faria para
declarar uma variável e imprimi-la de 0 a 9?

O código abaixo exemplifica como você poderia fazer:

Código 36: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int x = 0;
System.out.println(x++);
System.out.println(x++);
System.out.println(x++);
System.out.println(x++);
System.out.println(x++);
System.out.println(x++);
System.out.println(x++);
System.out.println(x++);
System.out.println(x++);

Copie e cole o código acima dentro de um método main em um arquivo Java


qualquer e você verá, que graças ao operador de incremento unário a variável
x vai do valor 0 ao 9, sendo impressa durante o processo.

Repetitivo, não? Seria tão bom se tivéssemos uma maneira de repetir


comandos Java sem repetir código...É nessas horas, quando você precisa
repetir comandos, que os laços de repetição são úteis!

Pare um minuto e pense como esse mesmo exercício (imprimir um número


de 0 a 9) poderia ser feito usando laços de repetição...

Aqui vai uma solução, agora usando um laço for:

Código 37: disponível em http://www.luiztools.com.br/livro-java-i-fontes

for(int i=0; i < 10; i++)


System.out.println(i);

Copie e cole esse código e verá que o resultado no console é o mesmo.

Muito menor, não?!

Como é uma tarefa repetitiva cuja condição de parada é numérica e os valores


vão incrementando unitariamente, o for é a melhor opção. Mesmo assim, a
título de exercício, vou mostrar implementações usando while:
Código 38: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int x=0;
while(x < 10)
System.out.println(x++);

E outra usando do/while:

Código 39: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int x=0;
do{
System.out.println(x);
} while(x++ < 10);

Ambos exemplos fazem exatamente a mesma coisa. Estudar algoritmos de


programação é exatamente isso: entender que diversos caminhos levam à
mesma solução. Cabe ao programador identificar qual o melhor, neste caso, o
for.

Um último ponto digno de nota é a forma como usei o incremento unário


nestes exemplos. Note que incrementei o valor de x dentro de um println e
dentro de uma estrutura while. Isso é perfeitamente possível e lhe permite
estratégias interessantes em seus algoritmos. Temos dois operadores de
incremento unário, o ++x e o x++. O primeiro aumenta o valor de x em 1 e
depois retorna o valor do mesmo, enquanto que o segundo retorna o valor de
x e depois o aumenta em 1. Pode parecer uma pequena diferença, mas analise
esse código:

Código 40: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int x=0;
System.out.println(x++);

O que será impresso?


A resposta é 0.

Já neste exemplo…

Código 41: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int x=0;
System.out.println(++x);

A resposta é 1. Capicce?

Então vamos passar à próxima estrutura, temos muito pra ver ainda dentro do
básico de Java!
Estruturas de desvio de fluxo
Existem várias estruturas de desvio de fluxo que podem provocar a
modificação da maneira com que as diretivas de um programa são executadas
conforme a avaliação de uma condição. O Java dispõe de duas destas
estruturas: if/else e switch/case.

Estrutura IF/ELSE
O if/else é uma estrutura simples de desvio de fluxo de execução, isto é, é
uma diretiva que permite a seleção entre dois caminhos distintos para
execução dependendo do resultado falso ou verdadeiro resultante de uma
expressão lógica.

Vamos começar do if básico:

if (expressão_lógica)
diretiva1;

A tradução literal de um if é SE. SE a expressão entre parênteses for verdade


(true), então a diretiva1 será executada. Caso contrário, ela é ignorada.
Exemplo:

Código 42: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int x = 0;
if(x == 0)
System.out.println("X é zero!");

O que acontece quando executamos esse código? E se alterarmos o valor


inicial de x (na primeira linha), fazendo ele receber 1 ao invés de 0?

A frase "X é zero" somente será impressa se a variável x for zero. Em


qualquer outra circunstância, não.
Note que, assim como acontece nos laços de repetição, se vamos executar
mais de uma diretiva, devemos agrupá-las dentro de chaves, como no
exemplo abaixo, levemente modificado do anterior.

Código 43: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int x = 0;
if(x == 0){
System.out.println("X é zero!");
x++;
}

Neste exemplo, como queremos executar dois comandos no caso do x ser


zero, devemos circundar os comandos com chaves. Podemos ler esta
estrutura como "se a variável x for igual a zero, imprimimos que X é zero e
depois incrementamos o mesmo".

Note também que a expressão lógica que vai dentro dos parênteses do if
aceitam qualquer expressão que retorne true ou false, usando os operadores
lógicos (<, >, <=, >=, ==, != e !). Sendo assim, podemos fazer coisas muito
mais complexas com um if do que apenas uma comparação de igualdade,
como no exemplo abaixo, onde vemos se um número é PAR (isto é, divisível
por 2):

Código 44: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int x = 0;
if(x % 2 == 0){
System.out.println("X é PAR!");
}

Você conhece o operador de módulo (%)? Falamos dele brevemente no


tópico sobre operadores, mas só agora que estou mostrando uma utilidade
dele: descobrir se um número é par ou não. O funcionamento do mod
(apelido popular do % entre programadores) é fazer a divisão de um número
pelo outro, mas ao invés de retornar o resultado, ele retorna o resto.

Ora, se dividirmos um número por 2 (x / 2) e o resto for zero, é porquê foi


uma divisão exata e ele é PAR, certo?

E agora, unindo o conceito do if e do for, como você faria para imprimir


todos os números pares de 1 a 20?

Tente fazer, e depois compare a sua solução com a apresentada abaixo:

Código 45: disponível em http://www.luiztools.com.br/livro-java-i-fontes

for(int i=1; i <= 20; i++){


if(i % 2 == 0){
System.out.println(i + " é PAR!");
}
}

Este for que criei no exemplo anterior está ligeiramente diferente. Primeiro,
eu inicializei a variável de controle com 1 ao invés do 0 tradicional. Além
disso, coloquei na expressão de controle o operador ‘menor ou igual que’,
comparando com o número 20, para que o 20 em si seja impresso também. Já
o if eu aproveitei do exemplo anterior, então nenhuma novidade aqui.

Copie e cole este código e veja como ele imprime corretamente somente os
números pares de 1 a 20.

Mas e se quiséssemos imprimir a mensagem "é ÍMPAR" para os demais


números? Como você faria?

Código 46: disponível em http://www.luiztools.com.br/livro-java-i-fontes

for(int i=1; i <= 20; i++){


if(i % 2 == 0){
System.out.println(i + " é PAR!");
}
System.out.println(i + " é ÍMPAR!");
}

Essa talvez tenha sido uma solução pensada por você, mas está errada.
Execute ela dentro de um método main no NetBeans e notará que ela sempre
imprime que todos os números são ÍMPARES, além de imprimir quando
algum é PAR também.

Porquê?

O if é um desvio de execução, mas ao término da execução da sua diretiva,


ele volta ao fluxo tradicional, como o fluxograma abaixo nos mostra.

Uma vez que a impressão de que o número é ÍMPAR está no fluxo normal,
ela sempre será executada após o if.

Mas então, como resolvemos isso?

Com a segunda parte da construção if/else, o else.


A tradução literal de else é SENÃO, e ele define basicamente o caminho
alternativo que seu programa tomará caso a condição do if não seja
verdadeira, como abaixo.

if (expressão_lógica)
diretiva1;
else
diretiva2;

Lemos essa estrutura como: "se a expressão lógica for verdadeira,


executamos a diretiva 1, senão, executamos a diretiva 2".

Dessa forma, conseguimos modificar nosso programa anterior para imprimir


que o número é ÍMPAR, quando ele não entrar no if que diz que ele é PAR,
como abaixo, usando else.

Código 47: disponível em http://www.luiztools.com.br/livro-java-i-fontes

for(int i=1; i <= 20; i++){


if(i % 2 == 0){
System.out.println(i + " é PAR!");
} else {
System.out.println(i + " é ÍMPAR!");
}
}

Lemos o trecho mais interno do algoritmo acima como: "se i for divisível por
2, então imprima que ele é PAR, senão, imprime que ele é ímpar".

O fluxograma que melhor define o comportamento de uma estrutura if/else


como essa é visto abaixo.
Neste modelo simples de if/else e no anterior, com apenas if, consideramos
que há sempre um ou no máximo dois caminhos alternativos para um dado
fluxo de execução. No entanto, existem fluxos ainda mais complexos, em que
podemos precisar de um encadeamento de execuções. Como no caso abaixo,
em que queremos que a palavra "FUNCIONOU" seja impressa somente
quando o número estiver entre 5 e 7.

Código 48: disponível em http://www.luiztools.com.br/livro-java-i-fontes

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


if(i >= 5){
if(i <= 7){
System.out.println("FUNCIONOU");
}
}
}

Alguns problemas lógicos como esse são facilmente resolvidos apenas


estudando e combinando os operadores lógico e relacionais, como no caso
abaixo, que faz exatamente a mesma coisa que o algoritmo anterior, mas de
maneira mais eficiente.

Código 49: disponível em http://www.luiztools.com.br/livro-java-i-fontes

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


if(i >= 5 && i <= 7){
System.out.println("FUNCIONOU");
}
}

Ou seja, somente entrará no if se ambas condições forem verdadeiras, uma


vez que usei o operador AND (E lógico). O estudo dos operadores lhe abre
um leque enorme de opções para otimizar o seu código e conseguir ‘mais’
com ‘menos’.

Para finalizar o estudo do if/else, cabe ressaltar que muitas vezes também
precisamos que nossos else’s também possuam condições, que o algoritmo
não entre dentro do else simplesmente porque não atendeu à condição do if.
Neste caso, podemos adicionar um if ao else, o que chamamos de else if.

Código 50: disponível em http://www.luiztools.com.br/livro-java-i-fontes

if(x == 1){
diretiva1
} else if(x == 2){
diretiva2
}

Lemos esta estrutura como: "se x é igual a 1, executamos a diretiva 1, senão,


se x for igual a 2, executamos a diretiva 2".

Neste caso, se o x for igual a 1, executaremos a primeira diretiva. Senão, caso


o x seja igual a 2, executaremos a segunda diretiva. Agora, se x não for 1 ou
2, ele passará ‘reto’ pelo if, apenas usando o fluxo principal da execução.
Podemos ainda criar um fluxo default (padrão), colocando um (e apenas um)
else no final da cadeia de ifs e else ifs.

Código 51: disponível em http://www.luiztools.com.br/livro-java-i-fontes

if(x == 1){
diretiva1
} else if(x == 2){
diretiva2
} else {
diretiva3
}

Neste caso, se o x não for 1, nem 2, executaremos a diretiva3.

A construção if/else if/else é muito poderosa e permite múltiplos fluxos de


execução alternativos, uma vez que podemos combinar inúmeras condições
diferentes.

No entanto, se suas comparações são sempre de uma variável em relação a


um valor, existe uma estrutura mais eficiente para isso: a switch/case.

Estrutura SWITCH/CASE
O switch/case é uma diretiva de desvio múltiplo de fluxo, isto é, baseado na
avaliação de uma variável é escolhido um caminho de execução dentre vários
possíveis. O switch/case equivale logicamente a um conjunto de diretivas if
encadeadas, embora seja usualmente mais eficiente durante a execução.

A sintaxe desta diretiva é a seguinte:

switch (variavel) {
case valor1: diretiva1;
break;
case valor2: diretiva2;
break;
default: diretiva_default;
}

As diretivas encontradas a partir do caso (case) escolhido são executadas até


o final da diretiva switch ou até uma diretiva break que encerra o
switch/case. Se o valor resultante não possuir um caso específico, é
executado a diretiva default colocada, opcionalmente, ao final da diretiva
switch/case.

O mesmo efeito obtido pela construção switch/case mostrada antes também


pode ser realizado (para fins didáticos) apenas com ifs e elses:

if(variavel == valor1)
diretiva1;
else if(variavel == valor2)
diretiva2;
else
diretiva_default;

Em um fluxograma, temos a estrutura switch/case representada da seguinte


maneira:
Note que o ponto de início de execução é um caso (case) cujo valor é aquele
da variável avaliada. Após iniciada a execução do conjunto de diretivas
identificadas por um certo caso, tais ações só são interrompidas com a
execução de uma diretiva break ou com o final da diretiva switch.

A seguir temos uma aplicação simples que exemplifica a utilização das


diretivas switch/case e break. Como de costume, sugiro criar um novo projeto
com o nome de ExemploSwitch, colando o código abaixo dentro do bloco
main:

Código 52: disponível em http://www.luiztools.com.br/livro-java-i-fontes

System.out.println("Digite uma vogal:");


Scanner teclado = new Scanner(System.in);
char letra = teclado.next().charAt(0);
switch(letra) {
case 'A': System.out.println("Vogal A");
break;
case 'E': System.out.println("Vogal E");
break;
case 'I': System.out.println("Vogal I");
break;
case 'O': System.out.println("Vogal O");
break;
case 'U': System.out.println("Vogal U");
break;
default: System.out.println("Não é uma vogal");
}

Para executar esse exemplo, basta clicar no botão de play (verde) no


NetBeans ou clique-direito do mouse sobre o arquivo ExemploSwitch,
escolhendo a opção Executar arquivo. Logo que o programa começar, ele vai
solicitar que você digite uma vogal, para depois imprimir a mesma ou lhe
xingar que não digitou uma, hehehe

A saída esperada depende do valor que você colocar na variável ‘letra’,


declarada logo no início do algoritmo e preenchida com o objeto teclado, que
vai aguardar até que você digite um caracter no teclado.

Podemos ler a estrutura switch/case anterior da seguinte forma:


"considerando a variável letra, caso seja A, imprima ‘Vogal A’, caso seja B,
imprima ‘Vogal B’...etc".
Arrays
Aprendemos nos tópicos anteriores como declarar variáveis e ler valores para
elas, certo? Mas e quando o que precisamos armazenar em memória não é
apenas um valor, mas diversos deles? E se eu lhe pedir para guardar 10
números inteiros digitados pelo usuário, como você faria?

Seguindo uma lógica recente que utilizamos, você declararia 10 variáveis do


tipo int, certo?

Mas e se você quisesse fazer um programa em que o usuário digitasse o


número de inteiros que vai informar? Tipo, o usuário escolhe quantos
números ele vai digitar, como faria neste caso?

É aí que entram os arrays!

Um array (também chamado de vetor em algumas linguagens de


programação) é um tipo especial de objeto que permite que a gente armazene
diversos valores de mesmo tipo dentro dele, cada um em uma posição de
memória dentro do array. Quando criamos um array, dizemos o tipo e a
quantidade máxima de elementos que ele poderá armazenar, todos de mesmo
tipo. Por exemplo:

Código 53: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int[] numeros = new int[3];

Aqui declaramos uma variável que é na verdade um array de inteiros,


demonstrado pelo uso de colchetes ([]) logo após o tipo do array. Essa
declaração (int[] numeros) indica que esse é um array de inteiros, e somente
podemos armazenar valores e variáveis int nele.

A segunda parte da declaração, que chamamos de inicialização, define o


tamanho máximo do array, ou seja, quantos valores ele poderá armazenar,
nesse exemplo, 3 valores.
Os elementos do array são numerados iniciando com zero (zero-based), e
índices válidos variam de zero ao número de elementos menos um. O
elemento do array com índice 1, por exemplo, é o segundo elemento no
array. O número de elementos em um array é seu comprimento (length).
Esse comprimento é especificado quando o array é criado e nunca muda seu
tamanho.

Para guardar valores dentro do array, usamos o nome que demos a ele,
seguido de colchetes e o número da posição onde queremos guardar o valor,
como abaixo:

Código 54: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int[] numeros = new int[3];


numeros[0] = 8;
numeros[1] = 4;
numeros[2] = 29;

Aqui temos um array de comprimento 3, onde guardamos valores nas


posições 0 (a primeira), 1 (a segunda) e 2 (a terceira e última). Claro que
podíamos ter pedido ao usuário para informar estes valores (incluindo o
tamanho do array, 3), mas para efeitos práticos defini eles com valores
literais.

Agora outro exemplo, onde crio um array e populo com nomes de pessoas:

Código 55: disponível em http://www.luiztools.com.br/livro-java-i-fontes

String[] inventores= new String[4];


inventores[0] = "Einstein";
inventores[1] = "Edson";
inventores[2] = "Galileu";
inventores[3] = "Da Vinci";

Mais tarde, quando quisermos acessar os elementos do array, basta


utilizarmos a sua posição (índice) para retornarmos o valor contido dentro
dela:

Código 56: disponível em http://www.luiztools.com.br/livro-java-i-fontes

String inventor = inventores[3];


System.out.println(inventor);

Considerando os exemplos anteriores de código, o que o trecho acima irá


imprimir no console quando executado?

Da Vinci! Pois esse foi o nome do inventor armazenado na quarta posição do


array (índice 3).

Mas voltando ao desafio inicial deste tópico, como faríamos para armazenar
um número arbitrário de valores?

Você lembra dos laços de repetição? Uma maneira muito inteligente de


popular arrays é com laços de repetição, como um for, por exemplo.

Código 57: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int[] numeros = new int[10];


for(int i=0; i < 10; i++)
numeros[i] = 1;

Note que usamos a própria variável de controle ‘i’ par acessar a posição do
array de números onde queremos guardar os valores. Notou algo estranho?
Sim, eu guardei o número 1 em todas posições do array.

Não entendeu? Use o seguinte código para imprimir todas posições do array:

Código 58: disponível em http://www.luiztools.com.br/livro-java-i-fontes

for(int i=0; i < 10; i++)


System.out.print(numeros[i]);
Você vai ver a impressão de 10 números 1 em sequência.

Como resolvemos isso? Pedindo ao usuário que digite os números e lendo o


teclado dele, como já fizemos antes!

Código 59: disponível em http://www.luiztools.com.br/livro-java-i-fontes

int[] numeros = new int[10];


System.out.println("Digite 10 números inteiros:");
Scanner teclado = new Scanner(System.in);
for(int i=0; i < 10; i++)
numeros[i] = teclado.nextInt();

for(int i=0; i < 10; i++)


System.out.print(numeros[i]);

Agora sim, se você executar este código dentro de um método main verá que
ele pedirá 10 números inteiros e depois imprimirá os 10 digitados em
sequência!

Para finalizar os testes e reforçar os conceitos, como você faria para que o
usuário escolhesse a quantidade de números que ele quer digitar? Essa
quantidade seria usada pelo sistema depois para coletar os números e
imprimi-los.

Vamos por partes!

O primeiro passo é pedir pro usuário digitar essa quantidade, usando ela para
criar o array no tamanho necessário (lembrando que não podemos alterar o
tamanho do array depois, então já temos de criá-lo do tamanho certo!).

Código 60: disponível em http://www.luiztools.com.br/livro-java-i-fontes

System .out.println( "Digite o tamanho do array:" );


Scanner teclado = new Scanner( System .in);
int tamanho = teclado.nextInt();
int [] numeros = new int [tamanho];

Na sequência, podemos pedir que ele digite os números, usando a variável


tamanho como valor de comparação para encerrar os laços de leitura de
números e impressão.

Código 61: disponível em http://www.luiztools.com.br/livro-java-i-fontes

System .out.println( "Digite o tamanho do array:" );


Scanner teclado = new Scanner( System .in);
int tamanho = teclado.nextInt();
int [] numeros = new int [tamanho];

for ( int i=0; i < tamanho; i++)


numeros[i] = teclado.nextInt();

for ( int i=0; i < tamanho; i++)


System .out.print(numeros[i]);

Muito legal, não?!

Atenção: você notou como em alguns momentos eu faço quebras de linha


para separar alguns blocos de código? Não há qualquer problema em usar
quantas linhas em branco você quiser em suas aplicações e é uma boa ideia
usá-las para separar blocos de código com um propósito específico, que
fazem uma tarefa do início ao fim.

No próximo capítulo vamos incrementar nossos conhecimentos de


programação para console, o que nos permitirá criar algoritmos ainda mais
interessantes!
6 Aplicações Console
Através da linguagem Java é possível construirmos aplicações de console,
isto é, aplicações que utilizam os consoles de operação dos sistemas
operacionais para a interação com o usuário, ou seja, para a realização das
operações de entrada de dados fornecidos pelo usuário e a exibição de
mensagens do programa.

Como console de operação ou terminal entendemos as seções ou janelas em


modo texto (que capazes de exibir apenas texto) de sistemas Unix, as janelas
"Prompt do MS-DOS" existentes no Windows e outras semelhantes
existentes nos demais sistemas operacionais.

As aplicações de console, embora em desuso para a construção de sistemas


mais sofisticados, podem ser utilizadas para a criação de programas utilitários
do sistema, tal como certos comandos do sistema operacional que na verdade
são programas específicos disponíveis apenas para utilização nos consoles.
Estrutura básica
Para construir-se aplicações de console basta uma classe (arquivo Java) onde
seja definido o
método main, conforme já fizemos nos exercícios dos capítulos anteriores.
Este método é o primeiro a ser executado numa aplicação, daí ser estático, ou
seja, não depende de mais nada no sistema para existir, apenas da própria
classe (arquivo) em que se encontra, como uma espécie de método
permanente, que sempre existe.

A assinatura do método main é a seguinte:

Código 62: disponível em http://www.luiztools.com.br/livro-java-i-fontes

public static void main (String args[]) {


//diretivas
}

Sendo um método público (public), o main pode ser chamado de qualquer


ponto da aplicação e até mesmo fora dela (pelo sistema operacional, por
exemplo), o que é muito importante para a inicialização das aplicações que
você vai desenvolver.

Além de público, sendo um método estático, o main não depende de nenhum


outro recurso do programa, exceto o próprio arquivo/classe Java onde ele está
inserido, para funcionar. Sendo assim, em nossos exercícios
implementaremos tudo o que nosso programa Java precisa para funcionar
dentro do nosso bloco de código main.

O bloco de código main também deve obrigatoriamente não retornar valores


(void) e receber um array de String como argumento (String[] args).

Esses são os requisitos mínimos de estrutura para que suas aplicações console
funcionem corretamente. Ao longo dos últimos capítulos criamos alguns
programas simples para console, testando-os no console do NetBeans. Neste
capítulo vamos ver em detalhes como funciona a entrada, processamento e
saída de dados de programas Java console, bem como criar programas
interativos completos para diversão e aprendizado.
Saída de Dados
As aplicações de console utilizam como padrão a stream de dados out,
disponível estaticamente através da classe System. Uma stream pode ser
entendida como um duto capaz de transportar dados de um lugar (um arquivo
ou dispositivo) para um outro lugar diferente. O conceito de stream é
extremamente importante pois é utilizado tanto para manipulação de dados
existentes em arquivos como também para comunicação em rede e outros
dispositivos.

A stream de saída padrão é aberta automaticamente pela máquina virtual Java


(JVM) ao iniciarmos uma aplicação Java e permanece pronta para enviar
dados. No caso a saída padrão está tipicamente associada ao dispositivo de
saída (display) ou seja, a janela de console utilizada pela aplicação conforme
designado pelo sistema operacional. Enquanto a stream de saída out é usada
para enviar informações pro usuário, a stream de entrada in é usada para ler
dados enviados por ele.

A stream de saída out é um objeto de escrita de dados que pode ser utilizado
através dos seguintes comandos:

Comando Descrição
print(valor) Imprime a variável ou valor literal passado dentro dos
parênteses, podendo ser de qualquer tipo primitivo ou
String
println(valor) Faz o mesmo que o método print, porém inclui uma
quebra de linha no final do valor escrito (lê-se print line)

Assim sendo, podemos escrever elementos no console usando uma das duas
opções abaixo, conforme nossa estratégia:

Código 64: disponível em http://www.luiztools.com.br/livro-java-i-fontes

System.out.print(valor);
System.out.println(valor);

E isso é tudo que precisamos saber, no momento, sobre a impressão (print)


de dados na saída (out) do sistema (System).
Entrada de Dados
Da mesma forma que toda aplicação de console possui uma stream associada
para ser utilizada como saída padrão, existe uma outra stream denominada de
entrada padrão, usualmente associada ao teclado do sistema. Essa stream, de
nome in, disponível estaticamente através da classe System é também aberta
automaticamente quando a aplicação é iniciada pela máquina virtual Java
(JVM) permanecendo pronta para fornecer os dados digitados.

Devemos observar que embora pronta para receber dados dos usuários, os
comandos disponíveis para a entrada destes dados são muito ruins, uma vez
que são orientados a ler bytes "crus" (raw bytes). Desta maneira, geralmente
utilizamos a entrada in em conjunto com algum outro objeto Java que nos
permita uma leitura de dados mais prática, como a classe Scanner.

Código 65: disponível em http://www.luiztools.com.br/livro-java-i-fontes

Scanner teclado = new Scanner(System.in);

No trecho de código acima, declaramos uma variável do tipo Scanner e nome


‘teclado’ que é inicializada com o System.in sendo passado como argumento.
Você aprenderá mais detalhes sobre inicialização de objetos no futuro, mas
por ora, basta entender que com exceção dos tipos primitivos e das Strings,
todo o resto precisa ser inicializado com a palavra reservada new (novo).
Sendo assim, estamos criando um novo (new) Scanner a partir da entrada
padrão do sistema, ou seja, estaremos "escaneando" o teclado do computador
do usuário da nossa aplicação console.

Uma vez declarada esta variável ‘teclado’, podemos usá-la quando quisermos
para ler as entradas digitadas pelo usuário e, para isso, temos vários
comandos à disposição, de acordo com a entrada que esperamos ler.

Comando Descrição
nextInt() Lê o próximo valor inteiro (4 bytes)
nextFloat(), Idem ao anterior, mas o valor é do tipo
nextDouble(), especificado no nome do método (float, double,
nextLong(), etc etc)
next() Lê a próxima palavra (palavras são separadas por
espaço em branco (‘ ’)
nextLine() Lê todo o texto que o usuário digitou, até
encontrar a primeira quebra de linha (‘\n’)

Sendo assim, após inicializarmos um objeto do tipo Scanner, podemos


chamar qualquer um dos comandos disponíveis na tabela anterior para ler os
dados que o usuário digitar, como abaixo.

Código 66: disponível em http://www.luiztools.com.br/livro-java-i-fontes

Scanner teclado = new Scanner(System.in);


System.out.println("Digite um número:");
int numero = teclado.nextInt();
System.out.println("Digite um caracter:");
char letra = teclado.next().chartAt(0);

Note que todos os comandos possuem comportamento bloqueante, isto é, eles


"interrompem" o fluxo natural do sistema até que o usuário digite alguma
coisa e pressione Enter, voltando à execução normal do software. Além disso,
caso o usuário invoque um comando referente a um tipo diferente ao que o
usuário informou na sua digitação, um erro ocorrerá, travando a aplicação.

Como assim?

Se o usuário digitar uma letra (a-z) e você chamar o comando nextInt(), por
exemplo, a aplicação irá travar! Claro, existem mecanismos em Java para
evitar isso, mas por ora, vamos confiar que o usuário seguirá corretamente as
instruções que você fornecerá à ele via System.out.

E por fim, existe ainda um efeito colateral do comportamento bloqueante do


Scanner. Eu mencionei antes que ele fica esperando que o usuário digite um
Enter para continuar a execução do sistema, certo? No entanto, quando ele
realiza a leitura de um tipo de dado ele consome os bytes do dado em
questão, mas não os dados do Enter (o byte ‘\n’).

Para que você entenda melhor o que estou falando, execute o seguinte código
no seu NetBeans:

Código 67: disponível em http://www.luiztools.com.br/livro-java-i-fontes

Scanner teclado = new Scanner(System.in);


System.out.println("Digite um número:");
int numero = teclado.nextInt();
System.out.println("Digite uma palavra:");
String palavra = teclado.nextLine();

O que aconteceu? Você não conseguiu digitar a palavra, certo? O sistema


pulou sozinho o seu nextLine(), ignorando-o. Isso porque quando o Scanner
leu os 4 bytes que formam o inteiro digitado pelo usuário, ele deixou pra trás
o ‘\n’ (Enter) que o usuário pressionou para confirmar a digitação. Na linha
abaixo, como ele mandou ler uma linha (nextLine), o Scanner encontrou logo
de cara um ‘\n’ (quebra de linha, Enter) "sobrando" no buffer do teclado e
entendeu que a palavra já foi digitada.

Curioso, não?

Para solucionar isso é bem simples: basta se lembrar sempre de chamar o


nextLine() na linha logo abaixo em que você fizer um nextInt() ou qualquer
outra leitura exceto outro nextLine(). Exemplo:

Código 68: disponível em http://www.luiztools.com.br/livro-java-i-fontes

Scanner teclado = new Scanner(System.in);


System.out.println("Digite um número:");
int numero = teclado.nextInt();
teclado.nextLine();//só o que mudou foi aqui
System.out.println("Digite uma palavra:");
String palavra = teclado.nextLine();

Agora se você executar, verá que ele vai esperar normalmente até que você
digite uma palavra e tecle Enter, porque "limpamos" o ‘\n’ do buffer do
teclado chamando um nextLine "sozinho" uma linha após o nextInt. É isso,
basta chamar esse nextLine sozinho após seus nextInt, nextDouble, etc e
tudo funcionará como esperado!

E isso é tudo que você precisa saber sobre a teoria de desenvolver aplicações
console. Que tal agora criarmos um sistema console de verdade?

Então vamos!
Criando Aplicações
Apesar das aplicações de console não terem o apelo atrativo das interfaces
gráficas, ainda assim é possível construir-se aplicações interessantes. Vamos
fazer algumas para exercitar?

Par ou Ímpar
Que tal criarmos um jogo de par ou ímpar? Esse é um jogo que todo mundo
conhece e que podemos facilmente fazê-lo para exercitar tudo o que vimos
até aqui.

Em nosso jogo, o usuário irá escolher PAR ou ÍMPAR e um número inteiro,


1 ou 2. Em seguida, a CPU vai jogar também um número, e se a soma dos
dois for PAR, ganha que escolheu essa opção!

Como começamos?

Primeiro, vamos criar um novo projeto de Aplicação Java no NetBeans, como


já fizemos outras vezes (Arquivo > Novo Projeto > Aplicação Java). Vamos
chamar esse projeto de ParOuImpar, que também será o nome da classe
principal, que contém o método main.

Segundo, nosso algoritmo de jogo de Par ou Ímpar começa com o jogo


perguntando se o usuário que PAR ou ÍMPAR. Não esqueça que você deve
salvar essa informação para uso posterior, certo? Além disso, todo o código
deve ser digitado dentro do método main!

Código 69: disponível em http://www.luiztools.com.br/livro-java-i-fontes

Scanner teclado = new Scanner(System.in);


System.out.println("Escolha PAR ou IMPAR. Digite 0 para escolher PAR ou
1 para IMPAR:");
int escolha = teclado.nextInt();//0 é par, 1 é ímpar. Essa variável vai ser usada
depois

if(escolha == 0)
System.out.println("O jogador escolheu PAR.");
else
System.out.println("O jogador escolheu IMPAR.");

Terceiro, agora precisamos pedir que o jogador faça a sua jogada, que deve
ser somente 1 ou 2, para simplificar.

Código 70: disponível em http://www.luiztools.com.br/livro-java-i-fontes

System.out.println("Faça sua jogada. Escolha 1 ou 2.");


int jogada1 = teclado.nextInt();//essa variável vai ser usada depois

Esse código deve ficar imediatamente abaixo do anterior. Agora, na


sequência, é a vez da CPU jogar. Mas como vamos fazer para criar uma
Inteligência Artificial (IA) para nosso jogo de par ou ímpar?

Que tal uma pseudo-IA, usando números aleatórios (sorteados)? Diversas


linguagens de programação possuem recursos para geração de números
aleatórios, e Java não é exceção. Assim, basta que a gente "gere" a jogada da
CPU, usando a classe Math para isso. A classe Math contém diversas
funções matemáticas, incluindo um gerador de números chamado random,
que gera números entre 0 e 1 (decimais). Como o que queremos é que a CPU
"escolha" um número entre 1 e 2, teremos de fazer alguns ajustes, como
arredondar o decimal gerado para o inteiro mais próximo (função ceil da
classe Math) e depois somar com 1.

Código 71: disponível em http://www.luiztools.com.br/livro-java-i-fontes

System.out.println("Agora é a vez da CPU jogar...");


double numero = Math.random();//gera um número decimal aleatório entre 0
e1
int jogada2 = Math.ceil(numero) + 1;//arredonda e soma 1, para gerar uma
jogada entre 1 e 2
System.out.println("A CPU jogou:" + jogada2);
Futuramente, com mais calma, podemos explorar mais a classe Math
(abreviação de Mathematics, matemática em Inglês), que possui muita coisa
interessante para lidarmos com números e operações matemáticas.

Mas agora, vamos encerrar o nosso jogo. O que falta? Ver quem ganhou, é
claro!

Para isso, devemos somar as duas jogadas e ver se o número resultante é par
ou ímpar, depois, comparar com a escolha do jogador, se ele quis par (0) ou
ímpar (1) lá no início do sistema.

Código 72: disponível em http://www.luiztools.com.br/livro-java-i-fontes

System.out.println("Calculando o vencedor");
int soma = jogada1 + jogada2;
boolean resultadoPar = soma % 2 == 0;
if(resultadoPar == true && escolha == 0)
System.out.println("O jogador ganhou");
else if(resultadoPar == false && escolha == 1)
System.out.println("O jogador ganhou!");
else
System.out.println("A CPU ganhou!");

Sim, esse código ficou mais complicado que o normal…

Começamos realizando a soma das jogadas e depois armazenamos em um


booleano se essa soma resulta em um número par ou não (true indica que o
resultado é par). Para descobrir a paridade do número, usamos o operador de
módulo (%), dividindo a soma por 2 e verificando se o resto é zero (divisão
exata, o que acontece somente em números pares).

Na sequência temos uma estrutura if/else if/else aqui, onde no primeiro if


testamos se o resultado é par e (AND lógico) o jogador escolheu PAR (0) no
início do jogo. Se ambas expressões não retornarem true, iremos ao else if,
onde testamos se o resultado não é par (false) e (AND lógico) se o jogador
escolheu IMPAR (1)no início do jogo. Qualquer uma dessas duas estruturas
iniciais, se verdadeiras, dão a vitória ao jogador. Em qualquer outro caso,
caímos no else e consequentemente a CPU venceu.

Que tal darmos mais uma caprichada nesse jogo?

Você notou que as jogadas e cálculos são instantâneos? Isso porque os


computadores atuais e até mesmo os smartphones são muito velozes para
fazer tarefas tão simples quanto um jogo de par ou ímpar. Se quiser fingir que
a máquina está pensando um pouco antes de fazer sua jogada, até para dar um
suspense no jogo, podemos "atrasar" a execução da tarefa usando o comando
Thread.sleep(1000), que atrasa o processador em 1000ms (1 segundo).
Obviamente você pode mudar esse valor conforme o seu gosto, mas
experimente colocar essa instrução antes das ações da CPU para ver que
interessante que fica.

O código abaixo, que mostra o jogo completo, incluindo essa alteração:

Código 73: disponível em http://www.luiztools.com.br/livro-java-i-fontes

Scanner teclado = new Scanner(System.in);


System.out.println("Escolha PAR ou IMPAR. Digite 0 para escolher PAR ou
1 para IMPAR:");
int escolha = teclado.nextInt();//0 é par, 1 é ímpar. Essa variável vai ser usada
depois

if(escolha == 0)
System.out.println("O jogador escolheu PAR.");
else
System.out.println("O jogador escolheu IMPAR.");

System.out.println("Faça sua jogada. Escolha 1 ou 2.");


int jogada1 = teclado.nextInt();//essa variável vai ser usada depois

System.out.println("Agora é a vez da CPU jogar...");


Thread.sleep(1000);//atrasa 1 segundo
double numero = Math.random();//gera um número decimal aleatório entre 0
e1
int jogada2 = Math.ceil(numero) + 1;//arredonda e soma 1, para gerar uma
jogada entre 1 e 2
System.out.println("A CPU jogou:" + jogada2);

System.out.println("Calculando o vencedor");
Thread.sleep(1000);//atrasa 1 segundo
int soma = jogada1 + jogada2;
boolean resultadoPar = soma % 2 == 0;
if(resultadoPar == true && escolha == 0)
System.out.println("O jogador ganhou");
else if(resultadoPar == false && escolha == 1)
System.out.println("O jogador ganhou!");
else
System.out.println("A CPU ganhou!");

Será que dá para incrementar ainda mais o nosso jogo?

Claro que sim! Que tal um esquema de rounds ou melhor de 3? Você pode
criar um array de 3 posições para armazenar quem venceu cada um dos
rounds e, se alguém levar 2 de 3, é o vencedor definitivo!

Mas ‘peraí, como que vamos rolar três partidas em sequência sem copiar e
colar esse monte de código três vezes?

Calma, uma coisa de cada vez!

Vamos começar ajustando nosso algoritmo para incluir um array de rounds


no início do algoritmo. Vou fazer um array de char, assim, guardo a letra J
(jogador) ou C (cpu) indicando quem ganhou aquele round (round 0, 1 e 2).

Código 74: disponível em http://www.luiztools.com.br/livro-java-i-fontes

char[] rounds = new char[3];


int roundAtual = 0;
//resto do código antigo (73) vai aqui embaixo
Depois, assim que uma partida acaba, devemos salvar a letra inicial do
vencedor dentro do array de rounds, na posição do roundAtual (e
incrementando ele para o próximo round acontecer). Isso no final do código,
mudando aquele if de quem é o vencedor:

Código 75: disponível em http://www.luiztools.com.br/livro-java-i-fontes

//o resto do código antigo (74 + 73) vai aqui em cima


System.out.println("Calculando o vencedor");
Thread.sleep(1000);//atrasa 1 segundo
int soma = jogada1 + jogada2;
boolean resultadoPar = soma % 2 == 0;
if(resultadoPar == true && escolha == 0){
System.out.println("O jogador ganhou este round");
rounds[roundAtual++] = 'J';
} else if(resultadoPar == false && escolha == 1){
System.out.println("O jogador ganhou este round!");
rounds[roundAtual++] = 'J'’;
} else {
System.out.println("A CPU ganhou este round!");
rounds[roundAtual++] = 'C';
}

Se você executar agora este jogo, vai conseguir jogar apenas um round e
depois o jogo vai encerrar, e não é isso que queremos. O que podemos fazer
para repetir o jogo por três rounds consecutivos?

Que tal um laço de repetição em volta do algoritmo, que se repete três vezes?
Excelente escolha! ;)

Apenas certifique-se de colocar toda a lógica do jogo (exceto o array de


rounds), dentro de um laço while como abaixo, que vai repetir três vezes,
armazenando o vencedor de cada round no array do início do algoritmo:

Código 76: disponível em http://www.luiztools.com.br/livro-java-i-fontes


char[] rounds = new char[3];
int roundAtual = 0;

System.out.println("Começando PAR ou ÍMPAR melhor de 3!");


while(roundAtual < 3){
//resto do código antigo (73 + 75) vai aqui dentro
}

E se alguém ganhar 2 seguidas, nesse caso não precisa de 3 rounds, certo?


Exato! Como podemos fazer isso?

Não é muito difícil. Que tal se após a segunda partida/iteração do laço while
(roundAtual == 2) a gente verifique se não há dois ganhadores repetidos no
array? (JJ ou CC). Pode funcionar, certo?! Nesse caso bastaria encerrar o laço
usando o comando break, como no código abaixo, que vai no final do laço
while, pouco antes dele fechar chaves.

Código 77: disponível em http://www.luiztools.com.br/livro-java-i-fontes

char[] rounds = new char[3];


int roundAtual = 0;

System.out.println("Começando PAR ou ÍMPAR melhor de 3!");


while(roundAtual < 3){
//resto do código antigo (73 + 75) vai aqui dentro

if(roundAtual == 2){
if(rounds[0] == 'J' && rounds[1] == 'J'){
System.out.println("O jogador ganhou duas em sequência!");
break;
} else if(rounds[0] == 'C' && rounds[1] == 'C'){
System.out.println("A CPU ganhou duas em sequência!");
break;
}
}
}
E para verificar quem ganhou ao término do terceiro round, basta comparar o
último vencedor dos rounds (round 3, o de desempate, posição 2 do array),
logo depois da verificação do round 2, com um else if:

Código 78: disponível em http://www.luiztools.com.br/livro-java-i-fontes

char[] rounds = new char[3];


int roundAtual = 0;

System.out.println("Começando PAR ou ÍMPAR melhor de 3!");


while(roundAtual < 3){
//resto do código antigo (73 + 75) vai aqui dentro

if(roundAtual == 2){
if(rounds[0] == 'J' && rounds[1] == 'J'){
System.out.println("O jogador ganhou duas em sequência!");
break;
} else if(rounds[0] == 'C' && rounds[1] == 'C'){
System.out.println("A CPU ganhou duas em sequência!");
break;
}
} else if(roundAtual == 3){ //else if adicionado para ver o vencedor do
round 3
if(rounds[2] == 'J'){
System.out.println("O jogador ganhou a melhor de 3!");
break;
} else if(rounds[2] == 'C'){
System.out.println("A CPU ganhou a melhor de 3!");
break;
}
}
}

Tcharam! Jogo concluído!


Perdeu alguma parte?

Segue abaixo o jogo completo, basta copiar e colar dentro do método main do
arquivo principal do projeto:

Código 79: disponível em http://www.luiztools.com.br/livro-java-i-fontes

char[] rounds = new char[3];


int roundAtual = 0;

System.out.println("Começando PAR ou ÍMPAR melhor de 3!");


while(roundAtual < 3){
Scanner teclado = new Scanner(System.in);
System.out.println("Escolha PAR ou IMPAR. Digite 0 para escolher PAR
ou 1 para IMPAR:");
int escolha = teclado.nextInt();//0 é par, 1 é ímpar. Essa variável vai ser
usada depois

if(escolha == 0)
System.out.println("O jogador escolheu PAR.");
else
System.out.println("O jogador escolheu IMPAR.");

System.out.println("Faça sua jogada. Escolha 1 ou 2.");


int jogada1 = teclado.nextInt();//essa variável vai ser usada depois

System.out.println("Agora é a vez da CPU jogar...");


Thread.sleep(1000);//atrasa 1 segundo
double numero = Math.random();//gera um número decimal aleatório entre
0e1
int jogada2 = Math.ceil(numero) + 1;//arredonda e soma 1, para gerar uma
jogada entre 1 e 2
System.out.println("A CPU jogou:" + jogada2);

System.out.println("Calculando o vencedor");
Thread.sleep(1000);//atrasa 1 segundo
int soma = jogada1 + jogada2;
boolean resultadoPar = soma % 2 == 0;
if(resultadoPar == true && escolha == 0){
System.out.println("O jogador ganhou este round");
rounds[roundAtual++] = 'J';
} else if(resultadoPar == false && escolha == 1){
System.out.println("O jogador ganhou este round!");
rounds[roundAtual++] = 'J';
} else {
System.out.println("A CPU ganhou este round!");
rounds[roundAtual++] = 'C';
}

if(roundAtual == 2){
if(rounds[0] == 'J' && rounds[1] == 'J'){
System.out.println("O jogador ganhou duas em sequência!");
break;
} else if(rounds[0] == 'C' && rounds[1] == 'C'){
System.out.println("A CPU ganhou duas em sequência!");
break;
}
} else if(roundAtual == 3){ //else if adicionado para ver o vencedor do
round 3
if(rounds[2] == 'J'){
System.out.println("O jogador ganhou a melhor de 3!");
break;
} else if(rounds[2] == 'C'){
System.out.println("A CPU ganhou a melhor de 3!");
break;
}
}
}

Estudar a criação de jogos simples como esse ajudam, e muito, a exercitar a


sua lógica, a compreender melhor os comandos do Java e são divertidos. Ao
menos eu achava quando estava aprendendo Java há 10 anos atrás, hehehe
Que tal agora avançarmos para um jogo mais complicado?

Papel, Pedra ou Tesoura


Saímos de um jogo simples, talvez o mais simples de todos, como o Par ou
Ímpar e agora vamos para um cujas regras são um pouco mais complicadas:
Papel, Pedra ou Tesoura.

A mecânica é semelhante: um jogador contra a CPU, cada um escolhe uma


dentre três opções de jogada: papel, pedra ou tesoura (1, 2 ou 3) e, uma vez
que ambos tenham mostrado sua escolha, o raciocínio para saber quem é o
vencedor pode ser visto na matriz abaixo:

Jogador x CPU Papel Pedra Tesoura


Papel Empate Papel vence Tesoura vence
Pedra Papel vence Empate Pedra vence
Tesoura Tesoura vence Pedra vence Empate

Note que sempre que ambos escolhem a mesma jogada, há empate, nesse
caso tendo de jogar novamente, até que um vença. Para os demais casos, a
lógica é que papel enrola pedra, pedra quebra tesoura e tesoura corta papel.

Raciocinando um pouco (e sugiro fazer isso sempre antes de começar a


programar) você vai perceber que o algoritmo é semelhante ao de par ou
ímpar, mudando a resolução de quem é o vencedor e a questão do desempate,
que deve exigir nova jogada até que haja um vencedor.

Vamos começar? Vou ser mais direto dessa vez, me atendo mais às partes
novas do algoritmo, tomando como base que você conseguiu executar com
sucesso o anterior.

Primeiro, crie um novo projeto no NetBeans (Arquivo > Novo projeto >
Aplicação Java) com o nome de PapelPedraTesoura e, no seu arquivo
principal, coloque dentro do main o seguinte código, que vai pedir para o
usuário escolher uma jogada, salvando a jogada em uma variável inteira.
Código 80: disponível em http://www.luiztools.com.br/livro-java-i-fontes

Scanner teclado = new Scanner( System .in);


System .out.println( "Escolha PAPEL (1), PEDRA (2) ou TESOURA (3):" );
int jogada1 = teclado.nextInt(); //Essa variável vai ser usada depois

if (jogada1 == 1)
System .out.println( "O jogador escolheu PAPEL." );

else if(jogada1 == 2)
System.out.println("O jogador escolheu PEDRA.");
else
System.out.println("O jogador escolheu TESOURA.");

Para a CPU jogar, faremos a mesma lógica com números aleatórios, que
fizemos pra sortear se ela ia jogar 1 ou 2 no jogo anterior, lembra? Aqui,
vamos sortear se ela vai jogar PAPEL (1), PEDRA (2) ou TESOURA (3),
mas de uma maneira um pouco diferente, porque não queremos apenas 1 ou
2, mas sim 1, 2 ou 3.

Código 81: disponível em http://www.luiztools.com.br/livro-java-i-fontes

//código 80, da escolha do jogador, vai aqui em cima

System .out.println( "Agora é a vez da CPU jogar..." );


Thread .sleep(1000); //atrasa 1 segundo
int jogada2 = ( int )( Math .random() * 3) + 1; //gera um número decimal
aleatório entre 1 e 3

if(jogada2 == 1)
System.out.println("A CPU escolheu PAPEL.");
else if(jogada2 == 2)
System.out.println("A CPU escolheu PEDRA.");
else
System.out.println("A CPU escolheu TESOURA.");

Note que incluí aquele truque de fazer a CPU esperar 1 segundo para dar sua
jogada (Thread.sleep) para dar aquele suspense.

O próximo passo é ver quem ganhou, o que devemos fazer logo abaixo do
código anterior, comparando as jogadas do jogador e da CPU segundo a
lógica deste jogo em questão.

Código 82: disponível em http://www.luiztools.com.br/livro-java-i-fontes

//código 80 + 81, vão aqui em cima

System .out.println( "Processando o vencedor" );


Thread .sleep(1000); //atrasa 1 segundo
if (jogada1 == jogada2){
System .out.println( "Empatou!" );
} else if (jogada1 == 1 && jogada2 == 2){
System .out.println( "Papel enrola pedra, o jogador ganhou!" );
} else if (jogada1 == 2 && jogada2 == 3){
System .out.println( "Pedra quebra tesoura, o jogador ganhou!" );
} else if (jogada1 == 3 && jogada2 == 1){
System .out.println( "Tesoura corta papel, o jogador ganhou!" );
} else {
System .out.println( "Se deu mal, a CPU ganhou!" );
}

Neste trecho de código temos a regra do jogo em si, represetada por lógica de
programação em Java. Testamos primeiro se houve empate (o que necessitará
que o jogo aconteça novamente!), depois as três possíveis situações do
jogador ganhar a partida, para, caso contrário (senão), cair no else que dá a
vitória para a máquina.
Simples, não?!

Caso queira repetir o jogo automaticamente em caso de empate, você pode


circundar todo o algoritmo dentro de um while infinito, e, em caso de vitória
de alguém, usar a diretiva break para encerrar a execução do laço, assim
como fazemos no caso da estrutura switch/case, lembra?

Temos ainda outro ajuste possível, que é o de simplificar o teste de quem


ganhou, usando de lógica OU (OR) com a combinação das três situações
possíveis de vitória por parte do jogador.

Ambas alterações, do loop de empate e da lógica OU, foram colocados no


código completo do jogo, reproduzido logo abaixo, para facilitar sua
execução.

Código 83: disponível em http://www.luiztools.com.br/livro-java-i-fontes

while( true ){

Scanner teclado = new Scanner(System.in);


System.out.println("Escolha PAPEL (1), PEDRA (2) ou TESOURA (3):");
int jogada1 = teclado.nextInt();//Essa variável vai ser usada depois

if(jogada1 == 1)
System.out.println("O jogador escolheu PAPEL.");
else if(jogada1 == 2)
System.out.println("O jogador escolheu PEDRA.");
else
System.out.println("O jogador escolheu TESOURA.");

System.out.println("Agora é a vez da CPU jogar...");


Thread.sleep(1000);//atrasa 1 segundo
int jogada2 = (int)(Math.random() * 3) + 1;//gera um número decimal
aleatório entre 1 e 3

if(jogada2 == 1)
System.out.println("A CPU escolheu PAPEL.");
else if(jogada2 == 2)
System.out.println("A CPU escolheu PEDRA.");
else
System.out.println("A CPU escolheu TESOURA.");

System.out.println("Processando o vencedor");
Thread.sleep(1000);//atrasa 1 segundo
if(jogada1 == jogada2){
System.out.println("Empatou!");
} else if((jogada1 == 1 && jogada2 == 2) ||
(jogada1 == 2 && jogada2 == 3) ||
(jogada1 == 3 && jogada2 == 1)){
System.out.println("Uhu, o jogador ganhou!");
break;
} else {
System.out.println("Se deu mal, a CPU ganhou!");
break;
}
}

Para explicar melhor aquele ifzão que fizemos ali, primeiro é necessário
entender que o uso dos parênteses serviu para "isolar" cada uma das
expressões AND (&&) que representam cada uma das possibilidades de
vitória pro jogador. As expressões são calculadas/resolvidas conforme os
parênteses mais internos para os mais externos, assim como em expressões
numéricas, que vemos na quarta série do ensino fundamental.

O resultado de cada uma dessas expressão AND (&&) é resolvido


logicamente com expressões OR (||), cujo efeito faz com que, se uma das três
expressões AND forem verdadeiras, o resultado do if por completo será true,
segundo a lógica booleana. Podemos ler aquele ifzão como: "se o jogador
escolheu papel e a CPU, pedra, ou, se o jogador escolheu pedra e a CPU,
tesoura, ou ainda, se o jogador escolheu tesoura e a CPU, papel, entra no if".
Soa estranho, mas é mais ou menos isso. Se qualquer uma das três condições
for verdadeira, o fluxo de execução do algoritmo vai entrar no if.
Outro ponto digno de nota é que você deve ter notado que fazer este
algoritmo foi infinitamente mais fácil do que fazer o anterior. Isso porque
conforme você for pegando prática, alguns conceitos se tornarão automáticos,
como o uso de estruturas if por exemplo, algo muito recorrente em
algoritmos.

Em nosso terceiro e último jogo desta etapa do seu aprendizado de Java, vou
pegar pesado!

Vinte Um
Vamos fazer um jogo de cartas chamado Vinte Um?

Neste jogo temos um baralho de cartas completo, com 52 cartas, sendo 13


cartas de cada um dos 4 naipes. Nós embaralhamos as cartas e o jogador pede
uma carta, somando o número da mesma (ignorando o naipe) à sua
pontuação. O jogador pode pedir quantas cartas quiser, uma de cada vez,
sendo seu objetivo chegar o mais próximo possível do número 21, sem passá-
lo. Se passar de 21, perde o jogo. Se chegar exatamente em 21, ganha o jogo.

Existem mais algumas regras, mas chego nelas quando for a hora.

Sendo um jogo originalmente de cartas, o primeiro passo é sempre


construirmos o baralho. Para isso, vamos começar criando um novo projeto
no NetBeans (Arquivo > Novo Projeto > Aplicação Java) com o nome de
VinteUm e, no arquivo principal onde está o main, vamos declarar um array
com 52 posições, uma para cada carta do baralho.

Em cada uma dessas posições (0 a 51), vamos guardar uma carta, de 1 a 13,
sendo que teremos quatro cartas número 1, quatro cartas número 2, etc,
representando a variação de naipes, que aqui vamos ignorar pois não afeta o
jogo. O código abaixo ilustra a criação desse baralho virtual.

Código 84: disponível em http://www.luiztools.com.br/livro-java-i-fontes

//criação do baralho
int [] baralho = new int [52];
for ( int naipe=0; naipe <= 3; naipe++){
for ( int numero=1; numero <= 13; numero++){
baralho[(naipe * 13) + numero - 1] = numero;
}
}

Note como encadeei dois laços for, um dentro do outro, para fazer o efeito de
gerar 4 cartas de cada um dos 13 números. Também usei uma expressão não
usual para determinar em qual posição do array cada uma das cartas deveria
estar, em ordem numérica, sem sobrepor nenhuma. A ideia é que as primeiras
treze cartas vão ocupar as posições de 0 à 12, na sequência, graças ao cálculo
que coloquei dentro do índice do array (os colchetes), o próximo jogo de 13
cartas vai ocupar da posição 13 à 25 e assim por diante.

Mas desse jeito elas vão ficar todos em ordem, facilitando o jogo, certo?

Sim, por isso nosso próximo passo, sempre que estivermos fazendo um jogo
de cartas, é embaralhar as mesmas.

Não existe uma única maneira de fazer nisso, na verdade em algoritmos


nunca há uma única maneira de fazer, mas o que vou lhe sugerir é usando os
conhecimentos que já temos, com números aleatórios. Assim, para cada
posição de uma carta do nosso array, vamos trocá-la de posição,
aleatoriamente, com outra carta, usando um laço for simples.

Código 85: disponível em http://www.luiztools.com.br/livro-java-i-fontes

//código 84 vai aqui em cima


//embaralhamento
for ( int i=0; i < 52; i++){
int carta = baralho[i];
int novaPosicao = ( int )( Math .random() * 52);
baralho[i] = baralho[novaPosicao];
baralho[novaPosicao] = carta;
}

Caso ache que esse laço não é o suficiente, você pode colocar um mais
externo, para repetir o embaralhamento mais de uma vez, assim como
fazemos em carteados tradicionais.

Uma vez que temos nosso baralho pronto, é hora de sacarmos uma carta por
vez, na ordem, enquanto o jogador quiser mais cartas, ao mesmo tempo em
que somamos cada carta retirada do baralho à pontuação dele.

Código 86: disponível em http://www.luiztools.com.br/livro-java-i-fontes

//código 84 + 85 vai aqui em cima


Scanner teclado = new Scanner( System .in);
int pontosJogador = 0;
int proximaCarta = 0;
int cartaAtual = 0;
boolean maisCarta = true ;

do{
cartaAtual = baralho[proximaCarta++];
System.out.println("Você sacou um " + cartaAtual);
pontosJogador+= cartaAtual;
System.out.println("Sua pontuação atual é " + pontosJogador);
System.out.println("Digite 1 para sacar mais uma carta, ou qualquer outro
número para parar.");
maisCarta = teclado.nextInt() == 1;
}while(maisCarta);

Note como declarei primeiramente todas as variáveis que vamos precisar ao


longo desse bloco de código nem no topo, para que fique mais fácil de se
organizar. O objeto ‘teclado’, do tipo Scanner, já é um velho conhecido
nosso, enquanto que ‘pontosJogador’ vão guardar a pontuação do jogador,
‘proximaCarta’ a posição da próxima carta a ser retirada do baralho (para
evitar repetições), ‘cartaAtual’ para sabermos a carta que acabou de ser
retirada e ‘maisCarta’, um booleano indicando se o jogador quer mais cartas
ou não, usado para encerrar a repetição do do/while seguinte.

A propósito, você entendeu porque decidi usar um do/while ao invés de um


for ou de um while? Primeiro, não poderia usar um for, uma vez que não
sabemos de antemão quantas cartas o jogador vai querer sacar. Segundo, até
poderíamos usar o while, mas se temos a certeza de que no mínimo uma carta
vai ser sacada (i.e. o while vai executar ao menos uma vez), o mais indicado é
a versão do/while.

Alguns pontos neste código são novidade e merecem a nossa atenção antes de
continuarmos.

Um deles diz respeito ao trecho pontosJogador+= cartaAtual’, mas o que


significa ‘+=’? Significa que vou pegar o mesmo elemento da esquerda da
operação, somar com o da direita e depois devolver o novo valor para o
elemento da esquerda, ou seja, pontosJogador+= cartaAtual’ é igual a
pontosJogador= pontosJogador + cartaAtual’, mas de uma maneira mais
reduzida. O mesmo vale se algum dia você enxergar ‘-=’, ‘*=’ e ‘/=’, cada
um funcionando de acordo com a operação que precede a atribuição (=).

Outro ponto é o ‘maisCarta = teclado.nextInt() == 1;’. Sabemos que


maisCarta é uma variável booleana, que deve receber true ou false como
únicos valores. No entanto, não precisamos escrever explicitamente true ou
false à direita da atribuição (=), mas sim, qualquer expressão que resulte em
true ou false. Neste exemplo, a expressão que temos à direita da atribuição é
uma igualdade. Se o número digitado pelo usuário (teclado.nextInt) for igual
à 1, essa expressão retornará true para a variável maisCarta, caso
contrário,false. Interessante, não?!

Mas vamos avançar. O próximo passo é ver o que aconteceu após o do/while,
que termina quando o jogador "diz" que não quer sacar mais cartas. Nesse
ponto que aplicamos as regras do jogo, para saber se o jogador venceu ou
não.
Código 87: disponível em http://www.luiztools.com.br/livro-java-i-fontes

//código 84 + 85 + 86 vai aqui em cima


if (pontosJogador == 21){
System .out.println( "Na mosca, o jogador venceu!" );
return ;
}
else if (pontosJogador > 21){
System .out.println( "Sinto muito, não foi dessa vez!" );
return ;
}
else
System .out.println( "Você fez " + pontosJogador+ " pontos. Agora é a vez
da banca!" );

Se o jogador fez exatamente 21 pontos, ele ganhou o jogo e tudo se encerra


com uma mensagem e um comando return, que significa ‘sai do main’, ao
menos por enquanto. ;)

Se o jogador fez mais de 21 pontos, ele perdeu automaticamente e tudo se


encerra com uma mensagem triste, e novamente um return para sair do jogo.

E por fim, o ponto mais curioso do código acima, se ele fez menos de 21
pontos, é a vez da ‘banca’ jogar. Banca é o nome que damos à ‘casa de jogos’
ou ao profissional que dá as cartas, contratado do cassino. O que quero dizer
aqui, é que o próximo passo é a CPU jogar, para ver se ela vencerá a partida
ou o jogador.

Basicamente a CPU vai sacar cartas com a seguinte lógica: ela quer fazer
mais pontos que o jogador, até um máximo de 21 pontos. Se a CPU fizer
mais de 21 pontos, ela perde automaticamente. Se ela fizer menos pontos que
o jogador, ela perde também. Se ela fizer mais pontos que o jogador, até um
máximo de 21, a vitória é da CPU.

Note que essa lógica é o que vai ditar o comportamento da CPU, a IA dela, e
não mais a aleatoriedade, como estávamos fazendo antes. Sendo assim,
vamos ao laço de inteligência artifical da CPU!

Código 88: disponível em http://www.luiztools.com.br/livro-java-i-fontes

//código 84 + 85 + 86 + 87 vai aqui em cima


int pontosCpu = 0;
cartaAtual = 0;

do {
System .out.println( "A CPU vai sacar uma carta!" );
Thread .sleep(1000);
cartaAtual = baralho[proximaCarta++];
System .out.println( "A CPU sacou um " + cartaAtual);
pontosCpu += cartaAtual;
System .out.println( "A pontuação da CPU é " + pontosCpu );

if (pontosCpu > 21){


System .out.println( "A CPU perdeu!" );
break ;
} else if (pontosCpu > pontosJogador){
System .out.println( "A CPU ganhou!" );
break ;
}
} while ( true );

Aqui eu criei uma variável para armazenar a pontuação da CPU (afinal, não
podemos usar a variável antiga para não perder o comparativo), zerei
novamente a variável de cartaAtual e iniciei um novo do/while, que
representa a IA da CPU.

Após o aviso de que será sacado uma carta, e nossa espera intencional de 1s,
a CPU saca uma carta usando a mesma lógica do jogador, mas ao invés da
tradicional pergunta se ela deseja sacar mais uma carta, a intrépida CPU se
foca apenas em calcular se ainda pode ganhar ou não. Se ela já passou de 21
pontos, ela perdeu, encerramos com um break. Se ela já passou dos pontos do
jogador, ela ganhou a partida. Caso contrário, ela vai sacar novamente uma
carta, até ganhar ou perder.

Isso por si só conclui o jogo. Algumas variações de Vinte Um que você pode
encontrar pela Internet ou em livros colocam a possibilidade de empate, caso
o jogador e a CPU alcancem 21 pontos. Nesse caso quem tivesse tirado mais
cartas ganharia, mas preferi dar a vitória para o jogador para simplificar, pois
isso iria requerer mais duas variáveis para mantermos controle, uma para o
número de cartas sacada pelo jogador e outra para a CPU.

Outro ajuste que poderia ser feito, esse bem mais interessante, seria um
esquema de apostas. Aqui, teríamos de manter uma variável numérica com o
saldo do jogador e outra com o total de apostas da rodada, sendo que a
banca/CPU sempre cobriria a aposta do jogador. Ele poderia jogar indefinidas
partidas, enquanto tivesse saldo.

Um terceiro ajuste, este beeem mais complicado, seria uma versão


multiplayer, para até 3 jogadores. Aqui teríamos de manter variáveis de
pontos (e saldo, se estiver usando apostas) para cada um deles, fazer cada um
jogar individualmente (cada um rodaria o primeiro do/while até o fim) e
depois no final calcular quem ganhou.

Ufa, é bastante trabalho, não é mesmo? Tenho certeza que agora que vimos
tudo isso, você tem plena capacidade para implementar essas modificações.
Caso queira uma ajuda, apenas mostrar como resolveu ou ainda uma solução
possível, entre em contato comigo através do meu blog luiztools.com.br ou
minha página no Facebook.com/luiztools.

O código a seguir, é a versão completa do VinteUm, apenas juntando todas as


partes anteriores.

Código 89: disponível em http://www.luiztools.com.br/livro-java-i-fontes

//criação do baralho
int [] baralho = new int [52];
for ( int naipe=0; naipe <= 3; naipe++){
for ( int numero=1; numero <= 13; numero++){
baralho[(naipe * 13) + numero - 1] = numero;
}
}

//embaralhamento
for(int i=0; i < 52; i++){
int carta = baralho[i];
int novaPosicao = (int)(Math.random() * 52);
baralho[i] = baralho[novaPosicao];
baralho[novaPosicao] = carta;
}

Scanner teclado = new Scanner(System.in);


int pontosJogador = 0;
int proximaCarta = 0;
int cartaAtual = 0;
boolean maisCarta = true;

do{
cartaAtual = baralho[proximaCarta++];
System.out.println("Você sacou um " + cartaAtual);
pontosJogador+= cartaAtual;
System.out.println("Sua pontuação atual é " + pontosJogador);
System.out.println("Digite 1 para sacar mais uma carta, ou qualquer outro
número para parar.");
maisCarta = teclado.nextInt() == 1;
}while(maisCarta);

if(pontosJogador == 21){
System.out.println("Na mosca, o jogador venceu!");
return;
}
else if(pontosJogador > 21){
System.out.println("Sinto muito, não foi dessa vez!");
return;
}
else
System.out.println("Você fez " + pontosJogador+ " pontos. Agora é a vez
da banca!");

int pontosCpu = 0;
cartaAtual = 0;

do{
System.out.println("A CPU vai sacar uma carta!");
Thread.sleep(1000);
cartaAtual = baralho[proximaCarta++];
System.out.println("A CPU sacou um " + cartaAtual);
pontosCpu += cartaAtual;
System.out.println("A pontuação da CPU é " + pontosCpu );

if(pontosCpu > 21){


System.out.println("A CPU perdeu!");
break;
} else if(pontosCpu > pontosJogador){
System.out.println("A CPU ganhou!");
break;
}
}while(true);
7 Seguindo em Frente
Este livro termina aqui.

Pois é, certamente você está agora com uma vontade louca de aprender mais
e criar aplicações incríveis que resolvam problemas das empresas e de quebra
que o deixem cheio de dinheiro na conta bancária, não é mesmo?

Este livro é propositalmente pequeno, com pouco mais de 100 páginas. Como
professor, costumo dividir o aprendizado de alguma tecnologia (como Java)
em duas grandes etapas: aprender o básico e executar o que foi aprendido no
mercado, para alcançar os níveis intermediários e avançados. Acho que este
livro atende bem ao primeiro requisito, mas o segundo só depende de você.

De nada adianta saber muita teoria se você não aplicar ela. Então agora que
terminou de ler este livro, inicie hoje mesmo (não importa se for tarde) um
projeto de aplicação novo. Ou então adicione os elementos que foram
mencionados, mas não implementados, no jogo Vinte Um do último capítulo.

Me despeço de você leitor com uma sensação de dever cumprido. Caso


acredite que está pronto para conceitos mais avançados, sugiro dar uma
olhada em meu blog http://www.luiztools.com.br, em minha página no
Facebook.com/luiztools e em meu outro livro que envolve programação Java,
o Criando apps para empresas com Android.

Também já está em desenvolvimento um segundo livro de Java, continuação


deste, explorando conceitos intermediários como Orientação à Objetos e
Interface Gráfica. Se quiser saber mais e até mesmo dar suas sugestões de
como gostaria que ele fosse, os mesmos canais que citei antes (blog e
Facebook) podem ser usados para essa finalidade.

Caso tenha gostado do material, indique esse livro a um amigo que também
deseja aprender a desenvolver em Java. Não tenha medo da concorrência e
abrace a ideia de ter um sócio que possa lhe ajudar nos projetos.

Um abraço e até a próxima!


Curtiu o livro?
Deixe seu feedback lá na Amazon para ajudar este humilde autor:
https://www.amazon.com.br/review/create-
review/ref=cm_cr_dp_d_wr_but_top?ie=UTF8&channel=glance-
detail&asin=B01MY7VBE5
Aproveita e também me segue nas redes sociais:
Facebook: http://fb.com/luiztools
Twitter: http://twitter.com/luiztools
Conheça meus outros livros:

Programação Web com Node.js


Criando apps para empresas com Android
Scrum e Métodos Ágeis: Um Guia Prático
Agile Coaching: Um Guia Prático
Node.js e Microservices
MongoDB para Iniciantes

Conheça meus cursos:

Curso online de Scrum e Métodos Ágeis


Curso online de Node.js e MongoDB

Você também pode gostar