You start a game, and that starts a goroutine that goes round in a loop getting scores from a channel. You have players which also have references to the channel and who put scores onto it.
When all the players have left the only thing that has access to the channel is the game's goroutine. It's not consuming CPU itself because it's simply waiting for something to be put on its channel, but it does still have its stack and other resources, and it now has no way to exit.
You can get this sort of resource leak in lots of ways in concurrent systems, and they all essentially boil down to the same thing, a thread or goroutine, or whatever, is waiting on a resource that nothing else has a reference to anymore, and there is no other way end it.
The "for score := range g.scores {" loop runs forever, since nothing ever closes the g.scores channel. I.e., the "range" only terminates when the channel is explicitly closed. Even if there are no current senders on the channel, and even if nobody else holds a reference to the channel (and thus nobody else could potentially create a new sender and start sending on that channel), Go doesn't realize it (garbage collection doesn't help here). The "range" waits forever.
Thus, all goroutines that run this code (via calls to NewGame(), via "go g.run()") will run forever, and leak, as long as something else in the program is running. When the rest of the program is done, Go will correctly detect that all these leaked goroutines are blocked and thus it's a deadlock, leading Go to panic ("no goroutines can proceed") and terminate.