Thread: Typedef Structs inside Typdef structs

  1. #1
    Registered User
    Join Date
    Dec 2011
    Location
    Barcelos, Braga, Portugal, Portugal
    Posts
    7

    Typedef Structs inside Typdef structs

    Hello, I'm currently making a game, called rubik cube, however, this is more a syntax question than it is about the game properly.

    I have defined the following structure, and can«t find out how to initialize the whole structure.

    Code:
    // each square of the little cubes in the rubik cube
    typedefstruct quadr
    {
            char collor;
            char axys;
    } quad;
    
    // Cubes in the rubik cube
    typedefstruct squareR
    {
            quad q[6];
            char axys;
            // Check if its side is valid, eg. If it shows on the rubik cube
            int valid;
    } square;
    
    // Rubik cube
    typedefstruct cubeR
    {
            square q[3][3][3];
    } cube;
    
    I was thinking of doing something like this:

    Code:
    void startup()
    {
    int x,y,z,w;
            for(x=0;x<3;x++)
            {
                    for(y=0;y<3;y++)
                    {
                            for(z=0;z<3;z++)
                            {
                                    for(w=0;w<6;w++)
                                    {
                                            //initialization goes here
                                    }
                            }
                    }
            }
    }
    
    The hard part i find by now, is making the initialization...

    The axys variable has to do to which side the cube(s) are turning to, so that i can show the correct collors.
    The collors at the beggining, will be filled probably with numbers from 0 to 5, or something like that.

    I would also appreciate some feedback on the way I'm trying to make the game, and know if I'm proceeding correctly.

    Thank you,

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    There should be a space between "typedef" and "struct".

    Code:
            // Check if its side is valid, eg. If it shows on the rubik cube
            int valid;
    If what you mean is "does this side of the cube show on the surface", shouldn't that be part of the quad struct? (IMO better names here might be side, piece, cube). Corner pieces have 3 visible sides, edge pieces have 2 visible sides, and center pieces only have 1 visible side. They are not interchangeable -- you cannot move a corner to an edge or an edge to the center, etc, on a rubik's cube. So depending on your logic, maybe you want to have a "type" member for each piece.

    Code:
    enum {
        CORNER,
        EDGE,
        CENTER
    };
    Altho that perhaps should not matter if you get the logic right, it may be helpful.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Dec 2011
    Location
    Barcelos, Braga, Portugal, Portugal
    Posts
    7
    Oh, yes, sorry, the typedef struct thing happened when I coppied it from my source.

    Anyway, yes, that does make sense.

    I'm having problem initializing the variables. Thats the biggest problem. Seen some things, but just don't how to proceede in filling the cube to the initial state. By initial state I mean, each side has it's color like if it was solved.

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Hmmm. I think rather than nested loops, you should initialize the cube and the 26 pieces within it, assigning them each a unique number, and their unique characteristics. So that's 1 loop and two types, which would be more like:

    Code:
    typedef struct _piece {
        int id;  // corresponds to "parts" array below
        int sides[6];
        int top;  // initially 0
        int left;  // initially 3
    } piece;
    
    typedef struct _cube {
        piece *parts[26]
    } cube;
    Of course, I'm not sure what you meant to do with that axys variable, and this is just how I would start thinking about it. "top" and "left" would indicate the current rotation of a piece, corresponding to which side in the "sides" array (these would be assigned enum colors) is in that position if they were numbered top=0, right=1, bottom=2, left=3, front=4, back=5.

    So the idea would be that the 26 pieces start in order, but the cube.parts array refers to static Cartesian positions (eg, cube.parts[0] could be the top back left corner, and initially point to the piece with id 0). That array could have the pointers rearranged, so, eg, if you rotate the left side back one turn, cube.parts[0] would still be top back left, but it would point to the piece with id 6, and piece 0 would be associated with parts[17] -- I'm numbering in horizontal rows back to front and skipping the center one, so the last piece on the second level (middle front right) would be 16. That gives me something feasible to work with, but I haven't thought beyond this, so I dunno how good an idea it is. Usually my intuition is pretty good, lol, but this is fairly complex.

    So: you definitely need to sit down and figure out the basic mechanics. If you have already, then post an explanation. If not, do so before you start to worry about the initialization. Don't just start pounding out code.

    Also, maybe you don't want to actually initialize the whole cube to a finished state, you want it random, but you do need to conceive of what the finished state would be and what rules govern the possible random states. If you can do that, you may actually have tackled the mechanics too.
    Last edited by MK27; 12-30-2011 at 11:16 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    It seems to me that you have too many pieces of data:

    If I understand correctly: quad is a single face of one of the small squares. square is 6 of these: a small cube. Finally cube is 27 of the small squares. Right? That makes 162 coloured sides.... which is many more than a rubik's cube actually has. I think the confusion is that you're treating it as though some sides of the small cubes can be hidden. I don't think this is the case: I think they're always all visible.

    I would probably just represent the cube as 6 sides of 9 colours. Moves have to update all appropriate sides.

    That's just my thoughts though....

    For initialisation with your current code... I think it'd go something like:

    Code:
    cube c;
    
    int x,y,z,w,s;
    for(x=0;x<3;x++)
    {
    	for(y=0;y<3;y++)
    	{
    		for(z=0;z<3;z++)
    		{
    			for (s = 0; s <= 6; s++)
    			{
    				c.q[x][y][z].q[s].collor = s;
    			}
    		}
    	}
    }
    To visualise what this does I think you need to number the sides, e.g. say that the sides facing you are number '0'. Then this loop will colour *every* side of every little cube facing you with colour '0'. Including the ones in the middle that will never be seen.

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by gremory View Post
    Hello, I'm currently making a game, called rubik cube, however, this is more a syntax question than it is about the game properly.

    I have defined the following structure, and can«t find out how to initialize the whole structure.
    In my experience, when you design a data structure that complex --especially for a realitively simple task--
    you're probably not thinking the problem through far enough to find a simpler way to do it.

  7. #7
    Registered User
    Join Date
    Dec 2011
    Location
    Barcelos, Braga, Portugal, Portugal
    Posts
    7

    Arrow

    Thankyou. I will explain then.

    I picked up a paper, drew and made everything look logic, and then tried to define the structure of what i made in the paper.

    So, First I thought about it this way.

    A cube has 27 cubes in it, that "would" have the same colors as the main cube if it was solved.
    So I would make an array[3][3][3].

    Therefor this structure:
    Code:
    // Rubik cube
    typedef struct cubeR
    { square q[3][3][3];
    }cube;


    Then I thought that if you are viewing the cube from a 3d perspective. You can imagine that it has two sides facing the X axis, two facing the Y axis, and two facing the Z axis. Therefor making the 6 sides of the cube.

    And why did I use that variable. Because, when filling the smaller cubes with colors, there are squares that dont face the outside of the cube. So at this point, I would pick up your sugestion and use the enum you sugested me.
    Instead of having little cubes with 6 squares with collors that dont even face the outside of the cube, I would probably use your sugestion. That is why I used the structure bellow. With the quad vector[6] (six sides of each little square).

    Code:
    // Cubes in the rubik cube
    typedef struct squareR
    { quad q[6];
    char axys;
    // Check if its side is valid, eg. If it shows on the rubik cube
    int valid;
    }square;


    I'm hopping you're understanding what I'm writting here.

    Then, For each of those little squares, on each of the 27 cubes, of the rubik cube, I had this:

    Code:
    // each square of the little cubes in the rubik cube
    typedef struct quadr
    {
            char collor;
    char axys;
    } quad;
    


    So once again, we have the axys variable. And why do I have an axys before and after. So that I can compare this axys variable to the main cube axys variable and see of they are the same, if they were the same, it would mean that they would be showing, and that way, they would be "valid".


    This is like the first part. My second part has another couple of structures defining the way you visually see it.

    Thankyou once again.

  8. #8
    Registered User
    Join Date
    Dec 2011
    Location
    Barcelos, Braga, Portugal, Portugal
    Posts
    7
    Quote Originally Posted by CommonTater View Post
    In my experience, when you design a data structure that complex --especially for a realitively simple task--
    you're probably not thinking the problem through far enough to find a simpler way to do it.
    I think you might be right...

  9. #9
    Registered User
    Join Date
    Dec 2011
    Posts
    795
    It would be the most "correct" (in the context of real life) to have all faces documented:

    Code:
    
    struct basic_cube {
        u8 faces[6]; 
    
    #define RED 0x1
    #define YELLOW 0x2
    #define GREEN 0x4
    #define BLUE 0x8
    #define WHITE 0x10
    
    };
    
    struct rubix {
        struct basic_cube rubix_cube[3][3][3]; /* no need for triple pointer, as the size is static */
        /* any other data you'll need to pass, goes here */
    }; 
    
    /* to init */
    
    struct rubix *init_cube(void)
    {
        struct rubix *tmp;
        tmp = malloc (sizeof(struct rubix)); /* bad practice, this is just proof-of-concept -.- */
    
        /* your for loops and everything else goes here */
    
        return tmp;
    }
    The problem is that while it only takes up 162 bytes in memory (after padding, assuming no __packed__), the for loops will take a lot of processor power. The best solution is to split it off into threads:

    Code:
    void *init_squares(void *data)
    {
        struct rubix *proc = (struct rubix *)data;
    
     /* 
     * for loops go here 
     * use the syntax (*proc->rubix_cube[0][0][0]) = RED;
     * you have to dereference the pointer or it won't work
     */
    
        return data; /* doesn't do anything, but makes gcc shut up */
    }
    
    struct rubix *blank;
    blank = malloc(sizeof(struct rubix));
    
    /* 
    * create your thread, pass it (void *)blank 
    * no example code, it depends on your computer
    */
    
    /* use the data by dereferencing the data in the struct */

  10. #10
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    27 instances of some small struct hardly warrants threads. Evan automated solving of the thing is something that I'd profile before considering adding threading.

    I've spent a little while thinking about alternative representations for this, like MK27 has. The key here is in having a representation where rotations can be performed easily. I considered something like dancing-links, but it really doesn't cut it; rotation is just too complex. Then there's representing every possible valid position and orientation of each block and just storing a collection of those, but there are 516 of them.
    Before telling the OP that the idea chosen is unnecessarily complicated, try and come up with something better yourself. It really is quite a hard problem.
    I've actually ended up deciding that I'd use a 3x3x3 array of something that has 6 color enums for of the top, left, bottom, right, front, and back squares. Essentially about what the OP has. It's the simplest thing I could come up with that allows for easy rotations.

    If you want to try and generate a random starting arrangement, then I suggest you do it by starting with a solved cube and then perform a lot of random rotations on it. Otherwise you're unlikely to prodice a solvable arrangement.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  11. #11
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Straight after answering this I went to another forum and look what I found: Rubik Cube C - GameDev.net
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  12. #12
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    The simplest structure might be something like this, with the face numbers also being the color numbers (since the middle squares are immobile).

    Code:
    #define NFACES 6
    #define NSQUARESPERFACE 9
    
    int cube[NFACES][NSQUARESPERFACE];
    int f, s;
    
    /* init */
    for (f=0; f<NFACES; ++f)
        for (s=0; s<NSQUARESPERFACE; ++s)
            cube[f][s] = f;
    The display operation should be fairly simple with this structure. The rotates might be a little hairy, but probably not too bad (each requires moving 16 numbers, eight on the side you're rotating, and eight around the edges of the four other faces involved).

  13. #13
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    Quote Originally Posted by iMalc View Post
    Before telling the OP that the idea chosen is unnecessarily complicated, try and come up with something better yourself. It really is quite a hard problem.
    *Guilty*. It IS a hard problem. It was only when I tried to explain my approach in a reply that I realised it was probably not viable.

    My idea was the same as oogabooga's, I think. Instead of building the big cube out of little cubes, I wanted to build it out of squares (9 squares on each face). Since these are the only things that'll be displayed, it seemed reasonable to not represent the interior sides of the little cubes.

    I think it'd work -- but it'd be a dull slog of hand calculating what number square on each face moves to what number square on another face for each rotation. I think you can rig it to be easy to calculate for 2 planes, but the 3rd plane of movement will always be horrible.

    I've been looking at this little java applet of a rotatable cube to help visualise the transformations needed - might be handy for others:
    Virtual Cubes Rubik's Cube | Instructions | Instructions

  14. #14
    Registered User
    Join Date
    Dec 2011
    Location
    Barcelos, Braga, Portugal, Portugal
    Posts
    7
    Quote Originally Posted by iMalc View Post
    Straight after answering this I went to another forum and look what I found: Rubik Cube C - GameDev.net
    Well yes, I did post it in two forums, this and that one. I don't think it's a bad idea. But definitely, I've been getting a better study of my problem here, and I am thankful for that.

    If it is a problem, just let me know...

  15. #15
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by gremory View Post
    Thankyou. I will explain then.

    I picked up a paper, drew and made everything look logic, and then tried to define the structure of what i made in the paper.

    So, First I thought about it this way.

    A cube has 27 cubes in it, that "would" have the same colors as the main cube if it was solved.
    So I would make an array[3][3][3].
    Seems to me the representation is much simpler than that...

    You have 6 faces, each a 3x3 matrix...
    Code:
    int rubic[6][3][3];
    The problem is not in how you depict it in data... the real task is how do you rotate the faces when rotating one of the 6 faces also rotates one row of the 4 adjoining faces... Seems to me the real magic is in the code not the picture.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Typedef, Structs, Reusability without OO
    By tempster09 in forum C Programming
    Replies: 6
    Last Post: 12-05-2009, 03:39 PM
  2. structs inside classes
    By *DEAD* in forum C++ Programming
    Replies: 10
    Last Post: 06-16-2007, 11:54 PM
  3. typedef and structs
    By ^xor in forum C Programming
    Replies: 8
    Last Post: 06-11-2005, 11:46 AM
  4. linked list inside array of structs- Syntax question
    By rasmith1955 in forum C Programming
    Replies: 14
    Last Post: 02-28-2005, 05:16 PM
  5. Help understanding typedef structs
    By difficult.name in forum C Programming
    Replies: 3
    Last Post: 09-22-2004, 12:43 AM