Completely develop the websocket-based online chess game [Gobang] from scratch, and complete all logic with only a few dozen lines of code.

Backgammon is a strategic game with simple and clear rules. The first to form a five-moon connection wins.
This course exercise adopts the way of two people playing chess online, which is especially suitable for playing with a mobile phone on the way to and from get off work.

The whole process is carried out on the ZhongTouch low-code application platform, using expressions to describe the game logic (a highly simplified version of JS).
This course focuses on learning the sending and receiving processing of websocket real-time messages.

Online Chess Demo for Two

 

Play it first: https://gobang.zc-app.cn
Because it is an online game, you need to log in. You can use your mobile phone and email to register separately, and use your computer and mobile phone to play with yourself.
Add after the URL /zto enter the development mode: https://gobang.zc-app.cn/z

For detailed teaching, please go to the Bilibili video: [Crowd Touch Course] Backgammon_哔哩哔哩_bilibili

checkerboard structure

$v.棋盘 = array(14, array(14, ""))

It is rendered with a nested data component using a 14*14 two-dimensional array, that is, the grid with the black line in the figure.

Square structure

$v.方阵 = array(15, array(15, ""))

The nested data component is rendered using a 15 * 15 two-dimensional array, that is, the point where the black lines cross in the figure, and the highlighted circle when the mouse hovers over the component.

player status

undefined, being invited, the opponent is playing chess, and your own side is playing chess.
The default is no value, indicating that the game has not started or is over (the victory and defeat have been scored). When the opponent plays chess, one's own side cannot make a move.

account login

Since you are playing online, you will be required to log in. You can register by phone or email.
Open the connection immediately after logging in, and you will be notified instantly through this connection socket when a player is online, a player is invited, and the other party makes a move.

Open connection socket: onLogin

$socket.open($c.exp, { channels: ["比赛"], onOnline: true, onOffline: true, allowMultiLogin: true })

The first parameter $c.exp is an object that can contain onConnect, onData, onReconnect, onError, the first two are required.

The second parameter is the option option. The channels you need to pay attention to are placed in the channels array. onOnline indicates whether to notify you when someone goes online, onOffline indicates whether to notify you when someone goes offline, and allowMultiLogin indicates whether the same account can be used in multiple logins. Log in from one place without forcing the previously logged-in account to go offline.

After connecting: onConnect

$socket.onlines(["比赛"])
$v.onlines = $r.比赛.filter('$x !== $c.me._id')
$v.onlines.forEach('$user.get($x)')
render()

After connecting, check the online players who follow the "competition" channel, exclude yourself and put them in the $v.onlines list to obtain user information in turn.

message format

There are multiple expressions starting with on below, all of which only receive socket messages. They all have a common format: typethe message type, xthe message body, fromand the message sender. The message torecipient sending time dare not used in this case.

Someone is online: onOnline

$v.onlines.push(x)
$v.onlines = $v.onlines.unique()
$user.get(x)

Put the online people into the above $v.onlines, and remove the duplicates.

Someone disconnected: onOffline

$v.对手 === x ? alert("对方断线了") : ""
$v.onlines.splice($v.onlines.indexOf(x), 1)

Once disconnected, remove him/her from $v.onlines. If it happens to be a chess player who is playing against you, a warning notification will be thrown.

After receiving data: onData

stopIf($c.me._id == from)
$c.exp[type].exc()
render()

First of all, it is necessary to exclude the data sent by yourself, because the socket broadcasts the message, and you can receive it yourself.
Then execute the corresponding expression according to the message type. The possible types are: on invited, on rejected invitation, on invited, on drop.

When other people log in, the question mark circle on the right of [Opponent] will flash, and clicking it will pop up a list of online players, and you can choose one of them to send a game invitation.

Send a game invitation

$socket.send($x, "on被邀", "邀请")
$v.状态 = "邀请中"
info("邀请已发出,请等待对方接受邀请")

Received the message: on was invited

stopIf($v.状态, '$socket.send(from, "on拒邀", "对方正在下棋")')
$user.get(from)
$v.对手 = from
$v.pop = "选棋子"

If you are playing chess, you can directly send an "on refusal" message to reject the invitation.
Obtain the user information of the other party, and a pop-up modal window prompts to accept or reject the invitation.

Received message: onReject invitation

$v.状态 = undefined
warn(x || "对方拒绝你的邀请")

Leave the previous "inviting" status empty, and the rejection message from the other party will pop up

select child

$v.己方 = "白" // "黑"
$c.exp.受邀.exc()

Accept invitation: Invited

$socket.send($v.对手, "on受邀", $v.己方)
$v.方阵 = array(15, array(15, ""))
$v.pop = undefined
$v.对方 = ($v.己方 === "黑" ? "白" : "黑")
$v.状态 = "己方出棋"
info("请出棋")

Send the "on invited" message to the other party, and bring the child of your choice.
Clear the phalanx and prepare to play chess.

Received the message: on was invited

$v.方阵 = array(15, array(15, ""))
$v.对手 = from
$v.对方 = x
$v.己方 = (x === "黑" ? "白" : "黑")
$v.状态 = "对方出棋"
info("对方已接受邀请,请等待对方先出棋")

fromIt is the user ID of the opponent, xand it is the seed selected by the opponent, so you can only choose another seed.

Lazi

stopIf($v.状态 !== "己方出棋" || $v.方阵[$parent.$index][$index] || $v.连续棋子.length > 4)
$v.落子点 = [$parent.$index, $index]
$socket.send($v.对手, "on落子", $v.落子点)
$("." + $v.己方 + "子声音").play()
$v.方阵[$parent.$index][$index] = $v.己方
$v.检查方向.forEach($c.exp.落_是否胜出)
$v.状态 = "对方出棋"

If it is not in the state of playing chess by one's own side, or the position of the chess piece is not in the square matrix, or more than 4 consecutive chess pieces have been formed, the chess piece cannot be placed.
Send the "on drop" message, and carry the coordinate axis of the drop point just now.
Play the sound of falling pieces, and place your own pieces on the falling points of the square matrix, and emit a halo through the dynamic class name.

$v.落子点[0] === $parent.$index && $v.落子点[1] === $index ? "光晕" : ""

Check whether the previous move can win.

Check wins (forms a five-son line)

To judge the outcome, you only need to check the positive and negative directions of the four connecting lines from the point [y, x] when placing a piece, and accumulate more than 4 consecutive pieces of the same color as the sound.

$v.check direction

[
    [
        [-1, 0],
        [1, 0]
    ],
    [
        [0, -1],
        [0, 1]
    ],
    [
        [1, -1],
        [-1, 1]
    ],
    [
        [-1, -1],
        [1, 1]
    ]
]

-1 means check backward, 0 means do not move, 1 means check forward. For example, [-1, 0] is to check in the negative direction on the X-axis, that is, the west direction; [1, -1] means to check in the positive direction of the X-axis first, and then check in the negative direction of the Y-axis, that is, the northeast direction.

Right now 

Is the game won?

$v.连续棋子 = [$v.落子点]
$l.方向 = $x[0]
$l.非连续 = false
$v.循环4次.forEach($c.exp.落_相邻同色)
$l.方向 = $x[1]
$l.非连续 = false
$v.循环4次.forEach($c.exp.落_相邻同色)
stopIf($v.连续棋子.length > 4, 'info(($v.状态 === "己方出棋" ? $v.己方 : $v.对方) + "子赢了"); $v.状态 = undefined;')

First take the current position as the first continuous chess piece, and $v.检查方向move 4 times in the first direction of the provided pair of directions (that is, cycle 4 times) to see if there are adjacent pieces of the same color, and then try 4 times in the other direction Second-rate.
If the tentative result is $v.连续棋子greater than 4, then the current player wins.

Check the same dice adjacent to the dice

$l.y = $v.落子点[0] + $l.方向[0] * $x
$l.x = $v.落子点[1] + $l.方向[1] * $x
!$l.非连续 && $v.方阵[$l.y][$l.x] === ($v.状态 === "己方出棋" ? $v.己方 : $v.对方) ? $v.连续棋子.push([$l.y, $l.x]) : $l.非连续 = true

A test direction includes the X-axis direction and the Y-axis direction. There are three shifting methods -1, 0, and 1. Move the coordinates respectively to check the chess pieces with new coordinates in the square matrix. Chess and this piece happens to be one's own color, then this piece is a part of continuous chess pieces. In other cases, it cannot be counted as consecutive pieces of the same color, for example, there is no piece on the coordinates, or it is the opponent’s piece, or it has been discontinuous before, so there is no need to continue checking this time.

The winning 5 pieces in a row will also emit a halo. The newly-fallen pieces in the front have sent halos through the dynamic class name, and now it is necessary to find out other chess pieces of the continuous chess pieces.

$v.连续棋子.length > 4 && $v.连续棋子.find('$x[0] === $ext.$parent.$index && $x[1] === $ext.$index') ? "光晕" : ""

We search from the continuous chess pieces to see if there is a chess piece whose coordinates are the same as the currently checked coordinates. $x[0] is the X coordinate of continuous pieces, and $x[1] is the Y coordinate. Note that this is the dynamic class name in the nested data component, $index is the subscript of the current data component, and $parent.$index is the subscript of the previous data component. But because they are placed in the find() function, it is necessary to add $ext.the data provided by the context outside their function. If not $ext., it becomes the context data provided by the find() function.

Students who are ready to study in depth, please go to the backgammon online game page, click the [Clone] button on the right, and make a copy of the entire game to play and change at will.

For more teaching videos, please go to the Bilibili space: the personal space of the Zhongtouch application platform_哔哩哔哩_Bilibili , which not only has various front-end visualization case demonstrations and explanations, but also multiple fully functional website application cases Demonstration and explanation of the development process.

Guess you like

Origin blog.csdn.net/weixin_52095264/article/details/125841390