You need to focus on data structures and how to work with them. Much of programming is having a toolkit of "solutions" (aka "patterns) to very simple problems, and being able to recognize when you can re-use one of those solutions to make whatever you need. And be able to refactor existing code in small steps. "knowing everything at the start" isn't how programming works. You break problems down into easier to understand components, and build up from the simplest system, in a consistent way.
e.g. the "Marines" example is a good test case. Say you want 10 marines, each marine is going to have stats and weapons. Start by just having an array of 10 ints, with each int holding "weapon type", with hard-coded weapons in code (e.g. "if (weaponType[ i ] == 2) cout << "power sword" etc). Try and make this, with just 2-3 weapon types.
So what's the logical next step here? Do only one thing. There are two choices. You could either improve the "marines" system, or you could improve the "weapons" system.
The weapon system obviously sucks since you have to edit the if statements whenever the weapon name gets printed out. So you can make an array of strings, which holds the weapon names. Hard-code this array, but use the marine's int to look up the value.
After you have the weapon look-up table working you can think of adding more data to the marines (each marine is just an int right now). The way to do this is refactoring. Make a struct which only holds a single int, then replace the int in the array with your struct. Re-wire all the references to the array to access the int.
Now, the above changes don't actually change what the program does, but they are the sort of framework-improving code that's critical to making the program better. Putting the weapon types into a table means it's much quicker to add new weapon types, and turning the marines into a struct allows you to add new variables for each marine more easily.