Liste chaînée personnalisée contenant des éléments indésirables
-
22-12-2019 - |
Question
J'ai créé une liste chaînée personnalisée et des classes de nœuds pour l'école et j'ai décidé de m'entraîner à l'utiliser en créant un jeu de type text-twist.
Dans ma classe de liste chaînée, j'ai une méthode traversée qui imprime le mot et la durée pendant laquelle le mot reste dans la console.
Le code que j'ai jusqu'à présent est le suivant :
MaListeLinkée.java
package game;
public class MyLinkedList {
public int counter;
public MyNode head;
public MyNode tail;
public MyLinkedList() {
counter = 0;
}
public void InsertToHead(MyNode m) {
if (counter == 0) {
head = tail = m;
} else {
m.setNext(head);
head.setPrev(m);
head = m;
}
counter++;
}
public int size() {
return counter;
}
public boolean isEmpty() {
if (counter == 0) {
return true;
} else {
return false;
}
}
public MyNode retrieveWord(String s) {
MyNode n = head;
while (n.next != null) {
if (s.equals(n.getWord())) {
return n;
} else {
n = n.next;
}
}
if (s.equals(tail.getWord())) {
return tail;
}
return null;
}
public MyNode retrieveLength(int l) {
MyNode n = head;
while (n.next != null) {
if (l == n.getLength()) {
return n;
} else {
n = n.next;
}
}
if (l == tail.getLength()) {
return tail;
}
return null;
}
public void traverse() {
MyNode n = head;
if (head != null) {
while (n.next != null) {
System.out.println(n.getWord() + "\t" + n.getLength());
n = n.next;
}
System.out.println(tail.getWord() + "\t" + n.getLength());
}
}
}
MonNode.java
package game;
public class MyNode {
public String word;
public int length;
public MyNode next, previous;
public MyNode() {
word = null;
length = 0;
next = null;
previous = null;
}
public MyNode(String w, int l) {
word = w;
length = l;
next = null;
previous = null;
}
public void setNext(MyNode n) {
next = n;
}
public void setPrev(MyNode n) {
previous = n;
}
public void toHead(MyNode n){
while(n.previous != null){
n.setPrev(n);
}
}
public void setWord(String w){
word = w;
}
public String getWord(){
return word;
}
public void setLength(int l){
length = l;
}
public int getLength(){
return length;
}
public boolean hasNext(){
return next != null;
}
}
Tri des mots.java
package game;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class WordSort {
Scanner wordScan;
public WordSort() {
MyLinkedList sixLetters = new MyLinkedList();
MyLinkedList fiveLetters = new MyLinkedList();
MyLinkedList fourLetters = new MyLinkedList();
MyLinkedList threeLetters = new MyLinkedList();
MyLinkedList rejects = new MyLinkedList();
try {
wordScan = new Scanner(new File("corncob_lowercase.txt"));
wordScan.useDelimiter("\r\n");
MyLinkedList ll = new MyLinkedList();
while (wordScan.hasNext()) {
String temp = wordScan.next();
MyNode node = new MyNode();
node.setWord(temp);
node.setLength(temp.length());
ll.InsertToHead(node);
if (temp.length() == 6) {
sixLetters.InsertToHead(node);
} else if (temp.length() == 5) {
fiveLetters.InsertToHead(node);
} else if (temp.length() == 4) {
fourLetters.InsertToHead(node);
} else if (temp.length() == 3) {
threeLetters.InsertToHead(node);
} else {
rejects.InsertToHead(node);
}
}
wordScan.close();
threeLetters.traverse();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("Missing File: corncob_lowercase.txt");
}
}
}
et enfin, Driver.java
package game;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Driver extends JPanel {
private static final long serialVersionUID = 1L;
public Driver() {
new WordSort();
}
public static void main(String[] args) {
JFrame frame = new JFrame("Hidden Word");
frame.setSize(500, 500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new Driver());
frame.setVisible(true);
}
}
Chaque fois que j'exécute ce code, toutes les listes chaînées (threeLetters
, fourLetters
, fiveLetters
, et sixLetters
) vont tout à fait bien jusqu'à la toute fin, quand threeLetters.traverse()
est appelé, j'obtiens cette sortie (uniquement la partie finale)
act 3
ace 3
aby 3
abe 3
abducts 7
abductors 9
abductor 8
abductions 10
abduction 9
abducting 9
abducted 8
abdominal 9
abdomens 8
abdomen 7
abdication 10
abdicating 10
abdicates 9
abdicated 9
abdicate 8
abbreviations 13
abbreviation 12
abbreviating 12
abbreviates 11
abbreviated 11
abbreviate 10
abattoirs 9
abattoir 8
abatement 9
abashed 7
abasement 9
abandons 8
abandonment 11
abandoned 9
abandon 7
abalone 7
aardwolf 8
abe 8
Je n'arrive pas à comprendre pourquoi cela se produit, mais on dirait que tout s'imprime après abe
et ça imprime abe
deux fois, une fois avec 3 lettres et une fois avec 8 lettres !
J'ai récupéré le fichier texte sur ce site :
La solution
Votre problème ici est principalement un problème de conception.Le principal défaut :essayer d'utiliser une instance MyNode
dans plusieurs listes chaînées.
Lorsque vous InsertToHead(node)
vous modifiez le contenu de node
lui-même, en particulier la tête et les références suivantes.
Réparer:Déclarez simplement un new MyNode
pour chaque LinkedList dans laquelle vous souhaitez l'utiliser.Dans votre projet en particulier, vous en utilisez deux pour un nœud donné. ll
et l'un des <inset_number>Letters
listes.Alors déclarez un nouveau MyNode
pour chaque liste :
...
while (wordScan.hasNext()) {
String temp = wordScan.next();
MyNode node = new MyNode();
MyNode node2 = new MyNode();
node.setWord(temp);
node2.setWord(temp);
node.setLength(temp.length());
node2.setLength(temp.length());
ll.InsertToHead(node2);
...
Cela devrait résoudre votre problème.
Si vous voulez savoir POURQUOI cela se produisait.Tracez le code.Il s'agit de tenter d'ajouter des nœuds qui ont déjà des nœuds supplémentaires attachés dans une liste.
Notes complémentaires:
Faites de votre mieux pour éviter
public
champs sauf si vous êtes SÛR de les vouloir.C'EST À DIRE.dansMyLinkedList
quelqu'un utilisant votre classe ne devrait pas pouvoir accéder (ou même voir !) lecounter
,head
outail
, donc ceux-ci devraient être faitsprivate
.Si vous voulez vraiment y accéder, créezget
etset
méthodesVotre imbriqué si bloque
WordSort
est un endroit parfait pour un changer comme ça:switch(temp.length()) { case 6: sixLetters.InsertToHead(node); break; case 5: fiveLetters.InsertToHead(node); break; case 4: fourLetters.InsertToHead(node); break; case 3: threeLetters.InsertToHead(node); break; default: rejects.InsertToHead(node); break; }
MyNode fonctionne bien en tant que classe distincte.Cependant, je choisirai souvent d'implémenter une classe simple comme un nœud en tant que classe imbriquée.Cela peut donner lieu à du code très propre.Essaye le!
Soyez prudent lors de la conception de vos cours.Il existe de nombreuses méthodes supplémentaires dans votre conception.Il peut être facile d’avancer en créant des méthodes que vous n’utiliserez peut-être jamais ou non.J'aime créer des méthodes uniquement lorsque je vois que j'en ai besoin dans une classe qui utilise la classe en question.
Bon codage !