To answer your first question, the snake is moving with the camera, not the blocks. The head is the only element that’s physics driven. You can store the path the head is taking and just map the rest of the body along that path, trimming at the position of the last active ball.
As for level design, it’s procedural. You can determine what’s legal and then add rows dynamically. For instance, you’ll never see 2 rows of blocks back to back.
My personal implementation went like this. I had a base class : Pattern. Then I had concrete implementations, say “FullRowOfBlocks”, “RowOfShortSplitters”, “RowOfLongSplitters”, etc. My CourseGenerator class held a Dictionary<Pattern, List> that determined what transitions were legal. Then I’d just spawn the rows, one at a time, based on how far the player had advanced.
There are also other minor rules to improve the experience of the user. Say in snake vs blocks, you have full rows of blocks sometimes. Those rows will always have at least 1 block the player can get through in order to avoid a scenario where the user just doesn’t have enough balls and the only possible outcome is losing. If the player had only 1 ball remaining, there’s going to be an open slot.