Saper w c++, funkcja rozlosowujaca miny

0

Witam
Mam do napisania w C++ grę saper.
Posiadam problem, z funkcja rozlosowujaca miny.
Funkcja ta powinna działać tak:
/miny nie powinny nachodzić na
siebie i wychodzić poza planszę. Podpowiedź: losujmy jakieś położenie i sprawdzajmy czy nie ma
tam już znaku ‘*’ lub czy nie wchodzimy na brzeg i jeśli coś nam przeszkadza losujemy nowe
położenie (I tak do skutku…). Losowana mina powinna dodawać +1 do położenia na prawo, lewo,
górę, dół od niej (o ile nie ma już tam miny lub o ile to nie ściana planszy)//
Napisałam kod, ale wyskakuje mi błąd "Segmentation fault(core dumped)" i nie potrafie go naprawic
Bardzo prosze o pomoc.
Moj kod:
class saper
{
int wymiar;
char** planszaKomputera;
char** planszaWidza;
int miny;
int nieodkryteNiezaminowane;
public:
saper(int x);
~saper();
void print();
void losowanie();
void sprawdzanie(int x, int y);
void wypis();
int puste();
int czytanie();

};
void saper::losowanie()
{
srand(time(NULL));
int x=0;
int y=0;
if(wymiar==5)
{
miny=6;
}
if(wymiar==7)
{
miny=20;
}
if(wymiar==9)
{
miny=30;
}

for(int i=0; i<miny; i++)
{
	
	if(planszaKomputera[x][y]!='*')
	{
		
		x=rand()%wymiar;
		y=rand()%wymiar;
		planszaKomputera[x][y]='*';
		for (int k = -1; k<2; k++)
        for (int l = -1; l<2; l++)
        {
			/*if ((x+l)<0 || (y+k)<0 ) continue; 
            if ((x+l)>wymiar || (y+k)>wymiar ) continue; 
            
            if (planszaKomputera[x+l][y+k]=='*') continue; 
            planszaKomputera[x+l][y+k]+=1; */
        }
	
		miny--; 
	} 
	//if(x<0 || y<0) continue;
	//if(x>wymiar || y>wymiar) continue;
	
} 

}

0

Mamy kilka problemów. planszaKomputera powinna być tablicą tablic, a jest char'em. Ładnie obiektowo byłoby zrobić klasę plansza i dziedziczące z niej planszaWidza oraz planszaKomputera. Ale nie komplikujmy. Po drugie cała planszaKomputera powinna być zainicjalizowana, np. wypełniona zerami. Dopiero wtedy można umieszczać ładunki. Po trzecie to miejsce gdzie dekrementujesz miny - to jest raczej zły pomysł. Powinno działać bez tego. Mam nadzieję, że wolno Ci używać STL - wówczas bardzo dobrym pomysłem byłoby użycie

std::vector<std::vector<char>> planszaKomputera, planszaWidza;

... bo dzięki temu nie piszemy po pamięci, tylko sprawdzamy czy jesteśmy w dopuszczalnym zakresie. Jeszcze pytanie, czy wolno Wam używać szablonów (ang. template)? To by trochę ułatwiło.

Mam akurat chwilę czasu, więc spróbuję napisać co mi chodzi po głowie:

class saper
{
  template <int WYMIAR> class wspolrzedna
  {
    private:
    int wartosc;
    public:
    wspolrzedna(int nowa_wartosc): wartosc{nowa_wartosc} {}
    bool czy_poprawna() const { return wartosc>=0 && wartosc<WYMIAR; }
    operator int() const { return wartosc; }
  };

  template <int WYMIAR> class pozycja
  {
    private:
    wspolrzedna<WYMIAR> x, y;
    public:
    pozycja(int nowe_x, int nowe_y): x{nowe_x}, y{nowe_y} {}
    bool czy_poprawna() const { return x.czy_poprawna() && y.czy_poprawna(); };
    int daj_x() const { return x; }
    int daj_y() const { return y; }
  };

  template <int WYMIAR> class plansza
  {
    protected:
    class pole
    {
      private:
      bool znane;
      enum class TYP { PUSTE, BOMBA, LICZNIK } moj_typ;
      int wartosc_licznika;
      public:
      pole(): znane{true}, moj_typ{PUSTE}, wartosc_licznika{0} {}
      TYP & daj_typ() { return moj_typ; }
      int & daj_licznik() { return wartosc_licznika; }
      void ustaw_znane(bool z) { znane=z; }
    };
    std::vector<std::vector<pole>> macierz_pol;
    public:
    plansza()
    {
      macierz_pol.resize(WYMIAR);
      for (int x=0; x<WYMIAR: x++)
      {
        macierz_pol[x].resize(WYMIAR);
      }    }
  };

template <int WYMIAR> class plansza_komputera: public plansza<WYMIAR>
{
    public:
    plansza_komputera(int miny)
    {
      while (miny>0)
      {
        pozycja<WYMIAR> p{rand()%WYMIAR,rand()%WYMIAR};

        if (macierz_pol[p.daj_x()][p.daj_y()].daj_typ()==pole::TYP::BOMBA)
          continue;

        macierz_pol[p.daj_x()][p.daj_y()].daj_typ()=pole::TYP::BOMBA;
        for (int dx=-1; dx<=1; dx++)
        {
          for (int dy=-1; dy<=1; dy++)
          {
            pozycja<WYMIAR> pd{p.daj_x()+dx,p.daj_y()+dy};
            if (pd.czy_poprawna())
            {
              macierz_pol[pd.daj_x()][pd.daj_y()].daj_licznik()++;            
            }
          }
        }
        miny--;
      }
    }
};
template <int WYMIAR> class plansza_widza: public plansza<WYMIAR>
{
  public:
  plansza_widza(const plansza_komputera<WYMIAR> & p)
  {
    for (int x=0; x<WYMIAR; x++)
    {
      for (int y=0; y<WYMIAR; y++)
      {
        macierz_pol[x][y] = p.macierz_pol[x][y];
        macierz_pol[x][y].ustaw_znane(false);
      }
    }
  }
};
  
};

Mam nadzieję, że rozumiesz ideę - w programowaniu obiektowym staramy się "upchać" kod do danych, na których on operuje. W moim przykładzie plansza_widza nie potrafi się zainicjować tak jak plansza_komputera, ale za to potrafi skopiować wszystkie dane z planszy komputera i ustawić flagę "znane" na false.

3

@misia91989:

losujmy jakieś położenie i sprawdzajmy czy nie ma
tam już znaku ‘*’ lub czy nie wchodzimy na brzeg i jeśli coś nam przeszkadza losujemy nowe
położenie (I tak do skutku…).

To brzmi jak bardzo zły pomysł. Tutaj jak można zrobić to lepiej: Moja implementacja losowania pól
Algorytm opisany przez ciebie będzie bardzo nieefektywny dla większej liczby bomb.

1 użytkowników online, w tym zalogowanych: 0, gości: 1