wiki:k2013/demot/demo5
Last modified 5 years ago Last modified on 2013-02-15 13:05:01

Demot » Demo 5, 18.2.2013

Muistathan harjoitustyön suunnitelman demo 5 palautukseen mennessä.

Tehtävien nimeämisestä: Anna C#-tiedostoille kuvaavat nimet. Esim. tehtG1.cs on huono. Opetellaan käyttämään nimiä, jotka toimisivat oikeassakin ohjelmassa. Pallopeli.cs on taas paljon parempi (ja muista se luokan nimen suhde tiedoston nimeen).

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();
}

a) Muuta funktiot Suurin ja Pienin 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]

b) Tee funktiot Suurin2 ja Pienin2 siten, että käyt taulukot for-silmukassa läpi. Muuta pääohjelmaa siten, että ensin käyttäjältä kysytään, montako lukua halutaan, ja taulukosta tehdään niin iso. Esimerkki ohjelman toiminnasta.

Voit käyttää taulukoiden hahmottamisessa ja läpikäymisessä apuna Taulukkoharjoittelu-ohjelmaa (kuva alla).

source:/malliohjelmat/taulukkoharj.png

Tehtävä 2

M: 16. Toistorakenteet. Tee aliohjelma TulostaKertotaulu(n), joka tulostaa luvun n kertotaulun for-silmukalla. Esimerkiksi kutsu 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ä ykkösestä alkaen. Toteutus while-silmukalla. Esimerkiksi kutsu 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 = 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 raja = 4; 
  int[] luvut = { 12, 3, 5, 9, 7, 1, 4, 9 };
  TulostaYli(luvut, raja);
  int summa = SummaYli(luvut, raja);
  Console.WriteLine("Yli " + raja + " olevien lukujen summa on: " + summa);
  Console.ReadKey();
}

tulostaisi

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

Tehtävä 5

Et tarvitse Visual Studiota/C#:ia tässä tehtävässä.

Moniulotteiset taulukot. Olkoon meillä 4 x 4 matriisi, siis 2-ulotteinen taulukko, jossa on 16 alkiota. (Tässä hakasulut kuvaavat vain matriisin reunoja, ei mitään sen "syvällisempää".):

[ 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">toinen 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>
/// </example>
public static xxx LaskeYhteen(xxx luku1, xxx luku2)
{
  // toteuta funktio
}

Huomaa! Liukulukuja (eli double, float tai decimal-lukuja) 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 (ks. http://bit.ly/1589Imk), mutta luku 0.75 on 2-potenssien summa

1 * 2-1 + 1 * 2-2

(ks. 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.

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";

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-2

Tee konsoliohjelma, joka tulostaa vaiheittain tehtävän 5 generaatioita. 2 pistettä saat, kun tehtävässä on myös automaattiset testit kummankin tapauksen 3:lle generaatiolle. Testaamisen helpottamiseksi tee funktio, joka palauttaa 2-ulotteisen taulukon merkkijonona.

G3

Mitä eroa on seuraavilla taulukoilla? Miksi C#:ssa on kaksi eri tapaa ilmaista moniulotteisia taulukoita?

int[,] a = new int[3, 2];
int[][] b = new int[3][];

G4-5

a) (1 p.) Tee tehtävä 4 käyttäen C#:n LINQ:ta ja Where-filtteröintiä. Vinkki: Saat muutettua Where:n palauttaman IEnumerable:n taulukoksi ToArray:llä.

b) (1 p.) Ota tehtävä 4:n taulukko ja sieltä sellaiset luvut, jotka ovat suurempia kuin 5 ja parillisissa indekseissä.