Razred Kvadrat

Razred Kvadrat

Avtor: Mateja Gorišek, pred. M.Lokar, prenos v NAUK Alja Gligić

Opis problema / navodilo naloge

Napišite razred Kvadrat, s katerim predstavite kvadrat. Kvadrat je predstavljen z dolžino ene stranice. Sestavite tudi metodi za izračun ploščine in obsega kvadrata.

  • Izračunajte, kakšno površino lahko prekrijete s kvadrati, ki so v tabeli.
  • Vrnite kopijo tistega kvadrata, ki ima najmanjši obseg.
  • Vsem tistim kvadratom v tabeli, katerih obseg je več kot 10% manjši od povprečnega obsega vseh kvadratov, spremenite stranico tako, da bodo imeli obseg (do zaokrožitvene napake) enak povprečnemu.
  • • Dodatna naloga: Izračunaj ploščino kvadratov in vrni kopijo tistega kvadrata, ki ima največjo ploščino.

    Razred naj obvezno vsebuje:
  • Minimalni (tj. prazni) konstruktor public Razred(), ki tvori objekt s privzetimi (smiselnimi!) vrednostmi.
  • Metodo public override string ToString(), ki vse podatke v objektu zapiše v obliki niza. Podatki naj bodo med seboj ločeni z znakom ';'.
  • Polni konstruktor public Razred(string s), ki s klicem Razred(niz) generira tak objekt Razred r, za katerega velja niz = r.ToString().
  • Metodo DodajNaDatoteko(string imeDatoteke), ki objekt this zapiše (oz. doda; glej metodo File.AppendText()) kot vrstico this.ToString() v tekstovni datoteki.
  • Metodo PreberiZDatoteke(string imeDatoteke), ki vrne tabelo objektov, kjer posamezni objekt vsebuje podatke, ki so zapisani v posamezni vrstici tekstovne datoteke.

    Vsi razredi morajo biti robustni – vsi konstruktorji in metode morajo biti taki, da objekta ne spravijo v nesmiselno stanje. Če je potrebno, pri klicu metode s nedopustnimi parametri sproži izjemo.

  • V testnem programu, s katerim prikažete ključne funkcionalnosti razreda, naredite naslednje:

    • Napišite metodo, ki ustvari vsaj ducat različnih objektov in jih zapišite na datoteko.
    • Napišite ustrezne metode za reševanje zastavljenih problemov.
    • V programu samem pa po vrsti :

      • Pokličite metodo, ki na datoteko zapiše ducat objektov.
      • Preberite vse podatke z datoteke v tabelo.
      • Tabelo pregledno izpišite.
      • Nato kličite metode, ki so potrebne, da rešite zastavljene probleme in pregledno izpišite rezultate.
      • Na koncu na isto datoteko ponovno zapišite vse objekte (ne glede na to, ali so jih zgornje metode spremenile ali ne).

Ideja rešitve

Najprej bomo napisali razred Kvadrat. Razred bo predstavljen z dolžino stranice (tipa double).

Najprej bomo v razredu napisali get in set metode. Z metodo get bomo vrnili vrednost stranice in s set metodo bomo nastavili stranici novo vrednost.

Razred bo vseboval tri konstruktorje: o Prazen konstruktor o Konstruktor, ki sprejme realno število (dolžino stranice) o Konstruktor, ki sprejme niz

V razredu bomo tudi napisali zahtevane (iz navodila) objekte in statične metode.

Pri pisanju razreda bomo ob nesmiselnem klicu metode sprožili tudi izjemo.

V testnem programu bomo najprej napisali vse metode, mi jih potrebujem, da bomo lahko razred testirali. Nato pa ga testiramo po navodilu iz besedila naloge.

Razlaga algoritma (metode set in get)

V razredu najprej deklariramo privatno spremenljivko, ki bo predstavljala dolžino stranice (tipa double ).
Nato napišemo najprej get(VrniKvadrat) in set(NastaviDolžinoStranice) metode.

V get metodi vrnemo vrednost stranice. V set metodi, pa najprej preverimo, ali je uporabnik vnesel smiselno vrednost stranice:

  • Če je vnesel nesmiselno vrednost, bomo sprožili izjemo.
  • Če je vnesel smiselno vrednost, bomo spremenljivki nastavili novo vrednost.

    private double _stranica;  // privatna spremenljivka stranica

    public double VrniKvadrat()
            { return this._stranica; } // metoda vrne vrednost stranice

    public void NastaviDolzinoStranice(double n)
            {
                if (n <= 0) { throw new Exception("Stranica kvadrata mora biti večja od nič"); }
                this._stranica = n;
            } // metoda spremeni vrednost stranice na n

Razlaga algoritma (konstruktorji in metoda ToString())

Konstruktorji razreda:

  • Prazen konstruktor. Ta konstruktor bo imel privzeto vrednost stranice. Za privzeto vrednost stranice smo določili stranico dolžine 1.
  • Konstruktor, ki sprejme dolžino stranice (tipa double). V tem primeru prav tako sprožimo izjemo, če uporabnik ne vnese pravilne vrednosti.
  • Konstruktor, ki sprejeme niz. Tukaj niz spremenimo v decimalno število in ga shranimo v spremenljivko _stranica.

     // prazen konstruktor
    public Kvadrat()
            {
                this._stranica = 1; // privzeta vrednost je stranica dolžine 1
            }

    // konstruktor
    public Kvadrat(double n)
            {
                if (n <= 0) { throw new Exception("Stranica kvadrata mora biti večja od nič"); }
                this._stranica = n;
            }

    // konstruktor, ki sprejme dolžino stranice v nizu
    public Kvadrat(string niz)
            {
                this._stranica = double.Parse(niz); // niz spremenimo v število
            }


    Kvadrat v nizu predstavimo le z dolžino stranice.

    // kvadrat v nizu predstravimo z dolžino stranice
    public override string ToString()
            {
                return "" + this._stranica;
            }

Razlaga algoritma (metoda DodajNaDatoteko in metoda PreberiZDatoteke)

Metoda DodajNaDatoteko:
V tej metodi odpremo najprej datoteko v katero bomo pisali. Tako datoteko na katero bomo pisali povežemo s podatkovnim tokom StreamWriter. V to datoteko bomo dodajali v vsako vrstico dolžino stranice oziroma kvadrat predstavljen z dolžino stranice. Na koncu, ko v datoteko več ne dodajamo kvadrate, moramo datoteko zapreti. Zapremo jo sClose().

 public void DodajNaDatoteko(string imeDatoteke)
        { // vrednost stranice kvadrata dodamo v datoteko, če datoteka še en obstaja, jo ustvari
            StreamWriter dat = File.AppendText(imeDatoteke);  // odpremo datoteko, v katero bom nekaj dodajali
            dat.WriteLine(this.ToString());  // zapišem predstavitev kvadrata
            dat.Close();  // daoteko na koncu zapremo
        }


Metoda PreberiZDatoteko:
Najprej preverimo ali datoteka še ne obstaja:

  • Če datoteka še ne obstaja, vrnemo izjemo.
  • V nasprotnem primeru datoteko odpremo za branje in iz datoteke preberemo vse vrstice ter jih shranimo v niz. Nato iz niza prestavimo kvadratke v tabelo, kvadratke ločimo glede na novo vrstico. Sedaj imamo tabelo nizov. Sedej moramo ustvariti še tabelo kvadratkov. Tako se sprehodimo čez tabelo in v novo tabelo dodajamo kvadratke, ustvarimo kvadratke, kjer pokličemo konstruktor, ki nam iz niza naredi kvadratke. Na koncu moramo datoteko še zapreti.

    public static Kvadrat[] PreberiZDatoteke(string imeDatoteke)
            {
                // če datoteka ne obstaja, vrnemo napako
                if (!File.Exists(imeDatoteke)) { throw new Exception("Datoteka na obstaja"); }
                StreamReader datBeri = File.OpenText(imeDatoteke);
                string niz = datBeri.ReadToEnd().Trim(); // preberemo celo datoteko in jo shranimo v niz
                string[] tabela = niz.Split('\n'); // v tabelo shranimo vse podatke iz datoteke, in jih pri tem ločimo glede na novo vrstico
                //naredimo tabelo krogov enake dolžine kot je tabela 'tabela'
                Kvadrat[] tabelaKvadratov = new Kvadrat[tabela.Length];
                //sprehodimo se čez tabelo 'tabela'
                for (int i = 0; i < tabela.Length; i++)
                {

                    tabelaKvadratov[i] = new Kvadrat(tabela[i]); // pri tem pokličemo konstruktor, ki sprejme niz
                }
                datBeri.Close();  // na koncu datoteko zapremo
                return tabelaKvadratov; // in vrnemo tabelo Kvadratov
            }

Razlaga algoritma (metodi ploscina in obseg)

V razredu napišemo še dve objektni metodi, to sta metodi, ki izračunata ploščino in obseg kvadrata.

Metoda za ploščino vrne ploščino kvadratka. Ploščino izračunamo kot , pri tem je a dolžina stranice.

Metoda za obseg pa vrne obseg kvadratka. Obseg kvadratka se izračuna kot , kjer je a dolžina stranica.

 public double ploscina()
        { // vrnemo ploščina kvadrata
            return Math.Pow(VrniKvadrat(), 2); //straniva ** 2
        }

public double obseg()
        {  // vrnemo obseg kvadrata
            return 4 * VrniKvadrat();  // 4 * stranica
        }

Razlaga algoritma (metoda povrsina)

Metoda, ki izračuna kakšno površino lahko prekrijemo s kvadratki, ki jih imamo zapisane v datoteki --> Metoda povrsina.

Metoda sprejme tabelo kvadratkov. Površino, ki jo lahko prekrijemo, bomo izračunali kot vsoto posameznega kvadratka v tabeli.

 public static double povrsina(Kvadrat[] tabela)
        {  // metoda mi vrne površino, ki jo lahko prekrijemo s kvadratki iz tabele
            double povrsina = 0; // na začetku je površina enaka 0
            for (int i = 0; i < tabela.Length; i++)
            {// površini prištejemo plošino posameznega kvadratka v tabeli
                povrsina += tabela[i].ploscina();
            }
            return povrsina;
        }

Razlaga algoritma (metoda najmanjsiObseg)

Metoda, ki nam vrne kopijo kvadratka, ki ima najmanjši obseg --> metoda najmanjsiObseg.
Ta metoda sprejeme tabelo kvadratkov. Najprej deklariramo spremenljivko najmansi v katero shranimo obseg prvega elementa v tabeli. Nato se sprehodimo čez celotno tabelo in iščemo obseg, ki je manjši od najmanjšega.
Če najdemo tak obseg, najmanjsega zamenjamo z njim.
Ko smo v tabeli našli kvadratek z najmanjšim obsegom, izračunamo še dolžino stranice, ki jo ima kvadratek. Na koncu vrnemo dolžino stranice tega kvadratka.

public static double najmanjsiObseg(Kvadrat[] tabela)
        { // metoda mi vrne kopijo tiste kvadratka v tabeli, ki ima najmanši obseg
            double najmanjsi = tabela[0].obseg(); // spremenljivko na začetku nastavim na obseg prvega kvadratka v tabeli
            for (int i = 1; i < tabela.Length; i++)
            {  // z zanko grem po tabeli kvadratkov od drugega kvadratka naprej
                if (tabela[i].obseg() < najmanjsi) // če je obseg posameznega kvadratka manjša od najmanjšega
                {
                    najmanjsi = tabela[i].obseg();  // vrednost spremenljivke najmanši spremenimo
                }
            }
            double najmanjsiKvadrat = najmanjsi / 4; // na koncu še izračunam stranico tega najmanjšega kvadratka
            return najmanjsiKvadrat;
        }

Razlaga algoritma (metoda spremeniStranico)

Nato napišemo metodo, ki tistim kvadratkom v tabeli, ki imajo obseg za več kot manjši od povprečnega, spremenimo stranico. Stranico spremenimo tako, da ji nastavimo novo vrednost, nova vrednost dolžine stranice je enaka povprečni stranici --> metoda spremeniStranico.

Torej metoda sprejeme tabelo kvadratkov. V metodi najprej izračunamo povprečni obseg kvadratkov. Povprečni obseg kvadratkov dobimo tako, da vsoto obsegov vseh kvadratkov delimo s količino kvadratkov v tabeli.
Sedaj, ko smo izračuna povprečni obseg, lahko izračunamo še dolžina povprečne stranice. Dolžino povprečne stranice dobimo tako, da povprečni obseg delimo s 4.
Nato lahko določim mejo obsega, saj bomo vsem kvadratkom, ki so pod to mejo spremenili stranico. Torej meja mora biti za manjša od povprečnega obsega. To dosežemo tako, da od povprečnega obsega odštejemo povprečni obseg, ki smo ga najprej pomnožili z . Tako dobimo mejo.

Sedaj lahko deklariram še tabelo kvadratkov v katero bom shranjevala vse kvadratke, tiste katerim bom spremenila dolžino stranice in tudi tiste, katerim dolžino stranice ne bom spremenila.
Tako se sprehodimo čez tabelo in preverjamo ali je obseg v tabeli pod mejo.

  • Če je pod mejo potem v novo tabeli kvadratkov dodamo nov kvadratek, ki ima povprečno dolžino stranice.
  • Če pa trenutni obseg ni pod mejo, potem element iz tabele dodamo v novo tabelo kvadratkov.

    Na koncu stara tabela kaže na novo tabelo.

 public static void spremeniStranico(Kvadrat[] tabela)
        { // metoda mi spremeni stranico vsem tistim kvadratkim, ki imajo za 10% in več manjši obseg od povprečnega
            double vsotaObsega = 0; // s to spremenljivko bom seštela obseg vseh kvadratkov v tabeli
            for (int i = 0; i < tabela.Length; i++)
            {
                vsotaObsega += tabela[i].obseg();
            }

            double povprecniObseg = vsotaObsega / tabela.Length; // izračunali smo povprečen obseg vseh kvadratkov v tabeli
            double povprecnaStranica = povprecniObseg / 4;  // dolžina stranice povprečnega kvadrata
            double meja = povprecniObseg - (povprecniObseg * 10 / 100); // meja pod katero moramo vsem kvadratom spremeniti stranico
            for (int j = 0; j < tabela.Length; j++)
            {
                if (tabela[j].obseg() < meja)
                {  // če ima kvadrat premajhen obseg, naredim nov kvadrat, ki ima sedaj stranico povprečen dolžine
                    tabela[j] = new Kvadrat(povprecnaStranica);
                }
                else { tabela[j] = tabela[j]; }
            }
        }

Razlaga algoritma (metoda najvecjaPloscina)

Dodatna statična metoda, ki vrne kvadrat, ki ima največjo ploščino --> metoda najvecjaPloscina.

Ta metoda prav tako sprejme tabelo kvadratkov. Iz tabele kvadratkov pa najprej izloči kvadratek z največjo ploščino.
Nato se sprehodimo čez celotno tabelo in če najdemo večjo ploščino v spremenljivko shranimo to večjo ploščino.
Nato pa izračunamo dolžino stranice kvadratka, ki jo tudi vrnemo kot rezultat.

public static double najvecjaPloscina(Kvadrat[] tabela)
        {
            double najvecja = tabela[0].ploscina(); // na začeku dodamo ploščino prvega kvadrata
            // to ploščino bomo spreminjali toliko časa dokler ne bomo našl večjo ploščino ali
            // pa bomo pregledali že celo tabelo
            for (int i = 0; i < tabela.Length; i++)
            {
                if (tabela[i].ploscina() > najvecja)
                {// če najdemo kvadrat, ki ima večjo ploščino
                    najvecja = tabela[i].ploscina(); // spremenljivki vrednost spremenimo
                }
            }
            double najvecjiKvadrat = Math.Sqrt(najvecja); // izračunamo še velikost stranice kvadrata
            return najvecjiKvadrat;
        }

Testni program (dodatne metode)

Pri testiranju razreda sem se navezala na navodilo iz naloge.
V testnem programu sem najprej napisala ustrezne metode, ki jih bom potrebovala za reševanje zastavljenih problemom.

Metoda TabelaVNiz:
To metodo bomo potrebovali, da bomo lahko izpisali tabelo. Tako bomo v niz dodali vse elemente tabele in jih ločili s podpičjem in presledkom.

public static string TabelaVNiz(Kvadrat[] tabela)
        {  // tabelo kvadratov zapišem v niz in ga izpišem
            string niz = "";
            for (int i = 0; i < tabela.Length; i++)
            {
                if (i > 0) { niz += "; "; } // če nismo na prvem mestu v tabeli, potem naredimo podpičje in presledek, s ketero ločimo elemente v tabeli
                niz += tabela[i];
            }
            return niz;
        }


Metoda nakljucniKvadrat:
Ta metoda mi bo ustvarila naključno dolžino stranice kvadrata in te naključne stranice naredila kvadratek ter ga shranila v tabelo. Torej najprej naredimo tabelo v katero bomo nato shranjevali kvadratke. Nato naredimo najprej vrečo naključnih števil. Sedaj pa v zanki, iz vreče vzamemo naključno celo število med 1 in 100. Iz tega števila nato naredimo kvadratek in ga shranimo v tabelotabelaKvadratkov. Na koncu te metode vrnemo to tabelo kvadratkov, ki smo jo napolnili z naključnimi kvadratki.

public static Kvadrat[] nakljucniKvadrati(int n)
        {  // metoda ustvari n nakljucnih kvadratov in jih doda v tabelo
            Kvadrat[] tabelaKvadratov = new Kvadrat[n];
            Random nakljucno = new Random();
            int stranica;
            for (int i = 0; i < n; i++)
            {
                stranica = nakljucno.Next(1, 101); // naključno število med 1 in 100
                tabelaKvadratov[i] = new Kvadrat(stranica); // naredim kvadrat z naključno stranico
            }
            return tabelaKvadratov;
        }


Metoda zapisiNaDatoteko:
V tej metodi najprej pokličemo prejšnjo metodo, ki nam naredi naključno tabelo kvadratkov. Nato iz te tabele kvadratke dodajamo na datoteko. Na datoteko dodajamo s pomočjo metode iz razreda (DodajNaDatoteko).

public static void zapisiNaDatoteko(int n, string imeDat)
        {
            Kvadrat[] tabelaKvadratov = nakljucniKvadrati(n); // naredimo tabelo naključnih kvadratov
            for (int i = 0; i < tabelaKvadratov.Length; i++)
            {
                tabelaKvadratov[i].DodajNaDatoteko(imeDat);  // kvadrat iz tabele zapišemo na datoteko
            }
        }


Metoda NaDatotekoIzTabele:
Ta metoda že na začetku sprejeme tabelo kvadratkov. Nato pa te kvadratke doda na datoteko, zopet s pomočjo metode iz razreda (DodajNaDatoteko).

public static void NaDatotekoIzTabele(Kvadrat[] tabela, string imeDat)
        {
            for (int i = 0; i < tabela.Length; i++)
            {
                tabela[i].DodajNaDatoteko(imeDat);  // vsak vadrat v tabeli dodamo na datoteko
            }
        }


Sedaj, ko imam napisane vse potrebne metode za testiranje, lahko začnem s testiranjem.
Razred in programe testiram po navodilu, ki je naveden v navodilu naloge. Tudi skoraj vsi testni primeru bodo po navodilu naloge. Testiranje

Testiranje

0%
0%