Native JS+Canvas to achieve backgammon game

rendering

The main functional modules are: 1. Man-machine fighting function 2. Repentance function 3

Second, code details

2.1 Man-machine versus function realization

As can be seen from the renderings, the horizontal and vertical positions of the board can be 15*15. Draw the board on canvas:

Var drawChessBoard = function(){for(var I = 0; i < 15; i++){ context.moveTo(15 + i * 30 , 15); context.lineTo(15 + i * 30 , 435); context.stroke(); context.moveTo(15 , 15 + i * 30); context.lineTo(435 , 15 + i * 30); context.stroke(); }}Copy the code

After knowing the number of squares, let’s see how many ways to win gobang:

Var wins = []; for(var i = 0; i < 15; i++){ wins[i] = []; for(var j = 0; j < 15; j++){ wins[i][j] = []; } } var count = 0; For (var I = 0; i < 15; i++){ for(var j = 0; j < 11; j++){ for(var k = 0; k < 5; k++){ wins[i][j+k][count] = true; } count++; }} for(var I = 0; i < 15; i++){ for(var j = 0; j < 11; j++){ for(var k = 0; k < 5; k++){ wins[j+k][i][count] = true; } count++; }} for(var I = 0; i < 11; i++){ for(var j = 0; j < 11; j++){ for(var k = 0; k < 5; k++){ wins[i+k][j+k][count] = true; } count++; }} for(var I = 0; i < 11; i++){ for(var j = 14; j > 3; j--){ for(var k = 0; k < 5; k++){ wins[i+k][j-k][count] = true; } count++; }}Copy the code

An array of computer and human wins defined by the total number of wins:

for(var i = 0; i < count; i++){
            myWin[i] = 0;
            _myWin[i] = 0;
            computerWin[i] = 0;
            _compWin[i] = 0;
 }
Copy the code

Then the man begins to play chess:

Onclick = function(e){if(over){// end of game return; } if(! me){ return; } var x = e.offsetX; var y = e.offsetY; var i = Math.floor(x / 30); var j = Math.floor(y / 30); _nowi = i; _nowj = j; if(chressBord[i][j] == 0){ oneStep(i,j,me); chressBord[i][j] = 1; For (var k = 0; k < count; K++) {/ / will probably win the case is added 1 if (wins [I] [j] [k]) {myWin [k] + +; _compWin[k] = computerWin[k]; ComputerWin [k] = 6; If (myWin[k] == 5){resulttXt. innerHTML = 'Congratulations, you have won! '; over = true; } } } if(! over){ me = ! me; computerAI(); }} / / back function available backbtn. ClassName = backbtn. ClassName. Replace (new RegExp (" (\ \ s | ^) unable (\ \ | $s) "), ""); }Copy the code

The oneStep() method is to draw a piece on the board:

Var oneStep = function(I,j,me){// debugger; context.beginPath(); context.arc(15 + i * 30, 15 + j * 30, 13, 0, 2 * Math.PI); / / circle context. ClosePath (); / / the gradient var gradient = context. CreateRadialGradient (15 + I * 30 + 2, 15 + j * 30-2, 13, 15 + I * 30 + 2, 15 + j * 30 - 2, 0); if(me){ 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

Play chess by computerAI()

Var computerAI = function (){var myScore = []; var computerScore = []; var max = 0; var u = 0, v = 0; for(var i = 0; i < 15; i++){ myScore[i] = []; computerScore[i] = []; for(var j = 0; j < 15; j++){ myScore[i][j] = 0; computerScore[i][j] = 0; } } for(var i = 0; i < 15; i++){ for(var j = 0; j < 15; j++){ if(chressBord[i][j] == 0){ for(var k = 0; k < count; k++){ if(wins[i][j][k]){ if(myWin[k] == 1){ myScore[i][j] += 200; }else if(myWin[k] == 2){ myScore[i][j] += 400; }else if(myWin[k] == 3){ myScore[i][j] += 2000; }else if(myWin[k] == 4){ myScore[i][j] += 10000; } if(computerWin[k] == 1){ computerScore[i][j] += 220; }else if(computerWin[k] == 2){ computerScore[i][j] += 420; }else if(computerWin[k] == 3){ computerScore[i][j] += 2100; }else if(computerWin[k] == 4){ computerScore[i][j] += 20000; } } } if(myScore[i][j] > max){ max = myScore[i][j]; u = i; v = j; }else if(myScore[i][j] == max){ if(computerScore[i][j] > computerScore[u][v]){ u = i; v = j; } } if(computerScore[i][j] > max){ max = computerScore[i][j]; u = i; v = j; }else if(computerScore[i][j] == max){ if(myScore[i][j] > myScore[u][v]){ u = i; v = j; } } } } } _compi = u; _compj = v; oneStep(u,v,false); chressBord[u][v] = 2; For (var k = 0; k < count; k++){ if(wins[u][v][k]){ computerWin[k]++; _myWin[k] = myWin[k]; myWin[k] = 6; If (computerWin[k] == 5){resulttxt. innerHTML = 'o(╯□╰)o, continue to win! '; over = true; } } } if(! over){ me = ! me; }}Copy the code

According to the corresponding weight, calculate the computer should be placed in the position.

2.2 Function of regret

I should mention that there is only one step of regret here. The main key points of the function are: 1, destroy the chess pieces just played; 2. Restore the state that was impossible to win before; Take a look at the code:

Backbtn. onclick = function(e){if(! backAble) { return; } over = false; me = true; ChressBord [_nowi][_nowj] = 0; MinusStep (_nowi, _nowj); minusStep(_nowi, _nowj); Var k = 0; k < count; K++) {/ / will probably win is minus 1 if (wins [_nowi] [_nowj] [k]) {myWin [k] -; computerWin[k] = _compWin[k]; ChressBord [_compi][_compj] = 0; MinusStep (_compi, _compj); Var k = 0; k < count; K++) {/ / will probably win is minus 1 if (wins [_compi] [_compj] [k]) {computerWin [k] -; myWin[k] = _myWin[i]; }} resulttxt. innerHTML = '-- Puzzle backgammon --'; returnAble = true; backAble = false; / / cancel the undo function available returnbtn. ClassName = returnbtn. ClassName. Replace (new RegExp (" (\ \ s | ^) unable (\ \ s | $) "), ""); }Copy the code

MinusStep () is the method of destroying a piece. Let’s see how it is destroyed.

Var minusStep = function(I,j) {context.clearrect ((I) * 30, (j) * 30, 30, 30); // Redraw the grid around the circle context.beginPath(); context.moveTo(15+i*30 , j*30); context.lineTo(15+i*30 , j*30 + 30); context.moveTo(i*30, j*30+15); context.lineTo((i+1)*30 , j*30+15); context.stroke(); }Copy the code

First erase the circle with clearRect(), and then redraw the grid around the circle, noting the corresponding position, which took some time to do.

2.3 Cancel the Regret function

After repentance, revocation is equivalent to restoring the state before repentance. The code is relatively simple:

Onclick = function(e){if(! returnAble) { return; } chressBord[_nowi][_nowj] = 1; OneStep (_nowi,_nowj,me); for(var k = 0; k < count; k++){ if(wins[_nowi][_nowj][k]){ myWin[k]++; _compWin[k] = computerWin[k]; computerWin[k] = 6; } if(myWin[k] == 5){resulttXt. innerHTML = 'Congratulations, you have won! '; over = true; ChressBord [_compi][_compj] = 2; OneStep (_compi,_compj,false); for(var k = 0; k < count; k++){ if(wins[_compi][_compj][k]){ computerWin[k]++; _myWin[k] = myWin[k]; myWin[k] = 6; } if(computerWin[k] == 5){resulttxt. innerHTML = 'o(╯□╰)o, continue to win! '; over = true; } } returnbtn.className += 'unable'; returnAble = false; backAble = true; }Copy the code

At this point, these three functions are relatively easy to complete.

Third, summary

The key points of a backgammon game are: 1. Know how many ways to win; 2. How to judge whether you have won; 3. Computer chess algorithm. Here cleverly use the array storage win method, judge whether to win, through weight comparison, calculate the position of the computer to play chess. In the process, I used canvas, which I had learned before. Although I had not used it for a long time, I checked some materials, reviewed how to draw lines and circles, and learned how to clear a circle. Then notice how classes are added and removed from elements using native Js.