Thread: Array Help?

  1. #16
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    This:
    Code:
    row6num1=row6[0];
    row6num2=row6[1];
    if (row6num1+row6num2 == 4)
    becomes this:
    Code:
    if (row6[0]+row6[1] == 4)
    But this:
    Code:
    if(grid[3][1]+grid[3][2]==4)
    only works if grid is a two dimensional array as suggested by Cat rather than a one dimensional array like the ones you are using.

  2. #17
    Registered User
    Join Date
    Nov 2006
    Posts
    25
    Daved, I'm redoing the code with a 6x6 array:

    Code:
    #include<iostream.h>
    #include<stdlib.h>
    #include<time.h>
    
    int grid[6][6];
    void randnums();
    
    int main()
    {
    	randnums();
    
    	for (int x=0;x<6;x++)
        {
            for(int y=0;y<6;y++)
            {
                cout<<grid[x][y]<<"	";
            }
            cout<<endl;
            cout<<endl;
        }
    
    	return 0;
    }
    
    
    
    void randnums()
    {
    	for (int x=0;x<6;x++)
    	{
    		for(int y=0;y<6;y++)
    		{
                grid[x][y]=rand()%36+1;
    		}
    	}
    
    }
    Am I wrong yet?

    EDIT: wow, yea I am! It is displaying the same numbers every time hahahaha
    EDIT2:
    Thanks manutd, I think the "srand(time(NULL));" not being in the randnum function caused the error, because I think it works now. (BTW, I hope that's where it goes)
    Last edited by JDrake; 11-14-2006 at 06:15 PM.

  3. #18
    MFC killed my cat! manutd's Avatar
    Join Date
    Sep 2006
    Location
    Boston, Massachusetts
    Posts
    870
    You want to seed rand.
    Silence is better than unmeaning words.
    - Pythagoras
    My blog

  4. #19
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> Am I wrong yet?
    Looks like a good start to me.

    If you're going to use your previous algorithm where you generated a row, and then checked it, and then generated it again, you will have to make some modifications, but it is definitely a good idea to start small.

    One good idea to add to your current code would be to have a const int SIZE = 6; as a global constant in your code. Then use SIZE everywhere you have 6 now. That way you can test it with a 3x3 matrix and then quickly switch to 6x6 by only changing a single line of code.

  5. #20
    Registered User
    Join Date
    Nov 2006
    Posts
    25
    So what would be the more efficient way of checking a row/column??
    I was just AFK and now I get back and still have no idea what to do...
    Code:
    grid[0][0]+grid[0][1]+grid[0][2]+grid[0][3]+grid[0][4]+grid[0][5]==36
    is just what I did last time...
    and I like the const int SIZE idea, but I don't know how I'd incorporate it into the checking part?

    Could you maybe explain:
    "The solution is to use a loop inside assignrow1 that calls checkrow1 and tries again if checkrow1 returns false (assuming you know how to return a value from a function). This will avoid calling nested functions back and forth."
    A little bit more? TY

    Can you make it so a number only gets picked once? Because in a Magic Square I think you can only have each number once
    Last edited by JDrake; 11-14-2006 at 07:36 PM.

  6. #21
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I just realized that in a magic square of 6x6, the rows, columns, etc must add to 111, not 36. That information might help you get success.

    Anyway, you start with SIZE defined to some number. I think you should start with it equaling 3, since that will make everything easier. Make sure your simple code above works with that. Also, srand goes at the beginning of main like you had it in the very first code you posted.

    So once you have it displaying your grid with SIZE = 3, change SIZE to 6 and make sure that small piece of code works again.

    Once you get that working, you can move on to the next part. The key is to think generically. Instead of thinking about a specific number like this:
    Code:
    grid[0][0]+grid[0][1]+grid[0][2]+grid[0][3]+grid[0][4]+grid[0][5]==36
    think about how you got that group. You changed the second index and added 1 to it each time while it was less than 6. So if you were to do that generically, you would do a loop from 0 to less than SIZE and change the second index each time. You are adding the variable each time, so you might do something like this:
    Code:
    int sum = 0;
    for (int columnIndex = 0; columnIndex < SIZE; ++columnIndex)
    {
        sum += grid[0][columnIndex];
    }
    if (sum == 111) // This needs to change if SIZE is not 6, perhaps another const int would be better.
    Remember that you will need to do that for each row, not just row 0. It is probably best to do one row at a time, generate the random numbers and check the sum, so you have to figure out where to put that code where it will make sense.

    I think that's enough for the next step. If you can get it working so that all the rows (or columns) add up correctly, then you can move on to the next thing.

    As far as making sure a number is picked only once, there are multiple ways to do that. The most beginner-friendly would be to have a separate array that has the size of SIZE*SIZE (since a 6x6 grid can have 36 numbers). That array will be bool values that are false if the number has been picked and true otherwise. When you use rand to get a number, you check its corresponding value in the array to see if it has been picked and if it has you pick another number. This is a very inefficient way to do things, but it will work for you. The best method is to use the random_shuffle function to shuffle an array of numbers, but I won't elaborate unless you ask because this doesn't seem like the kind of assignment you would be able to use that on.

  7. #22
    Registered User
    Join Date
    Nov 2006
    Posts
    25
    Here's what I have

    Code:
    #include<iostream.h>
    #include<stdlib.h>
    #include<time.h>
    
    void random1();
    void checkall();
    int norepeat[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    int row1[4];
    int row2[4];
    int row3[4];
    int row4[4];
    int randomnumber;
    
    
    int main()
    {
    
    	random1();
    	checkall();
    	
    
    
    	return 0;
    }
    
    void random1()
    {
    	srand(time(0));
    		
    	for (int a=0;a<4;a=a+0)
    	{
    		int randomnumber=rand()%16+1;
    		if (norepeat[randomnumber] == 0)
    		{
    			row1[a]=randomnumber;
    			norepeat[randomnumber]=1;
    			a=a+1;
    		}
    	}
    	
    	for (int b=0;b<4;b=b+0)
    	{
    		int randomnumber=rand()%16+1;
    		if (norepeat[randomnumber] == 0)
    		{
    			row2[b]=randomnumber;
    			norepeat[randomnumber]=1;
    			b=b+1;
    		}
    	}
    
    	for (int c=0;c<4;c=c+0)
    	{
    		int randomnumber=rand()%16+1;
    		if (norepeat[randomnumber] == 0)
    		{
    			row3[c]=randomnumber;
    			norepeat[randomnumber]=1;
    			c=c+1;
    		}
    	}
    
    	for (int d=0;d<4;d=d+0)
    	{
    		int randomnumber=rand()%16+1;
    		if (norepeat[randomnumber] == 0)
    		{
    			row4[d]=randomnumber;
    			norepeat[randomnumber]=1;
    			d=d+1;
    		}
    	}
    
    }
    
    void checkall()
    {
    	if(row1[0]+row1[1]+row1[2]+row1[3]==34 && row2[0]+row2[1]+row2[2]+row2[3]==34  && row3[0]+row3[1]+row3[2]+row3[3]==34 && row4[0]+row4[1]+row4[2]+row4[3]==34 && row1[0]+row2[0]+row3[0]+row4[0]==34 && row1[1]+row2[1]+row3[1]+row4[1]==34 && row1[2]+row2[2]+row3[2]+row4[2]==34
    		&& row1[3]+row2[3]+row3[3]+row4[3]==34 && row1[0]+row2[1]+row3[2]+row4[3]==34 && row1[3]+row2[2]+row3[1]+row4[0]==34)
    	{
    	cout<<row1[0]<<"	"<<row1[1]<<"	"<<row1[2]<<"	"<<row1[3]<<endl;
    	cout<<row2[0]<<"	"<<row2[1]<<"	"<<row2[2]<<"	"<<row2[3]<<endl;
    	cout<<row3[0]<<"	"<<row3[1]<<"	"<<row3[2]<<"	"<<row3[3]<<endl;
    	cout<<row4[0]<<"	"<<row4[1]<<"	"<<row4[2]<<"	"<<row4[3]<<endl;
    	}else
    	{
    		random1();
    	}
    
    
    
    }
    That should work I think, but it doesn't display anything so I wouldn't know. Is there any way to check to make sure it is working or something.

    BTW, the array only has to be 4x4 and it has to equal 34 on all sides, you were right about the 36, it should have been higher - I wasn't thinking...

  8. #23
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I see two problems. First, you have to be careful with array sizes again. Your norepeat array is almost correct, but you are using random numbers from 1-16 and your norepeat array has a size of 16 meaning its indexes go from 0-15. So you are writing memory past the bounds of your array. Either subtract 1 everytime you index the norepeats array, or just make the array size 17 so that index 16 is valid.

    The second problem is also with norepeats. If you fail to get a magic square in the first attempt, your code calls random1 again. But you never clear the norepeats array so it thinks everything is a repeat and never fills the square again. This is why nothing is displayed, because it goes into an infinite loop looking for a random number that hasn't been used yet.

    One other issue you still have is the same as you had in the beginning. You should not be calling random1() from inside checkall(). You will get a stack overflow again. Do you know loops yet? Do you know how to return a value from a function? If you do, then just return true or false from checkall() and use a loop to call random1 over and over again. This saves stack space so you don't keep adding to it.

  9. #24
    Registered User
    Join Date
    Nov 2006
    Posts
    25
    I thought what checkall() was doing was "us[ing] a loop to call random1 over and over again", but you don't want me to do that? Where should I be calling random1() if the checkall() is false?
    Should I have something in random1()
    do{
    }while(checktf==false);
    or similar?
    Wouldn't it be like random1(bool checktf)?

    We are only know the basics about returning/passing values from functions.. and if by loops you mean 'for, if, and do-while' then yea, I know them- but otherwise I guess not.

    Sorry for so many questions but thanks for your help so far

    PS: I changed the norepeat array to 17
    and right after I posted to code I realized about the resetting to 0, so I added this code into the else portion of the checkall() function:
    Code:
    for(int e=0;e<17;e++)
    		{
    		norepeat[e]=0;
    		}
    Does that look right?

  10. #25
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    A loop is a for, while or do-while. An if is not a loop.

    Your resetting of norepeats looks fine.

    All that is left, then, is getting your loop correct. Your idea seems like it could work as long as you do it correctly. Step one is to change checkall to return true or false based on whether the check succeeded or not. Then you add your loop to wherever you choose to put it. If you add it to random1, then after setting the random values you can call checkall and use that to control your loop. Finally, make sure you get rid of the call to random1 inside checkall.

    Once you make those changes, hopefully it will be working ok. After that there are some things you can do to have better code and better design, but at this point I wouldn't worry about that until later.

  11. #26
    Registered User
    Join Date
    Sep 2006
    Posts
    835
    Usually when a program has this much repetitiveness, it's a sign of bad design. Instead of having 4 arrays row1, row2, row3, and row4, I'd just have a single two-dimensional array row[4][4] (here the first index goes from 0 to 3, not from 1 to 4). Then the above code could be compressed tremendously with a few extra loops.

    Edit: Sorry Daved, I didn't read the last part of your last comment, just looked at that long piece of code above and couldn't resist an immediate reply. But changing to using row[4][4] is pretty trivial, and it might actually be easier to get the code working properly by fixing the design first. The more compact the code, the more likely that any single bug will screw up the execution in an obvious way, meaning the bug gets spotted and fixed. Having 4 separate loops instead of a single double loop makes it possible to have a typo in just one of the loops, which might not get noticed.
    Last edited by robatino; 11-17-2006 at 08:13 PM.

  12. #27
    Registered User
    Join Date
    Nov 2006
    Posts
    25
    Quote Originally Posted by Daved
    Your idea seems like it could work as long as you do it correctly. Step one is to change checkall to return true or false based on whether the check succeeded or not. Then you add your loop to wherever you choose to put it.
    That's what I'm not sure about. Do you know anywhere I can look at an example of passing true/false between multiple functions; or what I should search for?

    Robatino, I was told it'd be easier to do 4 arrays of 1 row than 1 array of 4 rows (for now), but I guess I could combine it. However, for now I think I just need to get a good understanding of the return(____); and functionhere(______) stuff because it doesn't make that much sense.

  13. #28
    Registered User
    Join Date
    Sep 2006
    Posts
    835
    Basically, you just replace row1[i] with row[0][i], row2[i] with row[1][i], etc. Also, the above 4 loops don't need 4 separate variables a, b, c, d - you can use the same variable name. Then it's obvious how to compress the 4 loops into a single double loop.

  14. #29
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Example of using a true/false return value:
    Code:
    void printOdd()
    {
        for (int i = 0; i < 10; ++i)
        {
            if (isOdd(i))
                std::cout << i << ' ';
        }
    }
    
    bool isOdd(int i)
    {
        if ((i % 2) == 0)
            return false;
        else
            return true;
    }
    The two dimensional array was already tried earlier in this thread. Apparently it didn't work out so well. I'd recommend getting the current code correct first, and then learning how to do it better.

  15. #30
    The larch
    Join Date
    May 2006
    Posts
    3,573
    So this is supposed to be a magic square, that is where each number is used once and rows and columns add up to the same value?
    I think these conditions are too restrictive to achieve the goal by trying random combinations. If I'm not mistaken, then there are 8 different solutions to 3*3 magic square (diagonals are also 15), while there should be 9! = 362,880 different ways to fill the square with unique numbers, and 9^9 = 387,420,489 ways if numbers are repeating.

    So you might need a more systematic approach. Here's a recursion tutorial that also has a full chapter about magic squares.
    Last edited by anon; 11-18-2006 at 02:04 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 05-29-2009, 07:25 PM
  2. Replies: 6
    Last Post: 11-09-2006, 03:28 AM
  3. [question]Analyzing data in a two-dimensional array
    By burbose in forum C Programming
    Replies: 2
    Last Post: 06-13-2005, 07:31 AM
  4. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM
  5. Quick question about SIGSEGV
    By Cikotic in forum C Programming
    Replies: 30
    Last Post: 07-01-2004, 07:48 PM