Ahoj, dostal jsem po Pacmanovi za úkol zpracovat "hru" Hanojské věže. Mělo to být udělané procedurálně bez oop a neměl jsem koukat na algoritmy na netu (dodržel jsem). Rád bych zdejší znalejší poprosil o revizi toho mého výtvoru. Funguje jak má. Otázkou je, je napsaný efektivně? Za každých pár vět, které zkritizují nějaký nešvar, budu vděčný.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Veze
{
class Program
{
static Stack<int> vezA = new Stack<int>();
static Stack<int> vezB = new Stack<int>();
static Stack<int> vezC = new Stack<int>();
static Stack<int> prac = new Stack<int>();
static bool konec = false;
static int pocetTahu = 0;
static void Main(string[] args)
{
// příprava základní věže
vezA.Push(5);
vezA.Push(4);
vezA.Push(3);
vezA.Push(2);
vezA.Push(1);
int ber;
int poloz;
Vypis();
while (!konec) // herní smyčka
{
do // cyklus ověřuje vstup - pouze čísla 1,2,3
{
Console.WriteLine();
Console.WriteLine("Přesunout kotouč z věže: ");
if (int.TryParse(Console.ReadLine(), out ber) && ber > 0 && ber < 4)
{
break;
}
Console.WriteLine("Nesprávné zadání!");
Console.WriteLine("Nesprávné zadání! Pokračuj stisknutím libovolné klávesy.");
Console.ReadKey();
Vypis();
}
while (true);
do //// cyklus ověřuje vstup - pouze čísla 1,2,3
{
Console.WriteLine("Polož kotouč na věž: ");
if (int.TryParse(Console.ReadLine(), out poloz) && poloz > 0 && poloz < 4)
{
break;
}
Console.WriteLine("Nesprávné zadání! Pokračuj stisknutím libovolné klávesy.");
Console.ReadKey();
Vypis();
}
while (true);
if (Legalni(ber, poloz)) //volám metodu, abych ověřil, je li tah podle pravidel
{
ProvedTah(ber, poloz); // pokud ano, provede se tah
pocetTahu++;
Vypis(); // aktualizace obrazovky
}
else
{
Console.WriteLine("Neplatný tah! Pokračuj stisknutím libovolné klávesy.");
Console.ReadKey();
Vypis();
}
}
Console.WriteLine("Vyhrál jsi, potřeboval jsi {0} tahů.", pocetTahu); //hráč splnil podmínky, herní smyčka končí
}
//***********************************************************************************************//
//***********************************************************************************************//
static bool Legalni(int ber, int poloz) //metoda posoudí tah podle pravidel
{ //V jednom tahu lze přemístit pouze jeden kotouč
bool tahJeOK = false; //Vždy se bere vrchní kotouč z některé věže a pokládá se na vrchol jiné věže
int kamen = 0; //Nesmí se položit větší kotouč na menší
switch (ber)
{
case 1:
if (vezA.Count > 0)
{
kamen = vezA.Peek();
tahJeOK = true;
}
break;
case 2:
if (vezB.Count > 0)
{
kamen = vezB.Peek();
tahJeOK = true;
}
break;
case 3:
if (vezC.Count > 0)
{
kamen = vezC.Peek();
tahJeOK = true;
}
break;
}
if (!tahJeOK)
return false;
switch (poloz)
{
case 1:
if (vezA.Count == 0)
tahJeOK = true;
else
if ((vezA.Peek() > kamen) && (vezA.Count + kamen < 6))
{
tahJeOK = true;
}
else tahJeOK = false;
break;
case 2:
if (vezB.Count == 0)
tahJeOK = true;
else
if ((vezB.Peek() > kamen) && (vezB.Count + kamen < 6))
{
tahJeOK = true;
}
else tahJeOK = false;
break;
case 3:
if (vezC.Count == 0)
tahJeOK = true;
else
if ((vezC.Peek() > kamen) && (vezB.Count + kamen < 6))
{
tahJeOK = true;
}
else tahJeOK = false;
break;
}
if (tahJeOK) return true;
else return false;
}
static void ProvedTah(int ber, int poloz) //hráčův záměr je legální, provedeme tedy tah
{
int kamen = 0;
switch (ber)
{
case 1:
{
kamen = vezA.Pop();
break;
}
case 2:
{
kamen = vezB.Pop();
break;
}
case 3:
{
kamen = vezC.Pop();
break;
}
}
switch (poloz)
{
case 1:
vezA.Push(kamen);
break;
case 2:
vezB.Push(kamen);
if (vezB.Count == 5)
konec = true;
break;
case 3:
vezC.Push(kamen);
if (vezC.Count == 5)
konec = true;
break;
}
}
static void Vypis() //vykreslí konzoli
{
int[] poleA = new int[5] { 0, 0, 0, 0, 0 }; //stacky věží převedu na pole abych mohl pracovat s objekty s pevným počtem prvků
int[] poleB = new int[5] { 0, 0, 0, 0, 0 };
int[] poleC = new int[5] { 0, 0, 0, 0, 0 };
string strVezA = " ";
string strVezB = " ";
string strVezC = " ";
string mezera = "";
string mezerab = "";
string mezerac = "";
string radek = "";
int nasobek = 0;
int j = 0;
foreach (var item in vezA) //zde se to převádí na ty pole
{
poleA[j] = item;
j++;
}
j = 0;
foreach (var item in vezB)
{
poleB[j] = item;
j++;
}
j = 0;
foreach (var item in vezC)
{
poleC[j] = item;
j++;
}
Array.Sort(poleA); Array.Reverse(poleA); // srovnám pole podle velikosti a otočím, aby začínalo nejvyšší hodnotou
Array.Sort(poleB); Array.Reverse(poleB);
Array.Sort(poleC); Array.Reverse(poleC);
Console.Clear();
Console.WriteLine("Na věži A je {0} kamenů, na věži B je {1} kamenů a na Věži C je {2} kamenů. Počet legálních tahů: {3}", vezA.Count, vezB.Count, vezC.Count, pocetTahu);
Console.WriteLine();
Console.WriteLine(" Věž A Věž B Věž C");
Console.WriteLine();
for (int i = 4; i >= 0; i--) //cyklus vykresluje věže. Vypočítá, kolik mezer je třeba přidat z obou stran, aby věž byla symetrická
{
nasobek = (10 - (2 * poleA[i])) / 2;
mezera = new string(' ', nasobek);
nasobek = (10 - (2 * poleB[i])) / 2;
mezerab = new string(' ', nasobek);
nasobek = (10 - (2 * poleC[i])) / 2;
mezerac = new string(' ', nasobek);
strVezA = mezera + new string('█', 2 * poleA[i]) + mezera;
strVezB = mezerab + new string('█', 2 * poleB[i]) + mezerab;
strVezC = mezerac + new string('█', 2 * poleC[i]) + mezerac;
radek = strVezA + " " + strVezB + " " + strVezC;
Console.WriteLine(radek);
}
}
}
}