/*
* Voici un codage possible de cet exercice
* La code fourni permet de mettre en oeuvre les deux parties de l'exercice.
* La première partie pourrait être réalisée sans passer par un tableau.
* L'usage du tableau est surtout destiné à faciliter la programmation
* de la seconde partie.
*/
import java.util.Scanner;
public class Sapin {
/*
* méthode remplissant le triangle, on construit à chaque ligne
* le tableau de char de la dimension
* correspondante (1 a la ligne 0, 3 à la ligne 1, etc)
*/
static void remplirTriangle(char[][] triangle, char c) {
int nbLigne = triangle.length;
int nbColonne;
for (int i = 0; i < nbLigne; ++i) {
nbColonne = i*2 + 1;
triangle[i] = new char[nbColonne];
for (int j = 0; j < nbColonne; ++j) {
triangle[i][j] = c;
}
}
}
/*
* Méthode ajoutant des guirlandes au triangle qui représente un sapin
* sans decorations.
*/
static void mettreGuirlande(char[][] sapinTriangle, String guirlande) {
int nbLigne = sapinTriangle.length;
// La variable pointeurChar stocke l'indice du prochain caractère de
// la guirlande à placer
int pointeurChar = 0;
int longueurChaine = guirlande.length();
// Cette variable permet de différencier le cas où l'on pose les guirlandes
// complètement, et le cas où l'on étend une guirlande sur les lignes
// supplémentaires
boolean completerGuirlande = false;
//les deux variables d'indice que l'on fera varier
int i = 0;
int j = 0;
while(i < nbLigne) {
// on vérifie d'abord que nous sommes dans une ligne impaire
// ou alors que l'on est en train de finir d'étendre une
// guirlande sur les lignes suivantes
if (i % 2 == 1 || completerGuirlande) {
// avec ces 2 instructions on remplace le caractère (i,j)
// du sapin par le prochain caractère à placer
// de la guirlande. pointeurChar donne la position
// de ce caractère dans la guirlande. On incrémente ensuite
// cette position en prenant le reste de la division
// par rapport à la longueur de la guirlande
//(quand on dépasse la position maximale possible, pointeurChar
// reprend la valeur 0)
sapinTriangle[i][j] = guirlande.charAt(pointeurChar);
pointeurChar = (pointeurChar + 1) % longueurChaine;
//ensuite il faut incrémenter les i et j en fonction de la
//situation
if ((j >= sapinTriangle[i].length - 1 && pointeurChar != 0) || completerGuirlande) {
// Ce if gère le cas assez compliqué où il faut finir d'étendre la
// guirlande sur la ligne d'en dessous. On utilise un boolean pour entrer
// dans ce if jusqu'à ce que pointeurChar vaille 0; à ce moment on sait
// que l'on a finit d'étendre la guirlande et on remet le boolean à faux. On
// incrémente alors le j d'une quantité aléatoire. On n'incrémente pas la ligne car il
// est tout à fait possible d'avoir couvert la deuxième ligne entièrement et
// d'être revenu à une ligne impaire, dans ce cas on doit simplement continuer
// avec la guirlande suivante
if (pointeurChar == 0) {
completerGuirlande = false;
j += random() + 1;
} else {
// sinon on gère les 3 cas possibles:
// 1. on arrive pour la première fois ici et on change de ligne et on affecte j
// au dernier index de la ligne d'en dessous
// sinon, on est en train de compléter la guirlande (variable à vrai), dans ce cas :
// 2. soit la ligne est paire, auquel cas on remplit de droite à gauche
// 3. elle est impaire et on remplit de gauche à droite (cas de longues guirlandes où l'on
// a recouvert toute la ligne supplémentaire et qu'on continue d'étendre sur la
// suivante
if (!completerGuirlande) {
completerGuirlande = true;
++i;
if (i < nbLigne) {
j = sapinTriangle[i].length - 1;
}
} else if (i % 2 == 0) {
--j;
if (j < 0) {
++i;
j = 0;
}
} else {
++j;
if (j >= sapinTriangle[i].length) {
++i;
if (i < nbLigne) {
j = sapinTriangle[i].length - 1;
}
}
}
}
} else {
// else de la condition
// (j >= sapinTriangle[i].length - 1 && pointeurChar != 0) || completerGuirlande)
//Dans ce cas on fait l'incrémentation normale de j, et éventuellement on ajoute
//le nombre aléatoire pour laisser un peu d'espace
if (pointeurChar == 0) {
j += random();
}
++j;
}
//finalement on fait la vérification finale, qui incrémente la ligne et remet j à zéro si nécessaire
if (i < nbLigne && j >= sapinTriangle[i].length && pointeurChar == 0) {
++i;
j = 0;
}
} else {
//si la ligne n'était pas paire, on incrémente la ligne
j = 0;
++i;
}
}
}
/* Méthode affichant le tableau sous forme triangulaire.
*/
static void afficherTriangle(char[][] triangle) {
int nbLigne = triangle.length;
int nbColonne;
int nbEspace;
for (int i = 0; i < nbLigne; ++i) {
nbEspace = ((2*nbLigne - 1) - (2*i + 1))/2;
for (int j = 0; j < nbEspace; ++j) {
System.out.print(" ");
}
nbColonne = triangle[i].length;
for (int j = 0; j < nbColonne; ++j) {
System.out.print(triangle[i][j]);
}
System.out.println();
}
}
/* Méthode ajoutant un tronc à l'arbre, elle choisit la hauteur et
* la largeur en fonction du nombre de ligne du sapin.
*/
static void afficherTronc(int nbLigne) {
int largeur;
int hauteur;
largeur = (nbLigne*2 - 1) / 5;
if (largeur % 2 == 0)
++largeur;
hauteur = Math.max(1, nbLigne/3);
for (int i = 0; i < hauteur; ++i) {
for (int j = 0; j < ((nbLigne*2 -1) - 3)/2; ++j)
System.out.print(" ");
for (int j = 0; j < largeur; ++j)
System.out.print("|");
System.out.println();
}
}
/*
* Méthode choisissant aléatoirement entre 2 et 3
*/
static int random() {
int val = (int)(Math.random()*2); // 0 or 1
return (val+2); //return 2 or 3
}
/*
* Programme principal
* on demande les données nécessaires à l'utilisateur et vérifie que
* les informations saisies soient correctes.
* On appelle ensuite les méthodes dans le bon ordre pour construire puis
* afficher le sapin
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char[][] triangle;
char symbole;
int nbLigne;
String guirlande;
System.out.print("Quel symbole voulez-vous pour les épines du sapin? ");
symbole = sc.nextLine().charAt(0);
do {
System.out.print("Combien de ligne (de 8 a 35)? ");
nbLigne = sc.nextInt();
} while (nbLigne < 8 || nbLigne > 35);
do {
System.out.print("Quelles guirlandes voulez-vous mettre " +
"(taille de 3 a 25 caractères et elles ne peuvent \n" +
"pas contenir le même caractère que celui utilisé pour les épines)? ");
guirlande = sc.next();
} while (guirlande.length() < 3 || guirlande.length() > 25 || guirlande.contains(Character.toString(symbole)));
System.out.println();
//on initialise seulement le nombre de lignes que contiendra ce tableau (ligne), on pourra ensuite
//choisir à chaque ligne le nombre d'éléments (colonne)
triangle = new char [nbLigne][];
remplirTriangle(triangle, symbole);
mettreGuirlande(triangle, guirlande);
afficherTriangle(triangle);
afficherTronc(triangle.length);
/* Note pour la partie 1: il suffit d'invoquer les méthodes suivantes
* (après la saisie des données utiles) :
*
* remplirTriangle(triangle, symbole);
* afficherTriangle(triangle);
*/
}
}