C# Játék programozás átírása a feltételeknek megfelelően
2020-12-13T15:25:52+01:00
2020-12-13T20:11:08+01:00
2022-07-19T00:42:37+02:00
Welfel
Sziasztok!

SOS-ban kellene a válasz. Írtam C#-ban egy játékot ami működik is. A baj az, hogy jó pár parancs nem fogadható el és nem tudom, hogyan kéne javítani.

Amit ki kell szedni a kódból:
• ne legyen this[pont p] indexelő -> cseréld ki egy függvényre
• ne legyen => operátor -> cseréld ki rendes get set blokkokra
• ne legyen List, vagy egy MyList saját lista implementációt csinálsz, vagy tömbre cseréld ki -> a saját lista osztály egy privát tömböt tartalmaz abból a típusból amiből helyettesíted a listát, van publikus Add, Get és Remove függvénye, a tömb mérete dinamikusan változzon, azaz Add esetén egy n+1 elemű új tömbbe átmásolod az eddigi elemeket és az utolsó helyre beszúrod az addolt elemet, remove esetén egy n-1 elemű tömb jön létre amibe azokat másolod csak át a régi tömbből ami nem a törlendő elem, a get pedig csak megkeres egy elemet és ha van akkor visszaadja, ha nincs akkor null vagy -1 vagy valami.

Holnap 18:00-ig kell leadjam. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Feleves_feladat_javitas { class Program { const string fajlnev = "leaderboard.txt"; static void Main(string[] args) { Console.CursorSize = 100; Console.SetWindowSize(80, 30); Console.SetBufferSize(80, 30); dicsosegtabla e = new dicsosegtabla(); Console.WriteLine("A kurzor mozgatása a WASD-ven illetve nyilakkal."); Console.WriteLine("Kérlek add meg a nevedet: "); e.Nev = Console.ReadLine(); Console.WriteLine("Mennyi ideig szeretnél játszani? (percben): "); if (int.TryParse(Console.ReadLine(), out int perc)) { e.Ido = perc; } else { e.Ido = 0; } Jatek game = new Jatek(79, 24, e.Ido * 60, 1.5); game.jatekMenet(); Console.Clear(); e.Eredmeny = game.Eredmeny; e.Mentes(fajlnev); dicsosegtabla[] bemenet = dicsosegtabla.Load(fajlnev); Console.WriteLine("Dicsőségtábla"); for (int i = 0; i < bemenet.Length; i++) { Console.WriteLine($"{bemenet[i].Nev,-30}{bemenet[i].Ido,3} perc {bemenet[i].Eredmeny,5} pont"); } Console.ReadLine(); } } public class szin { private const int max = 8; private static ConsoleColor[] colors = new ConsoleColor[] { ConsoleColor.Cyan, ConsoleColor.Green, ConsoleColor.Yellow, ConsoleColor.Red, ConsoleColor.Magenta, ConsoleColor.DarkCyan, ConsoleColor.DarkGreen, ConsoleColor.Blue }; private static char[] szimbolum = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', }; private int ertek; public ConsoleColor Color => colors[ertek]; public char Szimbolum => szimbolum[ertek]; public bool megjelol { get; set; } public szin(int ertek) { if (ertek >= max) throw new ArgumentException("Ismeretlen."); this.ertek = ertek; } public static szin CreateRandom(Random randomGenerator) { return new szin(randomGenerator.Next(max)); } public bool Equals(szin masik) { if (masik == null) { return false; } return this.ertek == masik.ertek; } public static szin Kulonbozo(szin jewel) { return new szin((jewel.ertek + 1) % max); } public void visszad(pont p) { Console.SetCursorPosition(p.X, p.Y); Console.ForegroundColor = this.Color; Console.Write(this.Szimbolum); } } public class palya { private readonly szin[,] jewels; public int szeles => jewels.GetLength(0); public int magas => jewels.GetLength(1); public palya(int szeles, int magas) { jewels = new szin[szeles, magas]; } public szin this[pont p] { get { if (IsInBounds(p)) { return jewels[p.X, p.Y]; } else { return null; } } set { if (IsInBounds(p)) { jewels[p.X, p.Y] = value; } } } public bool IsInBounds(pont p) { return p.X >= 0 && p.X < szeles && p.Y >= 0 && p.Y < magas; } } class Allapot { public bool Racs => ChangedCells.Count > 0; public bool VisszaIdo => DateTime.Now - utolsoIdo > TimeSpan.FromSeconds(1); public bool Szukseges => Racs || VisszaIdo; public List<pont > ChangedCells { get; } private DateTime utolsoIdo; public Allapot() { utolsoIdo = DateTime.MinValue; ChangedCells = new List<pont>(); } public void Idozito() { utolsoIdo = DateTime.Now; } } public class Jatek { private readonly Random random; private pont kuzorpozicio; // Esély egy ékszer létrehozására, amely garantáltan különbözik minden szomszédjától, hogy ellenőrizze a nehézségeket. private double Esely; private DateTime JatekVege; private int JatekHossz; private Allapot Allapot; private palya grid; public int Eredmeny { get; private set; } public Jatek(int szeles, int magas, int gameLengthSeconds, double difficulty) { grid = new palya(szeles, magas); random = new Random(); kuzorpozicio = new pont(szeles / 2, magas / 2); Esely = 1 - Math.Exp(-difficulty); this.JatekHossz = gameLengthSeconds; Allapot = new Allapot(); } public void jatekMenet() { Init(); Teljes(); bool fut = true; while (fut) { bool meccsvan = meccs(); bool ujertek = false; if (meccsvan) { Oszlopok(); } else { ujertek = OszlopToltes(); } // A felhasználótol bekért információ if (!meccsvan && !ujertek && Console.KeyAvailable) { fut = Felhasznalo(fut); } else { // discard all user input while it's not the user's turn while (Console.KeyAvailable) { Console.ReadKey(true); } } //A játék végeredménye if (DateTime.Now > JatekVege) { fut = false; } // Képernyő frissítése if (Allapot.Szukseges) { visszaFrissit(); } System.Threading.Thread.Sleep(30); // Az összes új ékszer/érték megállítása egy pillanatra if (meccsvan) { System.Threading.Thread.Sleep(100); } if (ujertek) { System.Threading.Thread.Sleep(200); } } GameOver(); } private void GameOver() { string uzenet = $"G A M E O V E R - {Eredmeny} pont"; Console.CursorVisible = false; Console.SetCursorPosition(0, grid.magas / 2 - 1); Console.WriteLine(new string(' ', grid.szeles)); Console.WriteLine(new string(' ', grid.szeles)); Console.WriteLine(new string(' ', grid.szeles)); Console.ForegroundColor = ConsoleColor.Red; Console.SetCursorPosition(grid.szeles / 2 - uzenet.Length / 2, grid.magas / 2); Console.Write(uzenet); Console.ReadKey(); } private void Init() { JatekVege = DateTime.Now.AddSeconds(JatekHossz); for (int col = 0; col < grid.szeles; col++) { for (int row = 0; row < grid.magas; row++) { pont p = new pont(col, row); szin jewel = szin.CreateRandom(random); while (jewel.Equals(grid[p.Bal]) || jewel.Equals(grid[p.Fel])) { jewel = szin.Kulonbozo(jewel); } grid[p] = jewel; } } } private bool meccs() { bool meccsvan = false; // A kitörlendő értékek/ékszerek megjelölése for (int col = 0; col < grid.szeles; col++) { for (int row = 0; row < grid.magas; row++) { pont p = new pont(col, row); szin mostani = grid[p]; if (mostani != null) { szin right = grid[p.Jobb]; szin down = grid[p.Le]; if (mostani.Equals(down)) { mostani.megjelol = true; down.megjelol = true; } if (mostani.Equals(right)) { mostani.megjelol = true; right.megjelol = true; } } } } // A kitörlendő ékszerek/értékek eltávolítása for (int col = 0; col < grid.szeles; col++) { for (int row = 0; row < grid.magas; row++) { pont p = new pont(col, row); szin mostani = grid[p]; if (mostani != null && mostani.megjelol) { grid[p] = null; Eredmeny++; Allapot.ChangedCells.Add(p); meccsvan = true; } } } return meccsvan; } private void Oszlopok() { // Az összes oszlopra: for (int col = 0; col < grid.szeles; col++) { int visszater = 0; // Insertion sort of one column. Sort all nulls to the top of the column (must be stable) // Egy oszlopot illeszt be. Mindenképp úgy rendezi, hogy az oszlopban a 0-kat a tetejére. for (int i = 1; i < grid.magas; i++) { int j = i - 1; pont p = new pont(col, j); szin mostani = grid[p]; szin alatti = grid[p.Le]; while (j >= 0 && mostani != null && alatti == null) { grid[p] = alatti; grid[p.Le] = mostani; j = j - 1; p = new pont(col, j); mostani = grid[p]; alatti = grid[p.Le]; // Elements of this column may change between 0th and i-th element, and must be redrawn. // Az elemek ebben az oszlopban, lehet változás a 0 és az i-dik elem között, és muszáj újrakészíteni visszater = i; } } // Mark changed cells for redraw // A megjelölt cserélt cellák/betűk/jelek újrakészítése for (int i = 0; i <= visszater; i++) { pont p = new pont(col, i); Allapot.ChangedCells.Add(p); } } } private bool OszlopToltes() { bool ujErtek = false; for (int col = 0; col < grid.szeles; col++) { pont p = new pont(col, 0); while (grid.IsInBounds(p) && grid[p] == null) { szin jewel = szin.CreateRandom(random); if (random.NextDouble() < Esely) { while (jewel.Equals(grid[p.Bal]) || jewel.Equals(grid[p.Jobb]) || jewel.Equals(grid[p.Fel]) || jewel.Equals(grid[p.Le])) { jewel = szin.Kulonbozo(jewel); } } grid[p] = jewel; Allapot.ChangedCells.Add(p); ujErtek = true; p = p.Le; } } return ujErtek; } private bool Felhasznalo(bool fut) { ConsoleKeyInfo keyInfo = Console.ReadKey(true); switch (keyInfo.Key) { case ConsoleKey.W: mozgathatoHa(kuzorpozicio.Fel); break; case ConsoleKey.A: mozgathatoHa(kuzorpozicio.Bal); break; case ConsoleKey.S: mozgathatoHa(kuzorpozicio.Le); break; case ConsoleKey.D: mozgathatoHa(kuzorpozicio.Jobb); break; case ConsoleKey.UpArrow: csereHa(kuzorpozicio.Fel); break; case ConsoleKey.LeftArrow: csereHa(kuzorpozicio.Bal); break; case ConsoleKey.DownArrow: csereHa(kuzorpozicio.Le); break; case ConsoleKey.RightArrow: csereHa(kuzorpozicio.Jobb); break; case ConsoleKey.Escape: fut = false; break; default: break; } Console.SetCursorPosition(kuzorpozicio.X, kuzorpozicio.Y); return fut; } private bool Cserelheto(pont from, pont to) { bool vegeredmeny = false; szin jewel = grid[from]; if (jewel == null) { return false; } foreach (pont point in to.nyilak) { if (!from.Equals(point) && jewel.Equals(grid[point])) { vegeredmeny = true; } }
Mutasd a teljes hozzászólást!
Na írogattam egy kicsit:

ne legyen this[pont p] indexelő -> cseréld ki egy függvényre:
Ezt szerintem nem lehet egy függvénnyel megcsinálni, csak kettővel, így javaslok egy
GetGridColor és SetGridColor függvényt.

public szin GetGridColor(pont p) { if (IsInBounds(p)) { return jewels[p.X, p.Y]; } else { return null; } } public void SetGridColor(pont p, szin sz) { if (IsInBounds(p)) { jewels[p.X, p.Y] = sz; } }
Használatra példák:

jewel.Equals(grid[p.Bal])
helyett:

jewel.Equals(grid.GetGridColor(p.Bal))
"setter":

grid[p] = jewel; // helyette: grid.SetGridColor(p, jewel);

ne legyen => operátor -> cseréld ki rendes get set blokkokra:
Tehát ne használd az úgynevezett "Expression-bodied members" szintaxist, hanem sima getter:

public ConsoleColor Color // az egész amúgy mehet egy sorba is { get { return colors[ertek]; } }
ne legyen List...:
Itt elegánsabb egy saját List osztály, mert akkor alig kell a kód többi részén változtatni:

class MyList { int count = 0; private pont[] changedCells = new pont[0]; private pont[] newArray; public int Count { get { return changedCells.Length; } } // ha megengedett, akkor ezzel használhatod a listát // foreach-csel is (pont p in ChangedCells.Cells), // ha nem, akkor marad a sima for ciklus, vagy GetEnumerator..., stb-t írsz public pont[] Cells { get { return this.changedCells; } } public void Add(pont p) { ++count; newArray = new pont[count]; for (int i = 0; i < changedCells.Length; ++i) { newArray[i] = changedCells[i]; } newArray[count - 1] = p; changedCells = newArray; } public pont Get(int idx) { if (idx >= 0 && idx < this.Count) { return changedCells[idx]; } else { // itt valamit vissza kell adni, amivel jelzed, // hogy érvénytelen elemre hivatkozol return new pont(-1, -1); } } public void Clear() { count = 0; changedCells = new pont[0]; } // Az idx-edik elem törlése, de ezt amúgy nem használod // a kódban, de a leírás szerint kell... // szerk: a Remove hibás volt, elvileg most már jó: public void Remove(int idx) { if (!(idx >= 0 && idx < this.Count)) { return; } --count; newArray = new pont[count]; int j = 0; for (int i = 0; i < this.Count; ++i) { if (i != idx) { newArray[j] = changedCells[i]; ++j; } } changedCells = newArray; } }
Remélem, világos, hogy hogyan kell használni, én teszteltem, és látszólag ugyanúgy működött a játék. Ha valami hiba maradt, azt már rád bíznám.
Teljes működő kódot nem szeretnék adni, így is megírtam helyetted :)

A kódod amúgy elég kaotikus, pl nem javasolt keverni az angol és magyar változóneveket, megjegyzéseket, a nevek nem mindig beszédesek, hol kis, hol nagybetűs egy függvény(metódus inkább C#-osan) stb.

Olvasnivaló, amik hasznosak lehetnek a feladat kapcsán:
Getter property with arguments
How to use foreach keyword on custom Objects in C#


Üdv.
Mutasd a teljes hozzászólást!

  • Üdv!

    Első körben nem ártana, ha valahogy sikerülne a teljes fordítható forráskódot beilleszteni.
    Ha esetleg a prog.hu fórummotorja rontotta el, akkor csatold mellékletként a .cs fájlt.
    Mutasd a teljes hozzászólást!
  • Bocsánat, csak eddig nem engedte.
    Itt van:
    Mutasd a teljes hozzászólást!
    Csatolt állomány
  • Na írogattam egy kicsit:

    ne legyen this[pont p] indexelő -> cseréld ki egy függvényre:
    Ezt szerintem nem lehet egy függvénnyel megcsinálni, csak kettővel, így javaslok egy
    GetGridColor és SetGridColor függvényt.

    public szin GetGridColor(pont p) { if (IsInBounds(p)) { return jewels[p.X, p.Y]; } else { return null; } } public void SetGridColor(pont p, szin sz) { if (IsInBounds(p)) { jewels[p.X, p.Y] = sz; } }
    Használatra példák:

    jewel.Equals(grid[p.Bal])
    helyett:

    jewel.Equals(grid.GetGridColor(p.Bal))
    "setter":

    grid[p] = jewel; // helyette: grid.SetGridColor(p, jewel);

    ne legyen => operátor -> cseréld ki rendes get set blokkokra:
    Tehát ne használd az úgynevezett "Expression-bodied members" szintaxist, hanem sima getter:

    public ConsoleColor Color // az egész amúgy mehet egy sorba is { get { return colors[ertek]; } }
    ne legyen List...:
    Itt elegánsabb egy saját List osztály, mert akkor alig kell a kód többi részén változtatni:

    class MyList { int count = 0; private pont[] changedCells = new pont[0]; private pont[] newArray; public int Count { get { return changedCells.Length; } } // ha megengedett, akkor ezzel használhatod a listát // foreach-csel is (pont p in ChangedCells.Cells), // ha nem, akkor marad a sima for ciklus, vagy GetEnumerator..., stb-t írsz public pont[] Cells { get { return this.changedCells; } } public void Add(pont p) { ++count; newArray = new pont[count]; for (int i = 0; i < changedCells.Length; ++i) { newArray[i] = changedCells[i]; } newArray[count - 1] = p; changedCells = newArray; } public pont Get(int idx) { if (idx >= 0 && idx < this.Count) { return changedCells[idx]; } else { // itt valamit vissza kell adni, amivel jelzed, // hogy érvénytelen elemre hivatkozol return new pont(-1, -1); } } public void Clear() { count = 0; changedCells = new pont[0]; } // Az idx-edik elem törlése, de ezt amúgy nem használod // a kódban, de a leírás szerint kell... // szerk: a Remove hibás volt, elvileg most már jó: public void Remove(int idx) { if (!(idx >= 0 && idx < this.Count)) { return; } --count; newArray = new pont[count]; int j = 0; for (int i = 0; i < this.Count; ++i) { if (i != idx) { newArray[j] = changedCells[i]; ++j; } } changedCells = newArray; } }
    Remélem, világos, hogy hogyan kell használni, én teszteltem, és látszólag ugyanúgy működött a játék. Ha valami hiba maradt, azt már rád bíznám.
    Teljes működő kódot nem szeretnék adni, így is megírtam helyetted :)

    A kódod amúgy elég kaotikus, pl nem javasolt keverni az angol és magyar változóneveket, megjegyzéseket, a nevek nem mindig beszédesek, hol kis, hol nagybetűs egy függvény(metódus inkább C#-osan) stb.

    Olvasnivaló, amik hasznosak lehetnek a feladat kapcsán:
    Getter property with arguments
    How to use foreach keyword on custom Objects in C#


    Üdv.
    Mutasd a teljes hozzászólást!
abcd