Read high quality code across all domains. It's the style and motivations behind the code design that is important.

Work on the project over a long period of time (like years). As your skill at coding improves, you will see the old problems in a new light. This makes your learning tangible. You remember how you used to think and notice how you think with your new information and your new understanding.

Rewrite the project from scratch every 6 months or year. It sounds like a lot of work but it is very fast and very rewarding because you can see how much progress you have made.

Get some great books and work through one every 3 months or so. My favorites are Clean Code and Pro C#. You can find awesome books by looking at Amazon reviews, Programmers SE or Stack Overflow.

Learning is a skill, and a critical one for programmers. Get good at it and find ways of learning that work for you.

For more practice (if you get bored of your project), got to Project Euler and solve problems.

Having your own project gives you the drive to learn and keep at it when things get rough. In fact, it gives you as much or more drive to learn than taking a class because (by definition) the goal interests you.

This drive will push you to do all the things ManuPK put in his answer and you'll like it because it'll allow you to get closer to finishing your project.

Most important requirement for learning is to have a concrete project to work on. One year back I was too confused about how to improve and try to code a great code in my first major project.

What I learned after researching a lot is code and just code with an aim in mind.

Another thing is try to follow coding conventions which exists in your choice of language. For example, in python world pep8 conventions are followed and I did the same. Don't ever think that let me code first and then I will worry about conventions. Conventions are there for your benefits, use them.

Learning to code is easy but learning to write proper and maintainable code is a must.

After some time (if you are in learning stage not on sharp deadlines) go back and read your old code again and there is lot of chance you will cringe at it or may want to improve it.

No code is perfect. Always try to refactor after writing a working code.

Always unit test your code because unit test brings out your mistakes very soon not when you have written so much code that it pains you to find out that small mistake.

Try to change only one variable at a time (ie: A new framework, a new ORM, a new work methodology).

As such you are proficient in one programming language, do as you would normaly do, but add a new element to it, like a framework. Next time, use the same framework, but add an other variable (like an ORM) and keep repeating.

Make sure to choose project that are not too wide, but not too small to make sure you can cover most use cases of your new element.

Treat every project as if it's a "pilot", this way you won't stay in your comfort zone and you will keep learning an improving.