PrefaceIn terms of layout, Gobang is much simpler to implement than those games whose goal is random movement, and the ideas are also clear. It is divided into: (1) Draw a chessboard; (2) Listen for click events and draw black and white chess pieces; (3) After each move, determine whether there are 5 connected pieces. If so, you win. The most complicated thing is probably how to judge whether Gobang has won, so let’s start with the simple one and draw a chessboard. 1. Draw a chessboardThe chessboard is very simple. Let's draw a 15*15 chessboard with intersecting horizontal and vertical lines: drawCheckerboard() { // Draw the chessboard let _this = this; _this.ctx.beginPath(); _this.ctx.fillStyle = "#fff"; _this.ctx.rect(0, 0, 450, 450); _this.ctx.fill(); for (var i = 0; i < 15; i++) { _this.ctx.beginPath(); _this.ctx.strokeStyle = "#D6D1D1"; _this.ctx.moveTo(15 + i * 30, 15); //Draw 15 lines vertically, 30px apart; _this.ctx.lineTo(15 + i * 30, 435); _this.ctx.stroke(); _this.ctx.moveTo(15, 15 + i * 30); //Draw 15 lines horizontally, 30px apart; _this.ctx.lineTo(435, 15 + i * 30); _this.ctx.stroke(); _this.resultArr.push(new Array(15).fill(0)); } } First use a 450 * 450 square as the base, leave a 15 width blank around it, and then draw lines with an interval of 30. In the for loop, we also initialized a 15 * 15 two-dimensional array and filled it with 0s. Yes, it is used to record the moves. 2. Listen for click events to draw black and white chess piecesOK, when we get the DOM, we listen to the click event to draw the chess piece:
handleClick(event) { let x = event.offsetX - 70; let y = event.offsetY - 70; if (x < 15 || x > 435 || y < 15 || y > 435) { // Click out of bounds return; } this.drawChess(x, y); if(this.winGame){ this.drawResult(); return; } this.whiteTurn = !this.whiteTurn; this.drawText(); } Code for drawing chess pieces: drawChess(x, y) { let _this = this; let xLine = Math.round((x - 15) / 30); // vertical line number x let yLine = Math.round((y - 15) / 30); // horizontal line number y if(_this.resultArr[xLine][yLine] !== 0){ return; } let grd = _this.ctx.createRadialGradient( xLine * 30 + 15, yLine * 30 + 15, 4, xLine * 30 + 15, yLine * 30 + 15, 10 ); grd.addColorStop(0, _this.whiteTurn ? "#fff" : "#4c4c4c"); grd.addColorStop(1, _this.whiteTurn ? "#dadada" : "#000"); _this.ctx.beginPath(); _this.ctx.fillStyle = grd; _this.ctx.arc( xLine * 30 + 15, yLine * 30 + 15, 10, 0, 2 * Math.PI, false ); _this.ctx.fill(); _this.ctx.closePath(); _this.setResultArr(xLine, yLine); _this.checkResult(xLine, yLine); } It is easy to calculate the chessboard intersection closest to the click coordinates. Of course, if a piece has already been placed there, you have to return. Then draw white or black pieces at the intersection, and use gradient fill here to make the chess pieces look more realistic. Next, record the chess piece status in the corresponding two-dimensional array: setResultArr(m, n) { let _this = this; _this.resultArr[m][n] = _this.whiteTurn ? 1 : 2; // White is 1; Black is 2 } 3. Check the winning and losing results of GobangHow to determine the outcome of winning or losing? To the naked eye, it is nothing more than establishing a coordinate system with the current move as the 0,0 origin, and then determining whether there are 5 consecutive pieces on the four lines of 0°, 180°, 45° and 135°. Compared with directly traversing and counting, a better way is to take out the data on four lines and then determine whether there are 5 consecutive 1 or 2 characters. Suppose the array coordinates of our placement are [m, n]. (1) Result array string of horizontal line: this.resultArr[m].join(''); (2) Result array string of vertical line: for(let i = 0; i<15; i++){ lineHorizontal.push(_this.resultArr[i][n]); } (3) 135° (top left to bottom right): j ranges from 0 to 15, take this.resultArr[m - j][n - j] and unshift it into the head of the temporary array, take this.resultArr[m + j][n + j] and put it at the end of the temporary array to form the result; (4) 45° (lower left to upper right): j ranges from 0 to 15, take this.resultArr[m + j][n - j] and unshift it into the head of the temporary array, take this.resultArr[m - j][n + j] and put it at the end of the temporary array to form the result; Of course, we need to judge whether the array is out of bounds. After getting the result string, we check whether there is a string like "22222" or "11111". If there is, it means victory. checkResult(m ,n){ // Check whether there are 5 connected pieces let _this = this; let checkStr = _this.whiteTurn ? CheckStrWhite : CheckStrBlack; // Take out the one-dimensional array of four lines [m,n] let lineVertical = _this.resultArr[m].join(''); if (lineVertical.indexOf(checkStr) > -1) { _this.winGame = true; return; } let lineHorizontal = []; for(let i = 0; i<15; i++){ lineHorizontal.push(_this.resultArr[i][n]); } lineHorizontal = lineHorizontal.join(''); if (lineHorizontal.indexOf(checkStr) > -1) { _this.winGame = true; return; } let line135 = []; for(let j = 0; j < 15; j++){ if(m - j >= 0 && n - j >= 0){ // Upper left corner line135.unshift(_this.resultArr[m - j][n -j]); } if(j > 0 && m + j < 15 && n + j < 15){ // Lower right corner line135.push(_this.resultArr[m + j][n + j]); } } line135 = line135.join(''); if(line135.indexOf(checkStr) > -1){ _this.winGame = true; return; } let line45 = []; for(let j = 0; j < 15; j++){ if(m + j < 15 && n - j >= 0){ // Upper right corner line45.unshift(_this.resultArr[m + j][n -j]); } if(j > 0 && m - j >=0 && n + j < 15){ // Lower left corner line45.push(_this.resultArr[m - j][n + j]); } } line45 = line45.join(''); if(line45.indexOf(checkStr) > -1){ _this.winGame = true; return; } } Finally, we show which side wins. At this point, a simple black and white chess game is ready~~~~~ As usual, here is the source code: <template> <div class="gobang"> <canvas id="gobang" width="800" height="600"></canvas> </div> </template> <script> const CheckStrWhite = "11111"; const CheckStrBlack = "22222"; export default { name: "Gobang", data() { return { ctx: null, winGame: false, whiteTurn: false, // White turn; true - Black turnresultArr: [] // Array recording chess piece positions}; }, mounted() { let _this = this; let container = document.getElementById("gobang"); container.addEventListener("click", _this.handleClick); _this.ctx = container.getContext("2d"); _this.ctx.translate(70,70); _this.drawCheckerboard(); }, computed:{ chessText(){ return this.whiteTurn ? 'White Chess' : 'Black Chess'; } }, methods: { drawCheckerboard() { // Draw the chessboard let _this = this; _this.ctx.beginPath(); _this.ctx.fillStyle = "#fff"; _this.ctx.rect(0, 0, 450, 450); _this.ctx.fill(); for (var i = 0; i < 15; i++) { _this.ctx.beginPath(); _this.ctx.strokeStyle = "#D6D1D1"; _this.ctx.moveTo(15 + i * 30, 15); //Draw 15 lines vertically, 30px apart; _this.ctx.lineTo(15 + i * 30, 435); _this.ctx.stroke(); _this.ctx.moveTo(15, 15 + i * 30); // Draw 15 lines horizontally, 30px apart; the chessboard is 14*14; _this.ctx.lineTo(435, 15 + i * 30); _this.ctx.stroke(); _this.resultArr.push(new Array(15).fill(0)); } _this.drawText(); }, drawChess(x, y) { let _this = this; let xLine = Math.round((x - 15) / 30); // vertical line number x let yLine = Math.round((y - 15) / 30); // horizontal line number y if(_this.resultArr[xLine][yLine] !== 0){ return; } let grd = _this.ctx.createRadialGradient( xLine * 30 + 15, yLine * 30 + 15, 4, xLine * 30 + 15, yLine * 30 + 15, 10 ); grd.addColorStop(0, _this.whiteTurn ? "#fff" : "#4c4c4c"); grd.addColorStop(1, _this.whiteTurn ? "#dadada" : "#000"); _this.ctx.beginPath(); _this.ctx.fillStyle = grd; _this.ctx.arc( xLine * 30 + 15, yLine * 30 + 15, 10, 0, 2 * Math.PI, false ); _this.ctx.fill(); _this.ctx.closePath(); _this.setResultArr(xLine, yLine); _this.checkResult(xLine, yLine); }, setResultArr(m, n) { let _this = this; _this.resultArr[m][n] = _this.whiteTurn ? 1 : 2; // White is 1; Black is 2 }, checkResult(m ,n){ // Check whether there are 5 connected pieces let _this = this; let checkStr = _this.whiteTurn ? CheckStrWhite : CheckStrBlack; // Take out the one-dimensional array of four lines [m,n] let lineVertical = _this.resultArr[m].join(''); if (lineVertical.indexOf(checkStr) > -1) { _this.winGame = true; return; } let lineHorizontal = []; for(let i = 0; i<15; i++){ lineHorizontal.push(_this.resultArr[i][n]); } lineHorizontal = lineHorizontal.join(''); if (lineHorizontal.indexOf(checkStr) > -1) { _this.winGame = true; return; } let line135 = []; for(let j = 0; j < 15; j++){ if(m - j >= 0 && n - j >= 0){ // Upper left corner line135.unshift(_this.resultArr[m - j][n -j]); } if(j > 0 && m + j < 15 && n + j < 15){ // Lower right corner line135.push(_this.resultArr[m + j][n + j]); } } line135 = line135.join(''); if(line135.indexOf(checkStr) > -1){ _this.winGame = true; return; } let line45 = []; for(let j = 0; j < 15; j++){ if(m + j < 15 && n - j >= 0){ // Upper right corner line45.unshift(_this.resultArr[m + j][n -j]); } if(j > 0 && m - j >=0 && n + j < 15){ // Lower left corner line45.push(_this.resultArr[m - j][n + j]); } } line45 = line45.join(''); if(line45.indexOf(checkStr) > -1){ _this.winGame = true; return; } }, drawText(){ let _this = this; _this.ctx.clearRect(435 + 60, 0, 100, 70); _this.ctx.fillStyle = "#fff"; _this.ctx.font="20px Arial"; _this.ctx.fillText('This round:' + _this.chessText, 435 + 70, 35); }, drawResult(){ let _this = this; _this.ctx.fillStyle = "#ff2424"; _this.ctx.font="20px Arial"; _this.ctx.fillText(_this.chessText+'Win!', 435 + 70, 70); }, handleClick(event) { let x = event.offsetX - 70; let y = event.offsetY - 70; if (x < 15 || x > 435 || y < 15 || y > 435) { // Click out of bounds return; } this.drawChess(x, y); if(this.winGame){ this.drawResult(); return; } this.whiteTurn = !this.whiteTurn; this.drawText(); } } }; </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped lang="scss"> .gobang { #gobang { background: #2a4546; } } </style> SummarizeThis is the end of this article about VUE+Canvas to implement a simple Gobang game. For more related VUE+Canvas Gobang game content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: Detailed explanation of how to install PHP curl extension under Linux
Setting min-width and max-width properties in tab...
How to set the position of the block element in t...
Table of contents introduce Installation and Usag...
This article example shares the specific code of ...
I chose node.js to build the server. Friends who ...
Table of contents 1. Test experiment 2. Performan...
FTP and SFTP are widely used as file transfer pro...
need: In the near future, we will implement the l...
Recently, I encountered many problems when instal...
Since I have parsed HTML before, I want to use Vu...
Table of contents Master-Master Synchronization S...
1. Brief Introduction Vue.js allows you to define...
The future of CSS is so exciting: on the one hand,...
In actual web page development, accordions also a...
Since Zabbix version 3.0, it has supported encryp...