Author Topic: Programming Megathread  (Read 143313 times)

SQL is so wordy it feels like you're shouting commands at the computer.


SELECT NAME FROM PLAYER WHERE ID = 2000

It literally sounds like you're commanding the computer. Makes sense to be in caps, it seems meek otherwise.

Wait, people did that?
Thats loving stupid.

I mean, back in the beginning I'm not even sure there was a lower case character set. It probably just stuck.

does anyone have any good references for actually getting good and knowledgeable with object orientated C++?

Like I get the basics of implementing common ADTs like stacks and queues, but I suck with the more advanced memory management functionalities and stuff like good exception handling. I want to get better.

Need a bit of help with C++, guys. And I apologise if the code snippets here are very messy; I've been just running through trying to implement everything, and I plan on coming back and cleaning all of my code and adding some better comments when it's ready.

I'm working on a version of Tic-Tac-Toe that would ideally support resizable maps. The game works perfectly as-is using a hardcoded array, which I can use a constant to quickly change the size of the grid, but I want to upgrade the system to using a vector instead so the user can specify the size of the grid when they start the game.

While I could use a single dimension array/vector and simply do a bit more math, using a multi-dimensional vector is more easily readable for myself. Moving on, I'm aware of how to initialise a multi-dimensional vector, as so:

Code: [Select]
#include <vector>
vector<vector<char>> myVec;

Theoretically, this is supposed to be usable the exact same as an array (with the [][] operators), so all I should need to do to make my program compatible is switch the function arguments to take this type of vector instead of an array, and change the initialisation function like so:

Code: [Select]
void InitialiseBoard(std::vector<std::vector<char>> boardVector)
{
for (int i = 0; i < BOARD_SIZE; i++)
{
std::vector<char> vecRow;
for (int j = 0; j < BOARD_SIZE; j++)
{
vecRow.push_back(' ');
}
boardVector.push_back(vecRow);
}
}

Now, this all works until the program gets to a specific link in a specific function, as shown below:

Code: [Select]
PlayerInput GetInput(std::vector<std::vector<char>> boardVector, bool *isPlayerOne)
{
char xPos = 0;
char yPos = 0;

while (true)
{
if (*isPlayerOne) std::cout << "\nPlayer One [X], please select a ROW [A - " << (char)('A' + (BOARD_SIZE - 1)) << "]: ";
else std::cout << "\nPlayer Two [O], please select a ROW [A - " << (char)('A' + (BOARD_SIZE - 1)) << "]: ";
while (true)
{
std::cin >> yPos;

if (yPos == QUIT_KEY_UPPER || yPos == QUIT_KEY_LOWER) { std::cout << '\n'; return PlayerInput::EXIT; }
else if (yPos == RESTART_KEY_UPPER || yPos == RESTART_KEY_LOWER) { std::cout << '\n'; return PlayerInput::RESTART; }
else if (yPos < 'A' || (yPos > ('A' + (BOARD_SIZE - 1)) && yPos < 'a') || yPos >('a' + BOARD_SIZE)) { SanitiseCoordInput(InputCoords::YAXIS); }
else if (yPos >= 'A' && yPos <= ('A' + BOARD_SIZE)) { yPos -= 'A'; break; }
else if (yPos >= 'a' && yPos <= ('a' + BOARD_SIZE)) { yPos -= 'a'; break; }
}

//Clear the input buffer even if the input was correct to prevent format breaking
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

if (*isPlayerOne) std::cout << "Player One [X], please select a COLUMN [1 - " << BOARD_SIZE << "]: ";
else std::cout << "Player Two [O], please select a COLUMN [1 - " << BOARD_SIZE << "]: ";
while (true)
{
std::cin >> xPos;

if (xPos == QUIT_KEY_UPPER || xPos == QUIT_KEY_LOWER) { std::cout << '\n'; return PlayerInput::EXIT; }
else if (xPos == RESTART_KEY_UPPER || xPos == RESTART_KEY_LOWER) { std::cout << '\n'; return PlayerInput::RESTART; }
else if (xPos < '1' || xPos > ('1' + (BOARD_SIZE - 1))) { SanitiseCoordInput(InputCoords::XAXIS); }
else { xPos = GetFixedNumber(xPos - '0'); break; }
}

/* THIS IS THE LINE WITH THE PROBLEM!!!! */
if (boardVector[xPos][yPos] == ' ') break;

else std::cout << "\nThere's already something at \'" << (char)(yPos + 'A') << (int)(xPos + 1) << "\'! Please try again.\n";
}

boardVector[xPos][yPos] = *isPlayerOne ? 'X' : 'O';
std::cout << '\n';
return PlayerInput::MOVE;
}

For some reason, Visual Studio breaks at if (boardVector[xPos][yPos] == ' ') break;, complaining that "Vector subscript out of range." It's able to correctly take all the input, but once it does that simple check for an empty space, kaput. I get that it's a standard out-of-range error that should indicate numbers that are are less than or greater than the vector's range, EXCEPT that this code works perfectly if I'm using a standard char[][] array and I designed several functions to prevent this kind of situation. I cannot see anything in this code that would cause an issue.

Does anybody have an idea on what the issue is here?

Here's the GetFixedPosition() function code, in case it helps:

Code: [Select]
int GetFixedNumber(int input)
{
int midNum = BOARD_SIZE / 2;

if (BOARD_SIZE % 2 != 0 && input == midNum) input++;
else if (input > midNum) input = BOARD_SIZE - input;
else if (input < midNum) input = -(input - BOARD_SIZE);

return input;
}

It's job is simply to swap the position of the numbers that the user inputs because the display of the grid is opposite the way the array is organised, and to also remove 1 from the result because the array is 0-indexed.

From my experience with 3d arrays in my Crypto class, I've found it to  be a huge pain in the ass passing them through functions.  Have you checked to see what values are in the vector to make sure it's actually passing through and isn't just null.

When you're pulling the xPos and yPos values from cin, does this make them a string? If so, the compiler could be interpreting the xPos and yPos by their strict string/char value, instead of a number. That'd be my guess, at least.

When you're pulling the xPos and yPos values from cin, does this make them a string? If so, the compiler could be interpreting the xPos and yPos by their strict string/char value, instead of a number. That'd be my guess, at least.
xPos and yPos are both char types, which is actually an integeral type (aka it only holds whole numbers; signed char specifically has a range of 0 - 255). cin itself attempts to store a user's input into the appropriate variables in the order you list them. When I do the following lines;

Code: [Select]
yPos -= 'A';
yPos -= 'a';
--
xPos - '0'

I'm essentially saying "take the character the user input and covert it back into normal number"; 'A', 'a' and '0' are the first characters for the Upper-case, Lower-case and Number range of characters, so removing them from the input character will convert them into a number I can use for my array.

Have you checked to see what values are in the vector to make sure it's actually passing through and isn't just null.
That was a great try, but it turned out that wasn't the problem. Firstly, let's have a look at what Visual Studio's debug tools tell us:

Code: [Select]
When using the Array Version:

xPos: 2
yPos: 0
boardArray[xPos][yPos] does exist, and is currently set to the value of ' '.

When using the Vector Version:

xPos: 2
yPos: 0
boardVector has a size of '0' and boardVector[xPos][yPos] doesn't exist.

Yup. Turns out my problem is that I made an assumption that vector types would be Pass-by-Reference like the array, when they actually work as Pass-by-Value. The VERY easy fix (pointed out by one awesome dude not on these forums) was simply to change all the (applicable) function arguments into references, which I also did for the isPlayerOne bool to keep it consistent.

Thanks for the attempts guys, back to coding :) Multi-dimensional arrays/vectors are awful memory-wise, and so I'm going to be converting the vector into a single dimension and simply have a Setter/Getter function that abstracts away getting the appropriate values (another great idea by the same dude).

Btw, when you create the board, you can just do something like
Code: [Select]
vector<vector<char>> boardVector(BOARD_SIZE, vector<char>(BOARD_SIZE, ' '));and it will create a 2D vector of BOARD_SIZExBOARD_SIZE filled with ' 's

Btw, when you create the board, you can just do something like
Code: [Select]
vector<vector<char>> boardVector(BOARD_SIZE, vector<char>(BOARD_SIZE, ' '));and it will create a 2D vector of BOARD_SIZExBOARD_SIZE filled with ' 's
Thanks. My idea I'm going for here is that the user can specify what size of board they want, and they can restart at any time which means I need to reinitialise the board anyway, so putting all of that in a reusable function/method is going to be a little bit easier in the long run.

My next big tweaks will include turning the whole game into a class (so I don't have to use references), turning the multi-dimensional vector into a single vector and using a Setter/Getter to abstract away the math involved (which is apparently extremely simple) and adding the ability to play with an AI bot instead of a second player.

EDIT: If the idea of classes works well, I might start adding some more basic games (like Hangman) in as different classes, and the user can select which game they'd like to play. I'm doing this really just to get a feel for the language and its differences to C# and try practice some of the concepts I've learned.
« Last Edit: May 07, 2016, 05:33:52 PM by McJob »

Yeah when I was doing hill-ciphers I found it a lot easier to just use a normal array and then use modulus and what not.

wtf is wrong with this code for finding min value of 10 scores?(c++)



the highlighted number is apparently the minimum even though none of the numbers are that small, or even negative...
it actually should be the last inputted number there, 21.



first of all that's kinda hard to read. use more spaces ! ! and indent properly

min = score[0];
for (y = 1; y <= 9; y++)
{
    if (min > score[y])
    {
        min = score[y];
    }
}
cout << min;


anyway, I don't think we could reasonably figure out what's wrong without the rest of the code. we don't know what type min is or the items in the array, and I'm sure that could cause problems like this
also when I rewrote that stuff I begrudgingly used the same brace style you did, but nevertheless I want to expose you to this way too. just in case you like it better

for (int i = 0; i < 10; i++) {
    // stuff
}
« Last Edit: May 09, 2016, 03:02:13 PM by Foxscotch »

there are ten numbers between 21 and 99 in the array and min is a float. i tried it as an int but got the same outcome.

whats odd is if i change if(min>score[y]) to if(min<score[y]) it finds the max value without any issues.

i figured it out. i had the input for the array starting at score[1] instead of score[0]

Hey, quick note, could you append a '\n' or endl to the end of you cout input? Just that way it'll add a newline and the prompt won't run directly off your result.