Making UNO is hard

On Pranab’s site

DRAFT (needs work or removal)

Show/Hide contents
  1. The journey
    1. The tough bit
    2. Giving up
    3. An undo system
  2. The game
  3. Conclusion
  4. Try the official UNO 2 GO by Mattel
  5. Additional implementation notes
  6. TODO

You should try making it yourself. I chose it as a “simple” project to have something other than endless tutorials, but it actually took me several months (probably because I’m a total beginner).

The journey🔗

I started out with generating the deck, then dealing cards to a player, making styles for layouts and cards, and finally coming around to modeling the game proper.

At this stage I started out trying to hook it up with my deck generation and dealing logic, before I had to stop and starting taking notes.

The tough bit🔗

I needed to know what information the game would need for validation, the exact rules we play by, and solutions to all the edge cases that might occur, for which I even asked some family members.

For example, think of a turn where you challenge the previous player, who played a draw 4, and you succeed, then you pick a card (to match the colour they chose?), and then you play the card you picked, because it’s a valid card to play.

Or consider how you’ll allow anyone to catch the last player to finish their turn if they forgot to say UNO (assuming you play by those rules).

Giving up🔗

I made several small prototypes, with variables like drawSum, isActive, direction, currentPlayer, currentPlayerIdx, discardPile, initialPlayers, prevCard, and more.

On top of that, I had to figure out project architecture, because this is my biggest project by a significant margin, so I gave up at that point, focussing on other things and trying to process it in the back of my mind.

An undo system🔗

I finally started again after two or three months, when I figured that I could remove all validation. Even after the idea entered my occassional pondering, it took me some time before I could accept it.

I think, if I were to do it again, I’d store all the validation state in variables, and the cards would be a separate system that interact with validation state at one or two places like placement and starting turn. Maybe I’d also go for a server-client structure.

The game🔗

I eventually landed on a peer-to-peer system, with a server hosting the pages and passing messages:

juan-cards started game

Players need to see what’s on the discard pile, a general sequence of players 1, along with the number of cards in their hand, a history to track what cards were played, and their hand, of course. Because there’s no validation, there’s also an ‘Undo’ button.

1

though the screenshot only shows 1 :p

juan-cards lobby

The login page is actually stupidly simple — it redirects you to /u/{user-name}, and the game logic reads the user-name from the URL. They basically have no relation to each other. You could skip past the login page to join.

juan-cards unstarted game

Until the game is started, there’s a ‘Start’ button, which disappears when you press it.

Conclusion🔗

Overall, I’m quite happy that I finished this project, even if I don’t have any validation.

The undo system actually works quite well, because people don’t actually think of cheating, and I’m playing with people who I’ve played with in-person, using physical cards, which has basically the same mechanics.

As for the peer-to-peer architecture, I chose it because I found it easier to conceptualise a single type of entity talking to more of its type, instead of trying to figure out the server/client divide.

Try the official UNO 2 GO by Mattel🔗

By the way, you should install UNO 2 GO on your respective (mobile) app store.

When you first start the game, make sure to keep sounds on and don’t skip anything.

Additional implementation notes🔗

TODO🔗

There’s a few things that could be used to improve the game right now, and a few ideas I’m considering for after I’ve progressed further in the tutorial 1.

1

javascript.info, btw. It’s free, concise, comprehensive, and includes good exercises.