I will elaborate slightly from other answers advocating the study of game programming and provide some basic insight.
The main task of your program is to loop (until game over, or the player is tired), and at each iteration:
- compute the current state of the game,
- render the view,
- read player input.
You don't have to do this in this order, the game should run fast enough to make it seems everything is happening simultaneously.
The state of the game is actually the state of all the elements that are part of the game:
- background,
- still objects,
- moving objects,
- objects generating other objects,
- objects destroying other objects,
- player,
- etc.
There might be rules governing how all these objects, different rules for different objects, interactions between objects, and more. It's up to you to code up these rules in the engine, and make sure all the objects get updated. The simplest way is to iterate through all your object list and update them one by one.
Rendering is basically going through all your objects and draw them on screen (if they are visible), according to their state (color, position, etc.).
Polling input is just that: verifying if the player did some input by using the keyboard, the mouse, the touchscreen, or anyother input device you wish to handle.
In your project's case, your object list will be just the list of falling characters, the main rule is gravity (or a constant speed going downard the bottom of the screen), and input is the keyboard.
If you wish to have the game running in text mode, the main hurdles will be moving the cursor around, get non blocking input, clear the screen. On UNIX, look for the curses library, which provide all the necessary functions.
Given the simplicity of the game, your program will certainly run very quickly, so you will want to include a small sleep period in the loop. However it is better to have a consistent framerate (at least 30hz), so you could measure the time taken to do the work, and have the process sleep for the remaining time to reach the correct time for one loop.
One last thing: don't look into threads or concurrent programming for this project, it would not help. The rendering has to be done by one single thread in most graphic setups, and you would end up doing a lot of synchronization, unless you use messaging between threads (that would be an interesting exercise, but keep it for version 2).