Miny - Kontrola počtu min, vítězství, zobrazení pole

Vydávání, hosting a aktualizace umožňují jeho sponzoři.
Tento článek je součástí porovnání programovacích jazyků C#, Java a GameMaker při tvorbě klasických Min (MineSweeper) viz: -> Miny aneb porovnání programovacích jazyků C#, Java, GM
Nyní napíšeme fce pro kontrolu počtu min v okolí tlačítka, kontrola vítězství, zobrazení volných polí a zobrazení celého minového pole.
C# zápis
Barva dle počtu min
Pouze vrací barvu dle zadaného počtu min.
// barva podle počtu min
public static Color getColor(int count_of_mines)
{
switch (count_of_mines)
{
case 0: return Color.White;
case 1: return Color.SkyBlue;
case 2: return Color.GreenYellow;
default: return Color.Orange;
}
}
Počet min v okolí
Projede okolí tlačítka a spočítá vrátí počet min v něm.
// projede okolí stisknutého tlačítka a vrátí počet min kolem něj
private int checkMinesAround(int x, int y)
{
int count = 0;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
// ošetření přetečení
if (((x + i < 0) || (x + i >= _xLength)) || ((y + j < 0) || (y + j >= _yLength)) || ((x + i == x) && (y + j == y)))
continue;
if (_minesArray[x + i, y + j])
count++;
}
}
return count;
}
Zobrazení volných polí
Rekurzivně projede okolí stisknutého tlačítka a pokud je hodnota v min v jeho okolí rovna nule, zkontroluje okolí jeho okolních tlačítek a postupuje stejným způsobem.
// projede všechny tlačítka od stisknutého, které mají v okolí nulový počet min a zobrazí je
public void showFree(int x, int y)
{
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
// ošetření přetečení
if (((x + i < 0) || (x + i >= _xLength)) || ((y + j < 0) || (y + j >= _yLength)))
continue;
if ((this.checkMinesAround(x + i, y + j) == 0) && (_buttons[x + i, y + j].Enabled == true) && (_buttons[x + i, y + j].Text != "?"))
{
_buttons[x, y].Text = "0";
_buttons[x, y].BackColor = Mines.getColor(0);
_buttons[x, y].Enabled = false;
this.showFree(x + i, y + j);
}
}
}
}
Zobrazení celého pole
Jednoduše projedeme celé pole. Povšimněte si odstranění události myši.
// zobrazí celé minové pole (při prohře či výhře)
public void showField()
{
for (int y = 0; y < _yLength; y++)
{
for (int x = 0; x < _xLength; x++)
{
if (_minesArray[x, y])
{
_buttons[x, y].Text = "M";
_buttons[x, y].BackColor = Color.Red;
}
else
{
_buttons[x, y].Text = checkMinesAround(x, y).ToString();
_buttons[x, y].BackColor = Mines.getColor(checkMinesAround(x, y));
}
_buttons[x, y].Enabled = false;
_buttons[x, y].MouseDown -= new MouseEventHandler(Mines_MouseDown);
}
}
}
Vítězství
Zkontroluje počet aktivních tlačítek a porovná tento počet z celkovým počtem min. Pokud se shoduje - zbývají pouze miny.
// pokud je počet aktivních tlačítek roven počtu min (zbývají pouze miny) -> vítězství
public bool checkVictory()
{
int enabled_buttons = 0;
foreach (Button but in _buttons)
{
if (but.Enabled == true)
enabled_buttons++;
}
if (enabled_buttons == _countOfMines)
return true;
else
return false;
}
Java zápis
Barva dle počtu min
Pouze vrací barvu dle zadaného počtu min.
// vrací barvu v závislosti na počtu min
public Color getColor(int count_of_mines)
{
switch (count_of_mines)
{
case 0: return Color.white;
case 1: return Color.blue;
case 2: return Color.green;
default: return Color.orange;// větší než 2
}
}
Nastavení tlačítka
Nastaví tlačítko dle zadaných parametrů.
public void setButton(String text, Color color, int x, int y)
{
buttons[x][y].setText(text);
buttons[x][y].setBackground(color);
buttons[x][y].setEnabled(false);
}
Počet min v okolí
Projede okolí tlačítka a spočítá vrátí počet min v něm.
// vrátí počet min kolem daného tlačítka
public int checkMinesAround(int x, int y)
{
int count = 0;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
// ošetření přetečení
if (((x+i < 0) || (x+i >= x_length)) || ((y+j < 0) || (y+j >= y_length)) || ((x+i == x) && (y+j == y)))
continue;
if (mines_array[x+i][y+j])
count++;
}
}
return count;
}
Zobrazení volných polí
Rekurzivně projede okolí stisknutého tlačítka a pokud je hodnota v min v jeho okolí rovna nule, zkontroluje okolí jeho okolních tlačítek a postupuje stejným způsobem.
// pokud je počet min daného tlačítka roven 0 projede jeho okolí a odkryje pole s ním spajaté, které také mají počet min v jejich okolí roven 0
public void showFree(int x, int y)
{
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
// ošetření přetečení
if (((x+i < 0) || (x+i >= x_length)) || ((y+j < 0) || (y+j >= y_length)) || ((x+i == x) && (y+j == y)))
continue;
if ((this.checkMinesAround(x+i, y+j) == 0) && (buttons[x+i][y+j].isEnabled() == true) && (buttons[x+i][y+j].getText() != "?"))
{
this.setButton("0", this.getColor(0), x+i, y+j);
this.showFree(x+i, y+j);
}
}
}
}
Zobrazení celého pole
Jednoduše projedeme celé pole. Povšimněte si odstranění události myši.
// zbrazí pole min (prohra/výhra)
public void showField()
{
for (int y = 0; y < y_length; y++)
{
for (int x = 0; x < x_length; x++)
{
if (mines_array[x][y])
this.setButton("M", Color.red, x, y);
else
this.setButton(String.valueOf(this.checkMinesAround(x, y)), this.getColor(this.checkMinesAround(x, y)), x, y);
}
}
}
Vítězství
Zkontroluje počet aktivních tlačítek a porovná tento počet z celkovým počtem min. Pokud se shoduje - zbývají pouze miny.
// po stisku tlačítka se zkontroluje kolik zbývá aktivních polí, pokud je číslo rovno počtu min vrátí true
public boolean checkVictory()
{
int enabled_buttons = 0;
for (int y = 0; y < y_length; y++)
{
for (int x = 0; x < x_length; x++)
{
if (buttons[x][y].isEnabled())
enabled_buttons++;
}
}
if (enabled_buttons == count_of_mines)
return true;
else
return false;
}
GameMaker - zápis
Barva a zobrazení počtu min
Tyto náležitosti se provádějí v draw eventu.
draw_sprite(sprite_index, -1, x, y);
draw_set_font(font0);
switch (mines_around)
{
case 0: draw_set_color(c_white); break;
case 1: draw_set_color(c_blue); break;
case 2: draw_set_color(c_green); break;
default: draw_set_color(c_red); break;
}
// vykreslí počet min okolo stisknutého tlačítka
if (sprite_index == spr_clicked)
draw_text(x - 3, y - 8, mines_around);
Počet min v okolí
Na tohle si napíšeme script, který pak budeme volat pomocí script_execute(název, parametry...)
Kontrola je mina
Přistoupí k objektu, dle souřadnic a zjistí z proměnné mine, která se nastavuje při vytváření polí, zda je na zadaném mina či ne.
//is mine
if (instance_exists(instance_position(argument0, argument1, obj_button)))
{
if (instance_position(argument0, argument1, obj_button).mine == true)
{
return true;
}
}
return false;
Počet min v okolí
//check_mines_around
count = 0;
if (script_execute(is_mine, argument0 - sprite_width, argument1)) { count += 1 }
if (script_execute(is_mine, argument0 + sprite_width, argument1)) { count += 1 }
if (script_execute(is_mine, argument0 - sprite_width, argument1 - sprite_height)) { count += 1 }
if (script_execute(is_mine, argument0, argument1 - sprite_height)) { count += 1 }
if (script_execute(is_mine, argument0 + sprite_width, argument1 - sprite_height)) { count += 1 }
if (script_execute(is_mine, argument0 - sprite_width, argument1 + sprite_height)) { count += 1 }
if (script_execute(is_mine, argument0, argument1 + sprite_height)) { count += 1 }
if (script_execute(is_mine, argument0 + sprite_width, argument1 + sprite_height)) { count += 1 }
return count;
V události Room start v obj_button tento script zavoláme a přiřadíme tlačítkům kolik mají min v okolí, pak je pouze zobrazíme v události draw.
// po vytvoření všech tlačítek se nastaví počet min okolo
mines_around = script_execute(check_mines_around, x, y);
Zobrazení volných polí
Tímto způsobem se projede okolí tlačítka - vpravo, vlevo, nahoře a dole. Rekurze pak zkontroluje zbytek. V kódu je jen kontrola pravého souseda.
// show_free
if (script_execute(check_mines_around, argument0 + sprite_get_width(spr_button), argument1) == 0)
{
with (instance_position(argument0 + sprite_get_width(spr_button), argument1, obj_button))
{
if (sprite_index != spr_clicked)
{
sprite_index = spr_clicked;
script_execute(show_free, argument0 + sprite_get_width(spr_button), argument1);
}
}
}
Zobrazení celého pole
Jednoduše projedeme celé pole. Povšimněte si fce screen_redraw, pokud ji nepoužijete, pak se při show_message nepřekreslí obrazovka a vy neuvidíte ono pole.
// show_all
for (i = 1; i < instance_count; i += 1)
{
with (instance_id[i])
{
if (mine == true)
sprite_index = spr_mine;
else
sprite_index = spr_clicked;
}
}
// překreslí se
screen_redraw();
Vítězství
Zkontroluje počet instancí, které nemají sprite roven spr_clicked -> tedy aktivní a porovná tento počet z celkovým počtem min. Pokud se shoduje - zbývají pouze miny.
// check_victory
clicked = 0;
for (i = 1; i < instance_count - 1; i += 1)
{
if (instance_id[i].sprite_index != spr_clicked) { clicked += 1 }
}
if (clicked == obj_controler.mines_count)
return true;
return false;
Pokračování > Zajímavosti a poznámky
Komentáře
Zatím nikdo nevložil komentář - buď první!