Schau mal hier.
Da hat jemand schon so ein Tool gebastelt.
Mfg evo2
Hi,
da ich noch nicht viel mit Datenbanken gearbeitet habe, möchte ich hier einfach mal nachfragen, ob mein DB-Design ok ist.
Ziel meiner DB gestützen Anwendung soll eine Art Fragebogen sein, indem der Anwender sich bei Computerproblemen selbst helfen kann.
z.Bsp: Anwender fragt, warum der Sound an seinem Rechner nicht funktioniert und er muß sich dann durch verschiedene Fragen (Boxen eingeschaltet, Treiber installiert, usw.) klicken, ähnlich wie bei der Windows Hilfe.
Außerdem soll der Weg, der zu einer Lösung des Problems geführt hat ebenfalls in einer Tabelle gespeichert werden.
So nun mein DB Design:
Habe an 3 Tabellen gedacht:
Fragenkatalog - Beinhalten die Fragen (incl. Hauptkategorien(Hardware/Software)
Kategorien - Beinhaltet die verschiedenen Kategorieklassen (1 = Hardware, 2 = Software, 3 = Subkategorie 1 usw.)
Loesung - Hier soll die Reihenfolge der Fragen gespeichert werden, nachdem eine bestimmte Reihenfolge zum Ziel geführt hat
Wie gesagt, hab noch nicht viel mit Datenbanken gemacht, also nicht gleich schlagen 😉
Danke schonmal im vorraus.
Mfg
evo2
Hi,
hab letztens auch sowas gebraucht.
Ist sicherlich nicht die schönste Art und Weise das zu bewerkstelligen, aber es funktioniert(hoffe ich 🙂 )
Hab da einiges im Internet gefunden und auch einiges selber gemacht.
Vielleicht hilf es ja.
private void button1_Click(object sender, EventArgs e)
{
DateTime dLastReboot = LastReboot();
MessageBox.Show("Letzter Neustart: " + dLastReboot.ToString() + "\n" +
"Uptime: " + Uptime(dLastReboot));
}
private DateTime LastReboot()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\cimv2", "Select * from Win32_OperatingSystem");
DateTime dLastReboot = DateTime.Now ;
foreach (ManagementObject queryObj in searcher.Get())
{
dLastReboot = fixdate((String)queryObj["LastBootUpTime"]);
}
return dLastReboot;
}
private string Uptime(DateTime dLastReboot)
{
DateTime dNow = DateTime.Now;
TimeSpan dUptime = dNow.Subtract(dLastReboot);
string sUptime = "Tage: " + dUptime.Days + " Stunden: " + dUptime.Hours +
" Minuten: " + dUptime.Minutes + " Sekunden: " + dUptime.Seconds;
return sUptime;
}
private DateTime fixdate(String sLastReboot)
{
String sJahr = sLastReboot.Substring(0, 4);
String sMonat = sLastReboot.Substring(4, 2);
String sTag = sLastReboot.Substring(6, 2);
String sStunde = sLastReboot.Substring(8, 2);
String sMinute = sLastReboot.Substring(10, 2);
String sSekunde = sLastReboot.Substring(12, 2);
return DateTime.Parse(sTag + "." + sMonat + "." + sJahr + " " + sStunde + ":" + sMinute + ":" + sSekunde);
}
Mfg.
evo2
Hoi,
ich versuche mich grad an einer Listview, in der man einzelne Columns ein bzw ausblenden kann und das in einer xml Datei gespeichert wird.
Hab mich für den Anfang an Save ListView settings orientiert, aber da wird das ganze in der Registry gespeichert und funktioniert so auch nicht mit xaml.
Die einzelnen Daten aus der XML Datei zu laden klappt soweit ganz gut. Hab das DataBinding an die Listview nun auch hinbekommen(aber wahrscheinlich etwas umständlich).
Mein XML Datei ist wie folgt aufgebaut:
<ArrayOfColumns_Manage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Columns_Manage>
<Name>PID</Name>
<Position>0</Position>
<Width>20</Width>
<Show>true</Show>
<Required>true</Required>
</Columns_Manage>
...
</ArrayOfColumns_Manage>
Das ist mein struct:
[Serializable]
public struct Columns_Manage
{
private string m_Name;
public string Name
{
get { return m_Name; }
set { m_Name = value; }
}
private int m_Position;
public int Position
{
get { return m_Position; }
set { m_Position = value; }
}
private int m_Width;
public int Width
{
get { return m_Width; }
set { m_Width = value; }
}
private bool m_Show;
public bool Show
{
get { return m_Show; }
set { m_Show = value; }
}
private bool m_Required;
public bool Required
{
get { return m_Required; }
set { m_Required = value; }
}
public Columns_Manage(string Name, int Position, int Width, bool Show, bool Required)
{
m_Name = Name;
m_Position = Position;
m_Width = Width;
m_Show = Show;
m_Required = Required;
}
}
Und so hole ich die Daten aus der XML Datei:
XmlSerializer xmlSer = new XmlSerializer(typeof(Columns_Manage[]));
FileStream stream = new FileStream(xmlDocPath + file, FileMode.Open);
m_Columns = (Columns_Manage[])xmlSer.Deserialize(stream);
stream.Close();
So nun zu meinen eigentlichen Fragen 😉
ObservableCollection<Columns_Manage> m_columns =
new ObservableCollection<Columns_Manage>();
XMLData xml = new XMLData();
public ColumnSettings()
{
//ObservableCollection füllen
foreach (Columns_Manage col in xml.m_Columns)
{
m_columns.Add(new Columns_Manage(
col.Name, col.Position, col.Width, col.Show, col.Required));
}
InitializeComponent();
listView1.ItemsSource = m_columns;
Ist das die normale Art eine ObservableCollection zu befüllen? Oder kann man dieses irgendwie anders/besser bewerkstelligen?
XAML
<CheckBox Margin="1,0,5,2" VerticalAlignment="Center"
IsChecked="{Binding Mode=TwoWay, Path=Show, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="{Binding Path=Name}"/>
Ich habe beim Databinding den Mode=TwoWay. Sprich, wenn jetzt ein Häckchen gesetzt bzw entfernt wird, sollte ich das ja nun irgendwie abfangen können. Nur wie?
Ist zwar ein bißel viel Text/Code für die kleine Frage, aber ich wollte es gut verdeutlichen 🙂
Ich hoffe mir kann da jemand ein Tipp geben bzw mich in die richtige Richtung schubsen.
Schonmal danke im vorraus.
Mfg
evo2
Hi,
ich bekomme sekündlich ca 30 Daten zu einer ID.
Die ID's können sich ändern, welche hinzukommen bzw welche wegfallen.
Die Anzahl der ID's schwankt dann zwischen 10 und 100(mit jeweils 30 Daten)
Nun zu meiner eigentlichen Frage.
Macht es hierbei Sinn die Daten in verschachtelte Hashtables bzw Dictionarys zu packen?
Dictionary<int, Dictionary<String, Dictionary<String, Dictionary<String, Dictionay<usw....>>>>>
Oder wär es hierbei besser die Sachen in ein Array oder ähnliches zu legen?
Wichtig dabei ist, das die Daten schnell gesucht und aktualisiert werden können.
Mfg
evo2
Hi,
anhand der Dateinamen wirst du sicherlich vieles finden. Aber das Problem wird sein, wenn im Dateinamen kein Setup, Install bzw *.msi vorkommt.
Außerdem könnte man noch prüfen ob der Windows Installer gestartet wird.
Was du dann noch machen könntest, per wmi die installierte Software zu überprüfen, ob was neues vorhanden ist. Das ist zwar dann schon zu spät, da das Programm bereits installiert ist, aber du könntest ja versuchen die zugehörige Uninstall.exe sofort wieder ausführen zu lassen.
Ist zwar nicht der eleganteste Weg, aber ich wüsste sonst nicht wie man das gestalten könnte.
Hab eben nochmal schnell gegoogelt und überlegt, ob man anhand der Hex Signatur einer Datei auf des Inhalt schließen kann, aber das bringt eher weniger.
Dabei hab ich gesehen, dass die MS Installer meistens eine digitale Signatur haben.
Man müsste ja jetzt nur diese Auswerten, wenn die nicht von MS ist, dann aus die Maus 😉
mfg
evo2
Kannst dir ja mal Yet Another Multicolumn Layout angucken.
Das verwende ich immer als Grundlage und läßt sich auch prima modifizieren.
Kurzbeschreibung YAML:
"Yet Another Multicolumn Layout" (kurz YAML) ist ein (X)HTML/CSS Framework zur Erstellung moderner und flexibler Layouts auf Grundlage von float-Umgebungen. Dabei stehen ein möglichst hohes Maß an Flexibilität für den Webdesigner und Zugänglichkeit für die Nutzer im Vordergrund. Innerhalb eines Tutorials wird die Funktionsweise der einzelnen Bausteine erläutert.
Mfg
evo2
Hi SimonKnight6600,
ich habe dein Programm getestet.
Ist eine praktische Sache um Programme deiner Gruppe immer Up2Date zu halten.
Habe da aber gleich einen Bug entdeckt.
Sobald man ein installiertes Programm offen hat und im Software Manager auf Deinstallieren klickt, kommt eine Fehlermeldung und der Software Manager schmiert ab(mit dem Fehler das die Datei nicht gelöscht werden konnte, was ja logisch ist, da ich diese ja offen habe).
Beim nächstes Starten zeigt er das Programm als nicht installiert an. Es ist aber noch da und man kann es ja auch noch starten.
Was noch fehlt wäre vielleicht, dass man einen Ordner aussuchen kann, wo man die ganze Tools hininstallieren möchte.
Mfg
evo2
Danke, hab es jetzt hinbekommen.
Sieht jetzt so aus:
while (Daten.Read())
{
HyperLink h = new HyperLink();
h.ID = "NavMain" + i;
h.Text = Daten.GetString(1);
h.NavigateUrl = Daten.GetString(6);
h.ToolTip = Daten.GetString(2);
CheckActiveLink(h);
Page.Master.FindControl("NavMain").Controls.Add(h);
Page.Master.FindControl("NavMain").Controls.Add(new LiteralControl("</li>"));
i++;
}
Mfg
evo2.
Hi,
danke erstmal für deine Antwort.
Hab da aber noch ein kleines Problem bzw weiß nicht genau, wie ich das anstellen soll.
Hab in meiner Masterpage ein folgenden Placeholder erstellt:
<asp:contentPlaceHolder ID=TopNav2 runat="server">
</asp:contentPlaceHolder>
dann hab ich ein Codefile in meiner Defaultpage erstellt und wollte dann mit
TopNav2.Controls.Add(button); meine Buttons hinzufügen.
Nur findet er hier den Placeholder TopNav2 nicht. Auch wenn ich das Codefile in der Masterpage verwende. Wo liegt mein Fehler?
Mfg
evo2
Hi,
ich probier seit ein paar Tagen mit ASP.Net rum.
Jetzt wollte ich ein dynamisches Menü erzeugen, sprich die Menüs sind in einer DaBa gespeichert und werden von dort aus geladen.
In meiner Masterpage liegt das Menü und soll auch dort erzeugt werden, da die Submenüs je nach Seite ändern.
Ich hab das wie folgt gemacht:
protected void Page_Load(object sender, System.EventArgs e)
{
string select = "SELECT * FROM menu WHERE nav_main = '1'";
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
SqlDataReader Daten;
conn.Open();
SqlCommand cmd = new SqlCommand(select, conn);
Daten = cmd.ExecuteReader();
int i = 0;
while (Daten.Read())
{
string test = Daten.GetString(1);
TopNav += "<li>";
TopNav += "<asp:HyperLink ID='TopNavLink" + i + "' runat='server' Text='" + Daten.GetString(1) + "' NavigateUrl='"
+ Daten.GetString(6) + "' ToolTip='" + Daten.GetString(2) + "' />";
TopNav += "</li>";
i++;
}
Anzahl = Daten.FieldCount;
conn.Close();
}
Dadurch hab ich ja in dem string TopNav mein Menü. Nur wird dieses nicht angezeigt.
Wenn ich mir dann im Browser den Quelltext anschaue, steht das ganze auch so drin:
<asp:HyperLink ID='TopNavLink0' runat='server' Text='Startseite' NavigateUrl='default.aspx' ToolTip='Startseite' />
Hat da jemand eine Idee woran das liegen könnte bzw wie es eventuell einfacher zu handeln wäre?
Und wie gesagt bin neu in Sachen ASP/ASP net also nicht gleich steinigen 😉
Mfg
evo2
Hab ich bereits probiert, aber sobald kein Treiber für den Monitor, also der Monitor auf Standard Monitor eingestellt ist, bekommt man bei der Abfrage keine Daten zurück.
Per Registry sind die Daten jedoch vorhanden.
Deswegen der Umweg über die Registry
mfg
evo2
Hi.
Bin grad dabei ein Programm zur PC-Inventarisierung zu schreiben.
Funktioniert soweit auch ganz gut. Die meisten Daten rufe ich per WMI ab, aber auch einige aus er Registry.
Jetzt hänge ich aber bei den EDID(Monitor) Daten aus der Registry.
Den Wert aus der Registry kann ich ohne Probleme Remote und lokal lesen. Nur weiß ich nicht genau, wie ich den weiterverarbeiten kann.
Hier mein Code:
//Monitorinformationen auslesen
public string MonitorInfo(string IP)
{
string monitorinfo = "";
string[] test = null;
string[] test5 = null;
string test6 = "";
byte[] EDID = null;
RegistryKey environmentKey = null;
string subkey = "SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\";
try
{
//Entsprechenden Subkey öffnen
environmentKey = RegistryKey.OpenRemoteBaseKey(
RegistryHive.LocalMachine, IP).OpenSubKey(subkey);
//alle SubkeyNamen lesen
test = environmentKey.GetSubKeyNames();
//alle Subkeys öffnen
foreach (string test2 in test)
{
environmentKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine,
IP).OpenSubKey(subkey + test2);
test5 = environmentKey.GetSubKeyNames();
//alle Subkeys öffnen und nach dem Value Class suchen.
//dann gucken, ob Value Class = Monitor ist
foreach (string test3 in test5)
{
environmentKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine,
IP).OpenSubKey(subkey + test2 + "\\" + test3);
test6 = Convert.ToString( environmentKey.GetValue("Class"));
//MessageBox.Show(test6);
if (test6 == "Monitor")
{
monitorinfo += Convert.ToString(environmentKey.GetValue("DeviceDesc")) + "\n";
monitorinfo += Convert.ToString(environmentKey.GetValue("Mfg")) + "\n";
//In Subkey "\\Device Parameters" wechseln
//Dort dann den Edid Wert abfragen(in Bytes)
environmentKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, IP).OpenSubKey(subkey + test2 + "\\" + test3 + "\\Device Parameters");
EDID = environmentKey.GetValue("EDID") as byte[];
//Editwert in String konvertieren(Hex)
string EDIDString = "";
for (int i = 0; i < EDID.Length; i++)
{
EDIDString += EDID[i].ToString("X2");
}
//EDITString sieht dann Beispielsweise so aus:
//"00FFFFFFFFFFFF000E115313323830412A0901020E241B96E90C
//C2A057479B2712484FFFFF80315945596159714F8199A959C14FD1
//404E0C80C0205E5F10204003085E04110000..."
}
}
}
}
catch (IOException ex)
{
MessageBox.Show(Convert.ToString(ex.Message));
}
environmentKey.Close();
//Datenzurückgeben
return monitorinfo;
}
Wie man sehen kann, gucke ich erst, welcher Subkey auch zu einem Monitor gehört und wechsel dann erst in den Subkey "Device Parameters". Dort frage ich dann den EDID Wert ab, in dem verschiedene Daten gespeichert sind.
Welche Werte gespeichert sind sieht man hier:
http://en.wikipedia.org/wiki/EDID
Jetzt hab ich schon einiges probiert, weiß aber absolut nicht, wie ich die Daten dann in Klartext bekomme. Zum Beispiel sollte als Manufacturer ID in meinem Fall HWP für Hewlett Packard rausgekommen, aber ich erhalte immer nur Sachen wie ein Viereck und ähnliches.
Vielleicht hat einer von euch schon einmal die EDID Daten abgefragt und kann mir einen Tipp geben.
Danke schonmal im vorraus.
Mfg
evo2
Hallo.
Hatte das auch zuerst mit regex probiert, aber nicht so recht hinbekommen.
Deswegen hab ich "meinen" Weg eingeschlagen.
mfg
evo2
so hab mir da jetzt mal was gebastelt. Ist sicherlich nicht der beste Code, aber funktioniert soweit 😉
Hab erstmal zum testen alles auf string gelassen, muß dann noch konvertiert werden und das Datum/Zeit richtig dargestellt werden, aber es wird erstmal alles getrennt.
public void FTPList_Parsen(string Zeile)
{
string rechte_Seite;
string[] temp;
//Ist Zeile Ordner(d), Datei(-) oder Link(l)
Ordner = Zeile.Substring(0, 1);
//Rechte
Rechte = Zeile.Substring(1, 9);
//der Reststring ohne Rechte. Also ab Zeichen 10 bis Stringlänge-10(weil wir fangen ja erst an bei 10 zu zählen)
rechte_Seite = Zeile.Substring(10, Zeile.Length-10);
//die Leerzeichen links entfernen
rechte_Seite = rechte_Seite.Trim();
//Nach dem Leerzeichen String splitten, um die Anzahl der Verweise zu erhalten
temp = rechte_Seite.Split(' ');
Verweise = temp[0];
//die länge der Verweise bestimmen und das von unserem rechte_Seite string wieder entfernen, da wir es nicht mehr brauchen
//Leerzeichen am Anfang und Ende gleich wieder entfernen
rechte_Seite = rechte_Seite.Substring(Verweise.Length, rechte_Seite.Length - Verweise.Length);
rechte_Seite = rechte_Seite.Trim();
//Jetzt wieder nach dem Leerzeichen String splitten, um den Besitzer der Datei zu erhalten
temp = rechte_Seite.Split(' ');
Besitzer = temp[0];
//die länge der Besitzer bestimmen und das von unserem rechte_Seite string wieder entfernen, da wir es nicht mehr brauchen
//Leerzeichen am Anfang und Ende gleich wieder entfernen
rechte_Seite = rechte_Seite.Substring(Besitzer.Length, rechte_Seite.Length - Besitzer.Length);
rechte_Seite = rechte_Seite.Trim();
//Jetzt wieder nach dem Leerzeichen String splitten, um die Gruppe der Datei zu erhalten
temp = rechte_Seite.Split(' ');
Gruppe = temp[0];
//die länge der Gruppe bestimmen und das von unserem rechte_Seite string wieder entfernen, da wir es nicht mehr brauchen
//Leerzeichen am Anfang und Ende gleich wieder entfernen
rechte_Seite = rechte_Seite.Substring(Gruppe.Length, rechte_Seite.Length - Gruppe.Length);
rechte_Seite = rechte_Seite.Trim();
//Jetzt wieder nach dem Leerzeichen String splitten, um die Gruppe der Datei zu erhalten
temp = rechte_Seite.Split(' ');
Groesse = temp[0];
//die länge der Groesse bestimmen und das von unserem rechte_Seite string wieder entfernen, da wir es nicht mehr brauchen
//Leerzeichen am Anfang und Ende gleich wieder entfernen
rechte_Seite = rechte_Seite.Substring(Groesse.Length, rechte_Seite.Length - Groesse.Length);
rechte_Seite = rechte_Seite.Trim();
//Jetzt wieder nach dem Leerzeichen String splitten, um die Gruppe der Datei zu erhalten
//ab jetzt ist alles nur noch durch 1 leerzeichen getrennt, kann also gleich der komplette rest zugewiesen werden
temp = rechte_Seite.Split(' ');
Monat = temp[0];
Tag = temp[1];
Zeit = temp[2];
Name = temp[3];
}
Für die, die es interessiert:
die LIST Replys von FTP-Servern sollten in der Regel dem ls command unter linux entsprechen und so aufgebaut sein:
Antwort:
drwxr-xr-x 2 251003ftp3 251003 4096 Jun 14 09:52 test
Bedeutung:
Stellen
1. Teil: 1 Dateiart (d = Ornder, - = Datei, l(L) = Link)
3 Rechte des User
3 Rechte der Gruppe
3 Rechte für andere
(r = Lesen, w = Schreiben, x = Ausführen)
LEERZEICHEN
2. Teil Verweise auf die Datei(also Datei kann verschiedene Namen haben, ist physikalisch nur einmal vorhanden)
LEERZEICHEN
3. Teil Name des Eigentümers
LEERZEICHEN
4. Teil Gruppenzugehörigkeit der Datei
LEERZEICHEN
5. Teil Größe der Datei in Bytes
LEERZEICHEN
6. Teil Letzte Änderung - Monat
LEERZEICHEN
7. Teil Letzte Änderung - Tag
LEERZEICHEN
8. Teil Letzte Änderung - Uhrzeit
LEERZEICHEN
9. Teil Datei/Ornder Name
Danke für eure Hilfe.
Mfg
evo2
Hi.
Beschäftige mich jetzt mit Netzwerkgeschichten.
Versuche grade einen FTP Clienten zu programmieren.
Das Verbinden und Dateiliste empfangen klappt wunderbar.
Das Empfange sieht dann in etwa so aus:
-rw-r--r-- 1 251003ftp3 251003 92747 Jun 14 09:42 bild.jpg
drwxr-xr-x 2 251003ftp3 251003 4096 Jun 14 09:52 test
Weiß nun nicht genau wie ich das voneinander trennen kann, um es mit Treeview anzeigen zu lassen, also nach Berechtigungen, Owner, Datum, Dateityp, Datei/Ordnername.
Hat einer ne Idee?
MFg
evo2
Hi.
Hab bis eben nochmal probiert, aber ich bekomme das nicht so richtig hin.
Wollte anstelle von
besucht[next.Kanister1,next.Kanister2] = true;
dann dieses hier nehmen:
Zaehler[next.Kanister1,next.Kanister2] = 1;
Zaehler2[current.Kanister1,current.Kanister2] = 1;
um somit zu merken, welchen Knoten ich erreicht habe, und mit dem Zähler 2, woher ich gekommen bin.
Nur bringt mich das ja nicht weiter, da er ja jeden Knoten erst durchprobiert, dann den nächsten usw.
Wollte das dann mit
Zaehler[i,i] = 1;
machen und nach jedem durchlauf erhöhen lassen, aber das i kann ich ja nicht Knoten gebunden machen, also das er das i nur für die Knoten zum Zielknoten erhöht und nich die Wege die nicht zum Ziel führen.
Dann hab ich noch einen Versuch unternommen und wie vorgeschlagen jeder Aktion eine Nummer verpasst.
Kanister1 füllen die 1, Kanister2 füllen die 2 ...bis zur 6 hoch.
Aber da ist dann wieder die Sache, daß er zwar die Nummern speichert, aber ich keine Vorgängerknoten habe bzw nicht weiß, welche Vorgängerknoten zu welchem Knoten gehören.
Kannst du vielleicht etwas genauer beschreiben, wie ich die Tiefe speichern kann bzw ich die Vorgängerknoten einem aktuellen Knoten zuordnen kann?
Mfg
evo2
Danke euch beiden, habs nun hinbekommen.
Programm läuft soweit nur braucht der bei mir mind. 8 Versuche um 2 Liter zu bestimmen. Normal sollte es aber schon in 5 Versuchen klappen.
public class CSuchen
{
const int Ziel = 2;
public void Loesen()
{
//Bool besucht = true, false?!
bool[,] besucht = new bool[4,5];
//Queue erzeugen
Queue myQ = new Queue();
//StartQueue auf 0,0 setzen
myQ.Enqueue(new CKnoten(0,0));
//0,0 als besucht markieren
besucht[0,0] = true;
//CKnoten current, next;
CKnoten current,next;
/*
//Zaehler für Anzahl der Knoten bis zum erreichen des Ziels.
//Array auf 0,0 setzen beim starten.
int i = 0;
int[,] Zaehler = new int[i,i];
*/
//Anzahl
int Anzahl=0;;
//solange Queue nicht leer
while( myQ.Count != 0 )
{
current = (CKnoten) myQ.Dequeue();
//Wenn Ziel gefunden, dann Ende
if( current.Kanister1 == Ziel || current.Kanister2 == Ziel || current.Kanister1 + current.Kanister2 == Ziel)
{
Console.WriteLine("Zielfüllstand von {0} Litern wurde erreicht!\n",Ziel);
Console.WriteLine("current.Kanister1: {0}\ncurrent.Kanister2: {1}",current.Kanister1, current.Kanister2);
Console.WriteLine("benötigte Versuche:{0}",Anzahl);
break;
}
//-->1.Neuer Knoten
//1. neuen Knoten erstellen
next = new CKnoten( current.Kanister1, current.Kanister2 );
next.FuellKanister1();
//Wenn noch nicht als besucht markiert, dann jetzt machen
if( !besucht[next.Kanister1,next.Kanister2] )
{
Console.WriteLine("Kanister1 füllen");
next.WriteLine();
//neue Knoten als besucht markieren
besucht[next.Kanister1,next.Kanister2] = true;
myQ.Enqueue( next );
}
//-->2.Neuer Knoten
//2. neuen Knoten erstellen
next = new CKnoten( current.Kanister1, current.Kanister2 );
next.FuellKanister2();
//Wenn noch nicht als besucht markiert, dann jetzt machen
if( !besucht[next.Kanister1,next.Kanister2] )
{
Console.WriteLine("Kanister2 füllen");
next.WriteLine();
//neue Knoten als besucht markieren
besucht[next.Kanister1,next.Kanister2] = true;
myQ.Enqueue( next );
}
//-->3.Neuer Knoten
//3. neuen Knoten erstellen
next = new CKnoten( current.Kanister1, current.Kanister2 );
next.LeerKanister1();
//Wenn noch nicht als besucht markiert, dann jetzt machen
if( !besucht[next.Kanister1,next.Kanister2] )
{
Console.WriteLine("Kanister1 leeren");
next.WriteLine();
//neue Knoten als besucht markieren
besucht[next.Kanister1,next.Kanister2] = true;
myQ.Enqueue( next );
}
//-->4.Neuer Knoten
//4. neuen Knoten erstellen
next = new CKnoten( current.Kanister1, current.Kanister2 );
next.LeerKanister2();
//Wenn noch nicht als besucht markiert, dann jetzt machen
if( !besucht[next.Kanister1,next.Kanister2] )
{
Console.WriteLine("Kanister2 leeren");
next.WriteLine();
//neue Knoten als besucht markieren
besucht[next.Kanister1,next.Kanister2] = true;
myQ.Enqueue( next );
}
//-->5.Neuer Knoten
//5. neuen Knoten erstellen
next = new CKnoten( current.Kanister1, current.Kanister2 );
next.FuellKanister2zu1(next.Kanister1, next.Kanister2);
//Wenn noch nicht als besucht markiert, dann jetzt machen
if( !besucht[next.Kanister1,next.Kanister2] )
{
Console.WriteLine("Kanister2 in Kanister1 füllen");
next.WriteLine();
//neue Knoten als besucht markieren
besucht[next.Kanister1,next.Kanister2] = true;
myQ.Enqueue( next );
}
//-->6.Neuer Knoten
//6. neuen Knoten erstellen
next = new CKnoten( current.Kanister1, current.Kanister2 );
next.FuellKanister1zu2(next.Kanister1, next.Kanister2);
//Wenn noch nicht als besucht markiert, dann jetzt machen
if( !besucht[next.Kanister1,next.Kanister2] )
{
Console.WriteLine("Kanister1 in Kanister2 füllen");
next.WriteLine();
//neue Knoten als besucht markieren
besucht[next.Kanister1,next.Kanister2] = true;
myQ.Enqueue( next );
}
//Zählvariable um 1 erhöhen, damit die Anzahl der Versuche bestimmt werden kann
Anzahl++;
}
}
}
Und mit dem merken, welche Schritte er ausgeführt hat um das Ziel zu erreichen, ist auch noch ne kleine Hürde für mich.
Wie Traumzauberbaum schon sagte is bool nicht wirklich zu empfehlen, da ich somit den Weg nicht "zurückverfolgen" kann.
Wollte es mit einem 2D Array lösen, da kann ich zwar alles auflisten, aber ich kann es nicht zuordnen, welcher Weg nun welcher war im Array.
Habt ihr dazu noch eine Idee?
Sorry wenn ich soviel Frage, aber wie gesagt bin Anfänger und mir fehlen manchmal die Ideen und Ansätze, wie ich was umsetzen kann.
Mfg
evo2
Hi.
So, hab jetzt die letzten Tage probiert das mit dem Queue einzubauen, aber so recht will das nicht. Hab auch dazu gegooglet und in der MSDN nachgelesen, aber nur mit mäßigem erfolg.
Queue<CKnoten> queue = new Queue<CKnoten>();
Hier verstehe ich zum Beispiel nicht, was das Cknoten da macht...zumal das wenn ich das so verwenden will, nicht funktioniert.
Bei dem was ich bis jetzt habe, hab ich immer Kommentare rangeschrieben, so wie ich denke, was dort abläuft.
Aber beim
current = queue.Dequeue();
kommt dann schon wieder ein Fehler:
"Implizite Konvertierung des Typs 'object' zu CKnoten' nicht möglich."
Bin auch nur ein Anfänger und weiß nicht so richtig, wie ich da jetzt weitermachen soll bzw. wieso da dieser Fehler auftritt.
Hier ist nochmal die Klasse CSuchen, den Rest habe ich bis jetzt nicht verändert.
public class CSuchen
{
const int Ziel = 2;
//Neue Instanz der Klasse Knoten erzeugen
//Werte für Kanister1 und Kanister2 gleich mit übergeben
CKnoten Kanister = new CKnoten(0,0);
public void Loesen()
{
//Bool besucht = true, false?!
bool[,] besucht = new bool[4,5];
//Queue erzeugen
Queue myQ = new Queue();
//StartQueue auf 0,0 setzen
myQ.Enqueue("0,0");
//0,0 als besucht markieren
besucht[0,0] = true;
//CKnoten current, next;
CKnoten current,next;
//solange Queue nicht leer
while( myQ.Count != 0 )
{
current = myQ.Dequeue(); //<-- Fehler: Implizierte Konvertierung des
// Typs object zu CKnoten nicht möglich.
//Hier hab ich erstmal nicht weitergemacht, da schon drüber der Fehler kam
}
}
}
Du hast natürlich recht. Das hatte ich bis jetzt gar nicht bedacht, daß in dem anderen Kanister ja ruhig noch was drin sein kann. 🤔
Ich werd dann das mit der Breitensuche mal probieren.
Mfg
evo2
//edit
Ui..auch noch Quellcode dabei 🙂
Ok, werd mal probieren wie ich das hinbekomme.
Danke nochmals.
Hallo.
Erstmal danke für eure Antworten.
@Traumzauberbaum:
Wie kommst du auf 9 Endzustände?
Endzustände wären doch nur (0,2), (2,0) und (1,1).
Und wie meinst du das mit dem Stack? Soll ich alle möglichen Kombinationen vorher schon abspeichern und die dann durchlaufen lassen?
@herbivore
Also ich hab den Startknoten: (0,0)
Auf den muß ich dann alle Schritte anwenden und erhalte wieder eine neue Liste auf die ich alle Schritte wieder anwende und dann immer soweiter, richtig?
Habt ihr vielleicht ein kleinen CodeSchnipsel dazu? Muß ja nix mit meinem Programm zutun haben, nur weiß ich im Moment gar nicht, wie ich das programmiertechnisch umsetzen sollte.
Mfg
evo2
Hi.
Weiß nicht genau, ob das Thema hier in Rund um die Programmierung oder in C# gehört. Hab es mal hierher gelegt. 😉
Ihr kennt sicher alle die Aufgabe.
Es gibt 2 Krüge, einen 4 LIter und einen 3 Liter Krug.
Wie bekommt man mit Hilfe von füllen, leeren und umfüllen 2 Liter abgemessen.
Soweit hört sich das ja einfach an. Nur weiß ich nicht wie man es anstellt, daß das Programm nicht einen bestimmten Zyklus, sondern einfach so probiert, ob es die Lösung findet und sich die Sachen merkt, die nicht funktioniert haben.
Habe eine Klasse geschrieben, in der die erlaubten Sachen, füllen, leeren und umfüllen definiert sind und eine Klasse Suchen. Da sollte er dann die Sachen durchgehen und schon probierte Möglichkeiten "markieren" und nicht mehr probieren.
Nur wie gesagt, weiß halt nicht genau, wie ich das anstellen soll.
Vielleicht hat einer von euch ja eine Idee dazu.
Hier mein bis jetzt versuchtes:
using System;
public class Wasserkrug
{
public static void Main()
{
const int Kanister1Max = 3;
const int Kanister2Max = 4;
const int Ziel = 2;
//Ausgabe der MaxFüllstände und des Zielfüllstandes
Console.WriteLine("maximaler Füllstand Kanister1: {0}", Kanister1Max);
Console.WriteLine("maximaler Füllstand Kanister1: {0}", Kanister2Max);
Console.WriteLine("Zielfüllstand: {0}", Ziel);
Console.WriteLine();
//Neue Instanz der Klasse CSuchen erzeugen
CSuchen Suchen = new CSuchen();
Suchen.Loesen();
}
}
//Klasse CKnoten
public class CKnoten
{
public int Kanister1; //3Liter Krug
public int Kanister2; //4Liter Krug
public CKnoten(int Kanister1, int Kanister2)
{
this.Kanister1 = Kanister1;
this.Kanister2 = Kanister2;
}
//Kanister1 füllen
public void FuellKanister1()
{
this.Kanister1 = 3;
}
//Kanister2 füllen
public void FuellKanister2()
{
this.Kanister2 = 4;
}
//Kanister1 leeren
public void LeerKanister1()
{
this.Kanister1 = 0;
}
//Kanister2 leeren
public void LeerKanister2()
{
this.Kanister2 = 0;
}
//Kanister2 in Kanister1 füllen bis Kanister1 voll ist
public void FuellKanister2zu1(int Kanister1, int Kanister2)
{
//Kanister1 = 3Liter
//Kanister2 = 4Liter
this.Kanister1 = this.Kanister1 + this.Kanister2;
if (this.Kanister1 > 3)
{
this.Kanister2 = this.Kanister1 - 3;
this.Kanister1 = 3;
}
else
{
this.Kanister2 = 0;
}
}
//Kanister1 in Kanister2 füllen bis Kanister2 voll ist
public void FuellKanister1zu2(int Kanister1, int Kanister2)
{
//Kanister1 = 3Liter
//Kanister2 = 4Liter
this.Kanister2 = this.Kanister1 + this.Kanister2;
if (this.Kanister2 > 4)
{
this.Kanister1 = this.Kanister2 - 4;
this.Kanister2 = 4;
}
else
{
this.Kanister1 = 0;
}
}
//Ausgabe der aktuellen Füllstände
public void WriteLine()
{
Console.WriteLine("Kanister1: {0}\nKanister2: {1}", Kanister1, Kanister2);
Console.WriteLine();
}
}
//Klasse CSuchen
public class CSuchen
{
const int Ziel = 2;
//Neue Instanz der Klasse Knoten erzeugen
//Werte für Kanister1 und Kanister2 gleich mit übergeben
CKnoten Kanister = new CKnoten(0,0);
public void Loesen()
{
//Kanister leeren
Kanister.LeerKanister1();
Kanister.LeerKanister2();
Kanister.WriteLine();
//Kanister fuellen
Kanister.FuellKanister1();
Kanister.FuellKanister2();
Kanister.WriteLine();
//Kanister2 in Kanister1 füllen bis er voll ist
Kanister.FuellKanister2zu1(Kanister.Kanister1,Kanister.Kanister2);
Kanister.WriteLine();
//Kanister1 in Kanister2 füllen bis er voll ist
Kanister.FuellKanister1zu2(Kanister.Kanister1,Kanister.Kanister2);
Kanister.WriteLine();
}
}
Und hier in Lösen seht ihr ja, daß er immer nur eine bestimmte Reihenfolge befolgt und das "Problem" somit ja nicht gelöst werden kann.
Könnte ja jetzt direkt die zu verwendenen Funktionen nacheinander hinschreiben, aber das ist ja nicht sinn der Sache.
Mfg
evo2