Commenting on my code [closed] - c++

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
I'm having difficulty commenting on my code for a blackjack app for c++. I have coded it but now I am confused as to what to put in for comments, my instructor is frugal when it comes to commenting.
Thanks for any and all help! :)
here is my code:
#include <iostream> // in/out for form
#include <ctime> // uses time for randomizing
#include <Windows.h> //
using namespace std; // prevents redundancey of ::STD
char enter[1]; //
int hand[52] = {}, dealer[52]; // array of 52 for 52 cards that holds zero
int GetScore(int param) // function prototype that calls getscore
{
int score = 0; //
int temp[52]; //
if(param == 0) for(int i = 0; i < 52; i++) temp[i] = hand[i]; //
if(param == 1) for(int i = 0; i < 52; i++) temp[i] = dealer[i]; //
for(int i = 0; i < 52; i++) //
{
if(temp[i] == 0) break; //
if(temp[i] != 11)
{
score += temp[i];
}
}
for(int i = 0; i < 52; i++) // simple loop to ....
{
if(temp[i] == 0) break;
if(temp[i] == 11)
{
if(temp[i] + score <= 21)
{
score += 11;
}
else
{
score += 1;
}
}
}
return score;
}
void ShowDealersHand(int show) //
{
cout << "\n Dealer's hand: "; //
if(show == 1) //
{
if(dealer[0] == 11)
{
cout << "A [Not Shown]";
}
else
{
cout << dealer[0] << " [Not Shown]";
}
}
else
{
for(int i = 0; i < 52; i++)
{
if(dealer[i] == 0) break;
if(dealer[i] == 11)
{
cout << "A ";
}
else
{
cout << dealer[i] << " ";
}
}
}
}
void Blackjack()
{
for(int i = 0; i < 2; i++) //
{
int num, temp;
if(hand[0] == 0) temp = 0;
else temp = 1;
num = rand() % 10 + 2;
hand[temp] = num;
num = rand() % 10 + 2;
dealer[temp] = num;
}
ShowDealersHand(1); //
cout << endl << endl << " Your hand: "; //
for(int i = 0; i < 52; i++) //
{
if(hand[i] == 0) break;
if(hand[i] == 11)
{
cout << "A ";
}
else
{
cout << hand[i] << " ";
}
}
cout << endl << " Your score: " << GetScore(0) << endl << endl;
while(GetScore(0) <= 21)
{
cout << " Hit(h) or stand(s): ";
cin >> enter;
if(strcmp(enter, "h") == 0)
{
int card = rand() % 10 + 2;
for(int i = 0; i < 52; i++)
{
if(hand[i] == 0)
{
hand[i] = card;
break;
}
}
cout << " Your hand: ";
for(int i = 0; i < 52; i++)
{
if(hand[i] == 0) break;
if(hand[i] == 11)
{
cout << "A ";
}
else
{
cout << hand[i] << " ";
}
}
cout << endl << " Your score: " << GetScore(0) << endl << endl;
if(GetScore(0) > 21)
{
cout << " - ..BUST.. -" << endl ;
cout << "\n - !!House Wins!! -";
goto end;
break;
}
}
else if(strcmp(enter, "s") == 0)
{
cout << endl;
break;
}
system("pause > nul");
}
Sleep(2000);
ShowDealersHand(0);
cout << endl << " Dealer score: " << GetScore(1) << endl << endl;
if(GetScore(1) < GetScore(0))
{
while(GetScore(1) < 17 && GetScore(0) <= 21)
{
Sleep(2000);
int card = rand() % 10 + 2;
for(int i = 0; i < 52; i++)
{
if(dealer[i] == 0)
{
dealer[i] = card;
break;
}
}
cout << " Dealer's hand: ";
for(int i = 0; i < 52; i++)
{
if(dealer[i] == 0) break;
if(dealer[i] == 11)
{
cout << "A ";
}
else
{
cout << dealer[i] << " ";
}
}
cout << endl << " Dealer score: " << GetScore(1) << endl << endl;
if(GetScore(1) >= GetScore(0)) break;
}
}
end:
if(GetScore(1) > GetScore(0) && GetScore(1) <= 21)
{
cout << " - !!House Wins!! -";
}
else if(GetScore(1) == GetScore(0) && GetScore(0) <= 21)
{
cout << " * Tie * - !!House Wins!! -";
}
else if(GetScore(0) <= 21)
{
cout << " - !!!You win!!! -"; // outputs if you win
}
system("pause > nul");
system("cls");
}
void main() // no return on main for form to start
{
srand((unsigned int)time(0)); // randomizer unasigned initializer
cout << " *-*-*-*-*Zachattack's Blackjack*-*-*-*-*" << endl << endl; // Name of program outputs to user
Blackjack();
}

As they are, you comments are useless. Take, for example, this:
int hand[52] = {}, dealer[52]; // array of 52 for 52 cards that holds zero
Anyone that uses C/C++ is expected to know what that line is doing, without having to read the comment.
Instead of commenting what your code does ("this line declares an int"), comment why the code does what it does (what you were thinking when you wrote that code), or, if the algorithm is complicated, comment on how it does something, or document how to use your functions.
For example, your GetScore function takes has a parameter called param. I've no idea what values I am expected to give to param, so you should explain it: "when param is 1, this happens, when it is 0, that happens".
Another example: in your code you have a line Sleep(2000). Why did you use that function? Explain it in a comment:
// Sleep 2 seconds to make the game more exciting
Sleep(2000);
Always assume that the person reading your code knows how to use the language. Never assume that the person reading your code is able to understand your way of thinking about a certain problem.

Comments should explain why, not what.
So your comment for using namespace std; is unnecessary, because any C++ programmer will already know what the using keyword does.
However, for the GetScore() function, you've omitted to give the rules for totalling the score.
The comments should add value, not just duplicate things that are obvious from even a cursory look at the code.
Assume the person reading the code is familiar with the programming environment, but wasn't party to what was going on in your mind as you wrote it.
Here's an example I sometimes use - a piece of code with useless comments (can you work out what is going on here, and why?):
// Is the new selection end above the selection start?
if newSelEnd.Line < FSelection.SelStart.Line then
begin
// Is the selection start at the left margin and above the selection end?
if (FSelection.SelStart.Line < FSelection.SelEnd.Line) and
(FSelection.SelStart.Column = 0) then
begin
// Move the selection start down one line
Inc(FSelection.SelStart.Line);
And with helpful comments:
if newSelEnd.Line < FSelection.SelStart.Line then
begin
// The new selection end is above the selection start, so will become the
// top of the new selection.
if (FSelection.SelStart.Line < FSelection.SelEnd.Line) and
(FSelection.SelStart.Column = 0) then
begin
// The start of the selection was at the top of the old selection and the
// new line is above this, so the selection is about to change direction.
// Since the start column is 0 we assume the original selection was an
// entire line, so we keep the original line selected by moving the start
// position down one line.
Inc(FSelection.SelStart.Line);

Function/method purpose with parameters purposes
Magic numbers
Those are my most important rules about commenting. Optional is "why am I iterating/what am I looking for" about loops. Magic numbers is every declaration/condition that uses const values like GetScore(0) <= 21, or hand[52].
Those are places that should be commented even for yourself... It feels realy good when you look at your code after year or more and still read it without any problem.

Apart from the other answers, often, it is a good idea to get rid of a comment by replacing it with a named function:
// Find top-scorers:
for (Iter it=scorers.begin(), end=scorers.end(); it!=end; ++it) {
...
{
top.push_back (*it);
}
}
Instead, do:
const std::vector<Scorer> top = find_top_scorers (scorers.begin(),
scorers.end());
This decreases miss-maintenance (comments are not enforced and may get out-of-date) and reusability. Personally, I always endeavour for commentless code, as I am sick of out-of-date comments, when possible and sane.
Of course, in the example above, you should probably use std::partial_sort, std::partition or std::stable_partition.
Also, magic numbers should be replaced by constants instead, with the same argumentation about miss-maintenance and reusability:
const float x = radius * 3.14159...; // radius * pi
const float pi = 3.14159...,
x = radius * pi;

Related

Two different pointer arrays, but they both point to the same address

I'm making a blackjack game and I have a pointer arrays for my dealer's and player's hand. The issue is that when I randomly generate cards to be stored in the array, they both have the same cards. Not sure if it is because they both point to the same address or something I haven't noticed.
#include <iostream>
#include <ctime>
#include <random>
#include <iomanip>
#include <cstdlib>
using namespace std;
class Blackjack
{
public:
Blackjack();
void playGame();
int pbalance;
int betamount;
int loop= 1;
int *playerbalances;
int pbalan,pbal;
void firstbalance();
void clearhand();
private:
int dhandSize;
int phandSize;
int dhandSum;
int phandSum;
int phit;
int pstand;
bool playerDone;
bool dealerDone;
void addPlayerCard();
void addDealerCard();
void printHand();
void sumHands();
void playerbalance();
void playerbet();
int *dhand[];
int *phand[];
};
Blackjack::Blackjack()
{
srand(time(0));
dhandSize = 0;
phandSize = 0;
dhandSum = 0;
phandSum = 0;
playerDone = false;
dealerDone = false;
}
void Blackjack::playGame()
{
if (pbal>0)
{
// Start the player and dealer with two cards
playerbet();
addPlayerCard();
addPlayerCard();
addDealerCard();
addDealerCard();
sumHands();
printHand();
if (dhandSum == 21)
{
cout << "Dealer has blackjack. Dealer wins.\n";
clearhand();
return;
}
else if (phandSum == 21)
{
cout << "Player has blackjack. Player wins.\n";
clearhand();
return;
}
while (dealerDone == false || playerDone == false)
{
if (playerDone == false)
{
cout << "Would you like to hit? (1 - Yes, 2 - No)\n";
cin >> phit;
if (phit == 1)
{
addPlayerCard();
printHand();
sumHands();
if (phandSum > 21)
{
cout << "Player's hand exceeded 21. Player loses"<<endl;
pbalan =(pbalan - betamount);
cout <<"[you lose $"<<betamount<<" of money!]"<<endl;
cout <<"[your current balance is: $"<<pbalan<<"]"<<endl;
clearhand();
return;
}
}
}
if (playerDone == false)
{
cout << "Would you like to stand? (1 - Yes, 2 - No)\n";
cin >> pstand;
}
if (pstand == 1)
{
playerDone = true;
}
if (dhandSum < 17 && dealerDone != true)
{
addDealerCard();
printHand();
sumHands();
if (dhandSum > 21)
{
cout << "Dealer hand exceeded 21. Dealer loses.\n";
return;
}
}
else if (dhandSum >= 17)
{
dealerDone = true;
}
if (phandSum == 21 && dhandSum == 21)
{
cout << "Push, player and dealer reached 21.\n";
return;
}
else if (phandSum == 21)
{
cout << "Player reached 21. Player wins.\n";
return;
}
else if (dhandSum == 21)
{
cout << "Dealer reached 21. Dealer wins.\n";
pbalan =(pbalan - betamount);
cout <<"[you lose $"<<betamount<<" of money!]"<<endl;
cout <<"[your current balance is: $"<<pbalan<<"]"<<endl;
return;
}
if ((playerDone == true && dealerDone == true) || (phandSize == 5 && phandSize == 5))
{
if (dhandSum < phandSum)
{
cout << "Sum of your hand exceeds the dealer's sum of " << dhandSum << "! You win!";
return;
}
else if (phandSum == dhandSum)
{
cout << "Dealer sum of " << dhandSum << " is equal to the sum of your hand. Tie game.";
return;
}
else if (dhandSum > phandSum)
{
cout << "Sum of your hand is lower than the dealer's sum of " << dhandSum << ". You lose!"<<endl;
pbalan =(pbalan - betamount);
cout <<"[you lose $"<<betamount<<" of money!]"<<endl;
cout <<"[your current balance is: $"<<pbalan<<"]"<<endl;
return;
}
}
}
}
}
void Blackjack::clearhand()
{
for (int i = 0; i < dhandSize; i++) { delete dhand[i]; }
for (int i = 0; i < phandSize; i++) { delete phand[i]; }
phandSize = 0;
dhandSize = 0;
}
void Blackjack::firstbalance()
{
cout << "Welcome to Blackjack" <<endl;
cout << "please enter a starting balance: " <<endl;
cin >> pbal;
playerbalances = &pbalan;
*playerbalances = pbal;
}
void Blackjack::playerbet()
{
cout << "how much do you want to bet?"<<endl;
cin >> betamount;
}
void Blackjack::addPlayerCard()
{
if (phandSize <= 5)
{
*phand[phandSize] = 1 + (rand() % 13);
phandSize++;
}
else
{
cout << "Sorry. You have reached the maximum number of cards (5)." << endl;
playerDone = true;
}
}
void Blackjack::addDealerCard()
{
if (dhandSize <= 5)
{
*dhand[dhandSize] = 1 + (rand() % 13);
dhandSize++;
}
else
{
dealerDone = true;
}
}
void Blackjack::printHand()
{
cout << "Your current hand is...\n";
for (int i = 0; i < phandSize; i++)
{
cout << " -" << *phand[i] << "- \n\n";
}
cout << "Dealer's current hand is...\n";
for (int j = 0; j < dhandSize; j++)
{
cout << " -" << *dhand[j] << "- \n\n";
}
}
void Blackjack::sumHands()
{
dhandSum = 0;
phandSum = 0;
for (int i = 0; i < dhandSize; i++)
{
dhandSum += *dhand[i];
}
for (int j = 0; j < phandSize; j++)
{
phandSum += *phand[j];
}
cout << "Current player hand sum is: " << phandSum << endl;
}
using namespace std;
int main()
{
int exitGame = 1;
int i = 0;
Blackjack play;
if (i<1)
{
play.firstbalance();
i++;
}
do
{
play.playGame();
play.clearhand();
cout << "\nWould you like to play again? (1 - Yes, 2 - No)\n";
cin >> exitGame;
}
while (exitGame == 1);
cout << "\nThanks for playing!\n";
return 0;
}
The dealer cards should be different from the player cards but they are identical when you run the program.
The shows code declares a class with two members, as follows:
int *dhand[];
int *phand[];
These are the two members of the class, but this is not valid, standard C++. Variable-length arrays are not standard C++.
As such, the entire logic in this code becomes unspecified behavior. The behavior you observed was that the two arrays appear to be the same. Right. That's what unspecified behavior means, and this appears to be the behavior that results with your specific C++ compiler and implementation. Your C++ compiler appears to implement this by creating a class member whose size is a grand total of 0 bytes (after all, the size of the array is not specified, so it's nuthin'), with the expectation that this will be the last class member, and the application will be responsible for allocating some extra memory in addition to the one that's required for an instance of this object, in order to achieve a pseudo-array in this fashion.
But with two class members declares thusly, this ends up with two class members that are effectively one and the same. Which is the behavior you observed. Other C++ compilers may very well report a compilation error, since the program being ill-formed, with respect to the C++ standard.
To fix this issue you should replace these class members with proper arrays. Perusing the shown code, it looks like you expect these arrays to be, essentially, variably-sized arrays. This is what std::vector is for, and your C++ book should have one or more chapters that fully explain how to use std::vector to implement an array-like object that can grow and shrink in size, accordingly.

Commenting out cin.ignore makes program run a ridiculous amount of iterations

I'm writing a program to simulate Left Right Center. If you're not familiar, the game involves 3 dice with 1 side "L", 1 side "R", 1 side "C", and 3 sides dots. Everyone starts with $3. If you roll an "L", you pass a dollar to the left. If you roll an "R", you pass a dollar to the right. If you roll a "C", you put a dollar in the center. If you roll a dot, you take no action. Play then passes to the left. Play continues until only 1 player has money remaining, and that player wins everything.
I got the program operating correctly, except for one strange thing. When I run it as below, it runs fine, usually taking 70-150 turns to complete. When I comment out the lines
cout << "In gameOver(). Number of brokeJamokes: " << brokeJamokes;
cin.ignore();
the program takes hundreds of thousands (or millions) of turns to complete. Why would a simple output change that?
Full code follows:
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int player[10] = {0};
int bank[10] = {0};
int rollDie() {
srand(time(NULL));
int randNum = rand()%6+1;
//cout << "In rollDie(), die roll is " << randNum << "\n";
//cin.ignore();
return randNum;
}
int distributeCash(int roll, int playerNum) {
if(roll == 1) { //pass left
bank[playerNum]--;
/* if active player is player 10 (player[9]), we need to pass to player 1 (player[0])
instead of the nonexistant player 11, so we change the array value to -1 */
if(playerNum == 9) {playerNum = -1; }
bank[playerNum + 1]++;
return 0;
}
if(roll == 2) { //pass right
bank[playerNum]--;
/* if active player is player 1 (player[0]), we need to pass to player 10 (player[9])
instead of the nonexistant player 0, so we change the array value to 11 */
if(playerNum == 0) {playerNum = 10;}
bank[playerNum - 1]++;
return 0;
}
if(roll == 3) { //pass to center
bank[playerNum]--;
return 0;
}
else {
return 0;
}
return 0;
}
int gameOver() {
int brokeJamokes = 0;
for(int i = 0; i < 10; i++) {
if(bank[i] == 0) { brokeJamokes++; }
}
cout << "In gameOver(). Number of brokeJamokes: " << brokeJamokes;
cin.ignore();
if(brokeJamokes==9) {return 1;}
else return 0;
}
void showWinner() {
for(int i = 0; i < 10; i++) {
if(bank[i] != 0) {
cout << "Player " << (i+1) << " is the winner!\n";
cin.ignore();
return;
}
}
}
int main()
{
int roll[3] = {0};
for(int x = 1; x < 10; x++) { //initialize all banks to 3 except test player (player 1)
bank[x] = 3;
}
bank[0] = 3; //test player bank initialization
int turnCount = 0;
while(!gameOver()){
for(int i = 0; i < 10; i++) {
if(gameOver()) {break;}
for(int j = 0; j < 3; j++) {
roll[j] = rollDie();
if(bank[i] != 0) {
distributeCash(roll[j], i);
}
}
/* cout << "After player " << (i + 1) << "'s roll: \n";
for(int l = 0; l < 10; l++) {
cout << "Player " << (l + 1) << " $" << bank[l] << "\n";
}
cin.ignore();
*/
turnCount++;}
}
showWinner();
cout << "Number of turns: " << turnCount << "\n";
cout << "Game over!\n";
}
As melpomene stated you repeatedly call srand, setting the same seed (as I think it uses time with a second resolution). Therefore you will get thousands or millions of 'random' numbers in a row of the same value until the time changes. Think what happens if everyone gets the same die roll, the game will never end.
When you have the cout line, it will slow the program considerably, so get less of the same roll in a row from setting srand to the same value.
To fix it move the call to srand to the main function so its only called once.

Display output 4 per line

I'm taking my first programming course and am new to this forum. Any help will be greatly appreciated! For one of my class assignments I had to write a program that would find the factors of a given number, I've got the program up and running but one of the stipulations is that the output must be displayed four to a line and that's where I'm running into trouble. I've read around on some other forums as well as here but I guess I'm not grasping what I would have to do in my particular case.
Here's my code as is:
#include <iostream>
using namespace std;
int main(){
int n;
while (cout << "Please enter a number: " && !(cin >> n) || (n < 0.0) || cin.peek() != '\n')
{
cout << "Input must be a positive number!" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
for (int i=2; i <= n; i++)
{
while (n % i == 0)
{
n /= i;
cout << "*" << i;
}
}
cout << endl;
system ("PAUSE");
return 0;
}
You're going to need to add a counter outside the loop.
//int counter = 0;
for (int i=2; i <= n; i++)
{
while (n % i == 0)
{
n /= i;
cout << "*" << i;
}
}
The counter will need to keep track of how many entries have been printed.
Once you have seen 4 entries printed:
print an extra newline
and set the counter back to 0
You may use the following:
void display_factors(std::size_t n, std::size_t factor_by_line)
{
const char* sep = "";
std::size_t count = 0;
std::cout << n << " = ";
for (int i = 2; i <= n; ++i) {
while (n % i == 0) {
n /= i;
if (count == factor_by_line) {
std::cout << std::endl;
count = 0;
}
++count;
std::cout << sep << i;
sep = " * ";
}
}
std::cout << std::endl;
}
Live Demo

Mastermind string cout issue

Ok I have been struggling with this code and I think I have it written out right but here is the rules from my teacher
1 = implies right Number, Right Place.
2 = implies right Number, Wrong Place.
0 = implies Wrong Number.
So the computer decides on 12345; the user guesses 11235; the computer should respond with 10221. Hint: Watch out for a double number like 11 when there is only one.
I have it where it does all of that except I can not get it to show a 0 when it is wrong can you please help me every single part is written except that part here is my code
// Programming 2
// Mastermind
#include "stdafx.h"
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <string>
using namespace std;
struct fields{//the list of variables used in my program
int size = 5;;
int range = 9;
char lowest = '0';
string guess;
string answer;
int number;
int correct;
int position;
bool gameover = false;
};
void gameplay(fields & info);//declaring the function
int main()
{
fields game;
gameplay(game);//calling the function
system("pause");
return 0;
}
void gameplay(fields & info){//calling the structure into the function
srand(time(0));//to randomize number
info.answer = "";//getting the number
for (int i = 0; i < info.size; i++)
{
char ch = info.lowest + rand() % info.range;
info.answer += ch;
}
info.number = 1;
info.correct = 0;
info.position = 0;
while (!info.gameover)//using a while loop to let them go until they guess it
{
cout << "Guess #" << info.number << ": Enter 5 numbers that are '0' through '9': ";//asking them to guess
cout << info.answer;
cout << "\n";
cin >> info.guess;
if (info.guess == info.answer)//if the guess is right this will end the game
{
cout << "Right! It took you " << info.number << " move";
if (info.number != 1) cout << "s";
cout << "." << endl;
info.gameover = true;
}
int correctNumbers = 0;
for (char const &ch : info.guess) //seeing if there are numebrs in the guess that is in the answer
{
if (info.answer.find(ch) != string::npos)
{
++correctNumbers;
}
}
int const digits = 5;
int correctPositions = 0;
int correctPosition[digits];
int test = 0;
for (int i = 0; i < digits; ++i)//telling which numbers is correct and displaying the 2 or 0 for number is correct or number is wrong
{
if (info.answer[i] == info.guess[i])
{
++correctPositions;
}
if (info.answer[i] == info.guess[i]){
correctPosition[i] = 2;
cout << correctPosition[i];
}
if (correctPosition[i] != 2){
correctPosition[i] = 1;
cout << correctPosition[i];
}
if (correctPosition[i] != 2 && correctPosition[i] != 1)){
correctPosition[i] = 0;
cout << correctPosition[i];
}
}
cout << "\nYou have " << correctPositions << " numbers in the correct position " <<endl;
cout << "You have " << correctNumbers <<" correct numbers in the wrong position"<< endl;
}
cout << "GAME OVER\n\n";
}

Painfully slow maze making program

I am writing a program that generates any size maze you want. It does this by first creating every cell in the maze and assuming they are entirely walled in. They are each declared as their own set. Then a random cell is selected and then a random direction to break down a wall. The random direction funcion makes sure that its also a valid direction for that cell. The program makes sure that the two cells its looking to join arent already connected somehow and if they arent it breaks the wall. If they are already connected either directly or indirectly then it selects a new random cell and direction. This continues until the number of sets left is just 1 ensuring that you can get from any point in the maze to any other point. The program works but it is painfully slow. I dont think it should be as slow as it is and I am unsure why.
I can imagine a scenario where all the cells are connected but one. Thus it would take a little while to randomly select that one cell and that could slow things down but I would imagine when you are dealing with under 100,000 cells it still shouldn't take as long as it does. Rand should be prettu fast at spitting out numbers.
Ive attatched my code below. Its fairly simple but I am sorry about the lack of notes.
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
class dset {
struct element {
element() { rank=0, parent=-1; }
int rank;
int parent;
vector<int> connections;
};
public:
dset(int nr=0,int nc=0);
int size() {return Nsets; }
int merge (int, int);
int find(int);
// Functions
bool isin(int i, vector<int> test);
int randdir(int i);
int randcell();
int dir(int, int);
void print();
vector<int> possibledir(int cell);
vector<int> walls(int cell, vector<int> possible);
private:
int Nsets;
int nrows, ncols;
vector<element> S;
};
int main(int argc, char* argv[]){
int nrows, ncols, cell, direction;
if (argc != 3){
cout << "Usage: nrows ncols\n";
}
stringstream convert;
convert << argv[1];
convert << " ";
convert << argv[2];
convert >> ncols;
convert >> nrows;
dset maze(nrows,ncols);
srand(time(NULL));
while(maze.size() != 1){
cell = maze.randcell();
// cell = 11;
direction = maze.randdir(cell);
// direction = 0;
// cout << "cell: " << cell << " direction: " << direction << " new cell: " << maze.dir(cell, direction) <<endl << endl;
// cout << maze.size() << endl<<endl;;
maze.merge(cell, maze.dir(cell, direction));
}
maze.print();
}
dset::dset(int nr,int nc) {
nrows = nr;
ncols = nc;
int N = (nrows * ncols);
if (0<N) S.insert(S.end(), N, element());
Nsets = N;
}
void dset::print(){
vector<int> wall;
cout << "MAZE " << nrows << " " << ncols << endl;
for ( int i = 0; i < (nrows*ncols); i++ ){
wall = walls(i,possibledir(i));
for( int j = 0; j < wall.size(); j++){
if (i < wall[j])
cout << i << " " << wall[j] << endl;
}
}
}
int dset::randcell(){
return (rand()%(nrows*ncols));
}
int dset::dir(int cell, int direction){
if(direction == 0)
return (cell - 1);
if(direction == 1)
return (cell - (ncols));
if(direction == 2)
return (cell+1);
if(direction == 3)
return (cell + ncols);
}
int dset::randdir(int i){
srand(time(NULL));
int direction;
vector<int> used;
//cout << "i : " << i << endl;
while (true){
direction = rand() % 4;
while (true){
if(isin(direction,used))
direction = rand()%4;
else
break;
}
// cout << "rand: " << direction << endl;
if(direction ==0){
if( i != 0){
// cout << 0 << " i%(ncols -1) :" << (i%(ncols -1)) << endl;
if(i%(ncols) != 0){
break;
}
}
}
if(direction == 1){
// cout << 1 << " i - ncols :" << (i-ncols) << endl;
if(i-ncols > 0){
break;
}
}
if (direction == 2){
// cout << 2 << " i%(ncols) :" << (i%ncols) << endl;
if ( i == 0 )
break;
if (i%ncols != ncols-1){
break;
}
}
if (direction == 3){
if (i+ncols < ((nrows*ncols))){
// cout << 3 << " i+ncols :" << (i+ncols) << endl;
break;
}
}
used.push_back(direction);
}
return direction;
}
vector<int> dset::possibledir(int cell){
vector<int> possible;
// cout << "cell " << cell << " possible connections:\n";
for (int i = 0; i < 4; i++){
if (i == 0){
if( cell != 0 ){
if(cell%(ncols) !=0){
// cout << dir(cell,i) <<endl;
possible.push_back(dir(cell,i));
}
}
}
if(i==1){
if (cell-ncols > 0){
// cout<<dir(cell,i) <<endl;
possible.push_back(dir(cell,i));
}
}
if(i==2){
if(cell == 0){
// cout<<dir(cell,i) <<endl;
possible.push_back(1);
}else if(cell%ncols != ncols-1){
// cout<<dir(cell,i) <<endl;
possible.push_back(dir(cell,i));
}
}
if(i==3){
if ( cell+ncols < ((nrows*ncols))){
// cout<<dir(cell,i) <<endl;
possible.push_back(dir(cell,i));
}
}
}
// cout << endl;
return possible;
}
vector<int> dset::walls(int cell, vector<int> possible){
vector<int> walls;
// cout << cell << " connection 0: " << S[cell].connections[0] << endl;
for(int i = 0; i < possible.size(); i++){
if (!isin(possible[i], S[cell].connections)){
// cout << "true\n";
walls.push_back(possible[i]);
}
// cout << "false\n";
}
return walls;
}
int dset::merge(int i, int j) {
int cell1 = i;
int cell2 = j;
i = find(i);
j = find(j);
if (i != j) {
element &Si = S[i];
element &Sj = S[j];
// Adjust Adjacency List
// cout << "inconnections\n";
S[cell1].connections.push_back(cell2);
S[cell2].connections.push_back(cell1);
// cout << "notinconnections\n";
// merge (union) by rank
if (Si.rank > Sj.rank) Sj.parent = i;
else if (Si.rank < Sj.rank) Si.parent = j;
else { Sj.parent = i; Si.rank +=1; }
Nsets -=1;
}
return find(i);
}
int dset::find(int i) {
if (S[i].parent == -1){
return i;
}
// recursive path compression
S[i].parent = find(S[i].parent);
return S[i].parent;
}
bool dset::isin(int i, vector<int> test){
bool out = false;
for(int j = 0; j < test.size(); j++){
if(test[j] == i)
out = true;
}
return out;
}
Please learn to pass by reference, not value.
For example:
bool dset::isin(int i, vector<int> test)
You are passing a vector by value. That means that an entire copy is made when the function is called. If your vector has 100,000 items, then an unnecessary copy is made. Change to this:
bool dset::isin(int i, vector<int>& test)
Now no copy is done. Make this same change in all of your other functions.
You also return a vector by value, but I would leave those alone unless it is proven that your compiler can't or won't optimize the copy away.
Also, make sure you are timing a release, optimized program, and not a "debug" or unoptimized program. Since you didn't mention the compiler you're using, use the settings that generate optimized code when building your program.
Although I do not know much about c++, it would seem to me from your program description at the start that your slowdown may happen when your program is determining whether two prospectively connectable cells are already connected. Since the majority if not all cases when this is done that are used must determine that the cells are NOT connected, so that there is only one proper solution, every time this is done your program has to examine/solve the entire maze to that point to make sure that there is no way in which it could already be connected. This means that as the existing part of the maze gets larger, the time it takes to complete this task will get longer and longer.
To test whether this is the case, you could have your program record how long it takes to determine if two cells are connected every time ( or 10 times) it does so, and if the times on the list get longer linearly, then this or something similar is part of the issue.
You could fix this by either allowing already-connected to be connected by another path, or by simplifying the way in which your program checks what cells are connected.
Sorry I can't give better code-specific advice, but I'm researching how to create a maze and ran across your question, hopefully my answer at least is food for thought.