As an example, here's how my current roguelike project is structured (in Java). It is using a 2D graphics engine so a lot of the rendering code was already taken care of for me. Criticism is welcomed.
This class sets up the state machine that manages the current state of the game. (in a menu vs. starting a new game vs. playing a saved game)
Each State class contains two loops: a loop for updating the logic and a loop for rendering. They also contain code for calling the
Game class and requesting a change to a different state.
A singleton that is initialized by the
Game class that loads all the needed resources and allows access to them. I don't like this design because it makes it hard to load/unload resources on different levels, for example. I would probably design this differently if I were starting over.
A map contains an array of tiles and a list of all the creatures and items on the map. It's a pretty basic class.
Creatures contain information about themselves including movement calculations (requiring them to know which Map they're in, and and to be able to query it to find out about obstacles). Deciding whether to do this, or have some kind of manager class take care of it for all the creatures is something I struggle with.
Creatures can have a list of AITasks, which are executed every time the creature's logic loop is run. The AITask has its own logic loop that issues commands to the creature, and a termination condition that determines if the task was completed successfully or not.
I implemented my own UI for this engine. Each UIElement has a rendering loop and a logic loop. They also have a loop for processing keyboard/mouse input. All elements can have a number of child elements, which are rendered after their parents, and take over the keyboard/mouse input. This lets you have menus with submenus, for example.