Jason Chi

xiangqi-app 4-4-2023

Picture of xiangqi-app

Description:

This is a xiangqi web app I build for xiangqi.com using HTML, CSS and Vanilla JS. I have added move validation, move record and game over check to this app.

Insights gained from the Xiangqi-app:

Creating the board

At the beginning, I did not have any ideas of how to build this app , so I went to different Xiangqi website to take a heap on how they structure their board. I observed that most of them are using HTML canvas, but that was not what I was looking for, as I wanted to build a chessboard using the DOM. I looked through the web, and I found that most people use a grid system of divs for the squares of the chessboard. At first I abandoned this idea, as the pieces of Xiangqi are placed on dots instead of squares. Nevertheless, I suddenly had an idea:"The players would not know or care how I structure the chess board of the website, it only matters to them that the pieces are on the dots. I can find a Xiangqi board background and scale the divs carefully such that the pieces are placed on the dots!" That was how I overcame the first setback of this project.

Interaction with the board and pieces

After creating the board, the next problem that I encountered was how to implement the movement of the pieces by clicking the board. My original thought was to add the 'click' event listener on the pieces and the board, every time the user clicks on the board, when the player clicked on the chess piece, the next click would be the destination. The problem with this approach was that only the first move would work. The event listener would stay with the first chess piece, and when player tries to make the second move, the piece that was clicked on the last round would also move towards the destination, the two event listeners also made the logic really messy and that was definitely not a desired outcome for me. And what if the player is clicking on the empty dot of the board? What if the player clicks on his own piece, then he chooses to move another piece instead? Or even clicking the opponent's pieces? The implementation was overwhelming at first, so I decided to break down the problem into smaller chunks.

The major issue of this problem is how to move the latest clicked piece but not the previous piece, so I decided to add this into the logic: Every time the player clicked on the board, if the player is clicking on a piece, I would store the details of that piece into a currentPiece variable, and then the next click would store the information of the destination to the destination variable. I can then manipulate the DOM, empty the destination and the starting point, and add the currentPiece back to the destination to simulate the movement of the piece. And that works perfectly fine. Based on this approach, I was able to add more logic to cover all the edge cases when the user is interacting with the board.

The move validation of the pieces

I later added the move logic of the pieces and showing their available paths on board. The hardest part to implement in this part is the move validation when the general is being attacked, there are plenty types of valid moves, for instance, some spots may be available for the general to escape, some others pieces may move to protect the king, and so on. After researching online for a couple of days, I decided to implement validation on every move:

  1. Write a function that can check the safety of the general(i.e. whether it is being attacked)
  2. If the general is safe, then do the normal validation check.
  3. If the general is under attack,
    • when the user click on one of his pieces , render all the possible moves of the selected piece
      • For every possible move, create a board position as if the move is made, and check the safety of the king in the new position again.
        • If the king is safe in the new position, it means that this possible move can save the king from danger, and hence would be valid.

demo of the xiangqi-app

Room for improvement

I stopped working on this project after adding FEN reader, FEN generator and the move record. I was really proud of this project as I thought it was challenging to a newbie in JavaScript. Nevertheless, there is always room for improvement. Firstly, most of the functions in this project are impure as they manipulate the DOM extensively. I come across the idea of functional programming recently, and I think writing pure functions does greatly help with code maintenance. Secondly, the JS file is now around 1000 lines long. At the time I was coding for this project, I thought it looked awesome when the file has 1000 lines, but the reality is quite the opposite to what I thought, a smaller file would help with the performance of the app as well as the maintenance. I would put some of the functions into a different file, for example the logic of the game/pieces, then import them at the script.js file. On the other hand, adding the chess game navigation, undo function, and drag-and-drop would also be intriguing for me. I would do this if I have time in the future.