wiki:k2012/demot/demo5
Last modified 6 years ago Last modified on 2012-02-09 11:46:43

Demot » Demo 5, 13.2.2012

Tehtävien nimeämisestä: Älä anna C#-tiedostoille nimiä, jotka eivät ole kuvaavia. Esim. tehtG1.cs on huono sen kannalta, että jos opetellaan käyttämään nimiä jotka toimisivat oikeassakin ohjelmassa. Pallopeli.cs on taas paljon parempi (ja muista se luokan nimen suhde tiedoston nimeen).

Ville 1

Tee Ville-tehtävät: 4.5, 4.6, 5.1-5.5, 9.1, 9.2, 9.3. Muista: Villen käyttöohje ja Ville-tehtävien palauttamisohjeet. Huom! Lue tarkasti kysymykset (montako kertaa, montako tulostetaan). Villen mallissa loppusulkuun } mennään kun silmukka loppuu.

TDD1

Jos tarkistat vähintään kahden funktion toiminnan automaattisella testillä (ComTest), saat merkitä yhden lisäpisteen. (Kuitenkaan tehtävästä 6 et voi tuplapisteitä saada :-)

Käyttääksesi ComTestiä asenna se tietokoneellesi edellä löytyvän linkin ohjeiden mukaan. Voit varmistaa että asennus on mennyt oikein läpi näin:

  1. Tee uusi projekti
  2. Copy-pasteta tämä testikoodi projektiisi
  3. Aja ComTest (Tools -> ComTest -> ComTest solution)
  4. Jos avautuu alas Test Results ja vihreä pallo missä lukee Passed, niin kaikki meni oikein. Muussa tapauksessa tutki asennusohjeita uudestaan ja kysy tarvittaessa apua ohjaajilta.

Palauta DemoWWW:ssä tekstitiedosto tdd.txt (jonka siis arvostelet yhden pisteen arvoiseksi), missä kerrot minkä tehtävän ja minkä funktion/funktioiden toiminnan testasit. Voit antaa samassa tiedostossa palautetta ja kehitysehdotuksia Comtestin käytöstä. Tehtävän "numeroksi" anna TDD1. Taulukon testaaminen ComTestillä:

/// int[] luvut = {1,3,6};
/// String.Join(luvut, " ") === "1 3 6";

Jos haluat viedä testiin taulukon "luomatta" sitä apumuuttujaan, niin seuraava auttaa:

/// SuurinJaPienin.Pienin(new int[]{1, 2 ,3}) === 1;

Valitettavasti 2-ulotteiselle taulukolle ei ole vastaavaa Join-funktiota, vaan sellaisen joutuu tekemään itse. StringBuilderin arvon testaaminen pitää suorittaa ToString()-metodin avulla

/// StringBuilder j1 = new StringBuilder("123");
/// Jonoja.LisaaAlkuunJaLoppuun(j1, "XX");
/// j1.ToString() === "XX 123 XX";

Tehtävä 1

M: 15. Taulukot. Ota Demon 4 tehtävän 5 mallivastaus (SuurinJaPienin.cs) ja muuta sen pääohjelma seuraavaksi:

public static void Main(string[] args)
{
  int[] luvut = new int[3];
  Console.Write("Anna 1. kokonaisluku >");
  luvut[0] = int.Parse(Console.ReadLine());
  Console.Write("Anna 2. kokonaisluku >");
  luvut[1] = int.Parse(Console.ReadLine());
  Console.Write("Anna 3. kokonaisluku >");
  luvut[2] = int.Parse(Console.ReadLine());
  
  int suurin = Suurin(luvut);
  int pienin = Pienin(luvut);
  
  Console.WriteLine("Suurin luku on " + suurin);
  Console.WriteLine("Pienin luku on " + pienin);
  Console.ReadKey();
}

Sitten muuta aliohjelmat niin, että ne käsittelevät kolmepaikkaista taulukkoa (tässä ensimmäisessä taulukkotehtävässäsi saat poikkeuksellisesti olettaa että taulukossa on tasan 3 alkiota, jatkossa tällaista oletusta ei saa tehdä). Ideana tässä on siis suurinpiirtein korvata koodissa (verrattuna demo4/tehtävä5:een)

 a => luvut[0]
 b => luvut[1]

Tehtävä 2

M: 16. Toistorakenteet. Tee aliohjelma TulostaKertotaulu(n), joka tulostaa n:n kertotaulun for-silmukalla. Esimerkiksi TulostaKertotaulu(3) tulostaisi:

 1 * 3 =   3
 2 * 3 =   6
 3 * 3 =   9
 4 * 3 =  12
 5 * 3 =  15
 6 * 3 =  18
 7 * 3 =  21
 8 * 3 =  24
 9 * 3 =  27
10 * 3 =  30

Tee vielä TulostaKertotauluWhile(n, m), joka tulostaa n:än kertotaulusta m-riviä. Toteutus while-silmukalla. Esimerkiksi TulostaKertotauluWhile(3, 5) tulostaisi:

 1 * 3 =   3
 2 * 3 =   6
 3 * 3 =   9
 4 * 3 =  12
 5 * 3 =  15

Tee sama vielä do-while -silmukalla. Mitä TulostaKertotauluDoWhile(6, 0); tulostaa jos ei tehdä mitään erikoislisäyksiä? Mitä pitäisi lisätä?

Tehtävä 3

M: 12.3 Muokattavat merkkijonot: StringBuilder. Tee seuraavaan pääohjelmaan tarvittava aliohjelma:

public static void Main(string[] args)
{
  StringBuilder jono;
  jono = new StringBuilder("kissa istuu");
  LisaaAlkuunJaLoppuun(jono, "***"); // jono muuttuu aliohjelmassa
  Console.WriteLine("Jono on nyt " + jono); 
  // tulostaa: Jono on nyt *** kissa istuu ***
}

Vinkki: Katso StringBuilderin dokumentaatiosta miten voit lisätä tekstiä jonon keskelle ja miten loppuun.

Tehtävä 4

M: 15. Taulukot, 16. Toistorakenteet. Olkoon meillä taulukko, joka sisältää int-tyyppisiä kokonaislukuja. Tee aliohjelma TulostaYli(taulukko, raja), joka tulostaa taulukosta kaikki ne luvut (alkiot), jotka ylittävät annetun rajan eli tietyn luvun. Päätä itse ja dokumentoi, että kuuluuko raja tulostettaviin vai ei. Tee vastaava funktio SummaYli(taulukko, raja), joka palauttaa rajan ylittävien taulukon lukujen summan. Esimerkiksi pääohjelma

public static void Main(string[] args)
{
  int[] luvut = { 12, 3, 5, 9, 7, 1, 4, 9 };
  TulostaYli(luvut, 4);
  int summa = SummaYli(luvut, 4);
  Console.WriteLine("Yli 4 olevien lukujen summa on: " + summa);
  Console.ReadKey();
}

tulostaisi

12 5 9 7 9
Yli 4 olevien lukujen summa on: 42

Tehtävä 5

Moniulotteiset taulukot. Et tarvitse Visual Studiota/C#:ia tässä tehtävässä. Olkoon meillä 4 x 4 matriisi (siis 2-ulotteinen taulukko):

[ 1 0 1 1 ]
[ 0 1 1 0 ]
[ 1 0 0 0 ]
[ 1 0 0 1 ]

Ykköset kuvaavat tässä "sopuleita", ja nollat ovat tyhjiä paikkoja.

Lisäksi olkoon seuraavanlainen algoritmi:

Jos ruudussa on sopuli (eli alkion arvo on 1)
  * Jos sillä on naapureita (ykkösiä) yksi tai 
    nolla kappaletta, se kuolee yksinäisyyteen 
    (muuttuu nollaksi).
  * Jos sillä on neljä tai enemmän naapureita, 
    se kuolee ylikansoitukseen (muuttuu nollaksi).
  * Sellainen, jolla on täsmälleen kaksi tai kolme 
    naapuria, selviää hengissä.
Jos ruutu on tyhjä (eli arvo on 0)
  * Jos on täsmälleen kolme naapuria, ruutu "herää 
    eloon" (muuttuu ykköseksi).

Tee yllä olevalle matriisille kolme seuraavaa generaatiota, eli käy jokainen alkio läpi yllä annettua algoritmia käyttäen. Naapureita ovat sekä pysty-, vaaka- että "vinot" naapurit.

Tee tehtävä kahdella eri tavalla

  1. Niin, että aina teet uuden tyhjän taulukon ja siihen vastinpaikkaan kuuluvan alkion arvon katsot edellisestä taulukosta em. säännöillä.
  2. Kopioit edellisen taulukon ja lähdet kopiota muuttamaan "laskemalla" arvot kopiotaulukosta itsestään. Alkiot käsitellään vasemmalta oikealle, ylhäältä alas.

Tuleeko eri tavoilla tehtynä eri tulos? Miksi?

Tehtävä palautetaan tekstitiedostona teht5.txt, joka sisältää alkuperäisen taulukon lisäksi kumpaankin eri tapaan kolme uutta samankokoista taulukkoa. Kirjoita taulukot allekkain tekstitiedostoon.

Tehtävä 6

(a) (0.5 p.) Lataa ja asenna ComTest. Voit laittaa itsellesi puoli pistettä kun ko. sivulla oleva esimerkkitesti (Example Test) menee läpi.

(b) (0.5 p.) Täydennä seuraavaan funktioon ComTest-testit, missä toinen laskettavista luvuista on negatiivinen, sekä ainakin yksi sellainen testi, missä tulos on negatiivinen. Paikka, mihin testit kirjoitetaan on tässä kommentoitu TODO-sanalla. Kirjoita myös ympärille luokka, sekä luokan pääohjelma omatoimisesti. Pääohjelma voi olla "tyhjä", eli sen ei tarvitse tehdä mitään.

Toteuta myös itse funktio ja täydennä puuttuvat sanat, jotka on alla xxx:llä). Aja testit ja totea että ne menevät läpi.

/// <summary>Lasketaan yhteen kaksi lukua</summary>
/// <param name="luku1">ensimmäinen yhteenlaskettava</param>
/// <param name="luku2">ensimmäinen yhteenlaskettava</param>
/// <returns>lukujen summa</returns>
/// @example
/// <pre name="test">
///  Laskut.LaskeYhteen(2, 3) ~~~ 5;
///  Laskut.LaskeYhteen(2.4, 0) ~~~ 2.4;
///  // TODO: testi jossa toinen on negatiivinen ja tulos positiivinen
///  // TODO: testi jossa toinen on positiivinen ja tulos negatiivinen
/// </pre>
/// @endexample
public static xxx LaskeYhteen(xxx luku1, xxx luku2)
{
  // toteuta funktio
}

Huomaa! Liukulukuja (eli reaalilukuja) ei saa ComTestissa verrata kolmella yhtäsuuruusmerkillä (===), vaan ne pitää verrata kolmella matomerkillä ~~~. Syy, ettei reaalilukuja saa (muutamia poikkeuksia lukuunottamatta) verrata ComTestissä === -merkinnällä eikä tavallisessa koodissa == -vertailuoperaattorilla, on, että muita lukuja kuin 2-potenssien summia ei voida ilmoittaa tietokoneilla tarkasti. Esim. luku 0.1 ei ole 2-potenssien summa joten sitä ei voida ilmoittaa tietokoneella tarkasti, vaan se on todellisuudessa (tietokoneen näkökulmasta) jotain himpun verran yli 0.1, mutta luku 0.75 on 2-potenssien summa 1 * 2-1 + 1 * 2-2, katso vaikka : http://bit.ly/zn6R9Y, joten se on "oikeasti" 0.75.

Ko. aiheesta tulee kyllä lisää juttua luennolla ja demoissa mutta tässä vaiheessa riittää muistaa, että jos funktion paluuarvon tyyppinä on double niin vertailu tehdään === -merkinnällä ComTestissa ja erityisesti HUOM!: "Normaalissa" koodissa pitää erittäin suurella varovaisuudella suhtautua double-lukujen vertailuun == -vertailuoperaattorilla, koska yleensä se menee pieleen.

B1

M: 12. Merkkijonot.: Tuliko Demo 4 tehtävässä 4 isot kirjaimet huomioitua? Muuta tehtävän 4 vastausta niin, että teet funktioaliohjelman (palauttaa siis merkkijonon), jota kutsutaan seuraavasti:

String tulos = MuutaKirjaimet(jono, 'r', 'l');

Funktio muuttaa sekä isot että pienet kirjaimet (vinkki: Kun funktiolle tuodaan esimerkiksi 'r' ja 'l', niin se pyytää vaihtamaan 'r' -> 'l' ja 'R' -> 'L'.) Tee tuota funktiota käyttäen ohjelma joka toimii seuraavasti:

Toittan mitä tanot, mutta en otaa tanoa kirjainta t!
Anna teksti >Seppo tykkää jätskistä.
Tanoit tiit: Teppo tykkää jättkittä.

Ohjelma saadaan siis kahden merkin vaihtamisella toimimaan edellisen kerran tehtävän 3 vastauksena.

B2

Ota Demo 4:n bonus ja guru-tehtävien pallopelin mallivastaus. Katso Jypelin ohjeista miten lisätään pistelaskuri ja sille tapahtuma kun tulee tarpeeksi pisteitä. Lisää pallopeliin laskuri jonka arvo kasvaa aina kun saat "metsästettyä" pallon puolen välin yläpuolella. Kun 10 palloa on saatu poksautettua, lisää tähän joku onnittelu (vaikka MessageDisplay-oliolla).

Mallivastauksessa käytetyt kuvat saat käyttöön seuraavasti:

  • ota kuvat.zip
  • pura se johonkin hakemistoon
  • mene siihen kansioon, johon purit kuvat
  • raahaa kuvat PallotContent -nimen päällä Visual Studiossa

Jos et halua käyttää kuvia, kommentoi koodista pois kaikki kuviin liittyä tai laita omia kuvia tilalle.

G1-3

Tee konsoliohjelma, joka tulostaa vaiheittain tehtävän 5 generaatioita. Täydellisen 3 pisteen merkinnän saat, mikäli tehtävässä on myös automaattiset testit kummankin tapauksen 3:lle generaatiolle. Testaamisen helpottamiseksi tee aliohjelma (funktio), joka palauttaa 2-ulotteisen taulukon merkkijonona.