Adhering to the will share, will not toss over the technical purpose. Their use of the weekend will be a small casual game – backgammon to comb once again, arranged into a small tutorial, share out to give you Pointers.
Backgammon rules
The rules of gobang I simply comb and transform as follows:
- Each side holds a piece of the same color;
- Empty checkerboard opening;
- Black first, white or white first, black, alternating down, each time only a son;
- If there are five consecutive pieces of the same color on horizontal, vertical or diagonal lines, the game ends;
The rules of the official game, you can poke baidu encyclopedia to understand ha – gobang.
The code skeleton
Here the realization of backgammon small game is written using javascript language, using es6 syntax, object-oriented thought.
// Set up five pieces of chess
class Gobang {
constructor(options={}){
this.options = options;
this.init();
}
init() {
const { options } = this; }}// instantiate the object
let gobang = new Gobang({});
Copy the code
The Gobang class above contains a constructor and init method. The constructor method is the default method of the class, which is automatically called when an object instance is generated using the new command. A class must have a constructor method; if it is not explicitly defined, an empty constructor method is added by default. And then there’s the init method, where I’m the entry method for the initialization of the whole class. Using an object-oriented approach to class writing, it is better to manage the extension of code and functionality.
Drawing board
There are two types of board, a visual (physical) board and a logical board, which you can’t see. The following diagram illustrates the physical and logical way a 20 by 20 board works.
Draw physical checkerboard, we use canvas related knowledge points here, control the brush to draw checkerboard:
// Draw the physical board
drawChessBoard() {
const context = this.chessboard.getContext('2d');
const {padding, count, borderColor} = this.options.gobangStyle;
let half_padding = padding/2;
this.chessboard.width = this.chessboard.height = padding * count;
context.strokeStyle = borderColor;
/ / drawing board
for(var i = 0; i < count; i++){
context.moveTo(half_padding+i*padding, half_padding);
context.lineTo(half_padding+i*padding, padding*count-half_padding);
context.stroke(); // The vertical axis is drawn here
context.moveTo(half_padding, half_padding+i*padding);
context.lineTo(count*padding-half_padding, half_padding+i*padding);
context.stroke(); // The horizontal axis is plotted here}}Copy the code
The padding used here, the count, borderColor is handed in at the time of instantiation. This improves configurability and management. The above code is to draw the physical checkerboard, so the logical checkerboard cannot be drawn, but we can represent it. Here we use the method of two-dimensional array to record logical positions, such as (0,0) point corresponding to the array subscript is [0][0]; Then the subscript of (1,2) points is [1][2]… And so on. We then assign the logical point a value of 0 to indicate that the current point has no child.
// Draw a logical matrix board
initChessboardMatrix(){
const {count} = this.options.gobangStyle;
const checkerboard = [];
for(let x = 0; x < count; x++){
checkerboard[x] = [];
for(let y = 0; y < count; y++){
checkerboard[x][y] = 0; }}}Copy the code
Now that you have physical and logical boards, you can consider associating physical boards with logical boards. This one is relatively simple, just calculate the actual cell position and do the division operation. The management of this step is covered in the following substeps.
Draw the pieces
There are two and only two kinds of pieces in backgammon – black or white. Here is also the use of canvas knowledge to draw chess pieces.
// Draw black or white
drawChessman(x , y, isBlack){
const context = this.chessboard.getContext('2d');
let gradient = context.createRadialGradient(x, y, 10, x- 5, y- 5.0);
context.beginPath();
context.arc(x, y, 10.0.2 * Math.PI);
context.closePath();
if(isBlack){
gradient.addColorStop(0.'#0a0a0a');
gradient.addColorStop(1.'# 636766');
}else{
gradient.addColorStop(0.'#d1d1d1');
gradient.addColorStop(1.'#f9f9f9');
}
context.fillStyle = gradient;
context.fill();
}
Copy the code
Fall everyone to fight
The methods for drawing black and white in the previous section were drawn on a separate page. Now we will draw the chess pieces and board integration, and implement the chess mode of everyone versus.
We listen for clicks on the board, then associate the physical board with the logical board points, and then sketch the pieces in their place.
// Listen to the box
listenDownChessman() {
// Listen for clicking on the checkerboard object
this.chessboard.onclick = event= > {
let {padding} = this.options.gobangStyle;
let {
offsetX: x,
offsetY: y,
} = event;
x = Math.abs(Math.round((x-padding/2) /this.lattice.width));
y = Math.abs(Math.round((y-padding/2) /this.lattice.height));
if(this.checkerboard[x][y] ! = =undefined && Object.is(this.checkerboard[x][y],0)) {this.checkerboard[x][y] = this.role;
// call the chessman method here
this.drawChessman(x,y,Object.is(this.role , 1));
// Switch the role of the piece
this.role = Object.is(this.role , 1)?2 : 1; }}}Copy the code
Realize the back
When both sides are playing chess, both sides are allowed to adjust the pieces that have been played, which is called “regret”. The following screenshot shows the function:
To implement the function, you need to know the history of the game and the current number of moves and roles. For the historical record, an object is used to store each step, and it is stored in a history array.
/ / back
regretChess() {
if(this.history.length){
const prev = this.history[this.currentStep - 1];
if(prev){
const {
x,
y,
role
} = prev;
this.minusStep(x,y);
this.checkerboard[prev.x][prev.y] = 0;
this.currentStep--;
this.role = Object.is(role,1)?1 : 2; }}}// Destroy the pieces
minusStep(x, y) {
const context = this.chessboard.getContext('2d');
const {padding, count} = this.options.gobangStyle;
context.clearRect(x*padding, y*padding, padding,padding);
}
Copy the code
The above code does implement the undo function, but in doing so, it has broken the UI of the board, because we are using the Canvas clearRect method to cover the removed pieces with the new quadrilateral, which also covers the physical board where the removed pieces are. To make up for the overwritten physical checkerboard, we have to redraw the new physical checkerboard line with the coordinates here. The fixes here take into account the different positions of the pieces on the board, and are made in nine different cases:
- Top left board
- Left edge checkerboard
- Bottom left checkerboard
- Bottom edge checkerboard
- Bottom right board
- Right edge checkerboard
- Upper right board
- Upper edge checkerboard
- Middle (non-boundary) board
// Patch up the deleted checkerboard and pass the different parameters of the nine cases
fixchessboard (a , b, c , d , e , f , g , h){
const context = this.chessboard.getContext('2d');
const {borderColor, lineWidth} = this.options.gobangStyle;
context.strokeStyle = borderColor;
context.lineWidth = lineWidth;
context.beginPath();
context.moveTo(a , b);
context.lineTo(c , d);
context.moveTo(e, f);
context.lineTo(g , h);
context.stroke();
}
Copy the code
Implement undo Repent
If there is permission to repent, then it is only reasonable that there is permission to revoke it. With the undo function, undo is required to know the history of the chess and the current step and the role of the pieces.
// Undo
revokedRegretChess(){
const next = this.history[this.currentStep];
if(next) {
this.drawChessman(next.x, next.y, next.role === 1);
this.checkerboard[next.x][next.y] = next.role;
this.currentStep++;
this.role = Object.is(this.role, 1)?2 : 1; }}Copy the code
Victory tip/Game over
The end of backgammon is when a winner has to be determined, or when there is no room on the board to play. Here is the entry point that determines victory as the end of the game. It also talks about what counts as a win for one side — a horizontal, vertical or diagonal line with five consecutive pieces of the same color. So we will deal with these four cases, we record in the matrix whether there are five consecutive 1’s (spots) or five consecutive 2’s (white) in the array of the current click point. In the following screenshot of the whitespace win on the X-axis, note the contents of the array printed to the right of the GIF:
// The referee looks at the pieces and decides the winner
checkReferee(x , y , role) {
if((x == undefined)||(y == undefined)||(role==undefined)) return;
const XContinuous = this.checkerboard.map(x= > x[y]); // On the X-axis
const YContinuous = this.checkerboard[x]; // on the y axis
const S1Continuous = []; // Store left slash chases
const S2Continuous = []; // Store right slash chases
this.checkerboard.forEach((_y,i) = > {
/ / left diagonal lines
const S1Item = _y[y - (x - i)];
if(S1Item ! = =undefined){
S1Continuous.push(S1Item);
}
/ / right diagonal lines
const S2Item = _y[y + (x - i)];
if(S2Item ! = =undefined) { S2Continuous.push(S2Item); }}); }Copy the code
So far, I have explained step by step how to develop a casual game that can be played on the PC – backgammon. Please correct the improper ha@ ~ @
The latter
Gobang experience address – casual game – gobang
Github – backgammon game
Github – Gobang tutorial
Writing articles is not easy, since you have seen here, leave a “like” and then go ~