Object oriented programming, static / singleton managers and factories. They are fairly advanced topics and can lead to a very complex learning process but they will lead you to the best and most expandable way of coding. I would highly recommend looking into the XNA Framework for some easy examples, maybe work through some of the Flat Red Ball engine tutorials to see some more of this style of code in action.
The basic idea is that you would write classes that represent logical "objects" and systems of your game / engine. Lets take a sprite for example (since you will undoubtedly be needing them in your game) The following is not real code but used to give a bit of an example.
class Sprite()
{
var image;
var position;
var collisionRect;
...
}
We see the same basic idea's you've probably seen before. A sprite is an object that represents a character or an interactive map object. It contains variables and methods that pertain to that particular sprite. You can extend, or derive from this Sprite class to make more advanced Sprite objects later on and when all is said and done you might have many different Sprite objects that handle different kinds of in game entities (characters, switches, traps, vehicles).
Now the next thing you would want to think of is a "Manager" object that could help you handle all of the sprites you will be using. This manager object would be a static or a singleton object, that is to say that by some means there is only one instance of this object in memory. This class IS the SpriteManager.
class SpriteManager
{
vector mSpriteList;
public Sprite loadSprite("name")
{
// Loads a sprite image, creates a "Sprite" class in the sprite list and returns
// a reference to that sprite.
}
public Sprite getSprite("name") { } // Returns the reference to a sprite in the list by it's name
....
}
There we go, you start to see why this would be helpful. Basically you want to keep all of your Sprites inside the master SpriteList. Your SpriteManager gives you a means of loading and unloading sprites to that list. The SpriteManager gives you functions you can use to get a reference to one of those sprites whenever you need it. This will help minimize memory overhead and waste later on.
Besides that, also start getting familiar with callbacks and event programming as well. This will help to easily arrange your code into the correct objects but still trigger it during certain dynamic conditions. This is a bit harder to explain in simple terms but still convey the importance. Lets say for example our Sprite object has a wakeUp() function. This function defines what a particular sprite does when the character "wakes up" in the morning. You may be monitoring 1,000 Sprites in a certain map, and instead of writing a loop that at 9am every morning it calls all of the characters wakeUp and each character decides if they want to participate in the wake up you'd rather tell your TimeManager who to wake up at 9am. So when you are constructing your characters (reading them from a file or whatever) you would also add the characters to the wake up list as they are created. To do this you could add a callback handler to the TimeManager's wakeUpList. When the TimeManager hits 9am it loops through the 30 names in it's wakeUpList and calls those sprites wakeUp() functions.
Granted that's a bit of a poor example as there are much better ways of doing something like that but hopefully it gives you an idea of why callbacks are handy. It allows you to manage a list of functions to call under a certain condition instead of coding the functions to check if they should run. This will start leading to more intuitive AI coding when the time comes.