Desenhar calendário

Bom dia!!!
Sou iniciante em Java e estou com dificuldade na resolução de um exercício: Desenvolva um algoritmo que “desenhe" um calendário, como o exemplo, para um determinado mês, tendo
como dados:
(i) o número de dias desse mês;
(ii) qual o dia da semana correspondente ao primeiro dia do mês.

Já fiz o algoritmo, no entanto não estou a conseguir desenhar o calendário na tela. O meu programa:

import java.util.Scanner;

public class Calendar {

	public static void main(String[] args) {
		
		        Scanner scan = new Scanner(System.in);
		        System.out.println("Em qual dia da semana começa o mês?(considere domingo = 1 e sábado = 7)");
		        int dia = scan.nextInt();
		        System.out.println("Quantos dias tem o mês?");
		        int dias = scan.nextInt();
		        System.out.println("D S T Q Q S S");
		        
		        for(int i = 1; i < dia; i++){
		            System.out.print("  ");
		        }
		        for(int i = 1; i <= dias; i++){
		            System.out.print("|" + i);
		            if(dia == 7){
		                dia = 1;
		                System.out.print("\\n");
		            }else{
		                dia++;
		            }

O resultado: Em qual dia da semana começa o mês?(considere domingo = 1 e sábado = 7)
1
Quantos dias tem o mês?
28
D S T Q Q S S
|1|2|3|4|5|6|7\n|8|9|10|11|12|13|14\n|15|16|17|18|19|20|21\n|22|23|24|25|26|27|28\n

O que se pretende:
Que apareça em forma de calendário.

D S T Q Q S S
---------------------
1 2 3 4 5 6 7
8 9 10 11..

mas em desenho.

Além disso, alguém sabe como fazer para a pessoa poder introduzir “segunda-feira”, “terça-feira” etc ao invés de números correspondentes como eu fiz?
Muito obrigado a todos pela atenção!

Sónia

Apenas uma barra, para mudar de linha. Com duas barras imprime uma barra

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

Obrigada! Já começa a ficar mais parecido:
D S T Q Q S S
|1|2|3
|4|5|6|7|8|9|10
|11|12|13|14|15|16|17
|18|19|20|21|22|23|24
|25|26|27|28|29|30

Mas ainda me falta alinhar e desenhar uma barra a separar os nomes dos dias dos números:

Creio que usar o printf seja uma opção nesse seu caso.

Fiz algumas adaptações ao teu código: uniformizei todos os dias a terem 3 caracteres: 1 ou 2 para o dia e um espaço a separar (tem um if para ver se o dia é menor ou não que 10) e adicionei o separador.

public class Calendar {

  public static void main(String[] args) {

    Scanner scan = new Scanner(System.in);
    System.out.println("Em qual dia da semana começa o mês? (considere domingo = 1 e sábado = 7)");
    int dia = scan.nextInt();
    System.out.println("Quantos dias tem o mês?");
    int dias = scan.nextInt();
    System.out.println("  D  S  T  Q  Q  S  S");
    System.out.println("---------------------");

    for (int i = 1; i < dia; i++) {
      System.out.print("   ");
    }
    for (int i = 1; i <= dias; i++) {
      if (i < 10) {
        System.out.print("  " + i);
      } else {
        System.out.print(" " + i);
      }
      if (dia == 7) {
        dia = 1;
        System.out.print("\n");
      } else {
        dia++;
      }
    }
  }
}

Usando printf…

import java.util.Scanner;

public class Calendario {
	public static void main(String[] args){
		short diasMes;
		short diaSemanaInicial;
		short contador = 0;
		Scanner leitor = new Scanner(System.in);
		Calendario calendario = new Calendario();
		
		System.out.print("Número de dias do mês: ");
		diasMes = leitor.nextShort();
		
		System.out.print("Dia da semana inicial: ");
		diaSemanaInicial = leitor.nextShort();
		
		System.out.printf("%5c%5c%5c%5c%5c%5c%5c", 'D', 'S', 'T', 'Q', 'Q', 'S', 'S');
		System.out.println("\n________________________________________");
		
		for(short i = 1; i <= diasMes; i++){
			if(i == 1){
				System.out.printf("%" + (diaSemanaInicial * 5) + "d", i);
				contador = diaSemanaInicial;
			}else{
				System.out.printf("%5d", i);
				contador++;
			}
			
			if(contador % 7 == 0){
				System.out.println("");
			}
		}
		System.out.println("\n");
	}
}

Rodando…
image
image

Muito obrigada pela sua resolução! De facto funciona. No entanto tenho algumas dúvidas porque a única coisa de matéria que nos deram para desenhar foi:

import javax.swing.*;
import java.awt.*;

class Painel extends JPanel {
   public void paintComponent(Graphics g){
      // assegura que o desenho vai ser feito de forma correcta
      super.paintComponent(g); // g representa a superfície de desenho
      g.drawLine (0, 0, 100, 100);
   }
}


public class Principal {
  public static void main(String[] args) {
      // cria a janela da aplicação
      JFrame j = new JFrame();

      // cria um painel ou superfície de desenho
      Painel p = new Painel();

      // define que quando se fechar a janela a aplicação termina
      j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      j.add(p);             // junta o painel à janela
      j.setSize(250, 250);    // junta o painel à janela
      j.setTitle ("Linha"); // junta o painel à janela
      j.setVisible(true);  // mostra-a
   }
}

e

Então não percebi o que usou nesta parte:

System.out.printf("%5c%5c%5c%5c%5c%5c%5c", 'D', 'S', 'T', 'Q', 'Q', 'S', 'S');
		System.out.println("\n________________________________________");

Paraalém disso existe alguma forma de o utilizador escrever o nome dos dias, exemplo segunda-feira, Domingo…

Mais uma vez muito obrigada pela ajuda!!!

Quando postar código, seleciona ele e clica em </>

image

Isso facilita a leitura dos colegas.

2 curtidas

Então, além dos métodos print (imprimir) e println (imprimir com separação de linha) existe o printf (imprimir com formato). O método printf aceita dois parâmetros, sendo que o primeiro deles é uma String de formato que define o formato com que o segundo parâmetro será presentado (a grosso modo). Nesse caso específico, indiquei que o tipo de dado é um char, por isso o “%c”. No entanto, eu posso usar flags (sinalizadores) para ‘melhorar’ o formato definido. Assim sinalizei a largura do campo (número de posições de caractere) que no caso é 5 alinhados à direita (por padrão). Como resultado prático, cada caracteres será exibido alinhado à direita colocando um espaço de 5 caracteres à esquerda.
No seu caso, no entanto, querem que tu faça com interface gráfica.

Sim!

Com interface gráfica (parece funcionar bem):

1 - Classe Painel:

import java.awt.Graphics;
import javax.swing.JPanel;

public class Painel extends JPanel{
	private int diasNoMes;
	private int diaSemana;
	private int posicaoX = 20;
	private int posicaoY = 70;
	
	public void paintComponent(Graphics grafico){
		int contador = 0;
		int[] abscissas = new int[7];
		super.paintComponent(grafico);
		
		abscissas[0] = 20;
		for(short i = 1; i < 7; i++){
			abscissas[i] = abscissas[i - 1] + 50;
		}
		
		grafico.drawString("Dom", abscissas[0], 45);
		grafico.drawString("Seg", abscissas[1], 45);
		grafico.drawString("Ter", abscissas[2], 45);
		grafico.drawString("Qua", abscissas[3], 45);
		grafico.drawString("Qui", abscissas[4], 45);
		grafico.drawString("Sex", abscissas[5], 45);
		grafico.drawString("Sáb", abscissas[6], 45);
		
		grafico.drawLine(20, 50, 400, 50);
		for(short i = 1; i <= diasNoMes; i++){
			if(i == 1){
				posicaoX = abscissas[diaSemana - 1] + 10;
				
				grafico.drawString("" + i, posicaoX, posicaoY);
				contador = diaSemana; //1
			}else{
				posicaoX += 50;
				grafico.drawString("" + i, posicaoX, posicaoY);
				contador++;
			}
			
			if(contador % 7 == 0){
				posicaoX = -20;
				posicaoY += 20;
			}
		}
	}
	
	public void setTotalDias(int diasNoMes){
		this.diasNoMes = diasNoMes;
	}
	
	public void setSemanaInicio(int diaSemana){
		this.diaSemana = diaSemana;
	}
}

2 - Classe Principal:

import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class Principal {
	public static void main(String[] args){
		String diasMes;
		String diaInicioSemana;
		JFrame janela = new JFrame();
		Painel painel = new Painel();
		
		diasMes = JOptionPane.showInputDialog(null, "Informe quantos dias tem o mês: ", 
			"Dias no Mês", JOptionPane.QUESTION_MESSAGE);
			
		diaInicioSemana = JOptionPane.showInputDialog(null, "Informe o dia da semana em que inicia: ", 
			"Dias no Mês", JOptionPane.QUESTION_MESSAGE);
		
		painel.setTotalDias(Integer.valueOf(diasMes).intValue());
		painel.setSemanaInicio(Integer.valueOf(diaInicioSemana).intValue());
		
		janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		janela.add(painel);
		janela.setSize(500, 250);
		janela.setTitle("Linha");
		janela.setVisible(true);
	}
}

Rodando (para as mesma entradas anteriores)

image
image
image
image

1 curtida

Muito Obrigada por tudo Iohannes, pela explicação e a resolução por passos.
Alterei apenas a parte das perguntas. Em vez de aparecer tudo em painel gráfico faz as perguntas na consola e só depois aparece o Calendário. Estava demasiado perfeito para as aprendizagens até agora eheh
Queria só confirmar uma coisa. Eu tenho o pacote Avaliação e dentro do pacote para as 2 classes tenho de ter um ficheiro para cada classe certo? Não posso ter 2 classes no mesmo ficheiro?
Muito obrigada mais uma vez!

Claro que pode, desde que as classes guardem alguma relação. Por exemplo, classes que trabalham com a parte interface com o usuário (telas) devem ficar em uma mesma pasta/ficheiro o que vem a ser um pacote (se usado o package). Classes que manipulam o banco de dados, ficam todas no pacote de model (ou DAO, dependendo do padrão) e por aí vai… No seu caso, como ambas são de interface de usuário, podem ficar na mesma pasta/ficheiro/pacote. Lembrando que nomes de pacotes começam com letra maiúscula por convenção. Logo, seria avaliacao e não Avaliacao e sem acentuação. Embora o Java aceite caracteres acentuados no nome de variáveis, classes, etc., porque usa como charset o Unicode em vez do ASCII, é bom evitar como boa prática.