While I absolutely recommend watching Clone trooper’s talk about procedural generation, I would also like to add a few things.
On an abstract level, you can thing of perlin noise as a random number generator that outputs a value between -.5 and .5, and will always return the same value if it’s given the same input. The useful thing about perlin noise is that “nearby” inputs produce similar outputs, hence allowing it to simulate hills and etc. You don’t need to have an understanding of exactly how it’s calculated and how it works to use this algorithm.
It’s not only for procedural generation though.
I am using noise in a project of mine to augment animations with a bit of randomness, but I don’t want the animation jumping between offset values, as would happen with “normal” random numbers. This could also be achieved with other functions, but noise suits my use case perfectly.
I am also using it to slightly offset the colour of blocks around a minecraft-style map, giving a nice texture to everything and making the map a lot more interesting. I can simply use the block coordinates as the inputs (scaled down/with a reduced frequency), and it has many desirable properties. Nearby blocks have similar colours, and I don’t need to sync between clients because they are all using the same inputs anyway. Traditional random numbers would be a huge headache, requiring syncing (if I want everything the same on each client) and causing a much more (ironically) noisy and messy result.