Chris Zetter

Multiplayer Crosswords

This post is about Several People are Solving which I made so I could complete crosswords together with others.

Two people filling out a recent crossword.

Doing Crosswords Together

When I was a student, I remember working on the Private Eye crossword with others to use up time we had between lectures. More recently I’ve tried to re-learn cryptic crosswords by completing them with people at work. My partner and I often share crosswords to keep us busy on long train journeys.

I wanted there to be an easy way to complete crosswords together that didn’t need people to pass a phone back and forth or for a copy of the crossword to be made in a shared Google Spreadsheet.

Readying a Grid

I really like the crossword tool on the Guardian’s website. It works well on large and small screens and has tools for checking and revealing clues. Usefully, the Guardian has chosen to open source their code under the Apache license. The Frontend repository serves all the pages on theguardian.com. After some searching, I found the React-based crossword component in their codebase.

But the crossword component was never intended to be used outside of the Guardian- the code was all tied together with the rest of the Frontend project. Running the full Frontend application or test suite isn’t even possible for people outside of the Guardian development team.

I forked the Frontend repository and removed the million-or-so lines of code that weren’t to do with crosswords. With a bit more work to untangle other dependencies and configuration, I was able to run the crossword component independently.

I imported the code into a new repository called react-crossword to make a clean break from Frontend project’s 1.6GB of git history that I no longer needed. I published the package on npm so that it would be easier to re-use from other projects.

Improving the Component

Extracting the component meant that it was now easier to work on. I was able to fix some bugs that I had found when completing crosswords on the Guardian site. One of the bugs prevented you from entering numbers as answers. I saw this was frustrating others by stopping them complete crosswords so took time to contribute my fix back to the Guardian.

When I later added other input sources to the crossword I found that some of the React components needed re-working. An example of this is the shuffle feature of the anagram helper which was being unexpectedly triggered each time the grid was updated in the background. I fixed this by making sure the render function of the anagram component was deterministic. I found ESLint helpful at identifying other code which doesn’t follow React best practices and could cause bugs, for example, referring to this.state within setState.

Sharing Moves using WebSockets

I wanted the crosswords to work a bit like secret chat rooms- each time you started a new crossword you should get sent to a new room. Anyone you shared the URL with would also be able to access that room and complete the crossword with you.

I thought that WebSockets would provide a good way to stream moves as they happen quickly to other players. I created a Rails application called Multicrosser to do this. Multicrosser uses Action Cable to work with WebSockets and record moves on the server in Redis so that the state of the grid could be stored and sent to any new players that joined.

After using Multicrosser for a while I found that any moves I made on my phone when I didn’t have a reliable internet connection were lost. I made an improvement so that moves that can’t be sent to the server are stored locally in a moves buffer. When the client reconnects again the moves in the buffer are rebroadcast to the server.

I didn’t want more recent moves to be overwritten so moves from the buffer are only applied if the cell they changed still had the same character in it as when the move was made. For example, if you change an ‘A’ to a ‘B’ while offline this move will be discarded if someone has since changed the ‘A’ to a ‘C’ and had broadcast it to the server before you.

What’s Next

I’ve ended up with something that feels collaborative since there’s no winner. By recording which player made each move and assigning points you could create something more competitive.

I also had the suggestion of showing something celebratory when a crossword is completed.

I think that crosswords are fun puzzles and would like to see more experiments with how they could work outside of printed media.

You can play multiplayer crosswords yourself. Pick a recent crossword and share the URL with a friend.

Read more by me, follow me on Mastodon or subscribe.