using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using System.Collections; using System.Windows.Forms; using System.Drawing; using System.Threading; namespace WindowsFormsApplication1 { class Vyhodnoceni { protected List SeznamUzlu; protected UzelStromu koren; public void PostavStrom() { XmlDocument zadaniSite = new XmlDocument(); zadaniSite.Load( NazevSouboru ); XmlNode korenovyElement = zadaniSite.DocumentElement; koren = new UzelStromu(); koren.hradlo = null; koren.naslednici = new List(); Dictionary ids = new Dictionary(); List ocekava = new List(); List co = new List(); foreach ( XmlNode element in korenovyElement.ChildNodes ) { switch ( element.Name ) { case "input": { UzelStromu novy = new UzelStromu(); novy.hradlo = new CisloHradlo(); foreach ( XmlAttribute atribut in element.Attributes ) { if ( atribut.Name == "id" ) { ids.Add( atribut.Value, novy ); break; } } novy.hradlo.PotrebujeVstupu = 1; SeznamUzlu.Add( novy ); koren.naslednici.Add( novy ); break; } case "gate": { //máme hradlo //projít atributy UzelStromu uzel = new UzelStromu(); //zjisti typ hradla switch ( element.Attributes[ "type" ].Value ) { case "and": { //and hradlo uzel.hradlo = new ANDHradlo(); break; } case "xor": { //xor hradlo uzel.hradlo = new XORHradlo(); break; } case "or": { //or hradlo uzel.hradlo = new ORHradlo(); break; } case "not": { //not hradlo uzel.hradlo = new NOTHradlo(); break; } } //pro počet vstupu, které jsou nutné pro výpočet hradla int pocetVstupu = 0; foreach ( XmlNode podelement in element.ChildNodes ) { if ( podelement.Name == "input" ) { //potřebuje další vstup pocetVstupu++; //očekává napojení ocekava.Add( uzel ); co.Add( podelement.Attributes[ "id" ].Value ); } else { //je výstupem, na který se bude nepojovat ids.Add( podelement.Attributes[ "id" ].Value, uzel ); } } //uložení potřebného počtu vstupů uzel.hradlo.PotrebujeVstupu = pocetVstupu; SeznamUzlu.Add( uzel ); break; } case "output": { //vystupni uzel UzelStromu uzel = new UzelStromu(); uzel.hradlo = new CisloHradlo(); //ochrana před vložením do fronty při výpočtu uzel.hradlo.PotrebujeVstupu = 0; //vložit mezi výstupní uzly uzel.hradlo.NazevHradla = element.Attributes[ "id" ].Value; vystupniUzly.Add( uzel ); //očekává napojení ocekava.Add( uzel ); co.Add( element.Attributes[ "id" ].Value ); SeznamUzlu.Add( uzel ); break; } } } //propoj vystupy a vstupy foreach ( KeyValuePair par in ids ) { //projdi pole "co" for ( int indexCo = 0; indexCo < co.Count; indexCo++ ) { //ocekava se napojeni if ( par.Key == co[ indexCo ] ) { //napojit par.Value.naslednici.Add( ocekava[ indexCo ] ); } } } } public List vystupniUzly; /// /// Základní konstruktor /// /// Název souboru popisu sítě public Vyhodnoceni( string parNazevSouboru ) { koren = null; vystupniUzly = new List(); NazevSouboru = parNazevSouboru; SeznamUzlu = new List(); PostavStrom(); } public string NazevSouboru; public void VycistiStrom() { foreach ( UzelStromu uzel in SeznamUzlu ) { uzel.hradlo.vstupy.Clear(); } } /// /// Vyhodnotí vstup /// /// hodnoty na vstupu /// výsledné hodnoty public List Vyhodnot( List vstupniHodnoty ) { //vyčistí strom od dřívějších hodnot VycistiStrom(); //vytvoří novou frontu Queue fronta = new Queue(); if ( koren.naslednici.Count > 0 ) { //Načtení vstupních hradel for ( int indexNaslednika = 0; indexNaslednika < koren.naslednici.Count; indexNaslednika++ ) { koren.naslednici[ indexNaslednika ].hradlo.vstupy.Add( vstupniHodnoty[ indexNaslednika ] ); fronta.Enqueue( koren.naslednici[ indexNaslednika ] ); } //dokud není fronta prázdná while ( fronta.Count > 0 ) { //získej uzel stromu UzelStromu AktualniUzel = fronta.Dequeue(); bool vystupHradla = AktualniUzel.hradlo.Vyhodnot(); //předej výsledek následníkům foreach ( UzelStromu uzel in AktualniUzel.naslednici ) { uzel.hradlo.vstupy.Add( vystupHradla ); //je hradlo připravené na výpočet? if ( uzel.hradlo.vstupy.Count == uzel.hradlo.PotrebujeVstupu ) { fronta.Enqueue( uzel ); } } } List vystup = new List( vystupniUzly.Count ); //získej výsledky z výstupních uzlů foreach ( UzelStromu uzel in vystupniUzly ) { vystup.Add( uzel.hradlo.vstupy[ 0 ] ? 1 : 0 ); } return vystup; } else { //vrat nulu return null; } } /// /// Garfické vyhodnocení /// /// Seznam vstupů /// Grafický panel /// Výsledky public List VyhodnotGraficky( List vstupniHodnoty, Panel pnl ) { VycistiStrom(); Queue fronta = new Queue(); Graphics grafika = pnl.CreateGraphics(); if ( koren.naslednici.Count > 0 ) { //Načtení vstupních hradel for ( int indexNaslednika = 0; indexNaslednika < koren.naslednici.Count; indexNaslednika++ ) { koren.naslednici[ indexNaslednika ].hradlo.vstupy.Add( vstupniHodnoty[ indexNaslednika ] ); fronta.Enqueue( koren.naslednici[ indexNaslednika ] ); } while ( fronta.Count > 0 ) { UzelStromu AktualniUzel = fronta.Dequeue(); grafika.Clear( Color.White ); Font pismo = new Font( "Arial", 20 ); bool vystupHradla = AktualniUzel.hradlo.Vyhodnot(); //grafická část grafika.DrawString( AktualniUzel.hradlo.Typ.ToString() + " " + ( vystupHradla ? '1' : '0' ), pismo, Brushes.Black, new PointF( 10, 10 ) ); Thread.Sleep( 500 ); foreach ( UzelStromu uzel in AktualniUzel.naslednici ) { uzel.hradlo.vstupy.Add( vystupHradla ); if ( uzel.hradlo.vstupy.Count == uzel.hradlo.PotrebujeVstupu ) { fronta.Enqueue( uzel ); } } } List vystup = new List( vystupniUzly.Count ); foreach ( UzelStromu uzel in vystupniUzly ) { vystup.Add( uzel.hradlo.vstupy[ 0 ] ? 1 : 0 ); } return vystup; } else { //vrat nulu return null; } } } enum TypHradla { AND, OR, XOR, NOT, CISLO } class UzelStromu { public IHradlo hradlo; public List naslednici = null; public UzelStromu() { hradlo = null; naslednici = new List(); } } interface IHradlo { string NazevHradla { get; set; } TypHradla Typ { get; } List vstupy { get; set; } bool Vyhodnot(); int PotrebujeVstupu { get; set; } } /// /// Implementace hradla typu NOT /// class NOTHradlo : IHradlo { private string _nazevHradla; public string NazevHradla { get { return _nazevHradla; } set { _nazevHradla = value; } } private int _potrebujeVstupu; public int PotrebujeVstupu { get { return _potrebujeVstupu; } set { _potrebujeVstupu = value; } } //typ hradla NOT private TypHradla _typ = TypHradla.NOT; public TypHradla Typ { get { return _typ; } } public bool Vyhodnot() { //Pouze jeden vstup if ( vstupy.Count == PotrebujeVstupu ) { //vrať opačnou hodnotu return !vstupy[ 0 ]; } else { throw new ArgumentOutOfRangeException( "Špatný vstup" ); } } private List _vstupy = new List(); public List vstupy { get { return _vstupy; } set { _vstupy = value; } } } class ANDHradlo : IHradlo { private string _nazevHradla = ""; public string NazevHradla { get { return _nazevHradla; } set { _nazevHradla = value; } } private int _potrebujeVstupu; public int PotrebujeVstupu { get { return _potrebujeVstupu; } set { _potrebujeVstupu = value; } } private TypHradla _typ = TypHradla.AND; public TypHradla Typ { get { return _typ; } } public bool Vyhodnot() { //Je vstup platný? if ( vstupy.Count == PotrebujeVstupu ) { //byly na vstupu zatím samé jedničky? bool SameJednicky = true; foreach ( bool hodnota in vstupy ) { //nalezena hodnota 0 if ( !hodnota ) { //končíme průchod SameJednicky = false; break; } } //výsledek hradla AND return SameJednicky; } else { //Chybný vstup throw new ArgumentOutOfRangeException(); } } private List _vstupy = new List(); public List vstupy { get { return _vstupy; } set { _vstupy = value; } } } /// /// Implementace hradla typu OR /// class ORHradlo : IHradlo { private string _nazevHradla = ""; public string NazevHradla { get { return _nazevHradla; } set { _nazevHradla = value; } } private int _potrebujeVstupu; public int PotrebujeVstupu { get { return _potrebujeVstupu; } set { _potrebujeVstupu = value; } } //hradlo typu OR private TypHradla _typ = TypHradla.OR; public TypHradla Typ { get { return _typ; } } public bool Vyhodnot() { //Vstup byl platný? if ( vstupy.Count == PotrebujeVstupu ) { //byla ve vstupu jednička bool jednicka = false; foreach ( bool hodnota in vstupy ) { //Pravdivá hodnota vstupu if ( hodnota ) { //Máme jedničku, průchod můžeme ukončit jednicka = true; break; } } //vrátí hodnotu or return jednicka; } else { //Chybný vstup throw new ArgumentOutOfRangeException(); } } private List _vstupy = new List(); public List vstupy { get { return _vstupy; } set { _vstupy = value; } } } /// /// Implementace hradla typu XOR /// class XORHradlo : IHradlo { private string _nazevHradla = ""; public string NazevHradla { get { return _nazevHradla; } set { _nazevHradla = value; } } private int _potrebujeVstupu; public int PotrebujeVstupu { get { return _potrebujeVstupu; } set { _potrebujeVstupu = value; } } //hradlo typu XOR private TypHradla _typ = TypHradla.XOR; public TypHradla Typ { get { return _typ; } } public bool Vyhodnot() { //je vstup platný if ( vstupy.Count == PotrebujeVstupu ) { //počet jedniček ve vstupu int pocetJednicek = 0; //pro každý vstup foreach ( bool hodnota in vstupy ) { //pokud je true if ( hodnota ) { //další jednička pocetJednicek++; } } //byl počet jedniček sudý? if ( ( pocetJednicek % 2 ) != 0 ) { //1 return true; } else { //0 return false; } } else { //Chybný vstup throw new ArgumentOutOfRangeException(); } } private List _vstupy = new List(); public List vstupy { get { return _vstupy; } set { _vstupy = value; } } } class CisloHradlo : IHradlo { private string _nazevHradla = ""; public string NazevHradla { get { return _nazevHradla; } set { _nazevHradla = value; } } private int _potrebujeVstupu; public int PotrebujeVstupu { get { return _potrebujeVstupu; } set { _potrebujeVstupu = value; } } private TypHradla _typ = TypHradla.CISLO; public TypHradla Typ { get { return _typ; } } public bool Vyhodnot() { //pouze jeden vstup if ( vstupy.Count == PotrebujeVstupu ) { return vstupy[ 0 ]; } else { //Chybný vstup throw new ArgumentOutOfRangeException(); } } private List _vstupy = new List(); public List vstupy { get { return _vstupy; } set { _vstupy = value; } } } }