Search In
• More options...
Find results that contain...
Find results in...

# managing multidimensional arrays

## Recommended Posts

Let's say I'm programming and make 3 frogs. Each frog has 3 attributes:
* size,
* red/green/blue color
* xy position

I could make a big multidimensional array like this:

frogs = [ [8,[0,255,0],[50,45]], [4,[255,0,0],[25,45]], [6,[0,0,255],[50,75]] ]

which would be used like this:
frogs[which frog][which attribute][R or G or B or X or Y if applicable]

So the 2nd frog's x value (25) is referred to as:
frogs[1][2][0]
(indexes start on 0, a neverending cause of headaches and off by 1 errors for lulz)

... but [1][2][0] is cryptic way to refer to something. Humans deal with language words better than numbers (you'll soon forget what the 2 even stands for). Plus cycling through multiple dimensions of an array beast with nested for loops often = headdesk for me

So instead you can make a larger number of variables to reduce the nested complexity (this is the same information in that frogs variable up there but spread out to reduce nesting):

sizes = [8,4,6]
RGBcolors = [[0,255,0], [255,0,0], [0,0,255]]
xyPositions = [[50,45], [25,45], [50,75]]

which is used like this:
anyOfTheseVariables[which frog][R or G or B or X or Y if applicable]

Or you could reduce nesting even more:

sizes = [8,4,6]
Rcolors = [0,255,0]
Gcolors = [255,0,0]
Bcolors = [0,0,255]
xPositions = [50,25,50]
yPositions = [45,45,75]

used like:
anyOfTheseVariables[which frog]
seems much easier to deal with?

Here is adding another dimension to the whole thing (4 frames for each frog).
3 frogs with 4 animation frames each, where size/color/position can have unique value each frame:

frogs =
[
[ [8,[0,255,0],[50,45]], [7,[0,235,0],[55,50]], [6,[0,215,0],[60,55]], [5,[0,195,0],[65,60]] ],
[ [4,[255,0,0],[25,45]], [6,[255,10,10],[30,45]], [8,[255,20,20],[35,45]], [10,[255,30,30],[40,45]] ],
[ [6,[0,0,255],[50,75]], [7,[50,0,255],[50,70]], [8,[100,0,255],[50,65]], [9,[150,0,255],[50,60]] ]
]

used like this:
frogs[which frog][which frame][which attribute][R or G or B or X or Y if applicable]

It just starts to suck when getting more nested/multidimensional. I can't visually make sense of that beast easily, or cycle through it with minimal mental effort.

I guess you could similarly reduce the nesting with multiple variables again:
sizesPerFrame = [ [8,4,6],[7,6,7],[6,8,8],[5,10,9] ]
RcolorsPerFrame = [ [0,255,0],[0,255,50],[0,255,100],[0,255,150] ]
etc. but these are multidimensional arrays again...

Or maybe just make a ton of different variables:

frame1_sizes = [8,4,6]
frame1_Rcolors = [0,255,0]
frame1_Gcolors = [255,0,0]
frame1_Bcolors = [0,0,255]
frame1_xPositions = [50,25,50]
frame1_yPositions = [45,45,75]

frame2_sizes = [7,6,7]
frame2_Rcolors = [0,255,50]
frame2_Gcolors = [235,10,0]
frame2_Bcolors = [0,10,255]
frame2_xPositions = [55,30,50]
frame2_yPositions = [50,45,70]

frame3_sizes = [6,8,8]
frame3_Rcolors = [0,255,100]
frame3_Gcolors = [215,20,0]
frame3_Bcolors = [0,20,255]
frame3_xPositions = [60,35,50]
frame3_yPositions = [55,45,65]

frame4_sizes = [5,10,9]
frame4_Rcolors = [0,255,150]
frame4_Gcolors = [195,30,0]
frame4_Bcolors = [0,30,255]
frame4_xPositions = [65,40,50]
frame4_yPositions = [60,45,60]

For these, there's no nesting. You can just go:
anyOfTheseVariables[which frog]
But maybe it has cons (having to create so many variables is a con but maybe getting rid of that nesting is worth it?)

Basically do you think this is a good idea? I've mostly only used python, so maybe C has some solution or there's a better way to do it that I don't know of, other than OOP which I so far kinda refuse to learn.

gggmork said:

other than OOP which I so far kinda refuse to learn.

Why? It's the most logical solution to your problem.

```struct Frog
{
float size;
float red, green, blue;
float x, y;
};

Frog frogs[8];

frogs[0].size = whatever;```
Where's the problem with OO paradigms exactly? It's about a gazillion times easier and less convoluted than what you tried to explain.

Yes, C has structs:

```struct frog {
int size;
float xPos;
float yPos;
rgb color;
};

struct rgb {
unsigned short red;
unsigned short green;
unsigned short blue;
};
```
Then you can just declare frogs and initialize their parts to whatever:
```frog frog1;
frog1.size = 5;
frog1.xPos = 2.55;
frog1.yPos = 80.06;
```
If I was just going to do it with arrays (hello, BASIC!) I'm not quite decided on which way I would hate the least. If you do everything in one array you generally are stuck with storing everything as the same data type, which totally sucks. I like being able to do things like have my RGB as integers (really they should be one byte, so maybe I'd use chars in C and cheat).

So if I were stuck exclusively using arrays like you showed I'd probably use something like your non-nested example.

EDIT: Gooberman's example is even better because he constructs an array of frogs, but same shit. He's also right about OOP. It's also used nearly everywhere, so you need to know how it works to understand a huge percentage of the code out in the world.

gggmork said:

Let's say I'm programming and make 3 frogs. Each frog has 3 attributes:
* size,
* red/green/blue color
* xy position

I could make a big multidimensional array like this:

Fail. This is not what arrays are meant for, nor is this even remotely helpful for what you're trying to do.

I kinda thought people would say that (I only read the first 2 replies before writing this, so will read the others now). Maybe I should finally learn it even though for some weird reason I feel like I should become more skilled in normal procedural programming before using OOP. It just seemed complex/difficult and not in line with my way of thinking based on my brief exposure to it.

I guess the main reason I made this post is I kinda suck at programming and am looking for tips or something. Some tips I've read are to 1) focus on data ('smart' data, 'dumb' programs) and 2) try to only make functions return stuff without side effects. The 2nd seemed helpful but only recently read about the first.

The OP was a simplification (believe it or not.. I guess I'm not succinct..) of something else I was trying to do (this is just a stupid idea but kinda for practice.. the animations might be interesting though):
Choose a random 8x8 block of pixels from some picture somewhere.
Double copy/mirror flip it so you have a symmetrical square (now 16x16).
Copy paste till you have 4x4 of those squares (now 64x64)
Make like 50 of these unique 64x64 things (each made of 16 symmetrical squares)
Now probably a block of keyboard keys (1234 qwer asdf zxcv or whatever) maps to each individual square, allowing you to select or deselect any amount.
The whole purpose is to make an animation so there's maybe 16 frames.
You can change various attribues of the selected squares on any specific selected frame.
The attributes are moving any column any speed down or up (or rows right or left), setting a 'warp' offset to any amount for any square for any frame, and setting any of the 50 patterns to any square on any frame (and preferably be able to add more stuff later).
Anyway, I'm retarded so have to sit and fail-think for hours before I even figure out what the data should look like. And just organizing all that complexity in a good way (or any way really) seems quite hard to me.

gggmork said:

I kinda thought people would say that (I only read the first 2 replies before writing this, so will read the others now). Maybe I should finally learn it even though for some weird reason I feel like I should become more skilled in normal procedural programming before using OOP. It just seemed complex/difficult and not in line with my way of thinking based on my brief exposure to it.

You're being stupid and your reasoning doesn't make any sense. The examples that have been given to you so far are in C, which isn't even an object oriented language.

If it "doesn't seem in line with your way of thinking" then you should change your way of thinking. I don't mean to sound dictatorial with that statement: the entire process of learning to program involves developing a way of thinking about how to structure code. The simple truth is that there are features found in every modern language specifically designed to solve the problem you're faced with.

Hopefully I understand your post. If not, sorry :)

I can avoid using true OOP and still keep the code readable if I do this in Lisp:

```(defmacro push-frog (size color x y frogs)
`(push (list :size ,size :color ,color :xy (list ,x ,y))
,frogs))

(defun get-frog-by-property (prop val frogs)
(loop for frog in frogs
when (equal (getf frog prop) val) collect frog))
```
Usage example:
```(defparameter *frogs* nil)

(push-frog 8 '(200 100 100) 18 23 *frogs*)

(get-frog-by-property :size 8 *frogs*)
```
Adding new properties is as easy as changing the PUSH-FROG macro.

Aliotroph? said:

If you do everything in one array you generally are stuck with storing everything as the same data type, which totally sucks.

Yeah, I noticed that in ACS (my closest exposure to c). Python does allow arrays of different data types which is why the op first frogs multidimensional array had arrays mixed with integers. Still I think I wish that I started using plain C from the beginning rather than python (I did try c++ way back but was way too much of a beginner to start there).

It's also used nearly everywhere

Yeah, almost all the pygame games I saw used it.. I was planning to flee to C to learn procedural and avoid learning OOP because I assumed c didn't use OOP.. but I guess it does. Still structs seem mild, helpful and easy to understand compared to OOP that I saw in other languages.

AndrewB said:

This is not what arrays are meant for, nor is this even remotely helpful for what you're trying to do.

Like if I want to move all 3 frogs 5 to the right:

numberOfFrogs = 3
frogs = [ [8,[0,255,0],[50,45]], [4,[255,0,0],[25,45]], [6,[0,0,255],[50,75]] ]
for i in range(numberOfFrogs):
frogs[ i ][2][0] += 5
(put spaces around i so it didn't turn on italics)
Maybe OOP is better but that seems at least remotely helpful (but I probably like the non nested better).

fraggle said:

your reasoning doesn't make any sense.

That wouldn't surprise me. But I first met OOP in actionscript3. As far as I could tell, as a beginner, you were forced to indent the code with package brackets then indent again with class brackets, maybe even as a separate file if I remember, which was kinda annoying for someone who just wanted to make hello world. Those struct things above look very simple and easy to understand, but python has "self" stuff, and once classes start spanning separate files, the hassle of juggling them made it not fun to learn. I'm also slightly autistic or something and prefer to tediously do what I've habitually done already, rather than try new things (hello, GETTING LAID!). (but this post has made me want to learn OOP because I respect the skill and knowledge of a lot of coders here, even though its fun to just complain about stuff, and c apparently uses more OOP than I previously thought).

Not sure if I should learn c or stay with python and learn oop there. What editors packages and stuff is good for (plain) c?

@Partition36: Is lisp your favorite language? I guess c seems less risky to try for me for the time being.

Aliotroph? said:

(hello, BASIC!)

On a side note to this entire conversation, my first language was QBASIC and it had the TYPE keyword that allowed user-defined records.

But I think that's something gggmork is getting confused with. A record in terms of computer science is a separate-but-related concept to object oriented programming. A procedural language can have records but not be object oriented (C, QBASIC). A record is a core part of the object oriented paradigm though. The important part is that relevant data is collected together in one convenient structure.

EDIT:

gggmork said:

Not sure if I should learn c or stay with python and learn oop there. What editors packages and stuff is good for (plain) c?

I'd personally say avoid plain C if you want to learn OOP, download MonoDevelop and learn C#. It's a much safer environment for an absolute beginner to learn OO in, mostly because it avoids memory management almost entirely.

Well, C doesn't have anything close to OOP in terms of features except structs. Structs are handy and many languages have them in some form, but OOP involves far more. For example, here's your frog in C#:

```class Frog
{
private int    size;
private float  xPos;
private float  yPos;
private byte[] rgb;

//we call this method when making a new frog,
//so let's give it defaults
public Frog()
{
this.size = 5;
this.xPos = 0.0;
this.yPos = 0.0;
this.rgb = new byte[3]{0,255,0};
}

//setting and getting the fields above is done
//with special functions (only doing size here)
int Size
{
get { return this.name; }
set { this.name = value; }
}

//and the best part is all the functions that
//do stuff to with the frog go in the object!
public void move(float xTarget, float yTarget)
{
//code to move frog here
}
}

//using the frog
Frog myFrog = new Frog();
myFrog.size = 12;
myFrog.move(5.62, 100,8234);
```
So now all your frogs not only know what properties they have, but have all the functions you need to make them move, eat or whatever.

And then you can have more powerful things. Say the things we described above are properties of all frogs, but you have LaserFrogs that have lasers on their heads. You can make a LaserFrog class and have it inherit all the properties of Frog. Then you can add new functions to it (shooting things?) and you only have to write any of the old things again if you need them to be different. Perhaps moving is slower because of the heavy laser, so you write the move() function again, but make it slower, thus overriding the one inherited from Frog.

I'd say stick with Python if you want to learn OOP without learning too many new things at once. I've never used it myself, but I do keep hearing good things.

Looking at your arrays, I'd say matlab is right up your alley.

Seriously though, OOP is a really simple concept and you should forget about C (over-complicates things and is an old language that no one but /unix nerds use) and Python (good for that first step but after that it's time to move on to real stuff. Who ever thought that dynamic types are a good idea?). If you're Greek you can go for Java, but I'd say grab a .Net SDK and #Develop and move on to C#. Ignore the suggestion to use MonoDevelop, it's an inferior ide made for Mono which is an inferior Lunix port of .Net.

Jodwin said:

Ignore the suggestion to use MonoDevelop, it's an inferior ide made for Mono which is an inferior Lunix port of .Net.

Except I'm coding in it professionally. One build runs on the several platforms that are in use around the office. And it's fairly feature complete against the .NET specification (it does treat WPF as a separate feature, but I'm not recommending a tool to learn WPF here).

The IDE itself isn't as smooth as Visual Studio, true, but it's much smoother than Xcode and Codewarrior (the other IDEs I've had a substantial amount of experience in).

There's really no valid reason to ignore Mono.

So I wasn't the only one who got a Matlab vibe from those crazy, nested arrays! Hehe, I like Matlab when I need to do stuff that plays with numbers. :D

What's with the Greek + Java bit? I don't get it.

C# is a pretty fun language to use. For the boring, web-app stuff I've been doing this year it seems to involve a lot less bullshit than using Java (doing it in Java we were bolting several different frameworks from different people together...). I'm not so sure I'd want to be doing that on a platform other than Windows, but I can't speak to Mono. Haven't used it.

GooberMan said:

Except I'm coding in it professionally.

And I made my bachelor's thesis about .NET vs. Mono vs. other .NET ports. ;)

Bottom line, Mono is fairly identical to .NET, but not perfectly so, and the differences are barely if at all documented. If you're going to be developing for Windows alone then using Mono is just stupid as there's less documentation and resources available, Mono has certain changes in it to support Lunix systems and portability which cause unexpected issues on Windows-only development and so forth. The only cases where you might consider Mono over .NET are if you're doing portable software or some scientific calculations (Mono is the fastest .NET-like in certain number-crunching benchmarks).

Oh, and then there's XNA, the "game development library" for .NET that comes with easy-to-use graphics, sound and certain logic libraries. Good luck using that with Mono.

The IDE I suggested wasn't Visual Studio: http://www.icsharpcode.net/opensource/sd/ . Although Visual Studio 2010 is nice too, #Develop is nearly as feature-laden (as far as .NET is concerned) and also free. If you want to be coding .NET without paying a dime (and without being paid a dime), #Develop is what I'd suggest (but if you're going pro with .NET then you'll need Visual Studio just because, well, you need it).

@Aliotroph: Greek+Java was a reference to Maes.

Jodwin said:

then there's XNA, the "game development library" for .NET that comes with easy-to-use graphics, sound and certain logic libraries. Good luck using that with Mono.

I don't recommend using that to anyone. Managed environments are not suitable for game development.

Writing a feature-parity Mono implementation of XNA is 100% possible though. Someone's actually trying, but they appear to not have much knowledge of DirectX for either Windows or the Xbox (of which I have years of experience). My OpenGL renderer matches my Direct3D renderer. But contributing to open source projects like that would breach just about every NDA I've ever signed.

(As a minor aside, I'm not running Mono on my Windows boxes, my Mono apps are running through the .NET runtime.)

Jodwin said:

@Aliotroph: Greek+Java was a reference to Maes.

I did catch the association, but I thought you were trying to make a broader point. Oh well.

Hmm, an open-source IDE for .NET. Might have to try that out. Maybe it will even run better on my creaky old Macbook than VS2008 does.

GooberMan said:

Managed environments are not suitable for game development.

So I guess that's why there are so many games written in Java. And I'm not referring to MIDP.

As for bolting different frameworks together...I'm using both Java and C# and it really depends on what you're trying to accomplish. Usually Java is used for boring "web programming" where it makes sense NOT reinventing the wheel (unless you like to write your own database connector, connection manager, report generators, business logic etc.), but if you had to do the same in C#, you would be equally looking for third party frameworks in no time. Also, most Java jobs require you to be proficient in using a particular framework to even be considered (the usual "culprits" are Spring, Hibernate, etc. and usually some flavor of a particular DBMS) because that's pretty much how the whole "web business" is run. And even if they used .NET you'd be required to use similar or even the same frameworks anyway.

AFAIK C# doesn't come particularly more well equipped for these tasks than Java (actually, it actually lags behind the Java base libraries in features, e.g. the Concurrency namespace wasn't as powerful as Java 1.5's until .NET framework 4). The only exception are some features like LinQ (again, if it makes sense to use it in your app) and lambda/functional programming extensions added in 4.0.

If, for whatever reason you're NOT doing "enterprise" and "web" programming, then Java and C# are really as good as any other general purpose language. E.g. in Mocha Doom I had to write my own stuff several times, and my MSc thesis is a numerical/DIP app written in C#, where I had to define tons and tons of custom classes and structs that could represent the required geometrical entities, objects, spectra, transforms etc. I also develop a lot of number crunching apps in Java for my day job, and for practically all of them I have to rewrite my own stuff, very rarely can I reuse anything.

Anyway, to the OP: dunno what language you're using (the examples reminded me of Matlab) but it SHOULD support some form of data structures. If it doesn't, ditch it.

And they're all horribly inefficient. Rage won't be ported to Java anytime remotely soon. But that's the story of the internet - just because something's not suited to it doesn't mean it isn't going to be done.

Please don't make me pull ye olde "Java beats C/C++ benchmarks" out again ;-)

I was really thinking about stuff like Minecraft and online games, but there are even flight simulators using OpenGL written in Java.

The only thing really preventing using managed environments NOW for commercial quality games like Rage is that you'd end up using a lot of glue C/C++ libraries anyway to access Direct3D, Cuda, GPGPU, OpenAL etc. (BTW, OpenGL is much more friendly to these languages, but other than id it's really a minority in the commercial market).

Even if using C#/Java would help speed up writing the logic code (and write more crash-proof code), few programmers would risk using a framework that doesn't work directly with the industry-standard tools, and the whole thing would feel like a needless abstraction layer.

Maes said:

Please don't make me pull ye olde "Java beats C/C++ benchmarks" out again ;-)

Please, pull out your specific cases. And then try commercial game development. And when you pull out your hair trying to find out where your frame spike is coming from only to realise it's a garbage collector firing when you don't want it to, come back to me.

(Granted, if Sony or MS were to put Java on their consoles, the call to gc() would probably execute immediately, but since the language spec doesn't guarantee immediate execution then that's all just pointless conjecture).

Java was designed to be hardware agnostic and managed, and as such isn't designed to go byte fiddling. There's substantially more to game development than how efficient the compiler is at translating x = x + 1 to machine language. The fact that managed languages like Java and C# hide away memory management is the sole reason it's not suited to game development. You know why you'd need a binding to OpenGL to do megatexturing like in Quake Wars and Rage? Because your alternative is an array. Even arraycopy (ie a hack added in to the language well down the track to try to get some speed out of it) wouldn't handle graphics hardware calls correctly.

But memcpy is child's play. The lack of pointers kill many of the memory and speed optimisations that C/C++ code can make. The data in commercial games these days is heavily optimised on disk. It's not a case of load and convert these days like everyone on the internet does it. The data that gets shipped with a game will more often than not (especially if it's a game with large voumes of data) be preprocessed so it can be loaded in to memory in the background and be ready to go with only minimal post-load processing occuring to unpack pointers. You don't have to worry about allocating objects and having everything safe in your managed environment. It's there because you know it's there.

And then there's assembly optimisations. They're still in use all over the place. Especially with all these new chips going about that don't have mature compilers. Last time I checked, GCC still can't target the NEON on the iPhone correctly. The PS3 and Xbox won't use their SIMD libraries unless you use compiler intrinsics (ie per-platform C++ calls) or write the assembly yourself. Write an efficient matrix multiply function in Java. I can write one that's faster than it every time. The lack of a fast vector and matrix math library kills it and you'll end up using JNI to write C code so you can get some speed.

You can continue writing your Doom port in Java, and I won't complain. But don't think for a second it's suited to modern high-budget game development. Much like XNA, it can get away with it for indie games where the expectations aren't so high.

Funny how you mentioned raw number crunching examples, because that's exactly where Java (at least) was able to beat straight C and C++ in those infamous benchmarks (google for them, I'm lazy), apparently because their JIT compilation was able to beat the statically compiled programs in those settings. It made the vaginas of some C/C++ fanboys sting, sure, but it's out there.

Throwing in memory management OTOH is another can of worms, but even then you can code in Java in such a way to trigger the GC as little as possible, as you should do in C++ and C anyway (reuse vs continuous allocation/deallocation).

It's sad that most Java and C# programming guides just teach to rely on the GC and never use e.g. reusable arrays or objects for certain tasks. Only on Android and MIDP programming guides you find a semblance of sanity in that respect. As for my DOom port, it impressed a seasoned colleague of mine seeing how much little pressure it put on the GC: no kidding, since I simply replicated what the C code did.

Good solid code will still remain good solid code in whatever language you write it it. Shitty code will just be made worse if you run it in an environment where its weaknesses are highlighted.

Maes said:

Throwing in memory management OTOH is another can of worms, but even then you can code in Java in such a way to trigger the GC as little as possible, as you should do in C++ and C anyway (reuse vs continuous allocation/deallocation).

They're called memory pools, and they're used often. Especially in such limited environments like a 386 or the last generation of consoles. We used strict rules with memory allocation and deallocation, namely you're only allowed to alloc on load and dealloc on unload. But that's one function of the garbage collector that isn't obvious - defragmentation of memory.

C++ has this wonderful concept known as placement new. It's an override of the new operator where you provide it with a preallocated chunk of memory. malloc a chunk of memory, placement new over that where you need your classes, and for deinitialisation you usually need to call the destructor explicitly which is a small price to pay for complete memory management. All the power of allocating the objects you need, but none of the memory fragmentation by allocating and deallocating whenever and wherever you want.

This is a concept that's missing from Java. Reusing byte arrays for data is all well and good. Allocating an object in to a byte array? I've not encountered anything comparable to placement new. As such, you either need to put a bunch of objects in to a reusable pool (and thus guess how many of those objects you'll ever use at once) or hope the garbage collector doesn't defragment memory in between the last unload and the next load.

The closest would be allocating an object of the proper type and reusing that when appropriate, never letting it go to the gc. Sure, it's not flexible, and you can't do pointer trickery with it. My point is that you can do good Java code as well as very bad C/C++ code if you put your mind at it (or if you don't).

In any case, the behavior of the GC is preselectable, and should really be fine tuned to your app. If you are doing web stuff, then you probably have lots of idle periods. When doing heavy time-critical stuff, you can do "lazy" defragmenting.

Now if you have something that's both heavy, memory intensive AND generates a lot of garbage and fragmentation along the way, the problem would lie mostly in the algorithmic part, not so much in the language iself. Such an application would be troublesome even if you code it in assembler.

gggmork said:

Like if I want to move all 3 frogs 5 to the right:
numberOfFrogs = 3
frogs = [ [8,[0,255,0],[50,45]], [4,[255,0,0],[25,45]], [6,[0,0,255],[50,75]] ]
for i in range(numberOfFrogs):
frogs[i][2][0] += 5
Maybe OOP is better but that seems at least remotely helpful (but I probably like the non nested better).

All I'll say is this: Good luck trying to understand what the hell is going on when you take a break and come back 3 months later to look at the code.

At least try using named constants/parameters for remembering what each dimension does, if you really HAVE to use arrays. E.g. instead of using expressions such as frogs[0][1][2] by numbers, create some constants like

ATTRIBUTE_COLOR=1, ATTRIBUTE_SPEED=2 etc.

and R=1, G=2, B-3, X=1, Y=2

so at least you can use expressions like

frog[i][ATTRIBUTE_COLOR][R]=...
frog[i][ATTRIBUTE_SPEED][Y]=...

Not perfect, but a helluva lot better than remembering numbers. Still, I'd recommend you move to structured objects or the closest equivalent you can find in your language.

gggmork said:

@Partition36: Is lisp your favorite language?

Pretty much. You could probably consider me a Lisp cultist.

For now I used python lists (arrays) to make a working version of the animation program I wanted, because I don't know OOP yet, and to show arrays can be "remotely helpful" in an aggravating way that quickly gets hard to manage (let me know if you want to see the code. You need python and pygame to run it).
Some of the arrays were 5 nests deep, heh heh:
frames[f][y][x][GRIDOFFSET][1] += 1
(Maes's idea to use a constant GRIDOFFSET instead of 0 or something was useful).
That's how I've always programmed so far (not like I've taken official classes or anything) so if OOP is a missing puzzle piece that would allow me to make better/more complex/maintainable/alterable/etc programs, then maybe ya'll can help me figure out how to organize this program into a 'classes'/oop type framework instead.

Here's an example gif of an animation it can produce:
http://img573.imageshack.us/i/doomanimgif.gif

Here's a pic of the running program with explanation written in gimp:
http://img703.imageshack.us/i/doomanimationexplanatio.jpg/

Though I want the # of frames and such to be easily alterable, there's currently 16 frames. Each frame has a 4x4 grid of squares. Each square has 3 variables. So essentially:
16 frames x 16 squares = 256 total squares (x 3 since there's 3 different variables per square = 768 total variables since you can select/change any variable of any square of any frame).

So should I make classes really hierarchical or something? Like a Square class than contains the 3 variables. Then a Frame class that contains 16 Square instances. Then an Animation class that contains 16 Frame instances. Or something else?

gggmork said:

So should I make classes really hierarchical or something? Like a Square class than contains the 3 variables. Then a Frame class that contains 16 Square instances. Then an Animation class that contains 16 Frame instances. Or something else?

What you said right now, pretty much. The ability to decide on-the-fly what works best and will work in the future as well comes only with experience though.