Diskuze: Generátor bludiště - nahrazení switch
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Zobrazeno 2 zpráv z 2.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Sice trochu pozdě, ale pokud jde čistě o switch, tak se dá určitě zjednodušit. Začal bych stejnými částmi a to tak, že bych je odstranil tedy vyšlo by:
int border = 0;
int step = 0;
switch (smer)
{
case 0: // vlevo
border = -sizeX;
step = -2;
case 1: //vpravo
border += sizeX;
step += 1;
for (int x = put.X; x != border; x += step)
{
if (pole[x, put.Y] == 2)
{
pole[x, put.Y] = 1;
position.Remove(new Position(x, put.Y));
pocet++;
if (pocet >= n)
break;
}
else if (pole[x, put.Y] == 0)
pole[x, put.Y] = 1;
else break;
}
break;
case 2: // nahoru
border = -sizeY;
step = -2;
case 3: //dolu
border += sizeY;
step += 1;
for (int y = put.Y; x != border; x += step)
{
if (pole[put.X, y] == 2) // nalezl základnu
{
pole[put.X, y] = 1; // položí zed
position.Remove(new Position(put.X, y)); // vymaže základnu
pocet++;
if (pocet >= n)
break;
}
else if (pole[put.X, y] == 0)
pole[put.X, y] = 1;
else break;
}
break;
}
Okay, takže počet cyklů se nám s mírnými úpravami změnil na
polovinu.
Jenže to pořád není to co chceme pořád tam máme switch který nechceme a
2 velmi podobné cykly.
Ok tak se zbavíme duplicity - vytáhneme cyklus ven:
int border = 0;
int step = 0;
int defaultI;
int IX;
int IY;
int stepX;
int stepY;
switch (smer)
{
case 0: // vlevo
border = 0;
step = -1;
defaultI = put.X;
IX = defaultI;
IY = put.Y;
stepX = step;
stepY = 0;
break;
case 1: //vpravo
border = sizeX;
step = 1;
defaultI = put.X;
IX = defaultI;
IY = put.Y;
stepX = step;
stepY = 0;
break;
case 2: // nahoru
border = 0;
step = -1;
defaultI = put.Y;
IX = put.X;
IY = defaultI;
stepX = 0;
stepY = step;
break;
case 3: //dolu
border = sizeY;
step = 1;
defaultI = put.Y;
IX = put.X;
IY = defaultI;
stepX = 0;
stepY = step;
break;
}
for (int i = defaultI; i != border; i += step)
{
if (pole[IX, IY] == 2) // nalezl základnu
{
pole[IX, IY] = 1; // položí zed
position.Remove(new Position(IX, IY)); // vymaže základnu
pocet++;
if (pocet >= n)
break;
}
else if (pole[IX, IY] == 0)
pole[IX, IY] = 1;
else break;
IX += stepX; // Přibylo
IY += stepY; // Přibylo
}
Dobře ale pořád máme ošlkivý switch který nás nutí nastavovat spousty věcí. Začít bychom opět mohli tím, že vynecháme duplicity. Ovšem zde už je porovnání obsahu switche více zřejmé. Můžeme tedy celý obsah switche vytáhnout ven a učinit tak změny vně:
int shift = (smer % 2) ? 0 : 2;
int border = 0;
int step = -1 + shift;
int defaultI, IX, IY, stepX, stepY;
if (smer < 2) {
defaultI = put.X;
IX = defaultI;
IY = put.Y;
stepX = step;
stepY = 0;
border += sizeX * (shift >> 1);
} else {
defaultI = put.Y;
IX = put.X;
IY = defaultI;
stepX = 0;
stepY = step;
border += sizeY * (shift >> 1);
}
for (int i = defaultI; i != border; i += step)
{
if (pole[IX, IY] == 2) // nalezl základnu
{
pole[IX, IY] = 1; // položí zed
position.Remove(new Position(IX, IY)); // vymaže základnu
pocet++;
if (pocet >= n)
break;
}
else if (pole[IX, IY] == 0)
pole[IX, IY] = 1;
else break;
IX += stepX; // Přibylo
IY += stepY; // Přibylo
}
Toto je asi finální kód, který by mohl nahradit switch. Ovšem switch je
sice méně přehledný, ale zato bude zabírat méně systémového času.
(není tam zbytek po dělení, if a násobení a je tam o dvě inkrementace v
cyklu méně) Ovšem zde se eliminují duplicity a razantně se zvyšuje
použitelnost toho cyklu. Toto řešení je zase náročnější na
představivost, jelikož musíš například v inkrementační části cyklu
pochopit, že step může být i záporný.
If lze taky vynechat, ale to už je jiná písnička.
Zobrazeno 2 zpráv z 2.