Quoridor: Coffee time for the mouse
As I cannot use scripts inside the browser, the rendering is done by the backend. And as I am/was a backend developer, I choose Java as it is the language I mostly work with.
The stack is Spring Boot (to develop quickly a stand alone application), Thymeleaf (to render the game via server-side templates) and Gradle (to build quickly the application).
Warning: do not get used to seeing these logos on other marmelab blog posts.
Marmelab does not develop using the Java stack. And I understand why.
Developing using the Java stack works like a charm but when I had to include it in the marmelab stack I get some troubles. The main problem was to include that stack inside a docker for the development. Usually, when developing a java application, you use docker for a publishing purpose. But at marmelab, we use docker for a development purpose as well.
I managed to include java/gradle inside a docker container and to run tasks. But it is overkill in that situation. And I am not the only one who gets troubles.
I did not manage to configure Travis CI to run the tests. I had grant errors with gradle when getting dependencies, even though I use sudo in the configuration file. It works only if you configure travis to run gradle commands.
New Data Structure
I was advised to change my data structure and use a graph to describe the board game:
- nodes for the squares,
- and edges to know if you can access the next square.
No edge means there is a fence between these squares.
With this structure, it is easy to know whether a path still exists from the pawn to its goal line. But it is difficult to detect if it is possible to insert a horizontal fence between two vertical fences or to insert a vertical fence between two horizontal fences. As a fence is two edges long, you do not know if you are at the beginning, in the middle or at the end of the fence.
A possible solution is to start from the beginning of the column or row and count the number of breaking edges to where you want to add the fence. If the count is even you can, odd you cannot.
I added a list of fences to accelerate the fence checking. With that list, I could both count the number of fences faster, and I know who put it up.
New UI, UX
In my first challenge, the keyboard was the best solution to interact with players. But now, in the browser, it is better to avoid it and to use exclusively the mouse. Forms are the only HTML component I can use if I want interactions with the players.
Moving a Pawn
To move a pawn, I added a clickable form on each square that the pawn can access. When the mouse pointer hovers over the form, the color of the square changes to indicate that the pawn can move.
In a two-player game, a pawn can move at the most in 5 directions (5 forms).
Putting up a Fence
At first, I thought to add an aside form, which asks for the northeast square and the direction - but you have to use the keyboard and the mouse. And the player has to think too much for a simple action.
I decided to use the same behaviour that I used for moving the pawn. I added a form on every possibility. Then, when the mouse hovers over the form, the shape of the fence is displayed.
Forms are at each possible square intersection.
The maximum number of forms is 8 lines x 8 columns x 2 (vertically and horizontally) = 128 forms! I never added or seen so many forms on a single page.
UX above all
This challenge was very interesting. Finding good solutions to ease the user experience was the most exciting part of that challenge. I am glad about the result. You can play using two players with moves and fences. The drawback is the user interface. I could not spend enough time on it. But I would like to improve my skills on CSS (maybe during the next challenge?).
You can still have a look at the code in the marmelab/quoridor-java GitHub repository.