preface
Hello, I'm Lin Sanxin. I believe you have read my previous introduction to canvas In order to get her started with canvas in 10 minutes, I stayed up late and wrote three small projects and this article , I already have an entry-level understanding of canvas. Today, I wrote three interesting games with canvas to make you happy. Yes, I have only you in my heart, not her.
It's 0:15 in the morning. Let's do it 🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍, Write this article while debugging!!!
Greedy snake 🐍
The final effect is as follows:
The implementation steps are divided into the following steps:
- 1. Draw the snake
- 2. Let the snake move
- 3. Random feeding of food
- 4. Snakes eat food
- 5. Edge detection and collision detection
1. Draw the snake
In fact, drawing a snake is very simple. A snake is composed of a snake head and a snake body. In fact, it can be represented by a square. The snake head is a square, and the snake body can be many squares
You can draw squares with CTX FillRect is used to draw the snake head, and the snake body is represented by the array body
// html <canvas id="canvas" width="800" height="800"></canvas> // js draw() function draw() { const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') // Constructor for small squares function Rect(x, y, width, height, color) { this.x = x this.y = y this.width = width this.height = height this.color = color } Rect.prototype.draw = function () { ctx.beginPath() ctx.fillStyle = this.color ctx.fillRect(this.x, this.y, this.width, this.height) ctx.strokeRect(this.x, this.y, this.width, this.height) } // Snake constructor function Snake(length = 0) { this.length = length // Snakehead this.head = new Rect(canvas.width / 2, canvas.height / 2, 40, 40, 'red') // Snake body this.body = [] let x = this.head.x - 40 let y = this.head.y for (let i = 0; i < this.length; i++) { const rect = new Rect(x, y, 40, 40, 'yellow') this.body.push(rect) x -= 40 } } Snake.prototype.drawSnake = function () { // Draw snake head this.head.draw() // Draw snake body for (let i = 0; i < this.body.length; i++) { this.body[i].draw() } } const snake = new Snake(3) snake.drawSnake() }
2. Let the snake move
There are two situations when a snake moves:
- 1. The snake moves to the right by default at the beginning
- 2. Through the direction key control, move in different directions
In both cases, the position of a square is moved every second
The principle of making the snake move is actually very simple. Let me take the snake moving to the right as an example:
- 1. First move the snake's head a square distance to the right, and the snake doesn't move
- 2. Add a square to the head of the snake
- 3. Square removal of snake tail
4. Use the timer to cause the snake to move to the right continuously
Snake.prototype.moveSnake = function () { // Put the snake head in the last state and spell it to the head of the snake const rect = new Rect(this.head.x, this.head.y, this.head.width, this.head.height, 'yellow') this.body.unshift(rect) this.body.pop() // Control the coordinates of the snake head according to the direction switch (this.direction) { case 0: this.head.x -= this.head.width break case 1: this.head.y -= this.head.height break case 2: this.head.x += this.head.width break case 3: this.head.y += this.head.height break } } document.onkeydown = function (e) { // Keyboard events e = e || window.event // Left 37 upper 38 right 39 lower 40 switch (e.keyCode) { case 37: console.log(37) // Ternary expression to prevent the left from moving to the right. The same is true below (greedy snakes can't turn around directly) snake.direction = snake.direction === 2 ? 2 : 0 snake.moveSnake() break case 38: console.log(38) snake.direction = snake.direction === 3 ? 3 : 1 break case 39: console.log(39) snake.direction = snake.direction === 0 ? 0 : 2 break case 40: console.log(40) snake.direction = snake.direction === 1 ? 1 : 3 break } } const snake = new Snake(3) // The default direction is 2, that is, right snake.direction = 2 snake.drawSnake() function animate() { // Empty first ctx.clearRect(0, 0, canvas.width, canvas.height) // move snake.moveSnake() // Repaint snake.drawSnake() } var timer = setInterval(() => { animate() }, 100) }
The results are as follows:
3. Put food at random
Put food at random, that is, draw a square on the canvas at random. Pay attention to the following two points:
- 1. The coordinates should be within the canvas
2. Food can't be thrown on the snake's body or head (it will knock the snake unconscious, hehe)
function randomFood(snake) { let isInSnake = true let rect while (isInSnake) { const x = Math.round(Math.random() * (canvas.width - 40) / 40) * 40 const y = Math.round(Math.random() * (canvas.height - 40) / 40) * 40 console.log(x, y) // It's guaranteed to be a multiple of 40 rect = new Rect(x, y, 40, 40, 'blue') // Judge whether the food overlaps with the head and body of the snake if ((snake.head.x === x && snake.head.y === y) || snake.body.find(item => item.x === x && item.y === y)) { isInSnake = true continue } else { isInSnake = false } } return rect } const snake = new Snake(3) // The default direction is 2, that is, right snake.direction = 2 snake.drawSnake() // Create random food instances var food = randomFood(snake) // Draw the food food.draw() function animate() { // Empty first ctx.clearRect(0, 0, canvas.width, canvas.height) // move snake.moveSnake() // Repaint snake.drawSnake() food.draw() }
The effect is as follows: the random food is drawn:
4. Snakes eat food
In fact, the snake eats food, which is very simple to understand, that is, when the snake head moves to overlap with the coordinates of food, even if it eats food, pay attention to two points:
- 1. After eating food, the snake's body should be extended by one space
- 2. After eating the food, the random food should change its position
const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') // A variable that defines whether a global eats food let isEatFood = false Snake.prototype.moveSnake = function () { // Put the snake head in the last state and spell it to the head of the snake const rect = new Rect(this.head.x, this.head.y, this.head.width, this.head.height, 'yellow') this.body.unshift(rect) // Judge whether the snake head overlaps with the food. If it overlaps, it means you have eaten it. If it doesn't overlap, it means you haven't eaten it isEatFood = food && this.head.x === food.x && this.head.y === food.y // Let's put a square above the head of the snake if (!isEatFood) { // If you don't eat it, you have to go to the tail, which is equivalent to that the whole snake hasn't grown this.body.pop() } else { // If you eat it, you don't go to the tail, which is equivalent to extending the whole snake by a square // And when you eat it, you have to regenerate a random food food = randomFood(this) food.draw() isEatFood = false } // Control the coordinates of the snake head according to the direction switch (this.direction) { case 0: this.head.x -= this.head.width break case 1: this.head.y -= this.head.height break case 2: this.head.x += this.head.width break case 3: this.head.y += this.head.height break } }
5. Touch the border and touch yourself
As we all know, when the snake head touches the border or the snake body, it will terminate the game
Snake.prototype.drawSnake = function () { // If you do if (isHit(this)) { // Clear timer clearInterval(timer) const con = confirm(`A total of ${this.body.length - this.length}A food, start over`) // Reopen if (con) { draw() } return } // Draw snake head this.head.draw() // Draw snake body for (let i = 0; i < this.body.length; i++) { this.body[i].draw() } } function isHit(snake) { const head = snake.head // Does it touch the left and right boundaries const xLimit = head.x < 0 || head.x >= canvas.width // Does it touch the upper and lower boundaries const yLimit = head.y < 0 || head.y >= canvas.height // Did you hit the snake const hitSelf = snake.body.find(({ x, y }) => head.x === x && head.y === y) // If one of the three is true, the game ends return xLimit || yLimit || hitSelf }
Since then, greedy snake 🐍 The game is complete:
6. All codes:
draw() function draw() { const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') // A variable that defines whether a global eats food let isEatFood = false // Constructor for small squares function Rect(x, y, width, height, color) { this.x = x this.y = y this.width = width this.height = height this.color = color } Rect.prototype.draw = function () { ctx.beginPath() ctx.fillStyle = this.color ctx.fillRect(this.x, this.y, this.width, this.height) ctx.strokeRect(this.x, this.y, this.width, this.height) } // Snake constructor function Snake(length = 0) { this.length = length // Snakehead this.head = new Rect(canvas.width / 2, canvas.height / 2, 40, 40, 'red') // Snake body this.body = [] let x = this.head.x - 40 let y = this.head.y for (let i = 0; i < this.length; i++) { const rect = new Rect(x, y, 40, 40, 'yellow') this.body.push(rect) x -= 40 } } Snake.prototype.drawSnake = function () { // If you do if (isHit(this)) { // Clear timer clearInterval(timer) const con = confirm(`A total of ${this.body.length - this.length}A food, start over`) // Reopen if (con) { draw() } return } // Draw snake head this.head.draw() // Draw snake body for (let i = 0; i < this.body.length; i++) { this.body[i].draw() } } Snake.prototype.moveSnake = function () { // Put the snake head in the last state and spell it to the head of the snake const rect = new Rect(this.head.x, this.head.y, this.head.width, this.head.height, 'yellow') this.body.unshift(rect) // Judge whether the snake head overlaps with the food. If it overlaps, it means you have eaten it. If it doesn't overlap, it means you haven't eaten it isEatFood = food && this.head.x === food.x && this.head.y === food.y // Let's put a square above the head of the snake if (!isEatFood) { // If you don't eat it, you have to go to the tail, which is equivalent to that the whole snake hasn't grown this.body.pop() } else { // If you eat it, you don't go to the tail, which is equivalent to extending the whole snake by a square // And when you eat it, you have to regenerate a random food food = randomFood(this) food.draw() isEatFood = false } // Control the coordinates of the snake head according to the direction switch (this.direction) { case 0: this.head.x -= this.head.width break case 1: this.head.y -= this.head.height break case 2: this.head.x += this.head.width break case 3: this.head.y += this.head.height break } } document.onkeydown = function (e) { // Keyboard events e = e || window.event // Left 37 upper 38 right 39 lower 40 switch (e.keyCode) { case 37: console.log(37) // Ternary expression to prevent the left from moving to the right. The same is true below (greedy snakes can't turn around directly) snake.direction = snake.direction === 2 ? 2 : 0 snake.moveSnake() break case 38: console.log(38) snake.direction = snake.direction === 3 ? 3 : 1 break case 39: console.log(39) snake.direction = snake.direction === 0 ? 0 : 2 break case 40: console.log(40) snake.direction = snake.direction === 1 ? 1 : 3 break } } function randomFood(snake) { let isInSnake = true let rect while (isInSnake) { const x = Math.round(Math.random() * (canvas.width - 40) / 40) * 40 const y = Math.round(Math.random() * (canvas.height - 40) / 40) * 40 console.log(x, y) // It's guaranteed to be a multiple of 40 rect = new Rect(x, y, 40, 40, 'blue') // Judge whether the food overlaps with the head and body of the snake if ((snake.head.x === x && snake.head.y === y) || snake.body.find(item => item.x === x && item.y === y)) { isInSnake = true continue } else { isInSnake = false } } return rect } function isHit(snake) { const head = snake.head // Does it touch the left and right boundaries const xLimit = head.x < 0 || head.x >= canvas.width // Does it touch the upper and lower boundaries const yLimit = head.y < 0 || head.y >= canvas.height // Did you hit the snake const hitSelf = snake.body.find(({ x, y }) => head.x === x && head.y === y) // If one of the three is true, the game ends return xLimit || yLimit || hitSelf } const snake = new Snake(3) // The default direction is 2, that is, right snake.direction = 2 snake.drawSnake() // Create random food instances var food = randomFood(snake) // Draw the food food.draw() function animate() { // Empty first ctx.clearRect(0, 0, canvas.width, canvas.height) // move snake.moveSnake() // Repaint snake.drawSnake() food.draw() } var timer = setInterval(() => { animate() }, 100) }
Star connection
The effect is as follows. Isn't it cool, brothers( Background picture You can download it yourself):
This little game can be divided into the following steps:
- 1. Draw a single little star and make it move
- 2. Make a hundred little stars
- 3. Connect when the stars are close
- 4. Move the mouse to generate small stars
- 5. Click the mouse to generate 5 small stars
1. Draw a single little star and make it move
In fact, moving the stars is very simple, that is, after clearing, redrawing the stars and using the timer, you will have the vision of moving. The point to note is: bounce when you hit the boundary.
// html <style> #canvas { background: url(./Light messenger.jpg) 0 0/cover no-repeat; } </style> <canvas id="canvas"></canvas> // js const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') // Gets the width and height of the current view let aw = document.documentElement.clientWidth || document.body.clientWidth let ah = document.documentElement.clientHeight || document.body.clientHeight // Assign to canvas canvas.width = aw canvas.height = ah // Monitor the real-time width and height when the screen changes window.onresize = function () { aw = document.documentElement.clientWidth || document.body.clientWidth ah = document.documentElement.clientHeight || document.body.clientHeight // Assign to canvas canvas.width = aw canvas.height = ah } // Whether solid or line, the color tone of this game is white ctx.fillStyle = 'white' ctx.strokeStyle = 'white' function Star(x, y, r) { // x. y is the coordinate and r is the radius this.x = x this.y = y this.r = r // speed parameter, value between - 3 and 3 this.speedX = (Math.random() * 3) * Math.pow(-1, Math.round(Math.random())) this.speedY = (Math.random() * 3) * Math.pow(-1, Math.round(Math.random())) } Star.prototype.draw = function () { ctx.beginPath() ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2) ctx.fill() ctx.closePath() } Star.prototype.move = function () { this.x -= this.speedX this.y -= this.speedY // When you hit the boundary, you just need to reverse the speed if (this.x < 0 || this.x > aw) this.speedX *= -1 if (this.y < 0 || this.y > ah) this.speedY *= -1 } // Randomly find a coordinate within the canvas and draw a star const star = new Star(Math.random() * aw, Math.random() * ah, 3) star // The movement of stars setInterval(() => { ctx.clearRect(0, 0, aw, ah) star.move() star.draw() }, 50)
Achieve the following movement and rebound effects:
2. Draw 100 little stars
Create an array stars to store the stars
const stars = [] for (let i = 0; i < 100; i++) { // Randomly find a coordinate within the canvas and draw a star stars.push(new Star(Math.random() * aw, Math.random() * ah, 3)) } // The movement of stars setInterval(() => { ctx.clearRect(0, 0, aw, ah) // Traverse mobile rendering stars.forEach(star => { star.move() star.draw() }) }, 50)
The effects are as follows:
3. Connect when the stars are close
When the difference between x and y of the two stars is less than 50, the connection is carried out. The connection only needs to use CTX Moveto and CTX Just lineto
function drawLine(startX, startY, endX, endY) { ctx.beginPath() ctx.moveTo(startX, startY) ctx.lineTo(endX, endY) ctx.stroke() ctx.closePath() } // The movement of stars setInterval(() => { ctx.clearRect(0, 0, aw, ah) // Traverse mobile rendering stars.forEach(star => { star.move() star.draw() }) stars.forEach((star, index) => { // Similar to bubble sorting, compare and make sure all stars are compared between two for (let i = index + 1; i < stars.length; i++) { if (Math.abs(star.x - stars[i].x) < 50 && Math.abs(star.y - stars[i].y) < 50) { drawLine(star.x, star.y, stars[i].x, stars[i].y) } } }) }, 50)
You can think about why two forEach cannot be executed together. This is a question worth thinking about, or you can combine it together, try the effect and get it. It's an assignment for everyone!
The effects are as follows:
4. The mouse moves with a small star
That is, the little star will go wherever the mouse goes, and the little star will connect with the little star close to it wherever it goes
const mouseStar = new Star(0, 0, 3) canvas.onmousemove = function (e) { mouseStar.x = e.clientX mouseStar.y = e.clientY } // The movement of stars setInterval(() => { ctx.clearRect(0, 0, aw, ah) // Mouse star rendering mouseStar.draw() // Traverse mobile rendering stars.forEach(star => { star.move() star.draw() }) stars.forEach((star, index) => { // Similar to bubble sorting, compare and make sure all stars are compared between two for (let i = index + 1; i < stars.length; i++) { if (Math.abs(star.x - stars[i].x) < 50 && Math.abs(star.y - stars[i].y) < 50) { drawLine(star.x, star.y, stars[i].x, stars[i].y) } } // Judge mouse star connection if (Math.abs(mouseStar.x - star.x) < 50 && Math.abs(mouseStar.y - star.y) < 50) { drawLine(mouseStar.x, mouseStar.y, star.x, star.y) } }) }, 50)
The effects are as follows:
5. Click the mouse to generate five small stars
The idea is to click the mouse to generate five small stars and add them to the array stars
window.onclick = function (e) { for (let i = 0; i < 5; i++) { stars.push(new Star(e.clientX, e.clientY, 3)) } }
The effects are as follows:
Final effect:
6. All codes
const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') // Gets the width and height of the current view let aw = document.documentElement.clientWidth || document.body.clientWidth let ah = document.documentElement.clientHeight || document.body.clientHeight // Assign to canvas canvas.width = aw canvas.height = ah // Monitor the real-time width and height when the screen changes window.onresize = function () { aw = document.documentElement.clientWidth || document.body.clientWidth ah = document.documentElement.clientHeight || document.body.clientHeight // Assign to canvas canvas.width = aw canvas.height = ah } // Whether solid or line, the color tone of this game is white ctx.fillStyle = 'white' ctx.strokeStyle = 'white' function Star(x, y, r) { // x. y is the coordinate and r is the radius this.x = x this.y = y this.r = r // speed parameter, value between - 3 and 3 this.speedX = (Math.random() * 3) * Math.pow(-1, Math.round(Math.random())) this.speedY = (Math.random() * 3) * Math.pow(-1, Math.round(Math.random())) } Star.prototype.draw = function () { ctx.beginPath() ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2) ctx.fill() ctx.closePath() } Star.prototype.move = function () { this.x -= this.speedX this.y -= this.speedY // When you hit the boundary, you just need to reverse the speed if (this.x < 0 || this.x > aw) this.speedX *= -1 if (this.y < 0 || this.y > ah) this.speedY *= -1 } function drawLine(startX, startY, endX, endY) { ctx.beginPath() ctx.moveTo(startX, startY) ctx.lineTo(endX, endY) ctx.stroke() ctx.closePath() } const stars = [] for (let i = 0; i < 100; i++) { // Randomly find a coordinate within the canvas and draw a star stars.push(new Star(Math.random() * aw, Math.random() * ah, 3)) } const mouseStar = new Star(0, 0, 3) canvas.onmousemove = function (e) { mouseStar.x = e.clientX mouseStar.y = e.clientY } window.onclick = function (e) { for (let i = 0; i < 5; i++) { stars.push(new Star(e.clientX, e.clientY, 3)) } } // The movement of stars setInterval(() => { ctx.clearRect(0, 0, aw, ah) // Mouse star rendering mouseStar.draw() // Traverse mobile rendering stars.forEach(star => { star.move() star.draw() }) stars.forEach((star, index) => { // Similar to bubble sorting, compare and make sure all stars are compared between two for (let i = index + 1; i < stars.length; i++) { if (Math.abs(star.x - stars[i].x) < 50 && Math.abs(star.y - stars[i].y) < 50) { drawLine(star.x, star.y, stars[i].x, stars[i].y) } } if (Math.abs(mouseStar.x - star.x) < 50 && Math.abs(mouseStar.y - star.y) < 50) { drawLine(mouseStar.x, mouseStar.y, star.x, star.y) } }) }, 50)
3. Gobang
See what will happen:
Gobang is divided into the following steps:
- 1. Draw a chessboard
- 2. When black and white chess is switched, it cannot cover the pit
- 3. Judge whether five children are connected. If so, you win
- 4. Egg: play chess with AI (realize single player game)
1. Draw a chessboard
It's actually very simple. Use CTX Moveto and CTX Lineto, draw 15 lines horizontally and 15 lines vertically, and it's OK.
// html #canvas { background: #e3cdb0; } <canvas id="canvas" width="600" height="600"></canvas> // js play() function play() { const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') // Draw chessboard // Horizontal, 15 lines in total for (let i = 0; i < 15; i++) { ctx.beginPath() ctx.moveTo(20, 20 + i * 40) ctx.lineTo(580, 20 + i * 40) ctx.stroke() ctx.closePath() } // Vertical, 15 lines in total for (let i = 0; i < 15; i++) { ctx.beginPath() ctx.moveTo(20 + i * 40, 20) ctx.lineTo(20 + i * 40, 580) ctx.stroke() ctx.closePath() } }
This draws the chessboard:
2. Switch between black and white chess
- 1. Click the event with the mouse to obtain the coordinates and draw the chess (ctx.arc)
- 2. Ensure that the played chess position cannot be played repeatedly
The first step is to obtain the mouse coordinates, but we should pay attention to one thing. The chess pieces can only be placed at the intersection of the line. Therefore, after obtaining the mouse coordinates, we should do some processing and round them to the nearest line intersection as the center of the circle
The second step, how to ensure that the chess position is not repeated? We can use a two-dimensional array to record. The initial value is 0. After playing black chess, it becomes 1 and after playing white chess, it becomes 2. However, it should be noted that the x and y of the array index are opposite to the x and y of the canvas coordinates, so the coordinates in the following code are reversed. I hope you can think about why.
// Whether to play black chess // Black chess go first let isBlack = true // Checkerboard 2D array let cheeks = [] for (let i = 0; i < 15; i++) { cheeks[i] = new Array(15).fill(0) } canvas.onclick = function (e) { const clientX = e.clientX const clientY = e.clientY // Round 40 to make sure the pieces fall at the intersection const x = Math.round((clientX - 20) / 40) * 40 + 20 const y = Math.round((clientY - 20) / 40) * 40 + 20 // Index of cheeks two-dimensional array // It's a little redundant. You can understand it better const cheeksX = (x - 20) / 40 const cheeksY = (y - 20) / 40 // The corresponding element is not 0, indicating that there is chess in this place. Return if (cheeks[cheeksY][cheeksX]) return // Black chess is 1 and white chess is 2 cheeks[cheeksY][cheeksX] = isBlack ? 1 : 2 ctx.beginPath() // Draw a circle ctx.arc(x, y, 20, 0, 2 * Math.PI) // Judge whether to go black or white ctx.fillStyle = isBlack ? 'black' : 'white' ctx.fill() ctx.closePath() // Switch black and white isBlack = !isBlack }
The effects are as follows:
3. Judge whether it is wulianzi
How to judge? There are four situations: upper and lower five Lianzi, left and right Wu Lianzi, upper left and lower right five Lianzi, upper right and lower left five Lianzi. As long as we judge them all every time we fall.
By the way, all codes are attached
play() function play() { const canvas = document.getElementById('canvas') const ctx = canvas.getContext('2d') // Draw chessboard // Horizontal, 15 lines in total for (let i = 0; i < 15; i++) { ctx.beginPath() ctx.moveTo(20, 20 + i * 40) ctx.lineTo(580, 20 + i * 40) ctx.stroke() ctx.closePath() } // Vertical, 15 lines in total for (let i = 0; i < 15; i++) { ctx.beginPath() ctx.moveTo(20 + i * 40, 20) ctx.lineTo(20 + i * 40, 580) ctx.stroke() ctx.closePath() } // Do you play black chess // Black chess go first let isBlack = true // Checkerboard 2D array let cheeks = [] for (let i = 0; i < 15; i++) { cheeks[i] = new Array(15).fill(0) } canvas.onclick = function (e) { const clientX = e.clientX const clientY = e.clientY // Round 40 to make sure the pieces fall at the intersection const x = Math.round((clientX - 20) / 40) * 40 + 20 const y = Math.round((clientY - 20) / 40) * 40 + 20 // Index of cheeks two-dimensional array // It's a little redundant, so you can understand it better const cheeksX = (x - 20) / 40 const cheeksY = (y - 20) / 40 // The corresponding element is not 0, indicating that there is chess in this place. Return if (cheeks[cheeksY][cheeksX]) return // Black chess is 1 and white chess is 2 cheeks[cheeksY][cheeksX] = isBlack ? 1 : 2 ctx.beginPath() // Draw a circle ctx.arc(x, y, 20, 0, 2 * Math.PI) // Judge whether to go black or white ctx.fillStyle = isBlack ? 'black' : 'white' ctx.fill() ctx.closePath() // canvas drawing is asynchronous, so you can draw it and then test whether you win or lose setTimeout(() => { if (isWin(cheeksX, cheeksY)) { const con = confirm(`${isBlack ? 'black ' : 'White chess'}Win! Start again?`) // Restart ctx.clearRect(0, 0, 600, 600) con && play() } // Switch black and white isBlack = !isBlack }, 0) } // Judge whether five connected children function isWin(x, y) { const flag = isBlack ? 1 : 2 // Up and down if (up_down(x, y, flag)) { return true } // left and right if (left_right(x, y, flag)) { return true } // Upper left and lower right if (lu_rd(x, y, flag)) { return true } // Upper right and lower left if (ru_ld(x, y, flag)) { return true } return false } function up_down(x, y, flag) { let num = 1 // Look up for (let i = 1; i < 5; i++) { let tempY = y - i console.log(x, tempY) if (tempY < 0 || cheeks[tempY][x] !== flag) break if (cheeks[tempY][x] === flag) num += 1 } // Look down for (let i = 1; i < 5; i++) { let tempY = y + i console.log(x, tempY) if (tempY > 14 || cheeks[tempY][x] !== flag) break if (cheeks[tempY][x] === flag) num += 1 } return num >= 5 } function left_right(x, y, flag) { let num = 1 // Look left for (let i = 1; i < 5; i++) { let tempX = x - i if (tempX < 0 || cheeks[y][tempX] !== flag) break if (cheeks[y][tempX] === flag) num += 1 } // Look right for (let i = 1; i < 5; i++) { let tempX = x + i if (tempX > 14 || cheeks[y][tempX] !== flag) break if (cheeks[y][tempX] === flag) num += 1 } return num >= 5 } function lu_rd(x, y, flag) { let num = 1 // Look up to the left for (let i = 1; i < 5; i++) { let tempX = x - i let tempY = y - i if (tempX < 0 || tempY < 0 || cheeks[tempY][tempX] !== flag) break if (cheeks[tempY][tempX] === flag) num += 1 } // Look down to the right for (let i = 1; i < 5; i++) { let tempX = x + i let tempY = y + i if (tempX > 14 || tempY > 14 || cheeks[tempY][tempX] !== flag) break if (cheeks[tempY][tempX] === flag) num += 1 } return num >= 5 } function ru_ld(x, y, flag) { let num = 1 // Look up to the right for (let i = 1; i < 5; i++) { let tempX = x - i let tempY = y + i if (tempX < 0 || tempY > 14 || cheeks[tempY][tempX] !== flag) break if (cheeks[tempY][tempX] === flag) num += 1 } // Look down to the left for (let i = 1; i < 5; i++) { let tempX = x + i let tempY = y - i if (tempX > 14 || tempY < 0 || cheeks[tempY][tempX] !== flag) break if (cheeks[tempY][tempX] === flag) num += 1 } return num >= 5 } }
4. Colored eggs: playing chess with AI
In fact, it is very simple. After playing chess, set a function: randomly find a position to play chess. In this way, the functions of playing chess and single player games with computers are realized. I have realized this function, but I won't write it out. Let's give it to you as your homework to consolidate this article. Ha ha ha ha
epilogue
I'm Lin Sanxin, an enthusiastic front-end rookie programmer. If you are self-motivated, like the front-end and want to learn from the front-end, we can make friends and fish together. Ha ha, fish school, add me, please note [Si no]