IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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

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


 

Článek pro vás napsal David Jančík
Avatar
Uživatelské hodnocení:
Ještě nikdo nehodnotil, buď první!
Autor je vášnivý programátor. Nezná slovo "nelze", nebojí se zkoušet nepoznané a pronikat do nových technologií.
Aktivity