Programozás tanfolyam

Feladatmegoldások: https://pastebin.com/3MJDSLKu

C# referencia dokumentáció: https://www.tutorialspoint.com/csharp/csharp_program_structure.htm

1. Telepítendő alkalmazások

2. Első projekt beindítása

  1. Mappa létrehozása,
  2. Parancssor megnyitása, megtalálni a létrehozott mappát,
  3. futtatni: “dotnet new console”, “dotnet run”
  4. VSCode indítása,
  5. File/Open… létrehozott mappa megnyitása,
  6. Omnisharp ablak megnytása (Zöld lángnyelv egészen alul),
  7. Terminal tab-fül,
  8. futtatni: “dotnet run”

3. Minta program átírása

using System;

namespace Oktatas
{
    class Program
    {
        static void Main(string[] args)
        {
            new Program().example1();
        }

        void example1()
        {
            Console.WriteLine("Hello World!");
        }
    }
}

3.1 Új eljárás létrehozása

using System;

namespace Oktatas
{
class Program
{
static void Main(string[] args)
{
new Program().example2();
}

void example1()
{
Console.WriteLine("Hello World!");
}
void example2()
{
Console.Write("Write your name:");
string name = Console.ReadLine();
Console.WriteLine("Hello " + name);
}

}
}

4. Blokkok, Változók és adattípusok, operátorok

4.1 Típusok és műveletek (operátorok)

        void example3()
        {
            int n1 = 1234;
            int n2 = 5678;
            int result = n1 + n2;
            Console.WriteLine("Sum is " + result);
        }

4.1.1 Feladat: Próbáljuk ki más műveleteket és értékeket is.

Figyeld meg: Osztás műveletnél is mindig egész számot kapsz. Miért? Hogyan lehet pontosabb eredményt megjeleníteni?

4.2 Bevitel és konverzió

        void example4()
        {
            Console.Write("Enter a number:");
            int n1 = System.Convert.ToInt32(Console.ReadLine());
            Console.Write("Enter second number:");
            int n2 = System.Convert.ToInt32(Console.ReadLine());
            int result = n1 + n2;
            Console.WriteLine("Sum is " + result);
        }

4.2.1 Feladat: Próbáljunk ki más műveleteket is.

4.2.2 Feladat: futtatás során adjunk meg “nem várt” értékeket!

4.2.3 Kód formázás

5. Vezérlési szerkezetek

5.1 Logikai kifejezések, elágazások

        void example5()
        {
            Console.Write("Enter a number:");
            int n1 = System.Convert.ToInt32(Console.ReadLine());
            Console.Write("Enter second number:");
            int n2 = System.Convert.ToInt32(Console.ReadLine());
            if (n2 == 0) {
                Console.WriteLine("Cannot divide with zero");
            }
            else {
                int result = n1 / n2;
                Console.WriteLine("The result of the division is " + result);
            }
        }

5.1.1 Feladat: Az example2-t írjuk át úgy, hogy ne fogadjon el 3 karakternél rövidebb nevet. (A név hosszát így bírjuk lekérdezni: name.Length )

5.1.2 Feladat: Az example2-t írjuk át úgy, hogy egy “jelszót” kérjen be a rendszer, helyes jelszóra írjon ki egy “titkot”, hibás jelszóra elutasító üzenetet.

5.1.3 Logikai operátorok átismétlése.

5.2 Ciklusok

        void example6()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.Write(" " + i);
            }
            Console.WriteLine();
        }
        void example7()
        {
            int i = 0;
            while (i < 10)
            {
                Console.Write(" " + i);
                i = i + 1;
            }
            Console.WriteLine();
        }

5.2.1 Feladat: “i = i + 1” helyett használjunk más megoldást!

5.2.2 Feladat: Jelenítsünk meg olyan számtani sorozatot, aminek a differenciája 2.

5.2.3 Feladat: A 4-es és 6-os példákból tanultak alapján készítsünk olyan megoldást, ahol egy megadott számig történik a számolás.

5.2.4 Feladat: Az előző feladatot alapul véve készítsünk el a következő megoldást. Egy számot bevisz a felhasználó. Ezután a pozitív egész számokat adjuk össze addig, amíg el nem érjük a felhasználó által megadott számot.

5.2.5 Feladat: “Gondoltam egy számra 1 és 100 között” játék elkészítése.

        void szamjatek()
        {
            Console.WriteLine("Gondolj egy számra 1 és 100 között!");
            int max = 101;
            int min = 0;
            while (true)
            {
                int mid = min + ((max - min) / 2);
                Console.WriteLine("Nagyobb mint " + mid + "? (I/N) ");
                string answer = Console.ReadLine();
                if ((answer == "I") || (answer == "i"))
                {
                    min = mid;
                }
                else
                {
                    max = mid + 1;
                }
                if ((min + 2) == max)
                {
                    Console.WriteLine("A(z) " + (min + 1) + " számra gondoltál.");
                    break;
                }
            }
        }

Véletlen szám generálása 1 és száz között a következő kóddal történhet:

Random rnd = new Random()
int veletlenszam = rnd.Next(100) + 1;

5.2.6 Feladat: Az 5.1.2-es “jelszóbekérő” feladat megoldását módosítsuk úgy, hogy háromszor próbálkozhat a jelszó megadásával!

6. Tömbök és Struktúrák

6.1 Tömbök

        void example8()
        {
            char[] letters = { 'r', 'e', 'd' };
            Random rnd = new Random();
            for (int i = 0; i < 4; i++)
            {
                int index = rnd.Next(letters.Length);
                char letter = letters[index];
                Console.Write(letter);
            }
            Console.WriteLine();
        }

6.1.1 Feladat: egy futtatásra több szót is kiírjon!

6.1.2 Feladat: a szavak hossza is legyen véletlenszerű!

6.1.3 DEBUG! (Image)

6.1.4 Hogyan fejleszthetnénk tovább az algoritmust, hogy “szebb” szavakat hozzon létre?

6.1.5 “string” típus

6.2 Struktúrák

        struct Vector
        {
            public int x;
            public int y;
        };
        void example9()
        {
            Vector[] vectors = new Vector[3];
            for (int i = 0; i < vectors.Length; i++)
            {
                Console.Write("X: ");
                vectors[i].x = System.Convert.ToInt32(Console.ReadLine());
                Console.Write("Y: ");
                vectors[i].y = System.Convert.ToInt32(Console.ReadLine());
                Console.WriteLine();
            }

            Vector result;
            result.x = 0;
            result.y = 0;
            foreach (Vector v in vectors)
            {
                result.x += v.x;
                result.y += v.y;
            }
            Console.WriteLine("Result is [" + result.x + ", " + result.y + "]");
        }

6.2.1 Figyeljük meg a “foreach” használatát!

6.2.2 Jelszó bekérő (example10)

        struct Credential
        {
            public string name;
            public string password;
        };
        void example10()
        {
            Credential[] logins = new Credential[2];

            logins[0].name = "john";
            logins[0].password = "secure";

            logins[1].name = "bob";
            logins[1].password = "pass";

            Console.Write("Login: ");
            string nameEntered = Console.ReadLine();
            Console.Write("Password: ");
            string passwordEntered = Console.ReadLine();

            for (int i = 0; i < logins.Length; i++)
            {
                if ((nameEntered == logins[i].name) && (passwordEntered == logins[i].password))
                {
                    Console.WriteLine("Welcome " + nameEntered + "!");
                    return;
                }
            }
            Console.WriteLine("Permission denied!");
        }

7. Metódusok

Az example9 átírása.

        void example11()
        {
            Vector[] vectors = new Vector[3];
            for (int i = 0; i < vectors.Length; i++)
            {
                Console.Write("X: ");
                vectors[i].x = System.Convert.ToInt32(Console.ReadLine());
                Console.Write("Y: ");
                vectors[i].y = System.Convert.ToInt32(Console.ReadLine());
                Console.WriteLine();
            }
            Vector result = addVectors(vectors);
            Console.WriteLine("Result is [" + result.x + ", " + result.y + "]");
        }
        Vector addVectors(Vector[] vectors)
        {
            Vector result;
            result.x = 0;
            result.y = 0;
            foreach (Vector v in vectors)
            {
                result.x += v.x;
                result.y += v.y;
            }
            return result;
        }

7.1.1 Figyeljük meg a metódus paramétereit és visszatérési értékét!

Láthatóság

Blokkok (ismétlés)

8. OOP

(Egyelőre most csak elméleti szinten, később a gyakorlatok során visszatérünk majd rá.)

Osztály vs. Példány – Osztály = típus leíró; Példányból lehet több is. (Class / Instance)

9. Közös feladatmegoldás

Együtt gondolkodva sajátítjuk el azt, hogy egy milyen módon álljunk hozzá egy komplexebb probléma megoldásához.

9.1 Véletlen szerű számok és a nagy számok törvénye

9.1.1 Feladat: Szimuláljunk dobókocka dobást véletlen szám generátorral. A dobást ismételjük meg 10-szer.

9.1.2 Feladat: Számoljuk össze, hogy az egyes számok hányszor jelentek meg. Mosmár csak a számolás eredménye érdekes, végezzük el a számolást 100, 1000, 100 000 dobásra. Mit tapasztalunk?

9.1.2 Feladat: Írjuk át az előző feladatot úgy, hogy számoljuk két 6-os előfordulása közben hány olyan dobás volt, ami nem 6-os. Csak az érdekel, hogy mi volt a legnagyobb távolság két 6-os dobása között.

9.1.3 Feladat: Írjunk olyan programot, ami egy megadott arab számot római számmal ír ki. (Maximum 2000-ig kell helyesen működjön.)

9.2 Játékok

9.2.1 Írjuk meg közösen a Mesterlogika (mastermind) játékot. Mindig a gép gondol egy feladványra, amit a felhasználónak kell megfejtenie.

Megoldás: https://pastebin.com/VKYyPN3s

Órai megoldás: https://pastebin.com/qWhxHWkE

9.2.2 Írjuk meg a Blackjack játékot.

Elvégzendő lépések:

  1. Hozzunk létre egy struktúrát a kártyalap típusok tárolására. Tulajdonságok: megnevezés, érték
  2. Töltsünk föl egy listát a létező kártyatípusokkal.
  3. Írjunk egy metódust, ami kioszt egy véletlenszerű kártyalapot.
  4. Osszunk ki kezdésből két kártyalapot.
  5. Hozzunk létre egy listát a kezünkben levő kártyák letárolására, kiosztáskor ebbe a “kézbe” kerüljenek kiosztásra a lapok. (Írjuk át a metódust, hogy legyen egy bemenő paramétere, ami a lista.)
  6. Hozzunk létre egy metódust, ami a “kézben” lévő kártyákat kiírja a képernyőre és egyúttal összeszámolja azok értékét. A metódusnak a “kéz” legyen a bemenő paramétere és az összérték a kimenő paramétere. (Figyeljünk rá, hogy két ász esetén is 22 helyett 21 az összérték!)
  7. Ha az összeszámolt érték nagyobb, mint 21, akkor vesztettünk.
  8. Ha nem vesztettünk, osszon nekünk még egy lapot. Képezzünk ciklust: Kiírat, 21 ellenőrzése, új lap osztása. (Addig játszik, amíg nem vesztünk.)
  9. Egészítsük ki, hogy csak akkor osszon, ha ezt szeretnénk.
  10. Vezessünk be egy újabb listát az osztó “kezében” lévő kártyák tárolására. Induláskor az osztó kezébe is osszunk egy lapot, és jelenítsük meg a kezében lévő lapokat (ami igazából jelenleg egy lap lesz). Használjuk a korábban megírt függvényeket, a kiírató metódust egészítsük egy újabb paraméterrel, ahol megadhatjuk, hogy az osztó vagy a játékos kezét jelenítjük meg.
  11. Egészítsük ki a programot úgy, hogyha a játékos nem kér újabb lapot, akkor addig osszunk az osztónak, amíg: a) túl nem lép 21-en; b) nagyobb egyelő lesz a lapjainak értéke a játékoséval. Első esetben a játékos nyer, második esetben a bank.

Házi feladat: Legyen egyenlőség is, kezelve.

Szorgalmi feladat: Legyen egy $100-as induló tőke és minden osztás előtt rákérdezünk, hogy ebből mennyit tesz fel. (Minimum $5-et föl kell tenni.) Ha veszít a játékos, akkor ezt a pénzt elbukja. Ha nyer, akkor a tőkéje a feltett pénzmennyiséggel növekszik. Egyenlőségnél pénzénél marad.

Megoldás: https://pastebin.com/cuvXtni5

9.2.3 Írjuk meg az akasztófa játékot. Szótár: https://github.com/laszlonemeth/magyarispell/tree/master/szotar

Elvégzendő lépések:

  1. Töltsük le a szótárt. A projektünk egy mappájában legyen szövegfájl. (Figyeljük meg a szövegfájl szerkezetét.)
  2. Töltsük be a szótárat (readDict()). Használjuk a System.IO.StreamReader-et, a mintaillesztést (reguláris kifejezés) és a collection-öket (List).
  3. Válasszunk ki egy szót a betöltött szótárból (pickWord()).
  4. Írjunk ki annyi pontot, ahány betűből áll a keresett szó. (displayMaskedWord())
  5. Kérjünk be egy betűt a felhasználótól (askForChar()), a beadott betűt tároljuk el egy listában. (Később több betű is lesz.)
  6. A szó kiírását (displayMaskedWord()) módosítsuk úgy, hogy ha keresett szó aktuális betűje szerepel a beadott betűk között, akkor a pont helyett az aktuális betűt írjuk ki.
  7. Továbbá módosítsuk ugyanezt a metódust, hogy ellenőrizze minden betűt kitaláltunk-e. (Ha legalább egy pontot kiírtunk, akkor nincs minden betű kitalálva.) Legyen ez a BOOL a visszatérési értéke a metódusnak.
  8. Szervezzünk ciklust: folyton írjuk ki az állást és kérjünk be új betűt, addig amíg az összes betű ki nem találjuk. (Az, hogy ki van-e találva minden betű a displayMaskedWord() visszatérési értéke lett.)
  9. A játék lényegében kész.
  10. Módosítsuk a displayMaskedWord() metódust, hogy írja ki a beadott betűket is. String.Join(“, “, guesses.ToArray())
  11. Módosítsuk a programot, hogy számolja, hány próbálkozás kellett a kitaláláshoz. (Kérdés, hogy ha már korábban beadott betűt újra bead, az új próbálkozásnak számít-e.) Kilépéskor jelenítsük meg a próbálkozások számát.

Megoldás-sablon: https://pastebin.com/g0CVUrpx

9.3 Életjáték

A feladat célja megprogramozni az “Életjáték” algoritmust. A játék leírását ez a link tartalmazza: https://hu.wikipedia.org/wiki/Életjáték. A játék grafikai elemeihez a StreamGraphics keretrendszert használjuk a következő sablonnal: https://pastebin.com/ZbH06NrM

Elvégzendő lépések:

  • Az ujMezo metódusban végigmenni az előző mező összes elemén.
  • Metódus létrehozása, ami megszámlálja, hogy az adott mező mellett hány életet tartalmazó mező található. (Egyelőre most mindig adjon vissza kettőt.)
  • Alkalmazzuk az előző számítás eredményét figyelembe véve a játékszabályokat (3 szabály). Kérdés, hogy az új mező adott cellájába kerüljön-e élet vagy sem.
  • A szomszédok számolását programozzuk le. Az eredmény egy összeadás lesz a környező mezőkön található életek számával. A környező mezők vizsgálatára segédfüggvényeket hozunk létre:
    • Hozzunk létre egy-egy függvényt a balra és a jobbra található mezők elemzésére. A visszatérési érték legyen 0 vagy 1.
    • Hozzunk létre egy-egy függvényt a fölötte és alatta lévő mezők elemzésére. Használjuk az imént megírt ballra/jobbra függvényeket!
    • Minden esetben figyejünk arra, hogy nem létezik nullánál kisebb pozíció és mezo.Length-nél kisebb pozíciók értelezettek csak.