Fix array not properly being assigned - c++

I am trying to assign a specific part of an array a new value, but it doesn't seem to be inserting the new value into the array.
char matrix[20][8] = {/*160 * '#'*/};
void Draw() {
system("CLS");
cout << "Welcome to Primitive Pong v1.0!" << endl;
for (int i = 0; i < 8; i++) {
cout << endl;
for (int j = 0; j < 20; j++) {
cout << matrix[i][j] << " ";
}
}
}
while (gameOver == false) {
matrix[10][4] = 'O';
Draw();
this_thread::sleep_for(chrono::milliseconds(1000));
}
I expect this to output a grid of 160 "#" with a "O" near the middle, but instead it just prints 160 "#". I am trying to make a game of console pong. I have tried using 'matrix[10][4] = {'O'};, but that does nothing different.

The problem is that you declare matrix[20][8] but then you access it as if its dimensions are [8][20] instead.
The total is the same but the access doesn't work correctly and, unfortunately, C++ will not check about this kind of mistake. Changing the code to
cout << matrix[j][i] << " ";
should make things work a you expect.

Related

Memory leak when printing 2D array

I have memory leak when i print my 2D array, i looped in data from a vector into a vector called grid
Some indexes in Grid is null for example grid[8][8] is null, but grid[1][1] has a value of 3.
When i display indexes of grid with null value gives me a memory leak.
Below are my code, Any recommendations will be appreciated!
void populateAppendixB(vector<string> cityLocation, int **grid, int col, int row) {
vector<int> data = appendixB_data(cityLocation);
vector<string> appendixB_coordinates = getCoordinates(cityLocation);
vector<int> x_value = returncolValue(appendixB_coordinates);
vector<int> y_value = returnrowValue(appendixB_coordinates);
//loop data into grid[][]
for (int i = 0; i < x_value.size(); i++) {
grid[x_value[i]][y_value[i]] = data[i];
}
cout << " ";
//Top outer Grid
for (int i = 0; i < col + 2; i++) {
cout << " # ";
}
cout << " # ";
cout << endl;
//end
//y-axis
for (int j = row; j >= 0; --j) {
cout << " " << j << " # ";
for (int i = 0; i <= col; ++i) {
//displaying data
if(grid[i][j] == 0) {
cout << " ";
}
else {
cout << grid[i][j] << " ";
}
}
//Right outer Grid
cout << "#";
cout << endl;
}
//Last row of #
cout << " ";
for (int i = 0; i < col + 2; i++) {
cout << " # ";
}
cout << " # ";
cout << endl;
cout << " ";
//x-Axis
for (int i = 0; i <= col; i++) {
cout << i << " ";
}
cout << endl;
}
You use grid[x_value[i]][y_value[i]] = data[i];, but will not fill all of the grid since you only fill in one value of each column of grid (you only do this loop: for (int i = 0; i < x_value.size(); i++) {). Unless the grid passed in is pre-filled in with 0's properly (impossible to tell given your submitted code), then this is probably undefined behavior.
Even if it is a pre-filled in 2d array, when you print the elements of grid, you iterate from [0, cols] and [0, rows], which is likely not what you want (that iterates cols+1 columns and rows+1 rows. So, at least that last value will be accessing memory that is probably not valid.
As previous comments mention, it's a better idea to just use std::vector (e.g. std::vector<std::vector<int>> while using .at(i).at(j) to access elements which make use of C++ exceptions rather than accessing bad memory) or even std::array which are better at preventing and catching many issues cleanly. If you're worried about speed, it's probably not a huge deal and you can avoid copies by e.g. passing by reference, wrapping things in smart pointers if applicable, move semantics, etc.
I solved my problem by setting all my 2D array values to { }, then populate the grid array with the values that i want specifically.
It solves the memory leak problem but i am not sure if it is a good practice.

How to update a game board? c++

I'm trying to make a dungeon crawlesque game and I have this code to create a game board. I'm using 'F' as the finish point and 'P' for the player.
void Gameboard::CreateGameboard()
{
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
GameGrid[i][j] = 'x';
}
}
cout << " 0 1 2 3 4 5 6 7 8 9 10" << endl;
cout << " +---------------------+" << endl;
for (int i = 0; i < 10; i++)
{
cout << " " << "|" << GameGrid[i][0];
for (int j = 0; j < 10; j++)
{
if (i == Spawn[0] && j == Spawn[0])
{
GameGrid[0][0] = 'P';
}
cout << " " << GameGrid[i][j];
}
cout << "|" << endl;
}
cout << " +---------------------+" << endl;
}
The problems I'm facing are. 'P' is being placed in the first two slots of the board and unsure why. And how would I update the board with player movement? I have a Player class with x,y position variables and my thought is to increment down/up based on where they're going. Is it required to reprint the whole board after every movement?
With your drawing of the board.
for (int i = 0; i < 10; i++)
{
cout << " " << "|" << ***GameGrid[i][0]***;
for (int j = 0; j < 10; j++)
{
cout << " " << GameGrid[i][j];
}
cout << "|" << endl;
}
You print out the first item of the row, then print the whole row, including the first item again. so each row will have a double up of the first item.
As for your second question, clearing the screen is exactly what you'll have to do. If you're using windows then you can use system("cls"); to 'clear' the console and then redraw. I would recommend putting the board drawing and board creation into different functions.

Char Array Formatting

I am working on a hangman game where incorrect letter guesses are stored in a char array called wrongletters. Of course, the user begins the game with zero wrongletters, so the wrongletters array remains empty upon declaration. The problem I am having is that when I try to display the wrong letters, the letters are spaced very far to the right because of all the other non-value elements in the array
Intended: (Guessed Letters: A B C D)
Current: (Guessed Letters: (Extra Spaces) A B C D)
Any thoughts? (I am aware game does not function properly yet):
void gameSequence() // Runs the hangman game loop
{
// Local and Global Variable Declaration and Initialization
char guessLetter = ' ';
guessWord = strToUpper(getNextWord());
string maskedWord(guessWord.size(), '_');
char wrongLetters[26] = {};
int numWrongLetters = sizeof(wrongLetters) / sizeof(wrongLetters[0]);
// Input, Process, and Output
cout << "\nLet's PLAY\n\n";
for (int i = 0; i < maskedWord.length(); i++)
cout << maskedWord[i] << " ";
while (incorrectCount < 6)
{
drawHangman(incorrectCount);
cout << "<<<<<<<<<< MAKE A GUESS >>>>>>>>>>\n\n";
cout << "Guessed Letters: ";
for (int i = 0; i < 26; i++)
cout << wrongLetters[i] << " ";
cout << "\n\nEnter a letter to guess: ";
cin >> guessLetter;
cout << endl;
guessLetter = toupper(guessLetter);
for (int i = 0; i < maskedWord.length(); i++)
cout << maskedWord[i] << " ";
if (guessWord.find(guessLetter) != string::npos)
{
for (int i = 0; i < maskedWord.length(); i++)
{
if (maskedWord[i] == guessLetter)
maskedWord[i] = guessLetter;
}
}
else
{
incorrectCount++;
wrongLetters[incorrectCount] = guessLetter;
bubbleSort(wrongLetters, numWrongLetters);
}
if (incorrectCount == 6)
{
drawHangman(incorrectCount);
cout << "Sorry you lose - the word was: " << guessWord << endl << endl;
}
}
incorrectCount = 0;
}
As I understand the array wrongletters contain at the beginning it of the wrong letters guesed so far. So there is no point of print all of it and especially sort all of it.
Hence you should change:
for (int i = 0; i < incorrectCount; i++) // incorrectCount replaced 26
cout << wrongLetters[i] << " ";
...
else
{
incorrectCount++;
wrongLetters[incorrectCount] = guessLetter;
bubbleSort(wrongLetters, incorrectCount+1); // incorrectCount replaced numWrongLetters
}
Otherwise when you sort all of the array the spaces go first before the wrong letters.
Because even if your char sequence is empty, you ask in your loop to display a space after the wrongLetters[i]. Replace the ' ' by endl and you will have
A
B
C
D

C++ Displaying An Organized List of Words

I am making a 20 questions game in C++ and have everything working, except for the displayWords function. The code I currently have keeps breaking. Any explanation would be appreciated! Thank you!
void displayWords()
{
int x = 0;
string words[50] = {"LCHS","Shark","Pencil","Pizza","New York","Fish","Car","Ice Cream","Los Angeles","Bird","Basketball","Fried Chicken",
"Dog","Tiger","Penguin","Plane","Rock","Barbecue Sauce","Mustard","Ketchup","Hot sauce","Peppers","Salt","Tacos","Shrimp","Pickels",
"Tomatos","Bannanas","Burger","Computer","Iphone","Motorcycle","Bicycle","Skateboard","Lightbulb","Golf Ball","Surfboard","Luggage",
"Rollercoaster","Cat","Lion","Cockroach","Grasshopper","Beach","Theme Park","Swimming Pool","Bowling Ally","Movie Theater","Golf Course","Shopping Mall"};
cout << "The following list of words are what the computer is capable of guessing" << endl;
cout << endl;
while(x < 50)
{
for (int y = 0; y <= 5; y++)
{
cout << words[x] << ", ";
if(x<50)
x++;
}
cout << endl;
}
}
I would like it to display the list of 50 words in an organized fashion.
By example, as:
for( int x = 0; x<sizeof(words)/sizeof(*words); x++ ) {
if( x%5==0 ) cout << endl; else cout << ", ";
cout << words[x];
}
take into account the problematic of the array's size calculation: see this link How do I find the length of an array?
If I understand correctly, you want your list displayed as 5 columns. Simplest way, use a nested for loop and proper formatting with std::setw (must #include <iomanip>):
for(size_t i = 0; i < 10; ++i)
{
for(size_t j = 0; j < 5; ++j)
{
std::cout << std::setw(20) << std::left << words[i * 5 + j];
}
std::cout << std::endl;
}
Your actual loop is incorrect, as it will lead to repetitions.
Maybe I'm not interpreting your question correctly but if you want to just print out the 50 words then you can use something like the code below. Not sure of the reason that the nested for loop iterating y was there.
Edit
void displayWords()
{
int x;
string words[50] = {"LCHS","Shark","Pencil","Pizza","New York","Fish","Car","Ice Cream","Los Angeles","Bird","Basketball","Fried Chicken",
"Dog","Tiger","Penguin","Plane","Rock","Barbecue Sauce","Mustard","Ketchup","Hot sauce","Peppers","Salt","Tacos","Shrimp","Pickels",
"Tomatos","Bannanas","Burger","Computer","Iphone","Motorcycle","Bicycle","Skateboard","Lightbulb","Golf Ball","Surfboard","Luggage",
"Rollercoaster","Cat","Lion","Cockroach","Grasshopper","Beach","Theme Park","Swimming Pool","Bowling Ally","Movie Theater","Golf Course","Shopping Mall"};
cout << "The following list of words are what the computer is capable of guessing" << endl;
cout << endl;
for(x = 0; x < words.size();x++)
{
cout << words[x]<< ", ";
}
}
Also some information on how the code is breaking, like are any errors being thrown or has debugging caused issues so far?

c++ toupper() to compare two strings

I have created a set of algorithms that takes an input of a string vector, checks whether any of the strings occur more than once: if so erases all additional occurrences of the string from the vector, then outputs the new, 'lighter' array without the redundancies.
It works great except now I am to make it case-insensitive; I am attempting to simply add the toupper() std function to the == comparison statement, however it does not seem to work.
I have a more familiar background with Java and am trying to learn C++.
Can someone please show me how to correct my syntax?
// Output old list.
cout << endl << "==========\nOld list:\n==========";
for (int i = 0; i < count; i++) {
cout << endl << list[i];
}
cout << endl << endl;
// Check uniqueness.
for (int i = 0; i < count; i++)
for (int j = i+1; j < count; j++) {
if (toupper(list[i]) == toupper(list[j])) {
list[j] = "";
count--;
}
}
// Output new list.
cout << endl << "==========\nNew list:\n==========";
for (int i = 0; i < count; i++) {
cout << endl << list[i];
}
cout << endl << endl;
Your loop leaves "holes" in the list array vector, but the size of the array vector does not change (but you decrease your upper bound count)
There are probably many other alternatives, but if you don't want to modify it much, probably you need in an addtional loop to copy non-empty elements from the list array into a new array
Edit: integrating some of the answers
First we're going to have a function to do the toUpper (this is modified from #Jim22150)
std::string stringToUpper(const std::string &input) {
std::string toBeModified=input;
std::transform(toBeModified.begin(), toBeModified.end(), toBeModified.begin(), ::toupper);
return toBeModified;
}
Now, we must not leave holes, so we should use erase (as #Scott Christopher Stauffe indicated):
// Output old list.
cout << endl << "==========\nOld list:\n==========";
for (int i = 0; i < count; i++) {
cout << endl << list[i];
}
cout << endl << endl;
// Check uniqueness.
for (int i = 0; i < count; i++)
for (int j = i + 1; j < count; j++) {
if(stringToUpper(list[i]) == stringToUpper(list[j])) {
list.erase(j,1);
count--;
}
}
}
// Output new list.
cout << endl << "==========\nNew list:\n==========";
for (int i = 0; i < count; i++) {
cout << endl << newlist[i];
}
cout << endl << endl;
#DaveS, thanks Dave I will try that; it looks clean and short. However, I found dirtier solution using transform and making a duplicate of the old vector.
// Output old list.
cout << endl << "==========\nOld list:\n==========";
for (int i = 0; i < count; i++) {
cout << endl << list[i];
}
cout << endl << endl;
// Check uniqueness.
for (int i = 0; i < count; i++)
for (int j = i + 1; j < count; j++) {
std::transform(list[i].begin(), list[i].end(), list[i].begin(), ::toupper);
std::transform(list[j].begin(), list[j].end(), list[j].begin(), ::toupper);
if (list[i] == list[j]) {
newlist[j] = "";
count--;
}
}
// Output new list.
cout << endl << "==========\nNew list:\n==========";
for (int i = 0; i < count; i++) {
cout << endl << newlist[i];
}
cout << endl << endl;
If you want to handle C++ strings as easily as Java strings, then the Boost String Algorithms Library is the way to go. Installing Boost may be a bit hard for a newbie C++ programmer (although it's a breeze compared to many other C++ libraries), but it pays off.
Your problem will essentially be reduced to this:
boost::algorithm::to_upper_copy(list[i]) == boost::algorithm::to_upper_copy(list[j])
I just did a quick google of toupper and I didn't find any string versions of it. The only standard touppper() I have seen is int toupper(int c); - that means you can only use it to compare individual characters! Have you tried stricmp()?
if ( 0 == _stricmp(list[i], list[j]) ) {
list[j] = "";
count--;
}
Depending on your compiler you may or may not have this function at your disposal.
First of all,
list[j] = ""; // should never work.
You can remove a char by using erase.
list.erase(j, 1);
Alternatively, to avoid this altogether, you could use a temporary "builder" string and just push_back chars to it when needed.