Enviar um café pro programador

Pode me ajudar a transformar cafeína em código?

Desafio do diamante

Nesse artigo iremos resolver o Desafio do Diamante em Java, que foi proposto na página de Exercícios envolvendo laços.



Desafio diamante de asteriscos:
Escreva um aplicativo Java que peça um número inteiro ímpar ao usuário e desenhe um diamante no seguinte formato:

    *
   ***
  *****
 *******
*********
 *******
  *****
   ***
    *


Nesse caso, o número é 9, pois há 9 colunas e 9 asteriscos na linha central.

SOLUÇÃO

Há duas coisas na figura: espaços em branco e asteriscos.
Vamos resolver esse desafio analisando o padrão do número de asteriscos (variável asteriscos) e do número de espaços em branco (variável espacos).

Antes de desenhar o diamante, temos que checar se o número que o usuário forneceu é ímpar, através de um teste condicional:
if(numero%2 != 0)

Se não for, o programa cai no else e nossa aplicação Java é finalizada.
Vamos desenhar o dito cujo.

Parte de cima do diamante
Qual o número inicial de espaços?
Note que é sempre: (numero-1)/2
...e essa é a lógica do problema, a parte mais difícil, que é notar esse padrão.

E o número de asteriscos inicial?
Fácil, é 1 e vai crescendo de 2 em 2 até que o número de asteriscos impressos seja igual a numero.

Pois bem, vamos desenhar linha por linha, imprimindo primeiro o número correto de espaços e depois o de asteriscos.
Esse controle de linhas é feito pela linha de código:
for(int linha=1 ; espacos > 0 ; linha++)

Ou seja, vamos imprimir da linha 1 até a linha central (note que a linha central é a que tem espacos=0).

Agora, dentro desse looping vamos imprimir, em cada linha, primeiro o número de espaços e depois os asteriscos.
Sabemos que o número inicial de espaços é (numero-1)/2 e o número inicial de asteriscos é 1.

Para imprimir o número correto de espaços e asteriscos vamos usar a variável count:
for(int count=1 ; count <= espacos ; count++)
for(int count=1 ; count <= asteriscos ; count++)

Após o looping maior, o das linhas, temos que decrementar o número de espaços em 1, e incrementar o número de asteriscos em 2, além da quebra de linha.


Parte de cima do diamante
A lógica é a mesma da de cima, porém o número de espaços aumenta em 2, e o número de asteriscos é decrementado em 2.
Outra diferença é que vamos imprimir uma linha a menos, pois a linha central já foi impressa. Assim, essas linhas são impressas desde a primeira abaixo da linha central, até enquanto houver asteriscos (até ter 1, que é o último):
for(int linha=1 ; asteriscos > 0 ; linha++)

Logo, nosso código Java fica assim:


import java.util.Scanner;

public class DesafioDoDiamante {
    public static void main(String[] args) {
        int numero,
            espacos,
            asteriscos;
        Scanner entrada = new Scanner(System.in);
        
        System.out.print("Insira um número ímpar: ");
        numero = entrada.nextInt();
        
        if(numero%2 != 0){
            
            //Imprimindo a parte de cima do diamante
            asteriscos = 1;
            espacos = (numero-1)/2;
            for(int linha = 1 ; espacos > 0 ; linha++){
                
                //Espaços
                for(int count = 1 ; count <= espacos ; count++){
                    System.out.print(" ");
                }
                
                //Asteriscos
                for(int count = 1 ; count <= asteriscos ; count++){
                    System.out.print("*");
                }
                
                espacos--;
                asteriscos += 2;
                System.out.println();
            }
            
            //Imprimindo a parte de baixo do diamante
            for(int linha=1 ; asteriscos > 0 ; linha++){
                
                //Espaços
                for(int count = 1 ; count <= espacos ; count++){
                    System.out.print(" ");
                }
                
                //Asteriscos
                for(int count = 1 ; count <= asteriscos ; count++){
                    System.out.print("*");
                }
                
                espacos++;
                asteriscos -= 2;
                System.out.println();
            }
            
        }else{
            System.out.println("Não é ímpar!");
        }
        
        
    }
}


Lembrando que essa é apenas uma solução, é possível fazer usando menos linhas, porém o entendimento é mais complicado. Tente!

11 comentários:

Unknown disse...

Incrível como este simples exercício desperta diversos conhecimentos!
parabéns pelo site!

Unknown disse...

Javascript: usando raiz quadrada você pode fazer a parte de baixa no mesmo laço!

x=5;
str="";
if(! x % 2)return false;
borda=x-1;
for(i=-borda;i<=borda;i++){
str+="\n";
for(j=0;j<Math.sqrt(i*i);j++)str+=" ";
for(j=0;j<(x-Math.sqrt(i*i))*2-1;j++)str+="*";
}

Unknown disse...

O meu ficou assim:


package diamante;

import java.util.Scanner;

public class Diamante {

public static void main(String[] args) {
int n;
Scanner entrada = new Scanner(System.in);

System.out.println("Informe um numero impar para o tamanho do diamente: ");
n = entrada.nextInt();
if (n % 2 == 0){
System.out.println("Número informado não é impar. Programa encerrando");
}
else {
for (int count_l = 0; count_l < n; ++count_l){
if (count_l <= n/2 ){
for (int count_c = 0; count_c < n; ++count_c){
if (count_c < n /2 - count_l || count_c > n/2 + count_l ){
System.out.print(" ");
}
else {
System.out.print("*");
}
}
}
else {
for (int count_c = 0; count_c < n; ++count_c){
if (count_c < n/2 - (n - count_l -1) || count_c > n/2 + (n - count_l -1) ){
System.out.print(" ");
}
else {
System.out.print("*");
}
}
}
System.out.print("\n");
}
}
}
}

Rerivaldo disse...

Eu usei um Do While, para repetir a pergunta se o usuário não digitar um número impar. Ficou assim:

import java.util.Scanner;
public class Diamante_de_Aster1 {
public static void main(String[]args){
int impar;
boolean continuar = true;
Scanner entrada=new Scanner(System.in);
do{
System.out.print("DIGITE UM NÚMERO INTEIRO IMPAR: ");
impar = entrada.nextInt();

if((impar%2)!=0){
continuar=false;
System.out.println("O NÚMERO DIGITADO É IMPAR: ");
System.out.println();
for(int cont=0;cont<=(impar/2)-0.5;cont++){
for(int cont1=0;cont1<((impar/2)-cont);cont1++){
System.out.print(" ");
}
for(int cont2=0;cont2<=2*cont;cont2++){
System.out.print("*");
}
System.out.println();
}
for(int cont4=1;cont4<=impar;cont4++){//EXECUTA A IMPRESSÃO DOS ASTERISCOS
System.out.print("*"); //DO MEIO DO DIAMANTE(LOSANGO).
}
System.out.println();
for(int cont=0;cont<=(impar/2)-0.5;cont++){

for(int cont2=0;cont2<=cont;cont2++){
System.out.print(" ");
}
for(int cont3=0;cont3<((impar-2)-2*cont);cont3++){
System.out.print("*");//EXECUTA A IMPRESSÃO DOS ASTERISCOS, INFERIORES.
}
System.out.println();
}
break;
}
else{
System.out.println("O NÚMERO DIGITADO É PAR!");
System.out.println();
}
}while(continuar);
}
}

Anônimo disse...

Olá pessoal. Evisclei.
Parabéns pela iniciativa, na internet tem muito mais sobre Java, mas é preciso garimpar em muitos locais diferentes.

Olha só como ficou o meu código do desafio, notem que eu consegui utilizar os mesmos laços tanto para a primeira quanto para a segunda parte do "diamante" com o auxilio de um 'if...else' e da Matemática -- santa Matemática. Com isso eu consegui diminuir muito o número de linhas de código.


Scanner entrada = new Scanner(System.in);

//Número ímpar qualquer
int n;
System.out.print("Informe um número impar qualquer: ");

n = entrada.nextInt();

for (int i = 1; i <= n; i++) {
//Espaços que serão inseridos antes dos asterísticos.
int espacos;
//Este if...else controla se o número de asteríscos é crescente ou decrescente.
if (i <= (n + 1) / 2) {
espacos = (n - 2 * i + 1) / 2;
} else {
espacos = (2 * i - n - 1) / 2;
}
//Varíavel utilizada para controle do laço 'while' e inserção de espaços ou asterísticos.
int j = 1;
//O número de repetições do laço 'while' é igual ao número de espaços
// que tem antes dos asterísticos mais o número de asterísticos.
while (j <= n - espacos) {
if (j <= espacos) {
System.out.print(" ");
} else {
System.out.print("*");
}
j++;
}
System.out.print("\n");
}

Ice Dragon disse...

Não quis olhar a solução e acabei perdendo umas 3 horas pra descobrir o que estava dando errado no meu diamante, no fim percebi que não era o inicio do laço que tinha q decrementar e sim a comparação...

fica ai meu diamante..



package diamante;
import java.util.Scanner;
/**
*
* @author E
*/
public class Diamante {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here


Scanner ent = new Scanner(System.in);

int tamanho;

System.out.print("Digite o tamanho do diamante: ");
tamanho = ent.nextInt();

if (tamanho%2 !=1) //se o numero for par o diamante será o numero + 1
{

tamanho = tamanho +1;
}

System.out.println("\n");

int m = (tamanho/2); //tamanho do espaço max do diamante.

//laço de repetição para criar cada linha
for (int i=1; i<=tamanho; i++)
{

if ((i==1)||(i%2!=0)) //if para imprimir só linhas impares
{
for (int es=1; es<=m; es++) //laço para impressão dos espaços (m decremento fora do laço)
{
System.out.print(" ");

}
m--;
for (int x=1; x<=i; x=x+1) //laço para impressação do *
{

System.out.print("*");
}
System.out.print("\n");// pula linha




}
}
//Parte de baixo do diamante m sempre será 1 na primeira linha
m=1;
for (int i=(tamanho-2); i>=1; i--) //laço de pular linha decrementando pra usar de valor nos *
{

if ((i==1)||(i%2!=0)) //imprime nas linahs impares
{
for (int es=1; es<=m; es++) //imprime espaços
{
System.out.print(" ");

}
m++; //incrementa m
for (int x=1; x<=i; x=x+1) //imprime *
{

System.out.print("*");
}
System.out.print("\n"); //pula linha




}





}
}

}

games disse...

O meu programa ficou com 34 linhas e seguiu uma lógica bem diferente. Usei mais funções. Usei o programa Geogebra pra achar a fórmula da função de uma reta a partir de dois pontos. E o meu programa n precisou de duas partes, uma pra parte de cima e outro pra parte debaixo. Acho muito legal isso de haver várias formas de resolver o mesmo problema.

package main;

import static java.lang.Math.abs;
import java.util.Scanner;

public class Main {

public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.println("Digite");
int f = entrada.nextInt();
if (f % 2 == 1) {
for (int linha = 1; linha <= f; linha++) {
for (int space = abs(linha - ((f + 1) / 2)); space > 0; space--) {
System.out.print(" ");
}
if (linha <= ((f + 1) / 2)) {
for (int sterix = (2 * linha - 1); sterix > 0; sterix--) {
System.out.print("*");
}
} else {
for (int sterix = ((-2) * linha + (2 * f + 1)); sterix > 0; sterix--) {
System.out.print("*");
}

}
System.out.print("\n");

}
} else {
System.out.print("Digite um número impar\n");
}
}
}

Anônimo disse...

Pode dar um exemplo com letrar ao invés de asteriscos?

Anônimo disse...

o meu ta uma bosta, mas pra quem quiser ver minha "obra prima" de nada mais nada menos que 57 linhas e me humilhar de tão ruim que tá...

/*
* Desafio do diamante de asteriscos
*
* 23/12/2016
* @Autor: Daniel Paulo Garcia
*/

import java.util.Scanner;

public class diamante{

public static void main(String[] diamante){
System.out.print("Digite o tamanho do diamante que deseja: ");
Scanner sizex = new Scanner(System.in);
int size;
int spaces;
int asterisks;

//Checa se o valor inserido é válido
while (true){
size = sizex.nextShort();
if (size % 2 == 0 || size < 1){
System.out.print("Valor inválido. Insira um número inteiro ímpar maior ou igual à um: ");
continue;
} else {
break;
}
}

//Desenha o diamante na tela
asterisks = 1;
spaces = (size-1)/2;
while (spaces > 0){
for(int i = 1; i <= spaces; i++){
System.out.print(" ");
}
for(int i = 1; i <= asterisks; i++){
System.out.print("*");
}
spaces--;
asterisks += 2;
System.out.println("");
}

while (asterisks > 0){
for (int i = 1; i <= spaces; i++){
System.out.print(" ");
}
for(int i = 1; i <= asterisks; i++){
System.out.print("*");
}
spaces++;
asterisks -= 2;
System.out.println("");
}
}
}

Unknown disse...

Fiz primeiramente como se fosse uma matriz, com elementos vazios e asteriscos. Muito grande e complicado. Depois segui a ideia do pessoal de contar os espaços e asteriscos, e fiz separados em 2 partes. Por fim, pensei em tentar juntar tudo numa parte só, e cheguei num algoritmo bem semelhante ao do Evisclei. Muito interessante esse desafio.

Segue:

import java.util.Scanner;
public class Ex2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);

// Reading the n and making sure that it is an odd number
int n = 0;
do {
System.out.println("Enter and odd number: ");
n = sc.nextInt();
} while (n % 2 == 0);



int e = 0, a;
//the 1st FOR is used to go to a new line
for (int linha = 1; linha <= n; linha++)
{
//creating the number of spaces per line and printing it
e = Math.abs((n/2 + 1) - linha);

for (int count = e; count > 0;count--)
{
System.out.print(" ");
} //end for espaços


//how to calculate the number of * per line.
if (linha <= (n/2 + 1))
{
a = 2*linha - 1;
} else {
a = (-2)*linha + (2*n +1 );
} //end if


//printing the * as calculated before
for (int counter = 1; counter <= a ;counter++) {
System.out.print("*");
} //end for *

System.out.println();

} //end for linha
} //end main
} //end Ex2

Darke disse...

A minha solução ficou um pouco embolada, mas deu certo.

Notem que eu criei uma função chamada "recebe()" que solicita o valor ao usuário, e continua solicitando até que este valor seja válido. Ou seja, não aceita 0, valores negativos e letras. Utiliza "try". Estou usando-a em todos os meus exercícios que requerem que um valor seja digitado pelo usuário.

package diamante;

/**
*
* @author Darke
*/
import java.util.Scanner;
import java.util.InputMismatchException;


public class Diamante {

/**
* @param args the command line arguments
*/
public static int recebe(){
Scanner entrada= new Scanner(System.in);
int valor=0;
try{
System.out.print("Digite o valor: ");
valor=entrada.nextInt();
if(valor<=1 || valor%2==0){
System.out.println("Valor inválido.");
valor=0;
}
}catch(InputMismatchException erro1){
System.out.println("Valor inválido.");
valor=0;
}
return valor;
}

public static void main(String[] args) {
int x=1, //Faz o giro pela quantidade de linhas
numero=0; //Recebe a quantidade de linhas
int y=1, //Imprime os espaços em branco
z=1; //Imprime os asterisco


while(numero==0){
numero=recebe();
}

int branco=0, asterisco=0;
// parte de cima
int anterior=0;

// Parte de cima
for(x=1;x<=(numero-1)/2;x++){

branco=(numero-x)/2;

if(branco==anterior){
branco=branco-1;
}
if(x!=1){
if(branco>=anterior){
branco=anterior-1;
}
}

asterisco=numero-(branco*2);

for(y=1;y<=branco;y++){
System.out.print(" ");
}
for(z=1;z<=asterisco;z++){
System.out.print("*");
}

anterior=branco;
System.out.println("");
}

// linha central

for(x=1;x<=numero;x++){
System.out.print("*");
}

// parte de baixo
System.out.println("");

anterior=(numero-1)/2;

for(x=(numero-1)/2;x>=1;x--){

branco=(numero-x)/2;

if(x==(numero-1)/2){ // se for a primeira vex
branco=1;
}else{ // aqui está o pulo do gato´para que dê certo
branco=anterior+1;
}

asterisco=numero-(branco*2);

for(y=1;y<=branco;y++){
System.out.print(" ");
}
for(z=1;z<=asterisco;z++){
System.out.print("*");
}

anterior=branco;
System.out.println("");
}
}

}

Contribuir com o Java Progressivo

Que tal apoiar e fazer crescer o ensino da programação no Brasil ?

Ajudar nosso país a crescer e se desenvolver cada vez mais, tecnologicamente?

Clica abaixo pra saber mais!

Apoiar o Projeto Progressivo


Tutoriais de Java