-2

I have an assignment for a CS class where I'm learning C++. For this assignment, I have to write a two dimensional character array which can be passed to a function. The array has to consist of 50 rows and 50 columns. All elements must be initialized to a space (' ').

I have creating the array here I have also written a for loop to place the array in a grid. Now, I have to assign asterisks randomly to elements of the array, which are still left blank, and I cannot figure out how to do so.

#include <iostream>
#include <iomanip>
#include <ctime>
#include <cstdlib>
#include <stdlib.h>

using namespace std;

int main()
{
    const int rows = 50; // Variables
    const int col = 50;
    const char SIZE = ' ';
    const int hgt = 48;
    int X = rand() % 50; // *Edited: This code was copied from an older save
    int y = rand() % 50;

    char board[rows][col]; // Array initialization
    int i;
    int j;
    int x;

    srand((unsigned)time(0));  
    for (i = 0; i < rows; i++) // For loop to place array in grid.
    {
        for (j = 0; j < col; j++)
        {
            board[i][j] = SIZE;
        }
            board[x][y] = '*'
   }

    cout << setfill('-') << setw(50) << "" << endl; // Grid
    for (X = 0; X < hgt; X++)
    {
        cout << "|" << setfill(' ') << setw(49) << "|" << endl;
    }
    cout << setfill('-') << setw(50) << "" << endl;

        cin.ignore();
    cout << "Press Enter to continue..." << endl;
    cin.ignore();
    return 0;
}

The array works, the grid works. I just cannot figure out how to assign asterisks randomly placed in the grid and how to pass that array into a function.

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
  • Why `board[x][y] = '*'` is inside `for`? It always does same thing, there is no point to repeat it. Also, when "printing" map, why you don't use array's values? As for placing asterisks, you did ok with one asterisk. If you need more add loop. – sklott Sep 04 '19 at 06:06
  • 1
    It's very odd to refer to the initial fill character as "SIZE". In what way do you feel that it is a size? (Words have meanings that don't disappear just because a computer is involved. Say what you mean; mean what you say.) – molbdnilo Sep 04 '19 at 06:06
  • It depends, how many asterisks you want to generate? Or is the number of asterisks also random? – slepic Sep 04 '19 at 06:10
  • Not to mention that `int x` is declared twice... – Scheff's Cat Sep 04 '19 at 06:10
  • `int x = rand() % 50;` is evaluated once; writing `x` is not equivalent to writing `rand() % 50`. You need to do it repeatedly. You know how to do things repeatedly. – molbdnilo Sep 04 '19 at 06:10
  • If the number of asterisks is random, then you can just initialize the array randomly with spaces and with some nonzero probability generate an asterisk instead. If it is fixed amount of asterisks, then do a for loop (that many times) and in the loop generate random x and y coordinates and assign asterisk to the element on that coordinate. If asterisk is already there, generate new x,y pair before you continue the loop. So it would actualy be a do-while in a for... – slepic Sep 04 '19 at 06:13
  • 1
    You tagged this question with c++ but you use c coding style. Use [std::array](https://en.cppreference.com/w/cpp/container/array), [range based for loop](https://en.cppreference.com/w/cpp/language/range-for)s, [](https://en.cppreference.com/w/cpp/numeric/random) and [](https://en.cppreference.com/w/cpp/algorithm). – Thomas Sablik Sep 04 '19 at 07:23
  • 1
    Don't use [using namespace std](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice). Don't include `` and `include ` at the same time. Choose one – Thomas Sablik Sep 04 '19 at 07:27
  • I'm learning C++ in the class but still in the fundamental stages of the language so maybe that's why the style appears to be C. I think I should have done more debugging of my code before posting here. Sorry for posting too soon but thank you for the help. Feel like these comments are leading me in the right direction. – Lost.CS.Student Sep 04 '19 at 07:29
  • 1
    Good point. You may (or may not) refer your teacher to this video [Stop Teaching C](https://www.youtube.com/watch?v=YnWhqhNdYyk). ;-) I must admit that I first learnt C (decades ago) and later switched to C++ (decades ago) which I'm afraid am still learning. Hard to leave C habits in C++ as most of them are still working in C++ (somehow)... – Scheff's Cat Sep 04 '19 at 07:32
  • `const int rows = 50; const int col = 50; char board[rows][col];` is not valid iso c++. The size of an array has to be a compile time constant. Since c++11 you can do `constexpr int rows = 50; constexpr int col = 50; char board[rows][col];` – Thomas Sablik Sep 04 '19 at 07:40
  • I wish my professor had taught us like that because I am most likely picking up these bad habits. I am not quitting though, just going to change my mindset – Lost.CS.Student Sep 04 '19 at 07:46

2 Answers2

0

Concerning

how to pass that array into a function

An array is a special case concerning function parameters:

void f(int a[10]);

isn't a function with a value parameter of int[10] as it looks like. Arrays are not passed by value – they decay to a pointer to first element. Hence, the above function declaration is the same as

void g(int *a); // the same as g(int a[]);

If the array is a 2d array (an array of arrays), this doesn't change:

void f(int a[10][3]);

is the same as:

void g(int (*a)[3]); // the same as g(int a[][3]);

The mix of pointer and dimension makes things a bit complicated: The parentheses around *a are absolutely necessary because

void h(int *a[3]); // the same as void h(int *a[]); or void h(int **a);

would have a pointer to pointer(s) as argument what is something completely different.

However, there is a very simple trick to come around all theses issues:

Using a typedef:

typedef char Board[10][3];

or using using (more modern):

using Board = char[10][3];

Now, things become very easy:

void f(Board &board); // passing array by reference

which could be also written as:

void f(char (&board)[10][3]);

but the latter might look a bit scaring.

Btw. passing the array by reference prevents that the array type decays to a pointer type like demonstrated in the following small sample:

#include <iostream>

void f(char a[20])
{
  std::cout << "sizeof a in f(): " << sizeof a << '\n';
  std::cout << "sizeof a == sizeof(char*)? "
    << (sizeof a == sizeof(char*) ? "yes" : "no")
    << '\n';
}

void g(char (&a)[20])
{
  std::cout << "sizeof a in g(): " << sizeof a << '\n';
}

int main()
{
  char a[20];
  std::cout << "sizeof a in main(): " << sizeof a << '\n';
  f(a);
  g(a);
}

Output:

sizeof a in main(): 20
sizeof a in f(): 8
sizeof a == sizeof(char*)? yes
sizeof a in g(): 20

Live Demo on coliru


Concerning

I just cannot figure out how to assign asterisks randomly placed in the grid

I cannot say it shorter than molbdilno:

You need to do it repeatedly.


For a demonstration, I re-designed OPs code a bit:

#include <iomanip>
#include <iostream>

const int Rows = 10; //50;
const int Cols = 10; //50;

// for convenience
//typedef char Board[Rows][Cols];
using Board = char[Rows][Cols];

void fillGrid(Board &board, char c)
{
  for (int y = 0; y < Rows; ++y) {
    for (int x = 0; x < Cols; ++x) board[y][x] = c;
  }
}

void populateGrid(Board &board, int n, char c)
{
  while (n) {
    const int x = rand() % Cols;
    const int y = rand() % Rows;
    if (board[y][x] == c) continue; // accidental duplicate
    board[y][x] = c;
    --n;
  }
}

void printGrid(const Board &board)
{
  std::cout << '+' << std::setfill('-') << std::setw(Cols) << "" << "+\n";
  for (int y = 0; y < Rows; ++y) {
    std::cout << '|';
    for (int x = 0; x < Cols; ++x) std::cout << board[y][x];
    std::cout << "|\n";
  }
  std::cout << '+' << std::setfill('-') << std::setw(Cols) << "" << "+\n";
}

int main()
{
  srand((unsigned)time(0));
  Board board;
  fillGrid(board, ' ');
  std::cout << "Clean grid:\n";
  printGrid(board);
  std::cout << '\n';
  populateGrid(board, 10, '*');
  std::cout << "Initialized grid:\n";
  printGrid(board);
  std::cout << '\n';
}

Output:

Clean grid:
+----------+
|          |
|          |
|          |
|          |
|          |
|          |
|          |
|          |
|          |
|          |
+----------+

Initialized grid:
+----------+
|          |
|      *   |
|**  * *   |
|     *    |
|          |
|          |
|*         |
|          |
|    *     |
|   * *    |
+----------+

Live Demo on coliru

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
0

This is may understanding of a c++ code style. Avoid c style arrays and use std::array. Don't use std::rand but use <random>. Use the stl containers and algorithms. Use range based for loops instead of classic for loops. Use const whenever you can.

#include <algorithm>
#include <array>
#include <iostream>
#include <random>

using Board = std::array<std::array<char, 50>, 50>;

void randomFill(Board &board, std::size_t count) {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> disX(0, board.size());
    std::uniform_int_distribution<> disY(0, board[0].size());
    while (count > 0) {
        const std::size_t x = disX(gen);
        const std::size_t y = disY(gen);
        if (board[y][x] == '*') continue;
        board[y][x] = '*';
        --count;
    }
}

int main() {
    Board board;
    for (auto &row : board) {
        std::fill(std::begin(row), std::end(row), ' ');
    }

    randomFill(board, 50);

    for (const auto &row : board) {
        for (const auto &field : row) {
            std::cout << field << ' ';
        }
        std::cout << '\n';
    }
    return 0;
}
Thomas Sablik
  • 16,127
  • 7
  • 34
  • 62