EDIT : Il aura fallut que j'écrive ici pour enfin allumer sur certains trucs! Par contre, j'ai encore besoin de vous!
Bonjour à vous tous!
Je suis nouvelle dans la programmation Java et j'aurais besoin de votre aide pour un projet.
Je dois faire un Sudoku qui utilise des fichiers .txt et je dois le transformer en tableau 9x9.
J'ai déjà fait un Sudoku mais qui utilise la méthode Random, pensez-vous que je peux simplement modifier mon programme pour ajouter les chiffres que je veux?
EDIT : J'ai changé la Random pour Scanner et ça fonctionne.
Deuxième question : mes fichiers .txt sont comme ceci :
Alors, je ne connais pas Java, mais il ressemble à d'autres langages comme C ou C++ Si j'ai bien compris, ton fichier contient 38 nombres de 0 à 999 (ou plutôt 888) Le premier des 3 chiffres du nombre représente x, ... Est-ce qu'il y a le modulo en Java? x = nombre / 100; // division entière y = (nombre / 10) % 10; z = nombre % 10;
Pour tester, il faut 0 <= x < 9 et 0 <= y < 9 et 1 <= z <= 9.
En principe, on ne met pas 0 dans une case, c'est 0 par défaut, alors:
if(0 <= x && x < 9 && 0 <= y && y < 9 && 1 <= z && z <= 9) {
// faire le sudoku
} else {
// message d'erreur
// exit ...
}
edit: je t'ai un peu trop simplifié les choses.
Avant la lecture, tu peux initialiser une variable erreur = 0
Si c'est correct, tu fais a[x][y] = z
Sinon, tu fais erreur++;
Quand tu as tout lu et avant d'essayer de résoudre, tu testes si erreur == 0 ou pas Pour recopier a dans b ,pourquoi ne peux-tu pas faire: for(int i = 0; i < 9; i++) { for(int j = 0; j < 9; j++) { b[i][j] = a[i][j]; } }
- Edité par PierrotLeFou 17 mai 2022 à 3:52:00
Le Tout est souvent plus grand que la somme de ses parties.
Autre solution, lire les positions des chiffres sous forme de chaînes de 3 caractères, au lieu d'entiers.
Merci de remplacer les 81 affectations par une boucle, ca fait mal aux yeux. Et il faut décomposer ce main qui fait tout en méthodes qui ne font qu'une chose (dialogue utilisateur, lecture des données dans fichier, affichage, exécution d'une partie,...), mais le font bien.
Programmer, c'est realiser un programme qui fait ce qu'on veut, en combinant les trucs de base que nous fournit le langage. En general il en faut un certain nombre pour faire le boulot, alors la difficulté c'est de construire ça sans s'y perdre.
Et pour ça, il faut organiser le code. Le découpage en méthodes, c'est une manière d'arriver rapidement à ce que ça marche. Pas un truc pour faire joli qu'on se garde pour la fin, le jour où ça marchera.
j'imagine le temps pris pour ecrire ses affectation
scanner.nextLine() pour avoir la ligne ( je suppose que tout est sur la meme ligne)
ensuite tu fais un split par espace sur la chaine retourné car si j'ai bien lu c'est sous le format xyz xyz xyz....
ensuite tu fais une boucle sur le résultat du String.split(" ")
sur chaque string retourné un ta_chaine.toCharArray() pour le passer en tableau de caractère et donc les indices 0 1 et 3 contiendrait x y et z
edit : les indices 0-1-2
ca marchera uniquement si chacun des x y z font toujours 1 caractères je ne connais pas sudoku mais je pense vu ce que tu as mis que 1 caractère suffit
Au départ on ne s'embête pas avec un fichier, on charge la grille à partir d'une chaine.Et on la fait écrire pour vérifier.
public static void main(String[] args) {
var donnees = "001 016 325 632 551 889";
var grille = new int[9][9];
remplir_grille(grille, donnees);
afficher_grille(grille);
}
On prendra les données dans un fichier plus tard.
Un Scanner peut prendre ses données dans une chaîne, pas seulement dans un fichier. Ne nous en privons pas
/**
* Ajoute dans la grille les valeurs indiquées par la chaine de données :
* pour chaque case un entier avec son numero de ligne et de colonne
* entre 0 et 8, et la valeur entre 1 et 9.
* @param grille
* @param donnees
*/
private static void remplir_grille(int[][] grille, String donnees) {
var scanner = new Scanner(donnees);
while (scanner.hasNextInt()) {
var element = scanner.nextInt();
var l = element / 100;
var c =(element / 10) % 10;
var v = element % 10;
grille[l][c] = v;
}
}
Remarque : on appelle les numéros de ligne et de colonnes l et c, parce que c'est plus simple à comprendre que i et j.
Pour l'affichage on se permet des fantaisies, une barre de séparation horizontale / verticale toutes les 3 cases.
On met un point pour les cases qui ont la valeur 0 (qui représentent une case vide)
private static void afficher_grille(int[][] grille) {
final String separation = "+---------+---------+---------+";
System.out.println(separation);
for (int l = 0; l < 9; l++) {
System.out.print("|");
for (int c = 0; c < 9; c++) {
if (grille[l][c] == 0) {
System.out.print(" . ");
} else {
System.out.format(" %d ", grille[l][c]);
}
if (c % 3 == 2) {
System.out.print("|");
}
}
System.out.println();
if (l % 3 == 2) {
System.out.println(separation);
}
}
}
à part ça tu nous a balancé du code, mais tu ne nous a pas dit ce qu'il était censé faire exactement. Vérifier le contenu d'un fichier de données ? c-a-d que toutes les cases y sont indiquées une fois et une seule, avec un contenu entre 1 et 9 ?
@michelbillaud: AbridgedRiver76parle bien d'un Sudoku. Il serait souhaitable d'apprendre et de comprendre la récursivité. Il ne s'agit pas pour l'instant de faire du code sophistiqué. Une simple force brute suffira.
Le Tout est souvent plus grand que la somme de ses parties.
Je dois faire un Sudoku qui utilise des fichiers .txt et je dois le transformer en tableau 9x9.
bon juste une petite remarque pourquoi ne pas utiliser csv au lieu de txt tu peux regarder opencsv pour java mais si tu est debutant je ne sais si tu vas sortir avec cet lib , justement csv va resoudre ta plus grande partit de ton probleme donc moi je ne conseil opencsv bien qu'il faudrait apprendre a utilise un package manager pour java et a l'installer et bien sur a l'utiliser
une autre remarque : dans le milieu professionnel il faudra apprendre (malheuresement chers francophone) a parler anglais et a coder en anglais
Je ne vois pas l'intérêt d'utiliser un fichier CSV. Un fichier .txt se gère très facilement. Sa ligne est un peu longue. J'espère que son éditeur peut la prendre. Avec Bloc-Notes (Notepad) sur Windows, on peut gérer beaucoup plus long.
On peut également utiliser le format suivant que j'ai parfois rencontré sur certains sites: 4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........ On linéarise la grille de telle sorte que les positions (i*9, i*9+8) représentent une ligne (i=0 à 8) Pour un débutant, ce n'est pas si mauvais d'écrire en français. Ça évite d'utiliser les mots clés du langage comme variable. Par exemple: new Ou un fichier copy.py en Python ...
- Edité par PierrotLeFou 18 mai 2022 à 0:59:08
Le Tout est souvent plus grand que la somme de ses parties.
c'est a dire qu'avec une lib csv java, elle va checker si il y a le meme nombre de colone dans chaque line ce qui te facilite le travail pour checker si c'est un sudoku
TheSmiley a écrit:
une autre remarque : dans le milieu professionnel il faudra apprendre (malheuresement chers francophone) a parler anglais et a coder en anglais
On peut également utiliser le format suivant que j'ai parfois rencontré sur certains sites: 4...3.......6..8..........1....5..9..8....6...7.2........1.27..5.3....4.9........
Si on rajoute l'idée d'ignorer tous les caractères sauf les points et les chiffres, ça permet de présenter les données sous une forme tout à fait naturelle
à part ça tu nous a balancé du code, mais tu ne nous a pas dit ce qu'il était censé faire exactement. Vérifier le contenu d'un fichier de données ? c-a-d que toutes les cases y sont indiquées une fois et une seule, avec un contenu entre 1 et 9 ?
Effectivement, j'ai omis quelques informations! Je vais donc vous copier-coller toutes les informations que j'ai
Problème
Dans un jeu de Sudoku, nous devons re-construire une grille comprenant 9 rangées et 9 colonnes. Chaque rangée et chaque colonne doit contenir tous les entiers de 1 à 9.
Vous devez créer un logiciel qui permet de charger des grilles de Sudoku à partir de fichiers, de manipuler les grilles (placements, vérifications), puis enfin de reproduire de nouveau les grilles soit à l’écran soit dans des fichiers. Les fichiers de Sudoku comportent une suite de triplets de chiffres séparés par des espaces, où chaque triplet correspond à :
x: numéro de la ligne.
y: numéro de la colonne.
z: valeur
En informatique, on numérote le plus souvent des colonnes et des rangées en commençant par zéro.
Dans ces exemples, les données ne sont pas nécessairement correctes. C’est votre travail de créer un programme qui peut traiter les erreurs.
Fonctionnalités/classes demandées Votre programme doit faire trois opérations spécifiques:
Charger un fichier contenant des données selon le format spécifié (une suite de triplets de chiffres séparés par des espaces). Vous pouvez choisir l’approche que vous préférez. Le fichier peut être récupéré en ligne, par l’ouverture d’un fichier sur votre disque ou par l’entrée standard (<tt>stdin</tt>). Votre code doit gérer les erreurs de lecture.
Valider que le ficher correspond à un tableau Sudoku valable. C’est-à-dire qu’il doit correspondre à un tableau 9×9 où chaque chiffre de 1 à 9 apparaît une seule fois par colonne et une seule fois par rangée. Pour les fins de ce travail, nous n’exigeons pas que chaque sous-grille de 3×3 contienne tous les chiffres de 1 à 9 (vous pouvez cependant faire cette vérification supplémentaire si vous le souhaitez). En cas d’erreur, votre programme doit générer une exception.
Votre programme doit ensuite appliquer une transposition au tableau correspondant à un calcul de matrice transposée et afficher le résultat à l’écran. Au lieu de l’afficher à l’écran, vous (en tant que programmeur) pouvez l’enregistrer comme nouveau fichier ou utiliser un autre moyen de transmission. Choisissez l’approche qui vous plaît le plus en tant que programmeur. Vous devez tester votre solution avec plus d’une grille; en particulier, incluez une grille qui est asymétrique (qui n’est pas identique à sa transposée) dans vos tests. Donnez le résultat d’au moins deux tests différents, au-delà du fichier partie1.txt. Vous pouvez utiliser des saisies d’écran pour présenter vos résultats.
As-tu réussi à charger les fichiers et valider que les entrées sont correctes? On ne te demande pas de résoudre un Sudoku mais de valider si c'est correct. Heureusement pour toi, on ne tedemande pas de valider les carrés, seulement les lignes et les colonnes. Réfléchis tout de même sur la façon de le faire.
Je vois 4 boucles imbriquées, les 2 premières par pas de 3 sur une longueur de 9 et les 2 dernières par pas de 1 sur une longueur de 3.
Mieux encore, les carrés sont numérotés de 0 à 8. Ça te sauvera une boucle.
la ligne de départ est (numéro/3)*3 et la colonne de départ est (numéro%3)*3
edit: alors, un petit cadeau, // Je suppose que v est un tableau de booléens de longueur 10 (pour éviter de soustraire 1) for(int carre = 0; carre < 9; carre++) { // Je remet à false mon tableau de booléens: for(int i=1; i<10; i++) v[i] = false; int l0 = carre / 3 * 3; int c0 = carre % 3 * 3; for(int l=l0; l<l0+3; l++) { for(int c=c0; c<c0+3; c++) { int chiffre = a[l][c]; if(v[chiffre]) { // afficher erreur et terminé si requis } v[chiffre] = true; } } } Pour valider, on peut se faire un tableau de booléens de 9 ou 10 positions (pas de calcul d'indice)
Tu remets à false toutes les valeurs de cetableau avant chaque ligne et/ou colonne. Tu commences par valider par lignes. Pour chaque valeur rencontrée sur la ligne, tu vérifies si la case correspondante dans ton tableau de booléen est vraie (true), si oui, c'est une erreur. Ensuite, tu mets la case à vrai. Si tous les chiffres sont différents, ça ne te dira jamais que la case est vraie avant de le mettre. Et tu recommences avec les colonnes. Pour la transposition, je te suggère de transposer dans une nouvelle matrice. N'essaies pas de le faire sur place.
Dans mon premier message je t'ai presque donné la solution:
il faut juste écrire: b[j][i] = a[i][j]; As-tu du code à nous présenter?
- Edité par PierrotLeFou 23 mai 2022 à 18:32:13
Le Tout est souvent plus grand que la somme de ses parties.
As-tu réussi à charger les fichiers et valider que les entrées sont correctes?
Bon, non, je n'ai pas réussis
Je me suis aidé beaucoup des codes de michelbillaud mais je n'y arrive toujours pas! Je commence sérieusement à perdre espoire de réussir mon cours J'ai l'impression de ne pas bien assembler les morceaux du casse-tête.
Voici ce que j'ai de (re)fait en ce moment (ps: il me reste a rejouter ce que tu m'a fournis comme information pour la validation) :
package com.company;
import java.io.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
var donnees = "partie2.txt";
var grille = new int[9][9];
var chemin = "partie2.txt";
remplir_grille(grille, donnees);
afficher_grille(grille);
lire_grille(grille, chemin);
File FichierNombre1 = new File("partie2.txt");
try (
FileReader chemin1 = new FileReader(FichierNombre1);
BufferedReader in = new BufferedReader(chemin1)
) {
System.out.println(in.readLine());
} catch (IOException e) {
System.out.println("Fichier introuvable");
}
}
private static void remplir_grille(int[][] grille, String donnees) {
var scanner = new Scanner(donnees);
while (scanner.hasNextInt()) {
var element = scanner.nextInt();
var l = element / 100;
var c = (element / 10) % 10;
var v = element % 10;
grille[l][c] = v;
}
}
private static void afficher_grille(int[][] grille) {
int opt;
Scanner in = new Scanner(System.in);
System.out.println("Voulez-vous jouer? 1 = Oui 2 = Non");
opt = in.nextInt();
int p = 0;
while (p == 0) {
switch (opt) {
case 1 -> {
final String separation = "+---------+---------+---------+";
System.out.println(separation);
int c = 0;
int l;
for (l = 0; l < 9; l++) {
System.out.print("|");
for (c = 0; c < 9; c++) {
if (grille[l][c] == 0) {
System.out.print(" . ");
} else {
System.out.format(" %d ", grille[l][c]);
}
if (c % 3 == 2) {
System.out.print("|");
}
}
System.out.println();
if (l % 3 == 2) {
System.out.println(separation);
}
}
//grille[l][c] = grille[c][l];
p++;
}
case 2 -> {
System.out.println("Bonne journée");
p++;
//continue;
}
default -> {
System.out.println("Sélectionnez une option svp");
//continue;
}
}
}
}
private static void lire_grille (int[][] grille, String chemin) throws IOException {
var reader = new BufferedReader(new FileReader(chemin));
for (int l = 0; l < 9; l++) {
for (int c = 0; c < 9; c++) {
while (true) {
var ch = reader.read();
//System.out.println("car " + ch);
if (ch == '.') {
grille[l][c] = 0;
break;
} else if (Character.isDigit(ch)) {
grille[l][c] = ch - '0';
break;
}
}
}
}
}
}
Je n'ai pas saisi si tu utilisais des caractères ou des nombres. Pour les cases vides, ce sera '.' ou 0? Pour moi, la fonction remplir_grille devrait mettre des 0 dans la grille. Pourquoi ne pas appeler afficher_grille après lire_grille? Dans ton code initial, tu semblais capable de lire tes nombres à partir du fichier, je me trompe? Tu appelles: remplir_grille(grille, donnees); afficher_grille(grille); lire_grille(grille, chemin); Avant d'ouvrir le fichier. Tu ne pourras rien lire de cette façon. Ta fonction afficher_grille ne devrait faire rien d'autre que d'afficher la grille justement. Le reste tu le mets dans la fonction main. Ce que tu fais dans remplir_grille pour mettre le contenu du fichier dans la grille, tu devrais le faire dans lire_grille. La logique du programme devrait être: tant qu'on veut jouer: ouvrir le fichier suivant initialiser la grille lire la grille afficher la grille valider la grille (je sais, c'est pas fait) redemander si on veut jouer.
Le Tout est souvent plus grand que la somme de ses parties.
Dans mon code initial, j'avais que quelques chiffres qui fonctionnaient mais pas plus malheureusement.
Donc si je comprend bien, dans la fonction afficher_grille je garde que la mise en forme de la grille et ma boucle je l'envoie dans le main. Je comprend que tu veux que je fusionne les deux méthodes remplir_grille et lire_grille? J'ai mis mon ouverture de ficher avant remplir_grille dans le main.
Avec les quelques changements :
package com.company;
import java.io.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws IOException {
File FichierNombre1 = new File("partie2.txt");
try (
FileReader chemin1 = new FileReader(FichierNombre1);
BufferedReader in = new BufferedReader(chemin1)
) {
System.out.println(in.readLine());
} catch (IOException e) {
System.out.println("Fichier introuvable");
}
var donnees = "partie2.txt";
var grille = new int[9][9];
var chemin = "partie2.txt";
//remplir_grille(grille, donnees);
int p = 0;
Scanner r = new Scanner(FichierNombre1);
int i1=r.nextInt(8);
while (p == 0) {
int x = i1, v = 0;
int[][] a = new int[9][9];
int[][] b = new int[9][9];
for (int l = 0; l < 9; l++) {
for (int c = 0; c < 9; c++) {
if ((x + c + v) <= 9)
a[l][c] = c + x + v;
else
a[l][c] = c + x + v - 9;
if (a[l][c] == 10)
a[l][c] = 1;
}
x += 3;
if (x >= 9)
x = x - 9;
if (l == 2) {
v = 2;
x = i1;
}
if (l == 5) {
v = 3;
x = i1;
}
}
int opt;
Scanner in = new Scanner(System.in);
System.out.println("Voulez-vous jouer? 1 = Oui 2 = Non");
opt = in.nextInt();
switch (opt) {
case 1 -> {
afficher_grille(grille);
for (int l = 0; l < 9; l++) {
for (int c = 0; c < 9; c++) {
b[l][c] = a[c][l];
lire_grille(grille, chemin, donnees);
}
}
p++;
}
case 2 -> {
System.out.println("Bonne journée");
p++;
continue;
}
default -> {
System.out.println("Sélectionnez une option svp");
continue;
}
}
for (int y = 0; y < 9; y++) {
for (int z = 0; z < 9; z++) {
System.out.print(b[y][z] + " ");
}
System.out.println("");
}
}
}
//private static void remplir_grille(int[][] grille, String donnees) {
// var scanner = new Scanner(donnees);
// while (scanner.hasNextInt()) {
// var element = scanner.nextInt();
// var l = element / 100;
// var c = (element / 10) % 10;
// var v = element % 10;
// grille[l][c] = v;
// }
//}
private static void lire_grille (int[][] grille, String chemin, String donnees) throws IOException {
var reader = new BufferedReader(new FileReader(chemin));
var scanner = new Scanner(donnees);
//for (int l = 0; l < 9; l++) {
//for (int c = 0; c < 9; c++) {
while (scanner.hasNextInt()) {
var ch = reader.read();
var element = scanner.nextInt();
var l = element / 100;
var c = (element / 10) % 10;
var v = element % 10;
grille[l][c] = v;
//System.out.println("car " + ch);
if (ch == '.') {
grille[l][c] = 0;
break;
} else if (Character.isDigit(ch)) {
grille[l][c] = ch - '0';
break;
}
}
// }
//}
}
private static void afficher_grille(int[][] grille) {
final String separation = "+---------+---------+---------+";
System.out.println(separation);
for (int l = 0; l < 9; l++) {
System.out.print("|");
for (int c = 0; c < 9; c++) {
if (grille[l][c] == 0) {
System.out.print(" . ");
} else {
System.out.format(" %d ", grille[l][c]);
}
if (c % 3 == 2) {
System.out.print("|");
}
}
System.out.println();
if (l % 3 == 2) {
System.out.println(separation);
}
}
}
}
Ton main, c'est le bazar (+ de 60 lignes). A decouper en méthodes qui ont chacune un rôle clairement identifiable.
Écris une méthode qui fait la lecture d'une grille dans un fichier, et lance une exception si les données sont invalides. C'est ce qu'on te demande.
Il y a plusieurs cas : données non numériques, ligne ou colonne qui vaut 9, case qui vaut 0, case déjà remplie, violation de contrainte ligne/colonne/bloc...
Ta cuisine avec la variable x, tu peux expliquer ?
Pour la vérification par bloc quand on a ajouté en (l,c)
Trouver les indices du coin du bloc (bl, bc)
Le bloc contient les cases (bl+i, bc+j) pour i et j entre 0 et 2
Bl s'obtient en arrondissant l au multiple de 3 inférieur.
Pour transposer (sur place), échanger les contenus de (l,c) et (c,l), .... pour l < c. Dans une méthode à part.
Je ne comprend pas ce que tu veux faire avec ce code: if ((x + c + v) <= 9) a[l][c] = c + x + v; else a[l][c] = c + x + v - 9; ... et bien d'autres lignes ... calculs étranges ?
Pour remplir la grille au début avant de lire le fichier: for(int l=0; l<9; l++) { for(int c=0; c<9; c++) { a[i][j] = 0; } }
Après que tu l'as remplie de cette façon, tu lis les valeurs du fichier sous forme de triplets de chiffres. Et tu fais le calcul que j'ai montré et qui se trouve dans lire_grille.
private static void lire_grille (int[][] grille, String chemin, String donnees) throws IOException { var reader = new BufferedReader(new FileReader(chemin)); var scanner = new Scanner(donnees); while (scanner.hasNextInt()) { var ch = reader.read(); var element = scanner.nextInt(); var l = element / 100; var c = (element / 10) % 10; var v = element % 10; grille[l][c] = v; } }
private static void afficher_grille(int[][] grille) { final String separation = "+---------+---------+---------+"; System.out.println(separation); for (int l = 0; l < 9; l++) { System.out.print("|"); for (int c = 0; c < 9; c++) { if (grille[l][c] == 0) { System.out.print(" . "); } else { System.out.format(" %d ", grille[l][c]); } if (c % 3 == 2) { System.out.print("|"); } } System.out.println(); if (l % 3 == 2) { System.out.println(separation); } } } }
- Edité par PierrotLeFou 29 mai 2022 à 3:55:24
Le Tout est souvent plus grand que la somme de ses parties.
Problème lecture de fichier .txt
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Le Tout est souvent plus grand que la somme de ses parties.
yasakani no magatama
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.
Le Tout est souvent plus grand que la somme de ses parties.