• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Potrzebuję pomocy przy pisaniu sapera

Object Storage Arubacloud
+5 głosów
2,659 wizyt
pytanie zadane 9 kwietnia 2015 w C i C++ przez mate2383 Nowicjusz (240 p.)

Cześć wszystkim, dopiero zaczynam przygodę z programowaniem jestem na 1 roku studiów. Mam problem a raczej wiele problemów z tworzeniem gry saper. Treść zadania jest taka : 

Celem zadania jest napisanie aplikacji do gry w sapera. Zadanie składa się z dwóch etapów:

Etap 1:

Klasy składowe:

  • Pole - klasa reprezentuje stan pojedynczego pola. Powinna zawierać informację o: byciu odkrytą/zakrytą, posiadaniu miny, byciu oznaczonym jako pole z miną.
  • Plansza - klasa reprezentuje planszę do gry. Powinna zawierać tablicę pól do gry, umożliwiać inicjalizację planszy (konstruktor) losującą początkowe położenie zadanej ilości min, sprawdzanie, czy na danym polu znajduje się mina, odkrywanie kolejnego pola i wyświetlanie aktualnego stanu gry.

Etap 2:

Dodanie obsługi biblioteki SFML - program powinien wyświetlać stan planszy w sposób graficzny:

  • biały kwadrat - pole zakryte
  • czerwony kwadrat - odkryta mina
  • niebieski kwadrat - zaznaczenie, że na polu prawdopodobnie znajduje się mina
  • wartość liczbowa - w przypadku odkrytego pola bez miny wypisuje ilość sąsiadujących pól z minami

W tej chwili naskrobałem coś takiego :

#include <SFML/Graphics.hpp>


#include <conio.h>
#include <windows.h>
#include <iostream>
#include <time.h>


#include <iostream>
#include <fstream>
#include <string>

using namespace sf;


using namespace std;

const int wys = 550;
const int szer = 550;

class Plansza{




};

class Punkt{

int wartosc;
bool odkryte;
bool flaga;
bool mina;
public:

bool czymina();


};


int main()
{
    int k,m, zarodek;
    zarodek= time(NULL);
    srand(zarodek);   // za zarodek wstawiamy pobrany czas w sekundach

    int koniec = 0;
    sf::RenderWindow window(sf::VideoMode(wys, szer), "SFML");


    sf::Font font;
    font.loadFromFile("arial.ttf");
    sf::Text tName;
    tName.setFont(font);
    tName.setColor(sf::Color::White);

    tName.setCharacterSize(20);
    tName.setString("1");
    tName.setPosition(sf::Vector2f(Mouse::getPosition(window)));

RectangleShape plansza[10][10];
	for(int i=0;i<10;i++)
	{
		for(int j=0;j<10;j++)
		{


			plansza[i][j].setSize(Vector2f(50,50)); //wielkosc pola to 50x50
			plansza[i][j].setPosition(2.5+i*55,2.5+j*55); // plansza zaczyna sie od 2,5 piksela, pola rozstawione co 5 pikseli

			plansza[i][j].setFillColor(Color(200,255,255));
			plansza[i][j].setOutlineColor(Color(255, 102, 0));
			plansza[i][j].setOutlineThickness(2.5f);
		}
	}

while(window.isOpen())
{
    Event event;

while(koniec==0)
{
while(window.pollEvent(event))
		{
			if(event.type == Event::Closed)

{
                sleep(seconds(2));

				window.close();

			}

			else if(event.type == Event::MouseButtonPressed)
			{
			    for(int o=1;o<10;o++)//mina
				{
				    k=rand()%10;
				    m=rand()%10;


				for(int i=0;i<10;i++)
				{
					for(int j=0;j<10;j++)
					{
						if(plansza[i][j].getGlobalBounds().contains(Vector2f(Mouse::getPosition(window))) )
						{


if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
            if (k==i&&m==j) //trafiles na mine
              {
plansza[i][j].setFillColor(Color::Red);
koniec=1;
                cout << "\nTrafiles na mine! Koniec gry.";
sleep(seconds(1));

              }

            else {

window.draw(tName);
tName.setPosition(sf::Vector2f(Mouse::getPosition(window)));
plansza[i][j].setFillColor(Color::Black);
            }
}
else if (sf::Mouse::isButtonPressed(sf::Mouse::Right))
{
    plansza[i][j].setFillColor(Color::Blue);
}
						}

						}
					}
				}
			}
		}


window.clear(Color(128,128,128));

		for(int i=0;i<10;i++)
			for(int j=0;j<10;j++)
               window.draw(plansza[i][j]);
               window.draw(tName);
               window.display();

}
sleep(seconds(2));

window.close();
}


    return 0;
}

 

Nie potrafie stworzyć klas z tego co stworzyłem w mainie, nie wiem co zrobić żeby miny losowały się raz a nie co każde kliknięcie (gdy kliknie się pare razy w ten sam kwadracik to w końcu będzie tam mina), co zrobić żeby tekst wyświetlał się na środku klikniętego kwadracika i nie znikał po kliknięciu na inny, generalnie mam same pytania frown Proszę o pomoc.

4 odpowiedzi

+3 głosów
odpowiedź 9 kwietnia 2015 przez MrWeb Stary wyjadacz (10,200 p.)
wybrane 10 kwietnia 2015 przez mate2383
 
Najlepsza

Cześć, muszę przyznać, że mnie zaciekawiłeś tym tematem. Już od dawna miałem się wziąć za naukę SFML a to pytanie będzie dobrą okazją :)

Widzę, że masz sporo pytań dotyczących mechaniki gry, jej okodowania itd, ale zanim zacznę cokolwiek pisać na temat gry chcę Ci przedstawić moją wersję klas Punkt i Plansza. Ty je zostawiłeś puste, i z kilkoma błędami więc pozwoliłem sobie na przygotowanie mojej interpretacji wink


class Pole
{
public:
  Pole(int _value, bool _isNaked, bool _isArmed, bool _isMarked) : value(_value), isNaked(_isNaked), isArmed(_isArmed), isMarked(_isMarked) { }
  Pole() : Pole(0, false, false, false) { }
  ~Pole() { }

  int  getValue() const    { return value; }
  bool getIsNaked() const  { return isNaked; }
  bool getIsArmed() const  { return isArmed; }
  bool getIsMarked() const { return isMarked; }

  void setValue(int _value)        { value = _value; }
  void setIsNaked(bool _isNaked)   { isNaked = _isNaked; }
  void setIsArmed(bool _isArmed)   { isArmed = _isArmed; }
  void setIsMarked(bool _isMarked) { isMarked = _isMarked; }

private:
  int  value; //wartosc pola
  bool isNaked; //jest odkryte ?
  bool isArmed; //posiada minę ?
  bool isMarked; //jest oznaczona przez gracza ?
};

enum GameState { START, PLAY, END };
class Plansza
{
public:
  Plansza(size_t x, size_t y, GameState _s) : gameState(_s) { }
  Plansza() : Plansza(10, 10, GameState::START) { }
  ~Plansza() { }

  void setPole(size_t _x, size_t _y, Pole& _p) { board[_x][_y] = _p; };
  void setGameState(GameState _s) { gameState = _s; }

  Pole& getPole(size_t _x, size_t _y) const { return board[_x][_y]; }
  GameState getGameState() const { return gameState; }

private:
  vector<vector<Pole>> board;
  GameState gameState;
};

Klasa Pole:

Pole(int _value, bool _isNaked, bool _isArmed, bool _isMarked) : value(_value), isNaked(_isNaked), isArmed(_isArmed), isMarked(_isMarked) { }

To jest konstruktor z użyciem http://www.p-programowanie.pl/cpp/lista-inicjalizacyjna/

 

 Pole() : Pole(0, false, false, false) { }

To jest delegowanie konstruktorów - dzięki temu nie muszę pisać wiele razy tego samego.

 

~Pole() { }

Destruktor jest pusty bo nie alokuję własnoręcznie pamięci, więc nie muszę się martwić o jej zwolnienie

 

  int  getValue() const    { return value; }
  bool getIsNaked() const  { return isNaked; }
  bool getIsArmed() const  { return isArmed; }
  bool getIsMarked() const { return isMarked; }

  void setValue(int _value)        { value = _value; }
  void setIsNaked(bool _isNaked)   { isNaked = _isNaked; }
  void setIsArmed(bool _isArmed)   { isArmed = _isArmed; }
  void setIsMarked(bool _isMarked) { isMarked = _isMarked; }

To są tzw gettery i settery, chodzi o to, by trzymać pola (inaczej mówiąc zmienne) obiektu z dala od użytkownika. Poczytaj więcej o enkapsulacji danych i napewno zrozumiesz smiley

 

  int  value; //wartosc pola
  bool isNaked; //jest odkryte ?
  bool isArmed; //posiada minę ?
  bool isMarked; //jest oznaczona przez gracza ?

Tu mamy faktyczne zmienne naszej klasy. Mają angielskie nazwy bo ładniej wyglądają wink

value - trzyma liczbę bomb wokół siebie - będziemy ją ustawiać wraz z losowaniem pól które należy uzbroić cheeky

isNaked - domyślnie jest ustawiona na 0 czyli że nie jest odkryta (użytkownik nie kliknął na dane pole). Będziemy ją zmieniać gdy użytkownik kliknie na to pole.

isArmed - będzie ustawiana wraz z losowaniem bomb.

isMarked - czy użytkownik oznaczył to pole prawym przyciskiem myszy ? Do tego będzie służyć nam ta zmienna.

 

Jeśli nadal nie do końca rozumiesz co tu się dzieje - obejrzyj pierwsze trzy odcinki tej serii https://www.youtube.com/playlist?list=PLOYHgt8dIdozvOVheSRb_qPVU-4ZJA7uB


Klasa Plansza

enum GameState { START, PLAY, END };

Wspomniałeś, że program ma zwracać aktualny stan gry więc dodałem takiego enuma, ale nie za bardzo widzę gdzie mógłby się przydać, gra ma po prostu za mało stanów i równie dobrze mógłbym je opisać komentarzami.

 

Plansza(size_t x, size_t y, GameState _s) : gameState(_s) { }

konstruktor jest narazie pusty, niedługo to poprawię. Zastanów się, co warto byłoby w nim napisać ?

 

  void setPole(size_t _x, size_t _y, Pole& _p) { board[_x][_y] = _p; };
  void setGameState(GameState _s) { gameState = _s; }
 
  Pole& getPole(size_t _x, size_t _y) const { return board[_x][_y]; }
  GameState getGameState() const { return gameState; }

setPole - ustawia wartości pola na podanych współrzędnych, nic trudnego wink

getPole - zwraca referencję (znak & po nazwie Pole) do aktualnego pola, a to znaczy, że będziemy mogli wywoływać metody klasy Pole! To nam niesamowicie ułatwi sprawę bo wszystko będzie się pięknie zazębiać :

plansza.getPole(4, 4).setIsArmed(true);

Dlaczego to działa ? Otóż, plansza to obiekt który stworzymy w main'ie.

Zawiera on metodę getPole która zwraca referencję do obiektu Pole

na rzecz którego wywołujemy metodę setIsArmed(true);

 

Jeśli nie rozumiesz tego co przed chwilą przeczytałeś, to poszukaj trochę informacji o referencjach, i odwoływaniu się do metod składowych obiektu wink

 

private:
  vector<vector<Pole>> board;
  GameState gameState;

Na koniec mamy dwie "zmienne składowe" naszej klasy:

board - obiekt klasy vector o specjalizacji klasy Pole - o co chodzi ? Vector to taka klasa zawarta w standardzie std która umożliwia nam robienie takich fajnych tablic u których nie da się przekroczyć zakresu - nie wystąpi nam błąd "off by one". Oczywiście można to też zrobić w ten sposób :

Punkt[10][10] board;

Ale jest to w kilku sytuacjach problematyczne - przypomnę o tym problemie gdy będziemy pisać funkcję do losowania bomb.

+1 głos
odpowiedź 10 kwietnia 2015 przez MrWeb Stary wyjadacz (10,200 p.)

Ufff... Na dzisiaj mi starczy programowania laugh

Chciałem wprowadzić kilka poprawek ale tak się rozpędziłem że mi wyszło coś zupełnie innego od oryginału. Zostawiłem tylko mechanikę działania głównej pętli, a całą resztę musiałem "zmodyfikować"

A teraz zadanie dla Ciebie - autorze tego tematu, przeanalizuj na spokojnie kod, i napisz mi w komentarzach których linii nie rozumiesz.


#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <unistd.h>
using namespace std;

#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>

//25%
#define LEVEL ((X * Y) / 4)

const size_t X = 10;
const size_t Y = 10;


class Pole
{
public:
  Pole(int _value, bool _isNaked, bool _isArmed, bool _isMarked)
  : value(_value), isNaked(_isNaked), isArmed(_isArmed), isMarked(_isMarked) { }
  Pole() : Pole(0, false, false, false) { }
  ~Pole() { }

  int  getValue()    const { return value;    }
  bool getIsNaked()  const { return isNaked;  }
  bool getIsArmed()  const { return isArmed;  }
  bool getIsMarked() const { return isMarked; }

  void setValue(int _value)        { value = _value;       }
  void setIsNaked(bool _isNaked)   { isNaked = _isNaked;   }
  void setIsArmed(bool _isArmed)   { isArmed = _isArmed;   }
  void setIsMarked(bool _isMarked) { isMarked = _isMarked; }

private:
  int  value; //wartosc pola
  bool isNaked; //jest odkryte ?
  bool isArmed; //posiada minę ?
  bool isMarked; //jest oznaczone przez gracza ?
};

enum GameState { START, PLAY, END };
class Plansza
{
public:
  Plansza(size_t x, size_t y, GameState _s = GameState::START);
  Plansza() : Plansza(10, 10, GameState::START) { }
  ~Plansza() { }

  void setPole(size_t _x, size_t _y, Pole& _p) { board[_x][_y] = _p; };
  void setGameState(GameState _s) { gameState = _s; }

  Pole& getPole(size_t _x, size_t _y) { return board[_x][_y]; }
  GameState& getGameState() { return gameState; }

private:
  void setBombs(size_t _x, size_t _y);

  vector<vector<Pole> > board;
  GameState gameState;
};

Plansza::Plansza(size_t _x, size_t _y, GameState _s) : gameState(_s)
{
  //tworzenie tablicy pól o wymiarach X, Y
  board.resize(_y); //ustaw Y kolumn
  for(size_t i = 0; i < _y; i++) //dla każdej kolumny...
  {
    board[i].resize(_x);  //ustaw X wierszy
  }

  setBombs(_x, _y);
}

void Plansza::setBombs(size_t _x, size_t _y)
{
  //(_x * _y) / 4 = 25% szans na trafienie (25 ze 100 pól jest uzbrojonych)
  for(size_t i = 0; i < ((_x * _y) / 4); i++)
  {
    size_t x = rand() % _x; //wylosuj liczbę z zakresu 0...X dla współrzędnej X
    size_t y = rand() % _y; //wylosuj liczbę z zakresu 0...Y dla współrzędnej Y

    if(board[x][y].getIsArmed() == false) //jeśli wylosowane pole NIE jest uzbrojone
    {
      board[x][y].setIsArmed(true); //ustaw na uzbrojone

      for(size_t i = (x > 0 ? x-1 : x); i < (x < _x ? x+1 : x); i++)
      {
        for(size_t j = (y > 0 ? y-1 : y); j < (y < _y ? y+1 : y); j++)
        {
          board[i][j].setValue(board[i][j].getValue() + 1); //zwiększ wartość pól wokół miny
        }
      }
    }
  }
}

 

Gotowa wklejka http://wklej.org/id/1684898/

Przy okazji pozdrowienia dla tych, którzy tu jeszcze zajrzą wink Jeśli znaleźliście jakieś błędy w działaniu programu to napiszcie mi o nich.

Dla ciekawskich zostawiłem jeden błąd logiczny, który nie jest może trudny do zauważenia, ale na pewno jest tym z rodzajów "gamebreaking" devil (i nie mówię tu o wysypaniu się programu)

+1 głos
odpowiedź 10 kwietnia 2015 przez MrWeb Stary wyjadacz (10,200 p.)

Dalsza część kodu cool

int main()
{
  //okno gry
  sf::RenderWindow window(sf::VideoMode(550, 550), "SFML");

  //czcionka używana do stylizacji tekstu
  sf::Font font;
  font.loadFromFile("/home/mrweb/Programming/cpp_eclipse/workspace/helpme/Debug/sansation.ttf");

  //tekst używany do wypisywania informacji (np wartość pola)
  sf::Text text;
  text.setFont(font);
  text.setColor(sf::Color::White);
  text.setCharacterSize(20);

  //kwadraciki planszy używane do graficznego przedstawienia stanów pól gry
  size_t defusersLeft = LEVEL;
  sf::RectangleShape plansza[X][Y];
  Plansza board(X, Y);
  for(size_t i = 0; i < X; i++)
  {
    for(size_t j = 0; j < Y; j++)
    {
      plansza[i][j].setSize(sf::Vector2f(50,50)); //wielkosc pola to 50pix x 50pix
      plansza[i][j].setPosition(2 + i * 55, 2 + j * 55); //2pix margines, 55pix szerokość i wysokość pola
      plansza[i][j].setFillColor(sf::Color::Cyan); //domyślny kolor środka
      plansza[i][j].setOutlineColor(sf::Color::Black); //domyślny kolor krawędzi pola
      plansza[i][j].setOutlineThickness(2.0f); //grubość krawędzi pola
    }
  }

  /////////////////////////////////////////////////////////////////////////////////////////////////
  //główna pętla okna
  bool quit = false;
  while(window.isOpen() && !quit)
  {
    sf::Event event;
    while(window.pollEvent(event))
    {
      //reakcja na kliknięcie przycisku [X]
      if(event.type == sf::Event::Closed)
      {
        window.close();
      }

      //reakcja na kliknięcie lewym przyciskiem myszy
      if((event.type == sf::Event::MouseButtonPressed) && (event.mouseButton.button == sf::Mouse::Left))
      {
        for(size_t i = 0; i < X; i++) //skan przez wszystkie wiersze...
        {
          for(size_t j = 0; j < Y; j++) //wszystkich kolumn
          {
            //jeśli aktualnie sprawdzana komórka zawiera pozycję kursora (trafiliśmy pole o współrzędnych i, j)
            if(plansza[i][j].getGlobalBounds().contains(sf::Vector2f(sf::Mouse::getPosition(window))))
            {
              if(board.getPole(i, j).getIsNaked() == false) //jeśli trafiliśmy na zakryte pole...
              {
                if(board.getPole(i, j).getIsArmed() == true) //i to pole było uzbrojone :<
                {
                  plansza[i][j].setFillColor(sf::Color::Red);
                  cout << "LPM [ " << i << " ][ " << j << " ] value = " << board.getPole(i, j).getValue() << endl;
                  cout << "koniec gry" << endl;
                  quit = true;
                } else //nie było uzbrojone! :D
                {
                  cout << "LPM [ " << i << " ][ " << j << " ] value = " << board.getPole(i, j).getValue() << endl;
                  board.getPole(i, j).setIsNaked(true);
                  plansza[i][j].setFillColor(sf::Color::Green);
                  //TODO wypisz wartość tego pola
                }
              }
            }
          }
        }
      }

      //reakcja na kliknięcie prawym przyciskiem myszy
      if((event.type == sf::Event::MouseButtonPressed) && (event.mouseButton.button == sf::Mouse::Right))
      {
        for(size_t i = 0; i < X; i++) //skan przez wszystkie wiersze...
        {
          for(size_t j = 0; j < Y; j++) //wszystkich kolumn
          {
            //jeśli aktualnie sprawdzana komórka zawiera pozycję kursora (trafiliśmy pole o współrzędnych i, j)
            if(plansza[i][j].getGlobalBounds().contains(sf::Vector2f(sf::Mouse::getPosition(window))))
            {
              if(board.getPole(i, j).getIsMarked() == false) //i to pole nie było oznaczone
              {
                if(defusersLeft) //i mamy jeszcze defusery (prawie jak w CS :D)
                {
                  plansza[i][j].setFillColor(sf::Color::Blue);
                  board.getPole(i, j).setIsMarked(true);
                  board.getPole(i, j).setIsArmed(false);
                  defusersLeft--;
                }
              }
              else //odznaczyliśmy zaznaczone (kliknięcie dwa razy w to samo miejsce)
              {
                  plansza[i][j].setFillColor(sf::Color::Cyan);
                  board.getPole(i, j).setIsMarked(false);
                  board.getPole(i, j).setIsArmed(false);
                  defusersLeft++;
              }
            }
          }
        }
      }
    }

    //cykl clear/draw/display
    window.clear(sf::Color::Black);

    for(size_t i = 0; i < X; i++)
    {
      for(size_t j = 0; j < Y; j++)
      {
        window.draw(plansza[i][j]);
        //todo draw board[i][j] value
      }
    }

    window.display();
    if(quit) sleep(3);
  }
  return 0;
}

 

komentarz 13 kwietnia 2015 przez mate2383 Nowicjusz (240 p.)

      for(size_t i = (x > 0 ? x-1 : x); i < (x < _x ? x+1 : x); i++)
      {
        for(size_t j = (y > 0 ? y-1 : y); j < (y < _y ? y+1 : y); j++)
        {
          board[i][j].setValue(board[i][j].getValue() + 1); //zwiêksz wartoœæ pól wokó³ miny
        }
      }

Tutaj powinno być zamiast i<(x<_x ? x+1 : x) i  i<(y < _y ? y+1 : y)

(x < _x ? x+2 : x+1) (y < _y ? y+2 : y+1) Jednak jeśli to zmienie to program się sypie (raz mi zadzialał i później się tylko sypał do czasu aż zmieniłem znowu na to co było) a z tym to chodzi o to żeby zliczało wszystkie miny wkoło punktu, sprawdzałem to tak: Dodałem funkcje kolorującą miny na czerwono i klikałem w koło nich i dzieje się coś takiego:

komentarz 13 kwietnia 2015 przez MrWeb Stary wyjadacz (10,200 p.)

Uu... dość duża pomyłka przy tych pętlach... Sorrki smiley

Widzę, że się nie obijałeś, tylko starałeś się przyswoić wszystko co napisałem, jestem dumny laugh Zrobiłeś też obsługę cyferek na odkrytych polach, brawo!

 

Wracając do problemu, najprawdopodobniej program się wysypuje bo przy losowaniu pól do zaminowania bo przekraczany jest indeks tablicy - już tłumaczę:

 

void Plansza::setBombs(size_t _x, size_t _y)
{
  //(_x * _y) / 4 = 25% szans na trafienie (25 ze 100 pól jest uzbrojonych)
  for(size_t i = 0; i < ((_x * _y) / 4); i++)
  {
    size_t x = rand() % _x; //wylosuj liczbę z zakresu 0...X dla współrzędnej X
    size_t y = rand() % _y; //wylosuj liczbę z zakresu 0...Y dla współrzędnej Y
 
    if(board[x][y].getIsArmed() == false) //jeśli wylosowane pole NIE jest uzbrojone
    {
      board[x][y].setIsArmed(true); //ustaw na uzbrojone
 
      for(size_t i = (x > 0 ? x-1 : x); i < (x < _x ? x+1 : x); i++)
      {
        for(size_t j = (y > 0 ? y-1 : y); j < (y < _y ? y+1 : y); j++)
        {
          board[i][j].setValue(board[i][j].getValue() + 1); //zwiększ wartość pól wokół miny
        }
      }
    }
  }
}

Ta funkcja losuje dwie wartości, x y z przedziału 0...9 (rozmiar siatki planszy).

Potem na podstawie wylosowanego punktu o koordynatach (x, y) zwiększa wartości pól wokół tego punktu, tak jak na profesjonalnie przgotowanej grafice 

komentarz 13 kwietnia 2015 przez MrWeb Stary wyjadacz (10,200 p.)
edycja 13 kwietnia 2015 przez MrWeb

I te warunki chciałem określić w pętlach, tak by zachowywały się elastycznie wobec krawędzi ścian
 

for(size_t i = (x > 0 ? x-1 : x); i < (x < _x ? x+1 : x); i++)
{
  for(size_t j = (y > 0 ? y-1 : y); j < (y < _y ? y+1 : y); j++)
  {
    board[i][j].setValue(board[i][j].getValue() + 1);
  }
}

Ale mi trochę nie wyszło cheeky

Proponuję zmienić te warunki na bardziej przejżyste "ify"

 

for(int i = x - 1; i <= x + 1; i++)
{
  for(int j = y - 1; j <= y + 1; j++)
  {
     if(x < 0) i++; else //za bardzo w lewo
     if(x > _x) i--; else //za bardzo w prawo
     if(y < 0) j++; else //za bardzo w górę
     if(y > _y) j--; //za bardzo w dół

     board[i][j].setValue(board[i][j].getValue() + 1); //zwiększ wartość pól wokół miny
   }
}</pre>

 

Znalazłem też kilka ważnych błędów w kodzie który Ci wysłałem więc jutro postaram się wstawić najnowszą wersję wraz z naprawionym indeksowaniem 
wink

Niestety, coś mi nawaliło i program wysypuje się po wczytaniu fonta przez co nie mogę wyświetlać wartości każdego pola, tak jak jest to u ciebie na screenshocie... Może uda mi się to naprawić, bo aż zazdroszczę, że u Ciebie są te wartości na odkrytych polach a u mnie nie cheeky

0 głosów
odpowiedź 14 kwietnia 2015 przez mate2383 Nowicjusz (240 p.)

Można powiedzieć że skończyłem :) Rozwiązałem problem z dodawaniem wartości 

for(size_t i = (x > 0 ? x-1 : x); i < (x < 9 ? x+2 : x+1); i++)
{
  for(size_t j = (y > 0 ? y-1 : y); j < (y < 9 ? y+2 : y+1); j++)
  {
    board[i][j].setValue(board[i][j].getValue() + 1);
  }

}

//czcionka u¿ywana do stylizacji tekstu
  sf::Font font;
  font.loadFromFile("arial.ttf");

Aby zadziałało trzeba wrzucić arail.ttf do folderu z kodem.

      if(board.getPole(i, j).getIsArmed() == true) //i to pole by³o uzbrojone :<
                {
                  plansza[i][j].setFillColor(sf::Color::Red);}

To odpowiada za kolorowanie min od razu po uruchomieniu. Wystarczy usunąć i mamy grę.

else //nie by³o uzbrojone! :D
                {
                  cout << "LPM [ " << i << " ][ " << j << " ] value = " << board.getPole(i, j).getValue() << endl;
                  board.getPole(i, j).setIsNaked(true);
                  plansza[i][j].setFillColor(sf::Color::Green);

                      text[i][j].setFont(font);
                      text[i][j].setColor(sf::Color::White);
                      text[i][j].setCharacterSize(20);
                      text[i][j].setPosition(22 + i * 55, 15 + j * 55);
                      if(board.getPole(i, j).getValue()==1){
                      text[i][j].setString("1"); }
                      if(board.getPole(i, j).getValue()==2){
                      text[i][j].setString("2"); }
                      if(board.getPole(i, j).getValue()==3){
                      text[i][j].setString("3"); }
                      if(board.getPole(i, j).getValue()==4){
                      text[i][j].setString("4"); }
                      if(board.getPole(i, j).getValue()==5){
                      text[i][j].setString("5"); }
                      if(board.getPole(i, j).getValue()==6){
                      text[i][j].setString("6"); }
                      if(board.getPole(i, j).getValue()==7){
                      text[i][j].setString("7"); }
                      if(board.getPole(i, j).getValue()==8){
                      text[i][j].setString("8"); }


                  
                }

A to odpowiada za wyswietlanie wartości pola, nie potrafie tego inaczej zapisać szukałem i niestety nie znalazłem nic co by mi pomogło to jakoś skrócić. 

 

 

komentarz 14 kwietnia 2015 przez mate2383 Nowicjusz (240 p.)

A to cały kod.


#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>

#include <conio.h>
#include <windows.h>
#include <time.h>
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <unistd.h>
using namespace sf;
using namespace std;





//25%
#define LEVEL ((X * Y) / 4)

const size_t X = 10;
const size_t Y = 10;


class Pole
{
public:
  Pole(int _value, bool _isNaked, bool _isArmed, bool _isMarked)
  : value(_value), isNaked(_isNaked), isArmed(_isArmed), isMarked(_isMarked) { }
  Pole() : Pole(0, false, false, false) { }
  ~Pole() { }

  int  getValue()    const { return value;    }
  bool getIsNaked()  const { return isNaked;  }
  bool getIsArmed()  const { return isArmed;  }
  bool getIsMarked() const { return isMarked; }

  void setValue(int _value)        { value = _value;       }
  void setIsNaked(bool _isNaked)   { isNaked = _isNaked;   }
  void setIsArmed(bool _isArmed)   { isArmed = _isArmed;   }
  void setIsMarked(bool _isMarked) { isMarked = _isMarked; }

private:
  int  value; //wartosc pola
  bool isNaked; //jest odkryte ?
  bool isArmed; //posiada minê ?
  bool isMarked; //jest oznaczone przez gracza ?
};


class Plansza
{
public:
  Plansza(size_t x, size_t y);
  Plansza() : Plansza(10, 10) { }
  ~Plansza() { }

  void setPole(size_t _x, size_t _y, Pole& _p) { board[_x][_y] = _p; };


  Pole& getPole(size_t _x, size_t _y) { return board[_x][_y]; }


private:
  void setBombs(size_t _x, size_t _y);

  vector<vector<Pole> > board;

};

Plansza::Plansza(size_t _x, size_t _y)
{
  //tworzenie tablicy pól o wymiarach X, Y
  board.resize(_y); //ustaw Y kolumn
  for(size_t i = 0; i < _y; i++) //dla ka¿dej kolumny...
  {
    board[i].resize(_x);  //ustaw X wierszy
  }

  setBombs(_x, _y);
}

void Plansza::setBombs(size_t _x, size_t _y)
{ int zarodek;
    zarodek= time(NULL);
    srand(zarodek);
  //(_x * _y) / 4 = 25% szans na trafienie (25 ze 100 pól jest uzbrojonych)
  for(size_t i = 0; i < ((_x * _y) / 4); i++)
  {
    size_t x = rand() % _x; //wylosuj liczbê z zakresu 0...X dla wspó³rzêdnej X
    size_t y = rand() % _y; //wylosuj liczbê z zakresu 0...Y dla wspó³rzêdnej Y

    if(board[x][y].getIsArmed() == false) //jeœli wylosowane pole NIE jest uzbrojone
    {
      board[x][y].setIsArmed(true); //ustaw na uzbrojone

for(size_t i = (x > 0 ? x-1 : x); i < (x < 9 ? x+2 : x+1); i++)
{
  for(size_t j = (y > 0 ? y-1 : y); j < (y < 9 ? y+2 : y+1); j++)
  {
    board[i][j].setValue(board[i][j].getValue() + 1);
  }

}
    }
  }
}



Jeśli ktoś ma jakieś sugestie to proszę pisać ;p MrWeb to złoty człowiek bez niego nic dalej bym siedział i nic nie wiedział :D

komentarz 14 kwietnia 2015 przez mate2383 Nowicjusz (240 p.)
int main()
{
  //okno gry
  sf::RenderWindow window(sf::VideoMode(550, 550), "SFML");

  //czcionka u¿ywana do stylizacji tekstu
  sf::Font font;
  font.loadFromFile("arial.ttf");

  //tekst u¿ywany do wypisywania informacji (np wartoœæ pola)

  sf::Text text[X][Y];






  //kwadraciki planszy u¿ywane do graficznego przedstawienia stanów pól gry
  size_t defusersLeft = LEVEL;
  sf::RectangleShape plansza[X][Y];
  Plansza board(X, Y);
  for(size_t i = 0; i < X; i++)
  {
    for(size_t j = 0; j < Y; j++)
    {
      plansza[i][j].setSize(sf::Vector2f(50,50)); //wielkosc pola to 50pix x 50pix
      plansza[i][j].setPosition(2 + i * 55, 2 + j * 55); //2pix margines, 55pix szerokoϾ i wysokoϾ pola
      plansza[i][j].setFillColor(sf::Color::Cyan); //domyœlny kolor œrodka
      plansza[i][j].setOutlineColor(sf::Color::Black); //domyœlny kolor krawêdzi pola
      plansza[i][j].setOutlineThickness(2.0f); //gruboœæ krawêdzi pola
      if(board.getPole(i, j).getIsArmed() == true) //i to pole by³o uzbrojone :<
                {
                  plansza[i][j].setFillColor(sf::Color::Red);}
    }
  }

  /////////////////////////////////////////////////////////////////////////////////////////////////
  //g³ówna pêtla okna
  bool quit = false;
  while(window.isOpen() && !quit)
  {
    sf::Event event;
    while(window.pollEvent(event))
    {
      //reakcja na klikniêcie przycisku [X]
      if(event.type == sf::Event::Closed)
      {
        window.close();
      }

      //reakcja na klikniêcie lewym przyciskiem myszy
      if((event.type == sf::Event::MouseButtonPressed) && (event.mouseButton.button == sf::Mouse::Left))
      {

        for(size_t i = 0; i < X; i++) //skan przez wszystkie wiersze...
        {
          for(size_t j = 0; j < Y; j++) //wszystkich kolumn
          {
            //jeœli aktualnie sprawdzana komórka zawiera pozycjê kursora (trafiliœmy pole o wspó³rzêdnych i, j)
            if(plansza[i][j].getGlobalBounds().contains(sf::Vector2f(sf::Mouse::getPosition(window))))
            {
              if(board.getPole(i, j).getIsNaked() == false) //jeœli trafiliœmy na zakryte pole...
              {
                if(board.getPole(i, j).getIsArmed() == true) //i to pole by³o uzbrojone :<
                {
                  plansza[i][j].setFillColor(sf::Color::Red);
                  cout << "LPM [ " << i << " ][ " << j << " ] value = " << board.getPole(i, j).getValue() << endl;
                  cout << "koniec gry" << endl;
                  quit = true;
                } else //nie by³o uzbrojone! :D
                {
                  cout << "LPM [ " << i << " ][ " << j << " ] value = " << board.getPole(i, j).getValue() << endl;
                  board.getPole(i, j).setIsNaked(true);
                  plansza[i][j].setFillColor(sf::Color::Green);

                      text[i][j].setFont(font);
                      text[i][j].setColor(sf::Color::White);
                      text[i][j].setCharacterSize(20);
                      text[i][j].setPosition(22 + i * 55, 15 + j * 55);
                      if(board.getPole(i, j).getValue()==1){
                      text[i][j].setString("1"); }
                      if(board.getPole(i, j).getValue()==2){
                      text[i][j].setString("2"); }
                      if(board.getPole(i, j).getValue()==3){
                      text[i][j].setString("3"); }
                      if(board.getPole(i, j).getValue()==4){
                      text[i][j].setString("4"); }
                      if(board.getPole(i, j).getValue()==5){
                      text[i][j].setString("5"); }
                      if(board.getPole(i, j).getValue()==6){
                      text[i][j].setString("6"); }
                      if(board.getPole(i, j).getValue()==7){
                      text[i][j].setString("7"); }
                      if(board.getPole(i, j).getValue()==8){
                      text[i][j].setString("8"); }



                }
              }
            }
          }
        }
      }

      //reakcja na klikniêcie prawym przyciskiem myszy
      if((event.type == sf::Event::MouseButtonPressed) && (event.mouseButton.button == sf::Mouse::Right))
      {
        for(size_t i = 0; i < X; i++) //skan przez wszystkie wiersze...
        {
          for(size_t j = 0; j < Y; j++) //wszystkich kolumn
          {
            //jeœli aktualnie sprawdzana komórka zawiera pozycjê kursora (trafiliœmy pole o wspó³rzêdnych i, j)
            if(plansza[i][j].getGlobalBounds().contains(sf::Vector2f(sf::Mouse::getPosition(window))))
            {
              if(board.getPole(i, j).getIsMarked() == false) //i to pole nie by³o oznaczone
              {
                if(defusersLeft) //i mamy jeszcze defusery (prawie jak w CS :D)
                {
                  plansza[i][j].setFillColor(sf::Color::Blue);
                  board.getPole(i, j).setIsMarked(true);
                  board.getPole(i, j).setIsArmed(false);
                  defusersLeft--;
                }
              }
              else //odznaczyliœmy zaznaczone (klikniêcie dwa razy w to samo miejsce)
              {
                  plansza[i][j].setFillColor(sf::Color::Cyan);
                  board.getPole(i, j).setIsMarked(false);
                  board.getPole(i, j).setIsArmed(false);
                  defusersLeft++;
              }
            }
          }
        }
      }
    }

    //cykl clear/draw/display
    window.clear(sf::Color::Black);

    for(size_t i = 0; i < X; i++)
    {
      for(size_t j = 0; j < Y; j++)
      {
        window.draw(plansza[i][j]);
        window.draw(text[i][j]);
        //todo draw board[i][j] value
      }
    }

    window.display();
    if(quit)
         sleep(seconds(2));
  }
  return 0;
}

 

Podobne pytania

+2 głosów
1 odpowiedź 277 wizyt
pytanie zadane 1 lipca 2015 w Java przez Mateep Użytkownik (850 p.)
0 głosów
0 odpowiedzi 175 wizyt
pytanie zadane 14 marca 2017 w Python przez anderpy Nowicjusz (120 p.)

92,621 zapytań

141,477 odpowiedzi

319,817 komentarzy

62,005 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...