I know for me, personally, when I'm learning a new language, what helps me most is to have a means of collecting simple user input through a console. (Text or numbers, that's all) What this allows me to do is make simple "games" that don't focus a lot on graphics/presentation/game design, but rather execution. It allows me to focus on figuring out how I can use the least code possible, how I can organize data in the best ways, how to disassemble the user's input into something that my program can read/respond to, etc, etc.
I recently learned Java, and mid way through learning I challenged myself to make an infinite math game. This was a game that would procedurally generate very simple math problems, solve them, present them to the player, and then compare the player's input to the solved problem. If they matched, I add to the player's score and allow them to move on, if they don't match, I end the game and present the player with their score. (And also reveal the correct answer)
Then, once I was more advanced in Java, I challenged myself to make an infinite word game. Which was more challenging, but in all different ways. It kept it very interesting. The math game was hard to make because I had to think up a way to put together numbers + operators into a string, while also keeping them as something that Java could evaluate into an answer, however the word game was hard because I had to find a way to store many many words and pick from them randomly. Additionally, I challenged myself to allow the player to use "hints" to reveal a single letter of the word, and every time they used one it would reveal the next letter, in order. I also added categories and organized the words that way to add additional challenge for myself.
I'm not sure these games exactly would be a good fit for you or your students (and I don't expect that they will be) but hopefully something along these lines could be very fun for them and challenge them in all the right ways. Hope this helps.