Как я могу заполнить 2d массив случайными символами? Использование классов в C ++ - PullRequest
0 голосов
/ 23 апреля 2020

Я делаю головоломку Word Search Puzzle для школы, и проблема, с которой я столкнулся, заключается в следующем.

Я пытаюсь заполнить двумерный массив случайными символами, что не сложно, но когда вы вводите классы и указатели .. Это сбивает с толку. Итак, у меня есть класс с именем Char, и его функция - генерировать случайный символ для хранения внутри 2d-массива, присутствующего в классе Board.

class Char
{
private:

    char Letters;

public:

    Char();
    Char(char let);
    ~Char();

    void Set_Letters(char let) { Letters = let; }
    char Get_Letters(void) { return Letters; }

    void Random(void);
    void View(void);
};

class Board
{

private:

    int BoardWidth;
    int BoardHeight;
    int numWords;
    Char** Caracters;

    Point P; //This is ponting to an other class called Point, it keeps track of the location of the Words that were read from the txt file
public:

    Board(void);
    ~Board();

    void Init(int Dx, int Dy);

    inline void Set_BoardWidth(int bW) { BoardWidth = bW; }
    inline void Set_Boardheight(int bH) { BoardHeight = bH; }
};

Так что это важные классы. В классе Board переменная, которую я использую для хранения 2d-массива, - это Char **, который я даже не знаю, является ли это правильным способом сделать это. Вот соответствующий код функций в классе Char:

void Char::Random()
{

    //The unsigned int is used to silence the error : "Possible loss of data"
    srand((unsigned int)time(NULL));
    Set_Letters('A' + (rand() % 26));
}

Это создает случайные символы, и это та часть, которая должна сохранять символы в 2d массиве.

void Board::Init(int Dx, int Dy)
{

    Set_BoardWidth(Dx);
    Set_Boardheight(Dy);

    Char Letter;
    int n = 0, m = 0;

    for (int j = 0; j < Dy; j++)
    {
        for (int i = 0; i < Dx; i++)
        {
            //Fill the array with random char´s
            Letter.Random();
            **Caracters = Letter.Get_Letters();
            //In this part im attributing a x and y value to the char
            P.Set_x(n); P.Set_y(m);
            n++; m++;
        }
    }
}

Ошибка, которую он мне выдает:

«Возникло исключение: нарушение прав чтения. this->Caracters was nullptr».

Я пытался создайте строку в классе Board для хранения всего этого, но, похоже, она не работает, по какой-то причине класс даже не распознает переменную, когда я ее использовал. Также пытался использовать char**, выдал мне ту же ошибку.

И это все, больше ничего не пробовал. После просмотра видео у меня появилась идея использовать вектор, но я еще не пробовал.

Я только что закончил изучать C в прошлом семестре, и я чувствую, что все еще слишком много схватился за это. И мне трудно разлучить их обоих. Поэтому, если у вас есть какие-либо советы о том, как я могу стать лучше и что я могу улучшить, я также пишу код, пожалуйста, дайте мне знать.

1 Ответ

0 голосов
/ 23 апреля 2020

Я создал пример кода, чтобы показать, как это можно сделать с помощью более современных библиотек C ++. rand() не рекомендуется, поскольку он просто не очень хорош в своей работе, и использование modulo arithmeti c для принудительного выбора диапазона также искажает результаты.

#include <iostream>
#include <random>

class Board {
 public:
  explicit Board(int rows, int columns)
      : m_rows(rows), m_columns(columns), m_board(rows * columns, '0') {
    for (auto& i : m_board) {
      i = capital(prng);
    }
  }
  void print() const {
    for (int i = 0; i < m_rows; ++i) {
      for (int j = 0; j < m_columns; ++j) {
        std::cout << m_board[i * m_columns + j] << ' ';
      }
      std::cout << '\n';
    }
  }

 private:
  int m_rows = 0;
  int m_columns = 0;
  std::vector<char> m_board = {};

  static std::random_device rd;
  static std::mt19937 prng;
  static std::uniform_int_distribution<char> capital;
};

std::random_device Board::rd;
std::mt19937 Board::prng(Board::rd());
std::uniform_int_distribution<char> Board::capital('A', 'Z');

int main() {
  Board board(5, 5);
  board.print();
}

Я избавился от класса персонажа; в этом не было необходимости Вместо массива мы будем использовать вектор. В целом, их лучше использовать. Обратите внимание, что это 1D. Это работает лучше, чем вектор векторов. Наш класс Board будет использовать некоторые арифметические c трюки, чтобы представить, что это 2D. Вы можете увидеть, как это работает в функции печати. ​​

Я включил в класс инструменты генератора случайных чисел как члены stati c. Это была еще одна проблема с вашим кодом; вы пересевали каждый раз, когда вызывали функцию Random(). Вы только семя один раз. static в классах C ++ означает, что все объекты этого типа имеют общие члены c.

static члены должны быть инициализированы вне класса, если они не inline static, и вы компилируете с C ++ 17 или выше. Я позволил конструктору заполнить доску случайными буквами. Это способ C ++ делать вещи, когда это возможно. Ваша Init() функция просто плохо выполняла работу конструктора.

Более того, я больше не управляю динамическими c ресурсами самостоятельно. Намного больше нужно go в этот класс, например, итератор и, возможно, operator[], но приведенный код решает вашу текущую проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...