Subnetting is difficult because it is taught mathematically by most instructors. I prefer to teach with pattern matching which makes more sense to people. Binary has distinct doubling patterns. For example, with one bit I have two combinations. Each bit added doubles the combinations I can work with. In the context of subnetting, all I'm doing is deciding how many bits I will use to identify either my host blocks or the number of networks I need. You can count these out on your fingers very quickly. (BTW fingers are allowd on the exam while calculators are not.)
The secret to the addressing is to create a subnet mask that identifies to the network devices the block sizes you need given some starting point which is usually the classful address.
We are all used to cutting up big things and making them smaller or aggregating small things to make something larger. That is all we are doing with network addressing. The classic patterns we see with cutting up a pizza are the exact patterns we see with network addressing. For instance, given a whole pizza (I use a round one), how can I cut it up to serve a certain number of people if I want everyone to have the same size piece and I need everyone to have at least one piece so I may have some leftovers? Let's say I have 6 people. I cut the pizza in half (2 equal size pieces), then half again (4 pieces), then half again (8 pieces) what have I done? I still have the original pizza, but it is "subnetted" to fit my needs. I can keep cutting the pizze up, but all the pieces must be the same size and I may get to a point that the pieces are so small that my guests don't get enough to eat.
With network addressing we use the subnet mask to cut up the address space. Each bit that is turned on (1) in the mask tells the network boxes that bit identifies part of the network. Each bit that is off (0) in the mask identifies hosts. Network boxes (routers) need to move traffic from one network to another so the subnet mask gives the information necessary for that decision.
So how do I chop up my address space? Some of it is already done with Class A, Class B, and Class C. For example, a Class C mask is written 255.255.255.0 which in binary looks like 11111111.11111111.11111111.00000000. Network devices read this as "use the first 24 bits in the address you've received to identify the network you're looking for". We can push the bit boundary right or left just by modifying the mask. Every bit moved to the right doubles the number of networks but they are only have the original size (think pizza slices). Every bit moved to the left halves the number of networks but makes them bigger (super pizzas).
This is just how I approach subnetting with people. It usually takes about 2 hours of class time, but I have found people who've thrashed with subnetting for years finally have the light turn on with patterns. Subnetting is just taking big address space and making is smaller (my kids do this with nesting blocks all the time!) or taking small address space and combining it into bigger space (summarizing).
HTH