Printing a grid - c++

I want to print a game board grid which will vary in size depending on what the user inputs. I also wanted to know would it be best or even be possible to make this same grid using an array or would I need some type of 2d array of some sort?
void printGrid(int &userRows, int &userColumns){
cout << "Enter the number of rows -> ";
cin >> userRows;
cout << "Enter the number of columns -> ";
cin >> userColumns;
for(int i = 0; i < userColumns; i++){
cout << "|";
for(int y = 0; y < userRows; y++){
cout << "-";
}
}
}
I got the nested loop part down pat. Just having an issue telling it to print a new line and to spawn one after the other. Thank you
Here is the final product I am going for

I got the nested loop part down pat. Just having an issue telling it to print a new line and to spawn one after the other.
Are you sure? That doesn't seem to produce anything close to the final product I am going for?
While that may produce "|" and "-" output, it ignores the column headings, the header separator, the row labels, the footer separator and the column footer.
In answer to the newline part of your question, you have two options, you can either output a newline with the macro endl or you can output a literal newline "\n". If you have declared using namespace std;, you can simply use the cout << endl; or cout << "\n";. otherwise you need to explicitly specify the std namespace, e.g. std::cout << endl; or std::cout << "\n";
To finish building your output with column heading, separators, row labels, footer separator and footer, just take it piece-by-piece. For example for your column headings, you could simply loop over your columns, outputting your loop counter + 1 with appropriate spacings:
for (int i = 0; i < cols; i++) /* output column headings */
if (!i)
std::cout <<" " << i+1;
else
std::cout <<" " << i+1;
std::cout << "\n";
(note: the use of the if (!i) (equivalent to if (i == 0)) to handle the first-column spacing separately)
For your heading separator, you could loop over the columns again, in like manner with the same check handling the first column differently.
for (int i = 0; i < cols; i++) /* output header separators */
if (!i)
std::cout <<" ---";
else
std::cout <<" ---";
std::cout << "\n";
Then the actual grid sections requires row-labels both before, and after, each row of the grid is output. Here you simply add a nested loop to loop over each row, but otherwise use a similar loop over each column with first row check, followed by a final output of the closing row-label for each row:
for (int i = 0; i < rows; i++) { /* output labeled grid rows */
for (int j = 0; j < cols; j++)
if (!j)
std::cout << (char)('A' + i) << " | |";
else
std::cout << " |";
std::cout << " " << (char)('A' + i) << "\n";
}
Finally, you just repeat what you did for the column headers and header separator in reverse order for your footer separator and footer, outputting the separator row first followed by the column footers, e.g.
for (int i = 0; i < cols; i++) /* output footer separators */
if (!i)
std::cout <<" ---";
else
std::cout <<" ---";
std::cout << "\n";
for (int i = 0; i < cols; i++) /* output column footer */
if (!i)
std::cout <<" " << i+1;
else
std::cout <<" " << i+1;
std::cout << "\n"; /* tidy up with new line */
That's pretty much it. You can throw together a short example using a class board to hold the rows and cols values and a constructor and a couple of member functions to update or request input for new row/column values, e.g. the following just outputs your 4x6 grid, then prompts for new rows and cols values, and finally output a 5x7 example:
#include <iostream>
class board {
int rows, cols;
public:
board() {};
board (int x, int y) { rows = x; cols = y; }
void prngrid ();
void setsize (int x, int y) { rows = x; cols = y; }
void setsize ();
};
void board::prngrid ()
{
std::cout << "\n"; /* output new line before grid */
for (int i = 0; i < cols; i++) /* output column headings */
if (!i)
std::cout <<" " << i+1;
else
std::cout <<" " << i+1;
std::cout << "\n";
for (int i = 0; i < cols; i++) /* output header separators */
if (!i)
std::cout <<" ---";
else
std::cout <<" ---";
std::cout << "\n";
for (int i = 0; i < rows; i++) { /* output labeled grid rows */
for (int j = 0; j < cols; j++)
if (!j)
std::cout << (char)('A' + i) << " | |";
else
std::cout << " |";
std::cout << " " << (char)('A' + i) << "\n";
}
for (int i = 0; i < cols; i++) /* output footer separators */
if (!i)
std::cout <<" ---";
else
std::cout <<" ---";
std::cout << "\n";
for (int i = 0; i < cols; i++) /* output column footer */
if (!i)
std::cout <<" " << i+1;
else
std::cout <<" " << i+1;
std::cout << "\n"; /* tidy up with new line */
}
void board::setsize ()
{
std::cout << "\nenter the number of rows -> ";
std::cin >> rows;
std::cout << "enter the number of cols -> ";
std::cin >> cols;
}
int main (void) {
board board1 (4, 6);
board1.prngrid();
board1.setsize();
board1.prngrid();
board1.setsize (5,7);
board1.prngrid();
return 0;
}
(note: you should add validation checks that rows and cols values are non-negative (or choose an unsigned type), and also check that they are reasonable for your screen output (e.g. less than 20 or so and at least 26 or less or you will run out of upper-case letters). Those checks, and adjustments for multi-digit headings, are left to you)
Example Use/Output
$ ./bin/board_grid
1 2 3 4 5 6
--- --- --- --- --- ---
A | | | | | | | A
B | | | | | | | B
C | | | | | | | C
D | | | | | | | D
--- --- --- --- --- ---
1 2 3 4 5 6
enter the number of rows -> 5
enter the number of cols -> 5
1 2 3 4 5
--- --- --- --- ---
A | | | | | | A
B | | | | | | B
C | | | | | | C
D | | | | | | D
E | | | | | | E
--- --- --- --- ---
1 2 3 4 5
1 2 3 4 5 6 7
--- --- --- --- --- --- ---
A | | | | | | | | A
B | | | | | | | | B
C | | | | | | | | C
D | | | | | | | | D
E | | | | | | | | E
--- --- --- --- --- --- ---
1 2 3 4 5 6 7
Look things over and let me know if you have further questions.

The problem is fairly easy, just understand the pattern! Here's the working code with live example.
#include <iostream>
using namespace std;
void printGrid(int &userRows, int &userColumns){
cout<<endl;
cout<<" ";
int i=1,j;
for(j = 0; j <= 4*userColumns; j++){
if(j%4==2)
cout<<i++;
else cout<<" ";
}
cout<<endl;
for(i = 0; i <= 2*userRows; i++){
if(i%2!=0)
cout<<(char)(i/2 +'A');
for(j = 0; j <= 2*userColumns; j++){
if(i%2==0)
{
if(j==0)
cout<<" ";
if(j%2==0)
cout<<" ";
else cout<<"---";
}
else{
if(j%2==0)
cout<<"|";
else cout<<" ";
}
}
if(i%2!=0)
cout<<(char)(i/2 +'A');
cout<<endl;
}
cout<<" ";
for(j = 0, i = 1; j <= 4*userColumns; j++){
if(j%4==2)
cout<<i++;
else cout<<" ";
}
cout<<endl;
}
int main() {
int userRows, userColumns;
cout << "Enter the number of rows -> ";
cin >> userRows;
cout << "Enter the number of columns -> ";
cin >> userColumns;
printGrid(userRows, userColumns);
return 0;
}
Live Code
Output:
Enter the number of rows -> 4
Enter the number of columns -> 6
1 2 3 4 5 6
--- --- --- --- --- ---
A| | | | | | |A
--- --- --- --- --- ---
B| | | | | | |B
--- --- --- --- --- ---
C| | | | | | |C
--- --- --- --- --- ---
D| | | | | | |D
--- --- --- --- --- ---
1 2 3 4 5 6

By adding the cout << endl; after the userRows for-loop has finish the process it will proceed with the next line until i < userColumns
for(int i = 0; i < userColumns; i++){
cout << "|";
for(int y = 0; y < userRows; y++){
cout << "-";
}
cout << endl; //end of every-line
}

When you say:
make this same grid using an array
I'm guessing you are asking how to handle values you can use to populate the grid. There are lots of ways to store a variable number of values. Here are a few (I'm assuming the values are of type char):
One dimensional std::vector
std::vector<char> gridValues;
gridValues.resize(userColumns * userRows);
Then, inside the for loops:
cout << gridValues.at( i + y*userColumns );
Two dimensional std::vector
std::vector<std::vector<char>> gridValues;
gridValues.resize(userRows);
for( int i = 0; i < userRows; ++i )
gridValues.at(i).resize(userColumns);
Then, inside the for loops:
cout << gridValues.at( y ).at( i );
One dimensional array
char* gridValues = new char[ userColumns*userRows ];
Then, inside the for loops:
cout << gridValues[ i + y*userColumns ];
Two dimensional array
char** gridValues = new char[ userRows ];
for( int i = 0; i < userRows; ++i )
gridValues[i] = new char[ userColumns ];
Then, inside the for loops:
cout << gridValues[ y ][ i ];
I would use the one-dimensional std::vector, because it's simple to setup and I don't have to worry about forgetting to delete the pointers at the end.
As a note, you may want to check you for loops. With userColumns = 3 and userRows = 2, the code you gave will print: |--|--|--. The variables are being used backwards.
Once you fix the order of the loops, JaxLee's answer will help you put the newline in the right spot.

Related

How to left shift a character array?

#include <iostream>
#include<string>
using namespace std;
int main()
{
//for left shift geeksforgeeks should become eksforgeeksge
//for right shift geeksforgeeks should become ksgeeksforgeeks
char* original = new char[100];
cout << "enter the array\n";
cin >> original;
cout << "the array entered is " << original << endl;
int temp = 0;
for (int i = 0; original[i] != '\0'; i++) { temp++; }
cout << "the size of array is " << temp << endl;
int num;
//left shift
cout << "enter the number of digits to be left shifted\n";
cin >> num;
char* temp1 = new char[temp - num];
char* temp2 = new char[num];
int tempn= temp-num;
//storing the characters in the short std::array
for (int i = temp - num; i < temp; i++) {
temp2[i] = original[i+temp-num];
cout << temp2[i];
}
//storing the characters in the larger std::array<T, N> ;
for (int i = 0; i < temp - num; i++) {
temp1[i] = original[i];
cout << temp1[i];
}
cout << endl;
cout <<"the left shifted array is\n ";
for (int i=0; i<num;i++){
original[i]=temp2[i];
cout << original[i];
}
for (int i=0; i < temp; i++){
original[num+i]=temp1[i];
cout <<original[num+i];
}
I have tried to implement a left shift on the dynamic array. But, this does not give the correct answer. It does not display the initial characters after left shifting. The issue is in storing the new array temp2 in the original array. But I cannot figure out how to fix this. Please help.
Given an array of 4 characters:
+---+---+---+---+
ltrs = | a | b | c | d |
+---+---+---+---+
Step 1: copy the first character to a temp variable:
const char temp = ltrs[0];
Step 2 copy slot 1 to slot 0:
+---+---+---+---+
ltrs = | b | b | c | d |
+---+---+---+---+
^ |
+---+
Step 3: keep copying until end of array:
+---+---+---+---+
ltrs = | b | c | d | d |
+---+---+---+---+
Step 4: Copy the temporary variable to the last position in the array:
+---+---+---+---+
ltrs = | b | c | d | a | <--- temp
+---+---+---+---+
Changing to a larger array size is left as an exercise for the OP.

How can I print the empty spaces with " | | " until the line ends [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last year.
Improve this question
I am working with vectors and I wanna know how I can print the empty spaces in between until the line ends.
void print_vector(const std::vector < int > & v, int print_cols, int col_width) {
//dash
cout << string(print_cols * (col_width + 2) + 1, '-');
cout << endl;
//printing the vector in formated output
cout << "|";
for (size_t x = 0; x < v.size(); x++) {
cout << right << setw(col_width) << v[x] << " |";
//prints new line if it reaches limit of numbers per line
if ((x + 1) % print_cols == 0) cout << endl << "|";
}
//dash
cout << endl << string(print_cols * (col_width + 2) + 1, '-');
cout << endl;
}
this is my current output: my output so far and sorry I can't embed images yet it wont let me.
But this is the output that I want output needed
void print_vector(const std::vector < int > & v, int print_cols, int col_width) {
//dash
cout << string(print_cols * (col_width + 2) + 1, '-');
cout << endl;
//printing the vector in formated output
cout << "|";
size_t x = 0;
for (x = 0; x < v.size(); x++) {
cout << right << setw(col_width) << v[x] << " |";
//prints new line if it reaches limit of numbers per line
if (x < v.size() - 1) {
if ((x + 1) % print_cols == 0) {
cout << endl << "|";
}
}
}
size_t remain = print_cols - (x % print_cols);
for (size_t i = 0; (remain != print_cols) && i < remain; ++i) {
cout << right << setw(col_width) << " " << " |";
}
//dash
cout << endl << string(print_cols * (col_width + 2) + 1, '-');
cout << endl;
}
Sample outputs:
-------------------------------------------------
| 1 | 2 | 3 | 4 |
| 5 | 6 | 7 | 8 |
| 9 | | | |
-------------------------------------------------
-------------------------------------
| 1 | 2 | 3 |
| 4 | 5 | 6 |
| 7 | 8 | 9 |
-------------------------------------
You can add an extra loop after the one you have and before the bottom row of dashes:
The loop would print a given number of blank columns.
The number of blank columns can be computed as print_cols - v.size() % print_cols.
The loop should not be executed if the number of blank columns is equal to the total number of columns. That would print a full row of empty columns. That case happens when the vector you want to print has a number of elements that is an exact multiple of the number of columns.
Every iteration of the loop should print col_width + 1 blanks and a '|' (or if you prefer it, to make it more consistent with your other code, col_width blanks plus a " |").
Yet you should fix another issue with your code:
The check for reaching the end of the row (enabling the print of a new line and a '|') should be instead a check for starting a row.
 
If you do it at the end, for the case when the last element of the vector goes in the last column, you will unnecessarily add a new row.
 
Doing it at the beginning, since you know you have at least one more number to show, you can print "\n|" and then the number.
 
The check x % print_cols == 0 will tell you if x is the index of the first element of a row.
[Demo]
#include <iomanip> // setw
#include <iostream> // cout
#include <numeric> // iota
#include <string>
#include <vector>
void print_vector(const std::vector<int>& v, int print_cols, int col_width) {
// dash
std::cout << std::string(print_cols * (col_width + 2) + 1, '-');
// printing the vector in formated output
for (size_t x = 0; x < v.size(); x++) {
// prints new line if it is the first element of the line
if (x % print_cols == 0) {
std::cout << "\n|";
}
std::cout << std::right << std::setw(col_width) << v[x] << " |";
}
// prints last empty columns
if (int number_of_blank_columns = print_cols - v.size() % print_cols;
number_of_blank_columns != print_cols) {
for (int x = 0; x < number_of_blank_columns; x++) {
std::cout << std::string(col_width + 1, ' ') << "|";
}
}
// dash
std::cout << "\n" << std::string(print_cols * (col_width + 2) + 1, '-') << "\n";
}
int main() {
{
std::vector<int> v(8);
std::iota(std::begin(v), std::end(v), 100);
print_vector(v, 5, 4);
}
std::cout << "\n";
{
std::vector<int> v(10);
std::iota(std::begin(v), std::end(v), 100);
print_vector(v, 5, 4);
}
}
// Outputs:
//
// -------------------------------
// | 100 | 101 | 102 | 103 | 104 |
// | 105 | 106 | 107 | | |
// -------------------------------
//
// -------------------------------
// | 100 | 101 | 102 | 103 | 104 |
// | 105 | 106 | 107 | 108 | 109 |
// -------------------------------

toString function from 2D array

Very sorry if this is too long-- I posted a question yesterday about a game program I am trying to write and with the help of some people, I managed to figure everything out pretty quickly.
The very large majority of the program is complete, but I have one last weird task to complete. I have a function written, printGrid, that prints one random element from each 16 bundles of characters from within a char array. For example (It's very ugly-- please excuse my beginner code):
char gameZero[outer_size][inner_size] = {
{'A','A','C','I','O','T'}, {'A','H','M','O','R','S'},
{'E','G','K','L','U','Y'}, {'A','B','I','L','T','Y'}, {'A','C','D','E','M','P'},
{'E','G','I','N','T','V'}, {'G','I','L','R','U','W'}, {'E','L','P','S','T','U'},
{'D','E','N','O','S','W'}, {'A','C','E','L','R','S'}, {'A','B','J','M','O','Q'},
{'E','E','F','H','I','Y'}, {'E','H','I','N','P','S'}, {'D','K','N','O','T','U'},
{'A','D','E','N','V','Z'}, {'B','I','F','O','R','X'}
};
void printGrid() {
mt19937 gen(time(nullptr));
uniform_int_distribution<int> random_inner(0, inner_size - 1);
int n = random_inner(gen);
cout << "+---+---+---+---+\n";
for (int i = 0; i < 4; i++)
cout << "| " << gameZero[i][n] << " ";
cout << "\n+---+---+---+---+\n";
for (int i = 4; i < 8; i++)
cout << "| " << gameZero[i][n] << " ";
cout << "\n+---+---+---+---+\n";
for (int i = 8; i < 12; i++)
cout << "| " << gameZero[i][n] << " ";
cout << "\n+---+---+---+---+\n";
for (int i = 12; i < 16; i++)
cout << "| " << gameZero[i][n] << " ";
cout << "\n+---+---+---+---+\n";
}
This will print a 4x4 game board for the user to see. I am now trying to write a sort of toString function, which takes the random numbers generated in printGrid and prints them out into a single line string with no spaces. The issue I am trying to wrap my head around is, I have this assortment of characters that changes each time the player begins a new game. These 16 characters are coming from a set array of 16 die, holding 6 characters each. Is the only way to make this possible to store these new randomly chosen characters into an empty array so the user can simply print them with the toString function when desired? Another obstacle I would have to then tackle is deleting the array every time the user wants to begin again. If this is the case, could I store them in a vector and use something like vector::clear to solve that?
Current output of printGrid function:
+---+---+---+---+
| T | M | E | L |
+---+---+---+---+
| A | V | L | S |
+---+---+---+---+
| E | A | Qu| F |
+---+---+---+---+
| E | D | N | O |
+---+---+---+---+
Desired output of toString function I would like to create:
TMELAVLSEAQuFEDNO
Very sorry if this is too much to read or too confusing- I've been working on this almost all day and my brain is a bit fried at the moment. Any tips are greatly appreciated!
You have the logic to select the characters, example:
for (int i = 0; i < 4; i++)
cout << "| " << gameZero[i][n] << " ";
You could use std::string and operator += to append the characters to a string:
std::string all_letters;
for (int i = 0; i < 4; ++i)
{
all_letters += gameZero[i][n];
}
Edit 1: Expanding the loop
Since you don't need to print by row, you can iterate through the entire array:
std::string all_letters;
for (int i = 0; i < 16; ++i)
{
all_letters += gameZero[i][n];
}

How can I print a board using a two dimensional array?

I want to print a 5x5 board for a game, at the moment I can only print 5 lines while populating the array. My board currently looks like this:
Which is technically a 2 row 5 columns board.
This is the output I expect:
The problem is that I need a 5x5 version of that same board but it only prints 5 lines (which is the size of the array).
I've tried changing the for loop many times but nothing has worked so far
This is my code:
//
// Created by renan on 31/08/2019.
//
#include <iomanip>
#include <iostream>
#include "Board.h"
void Board::displayBoard() {
for (int row = 0; row < ROWS; row++) { //ROWS and COLS
are integers with value 5
for (int col = 0; col < COLS; col++) {
board[row][col] = ' ';
if (row % 2 == 0) {
cout << " ---";
} else {
if (col == 0) {
cout << "|";
}
if(board[row][col] == ' '){
cout << setw(4) << "|";
} else {
cout << setw(1) << board[row][col] << " |";
}
}
}
cout << endl;
}
}
Board.h
#include <iostream>
using namespace std;
class Board {
private:
static const int ROWS = 11;
static const int COLS = 5;
char board[ROWS][COLS];
public:
void displayBoard();
};
I corrected and simplified your code a bit. Hope it will help you to understand what was wrong with your code.
void drawHorizontalSeparater() {
for (int i = 0; i < 5; i++) {
cout << " ---";
}
cout << endl;
}
void drawSeparatedValues(int row) {
cout << "|";
for (int col = 0; col < 5; col++) {
board[row][col] = ' ';
cout << " " << board[row][col] << " |";
}
cout << endl;
}
void displayBoard() {
drawHorizontalSeparater();
for (int row = 0; row < 5; row++) {
drawSeparatedValues(row);
drawHorizontalSeparater();
}
}
Result:
--- --- --- --- ---
| | | | | |
--- --- --- --- ---
| | | | | |
--- --- --- --- ---
| | | | | |
--- --- --- --- ---
| | | | | |
--- --- --- --- ---
| | | | | |
--- --- --- --- ---

improve 2D array in C++

This is may code for 2D array. I will using it for Battleship game.
I want to ask, if its necessary to use a dynamic memory because I have two 2D array. Also I want to ask if anyone can tell my how to improve or fix my code
I'm not sure that I used the Class correct, but its my first time
enter code here
#include <iostream>
#include<array>
#include <string>
#include <stdlib.h>
#include <vector>
using namespace std;
class Board {
public:
int grid[15][15];
int initBoard(int A, int B)
{
int grid[A][B];
for(int col=0; col<A; col++) //Outer column loop
{
for(int row=0; row<B; row++) //Inner row loop
{
grid[col][row]=0;
}
}
}
void printBoard(int A, int B)
{
if (B == 10){
cout<<endl;
cout<<" ---{WELCOME TO THE BATTLESHIP}---\n"<<endl;
cout << " 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |" << endl << endl;
}
else if (B == 15){
cout<<endl;
cout<<" ---{WELCOME TO THE BATTLESHIP}---\n"<<endl;
cout << " 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12| 13| 14|" << endl << endl;
}
for(int i=0; i<A; i++) //column loop
{
for(int j=0; j<B; j++) //row loop
{
if(j==0)
{
if(i<=9){
cout << i << " " ; //print row number and spaces before new row
}
else if(i>=10){
cout << i << " " ;
}
}
grid[i][j]=0;
cout << grid[i][j] ;
if(j <= B)
{
cout << " | ";
}
}
cout << endl; //new line at end of column
}
cout << endl;
}
}:
int main(){
system("clear");
cout<<endl;
cout<<"***------GAME MENU------***"<<endl<<endl;
int b;
string name;
string surname;
cout<<" Choose Difficulty\n\n"<<" 1 for Easy\n"<<" 2 for
Hard\n"<<endl;
cout<<"***---------------------***"<<endl<<endl;
cout<<"Enter your name: ";
cin>>name;
cout<<"Enter your surname: ";
cin>>surname;
cout<<"Enter your choice -->";
cin>>b;
system("clear");
if (b==1){
Board easy;
easy.initBoard(10,10);
easy.printBoard(10,10);
cout<<endl;
}
else if(b==2){
Board hard;
hard.initBoard(15,15);
hard.printBoard(15,15);
cout<<endl;
}
return 0;
}
if its necessary to use a dynamic memory because I have two 2D array.
On my system, Ubuntu 17.10, each thread stack size is 8 MB (default). You need to figure out your per thread auto-var size, and if your grid is smaller, and enough size is left for max depth function calls, you will not need to use dynamic memory.
Generally, I would not resist using dynamic memory.
Because I have 2D array
The dimensionality has no impact. The grid (made with std::array) takes a fixed number of bytes, and the elements are back to back.