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];
}
Related
#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.
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 |
// -------------------------------
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.
Hello I am trying to create a tick Tack Toe Game For my College Project,
The Board size of the game needs to be GENERIC using 2D array in C++.
So I'm having trouble while initializing Default numbers(Places) identifier in an array
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
Boards[i][j] = initial++;
}
}
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
if (Boards[i][j] < 10) cout << " " << Boards[i][j] << " | ";
else cout << Boards[i][j] << " | ";
}
cout << endl;
}
As the variable 'initial' is a integer and i have to increment it in loop.I am quite not sure how to save it in char array (BOARD) Board needs to be char to display X,O
Now that you have posted the full code, I can see a problem on this line and the other one like it:
cout << Boards[i][j] << " | ";
Since the type of Boards[i][j] is a char, the C++ standard library will just send that char to your terminal, and the terminal will try to interpret it as an ASCII character. You need to cast it to an int first so that the C++ standard library will format it properly for you:
cout << (int)Boards[i][j] << " | ";
So I am trying to print a board exactly like this with the multidimensional array
char score[10][10] = {' '};
a b c d e f g h i j
+-------------------+
0| |
1| |
2| |
3| |
4| |
5| |
6| |
7| |
8| |
9| |
+-------------------+
Currently this is my code:
#include <iostream>
using namespace std;
#include <vector>
#include <string.h>
int main() {
char score[10][10] = {' '};
cout << " a b c d e f g h i j" << endl;
cout << " +-------------------+" << endl;
for (int i = 0; i < 10; i++) {
cout << " " << i << "|";
for (int j = 0; j < 10; j++) {
cout << score[i][j];
}
if(i == 0) {
cout << " |";
} else {
cout << " |";
}
cout << endl;
}
cout << " +-------------------+" << endl;
}
As you can see my code is inefficient and lengthy.
What would be the most efficient possible way ( or a more efficient way) of printing the board as exactly shown above with the multidimensional score array?
As the comments have pointed out, your code is almost efficient as possible. Making it shorter would do little to its run-time and instead obscure its meaning. There are however a few things you can do to speed it up.
Avoid an extra call to operator<<, evaluation of std::end, and unnecessary buffer flushes by using \n and including it in your existing string literals (evaluated at compile time).
Use printf instead of cout. See "performance" section of this article.
As already pointed out by others, there are not many ways to make this more efficient, particularly if constrained to use the cout stream.
But for the "lengthy" part, this is a few lines and characters shorter, albeit C++11:
cout << " a b c d e f g h i j\n"
" +-------------------+\n";
for (int i = 0; i < 10; i++) {
cout << ' ' << i << '|';
for (char s : score[i])
cout << s;
cout << " |\n";
}
cout << " +-------------------+\n";
I don't understand why the spaces should be printed at the end instead of aligning the inner columns nicely, but I followed what you did in your code.
I have also got rid of the unnecessary endl which triggers stream flush and changed single letter strings to character constants, but I'm a bit doubtful of the resulting efficiency gain there. After all, it's just printing some output, not a time-critical computation task.
I'm going to assume that when you said you wanted to make it efficient and not lengthy what you really meant was that you wanted it to be correct and readable.
I don't believe what you currently have is "correct". I assume that char score[10][10] will contain a single printable character for each square of the board and perhaps a null character for cells where you don't want to print anything. And you want to print the contents of score into the template shown. As it stands, if you put anything other than a single space into char score[10][10] you will mess up your template.
As for readability, I think what you currently have is reasonably readable, perhaps it would benefit by having some functions extracted with meaningful names but that is just my personal preference. Based on my assumptions about what you were trying to do here is my corrected and refactored version:
#include <iostream>
#include <vector>
#include <string>
void printHeader() {
std::cout << " a b c d e f g h i j\n";
std::cout << " +-------------------+\n";
}
void printFooter() {
std::cout << " +-------------------+\n";
}
void printRowStart(int i) {
std::cout << " " << i << "|";
}
void printRowEnd() {
std::cout << "|\n";
}
void printSquare(char score) {
char printable_score = (score != '\0') ? score : ' ';
std::cout << printable_score;
}
void printRowScore(char (&row_score)[10]) {
printSquare(row_score[0]);
for (int i = 1; i != 10; ++i) {
std::cout << " ";
printSquare(row_score[i]);
}
}
void printScore(char (&score)[10][10]) {
printHeader();
for (int i = 0; i != 10; ++i) {
printRowStart(i);
printRowScore(score[i]);
printRowEnd();
}
printFooter();
}
int main(){
char score[10][10] = { { 0 } };
// Added to test assumed usage
score[4][5] = 'x';
score[4][6] = 'x';
printScore(score);
}
You might also want to consider making the code print to a generic ostream to make it more testable.