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:

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

    ResponderExcluir
  2. 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+="*";
    }

    ResponderExcluir
  3. 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");
    }
    }
    }
    }

    ResponderExcluir
  4. 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);
    }
    }

    ResponderExcluir
  5. 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");
    }

    ResponderExcluir
  6. 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




    }





    }
    }

    }

    ResponderExcluir
  7. 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");
    }
    }
    }

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

    ResponderExcluir
  9. 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("");
    }
    }
    }

    ResponderExcluir
  10. 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

    ResponderExcluir
  11. 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("");
    }
    }

    }

    ResponderExcluir