Вывод сообщения на экран при условии

Есть код змейки, работает нормально (делал по учебнику). При столкновении с границей поля или с собой, игра выводит на экран сообщение "Конец игры". Я попытался добавить похожее условие, если игрок собирает 3 яблока, то выводится сообщение и победе, но у меня какая-то ошибка, браузер ругается на return в 190 строке...

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Змейка!</title>

  <link rel="preconnect" href="https://fonts.gstatic.com">
  <link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet">

</head>
<style>
    canvas {
        /*background-color: #839C86;*/
        background-image: url(https://i.pinimg.com/originals/31/fe/12/31fe123182f2a5f956bf542af837ca12.jpg);
        margin-left: 35%;
        margin-top: 1%;
    }
    body {
        background-image: url(Snake/img/Background.jpg);
    }
    text {
        color: white;
    }
    button {
        margin-top: 4%;
        margin-left: 58%;
        font-family: 'Press Start 2P';
        font-size: 10px;
    }

    .gradient {
        background: rgb(255,0,0);
        background: linear-gradient(90deg, rgba(255,0,0,1) 7%, rgba(19,121,9,1) 27%);
    }
</style>
<body>

<button class="update">
    Restart
</button>

<canvas id="canvas" width="400" height="400"></canvas>
<script src="https://code.jquery.com/jquery-2.1.0.js"></script>
 <script>
 
// Настройка «холста»
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

// Получаем ширину и высоту элемента canvas
var width = canvas.width;
var height = canvas.height;
 
// Вычисляем ширину и высоту в ячейках
var blockSize = 10;
var widthInBlocks = width / blockSize;
var heightInBlocks = height / blockSize;
 
// Устанавливаем счет 0
var score = 0;
 
// Рисуем рамку
var drawBorder = function () {
  ctx.fillStyle = "#383838";
  ctx.fillRect(0, 0, width, blockSize);
  ctx.fillRect(0, height - blockSize, width, blockSize);
  ctx.fillRect(0, 0, blockSize, height);
  ctx.fillRect(width - blockSize, 0, blockSize, height);
};
 
// Выводим счет игры в левом верхнем углу
var drawScore = function () {
  ctx.font = "20px 'Press Start 2P'";
  ctx.fillStyle = "White";
  ctx.textAlign = "left";
  ctx.textBaseline = "top";
  ctx.fillText("Счет: " + score, blockSize, blockSize);
};
 
// Отменяем действие setInterval и печатаем сообщение «Конец игры»
var gameOver = function () {
  clearInterval(intervalId);
  ctx.font = "30px 'Press Start 2P'";
  ctx.fillStyle = "White";
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";
  ctx.fillText("Конец игры", width / 2, height / 2);
};

var Win = function () {   //Переменная Win с сообщением.
  clearInterval(intervalId);
  ctx.font = "30px 'Press Start 2P'";
  ctx.fillStyle = "White";
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";
  ctx.fillText("Победа !", width / 2, height / 2);
};
 
// Рисуем окружность (используя функцию из главы 14)
var circle = function (x, y, radius, fillCircle) {
  ctx.beginPath();
  ctx.arc(x, y, radius, 0, Math.PI * 2, false);
  if (fillCircle) {
    ctx.fill();
  } else {
    ctx.stroke();
  }
};
 
// Задаем конструктор Block (ячейка)
 var Block = function (col, row) {
  this.col = col;
  this.row = row;
};
 
// Рисуем квадрат в позиции ячейки
Block.prototype.drawSquare = function (color) {
  var x = this.col * blockSize;
  var y = this.row * blockSize;
  ctx.fillStyle = color;
  ctx.fillRect(x, y, blockSize, blockSize);
};
 
// Рисуем круг в позиции ячейки
Block.prototype.drawCircle = function (color) {
  var centerX = this.col * blockSize + blockSize / 2;
  var centerY = this.row * blockSize + blockSize / 2;
  ctx.fillStyle = color;
  circle(centerX, centerY, blockSize / 2, true);
};
 
// Проверяем, находится ли эта ячейка в той же позиции, что и ячейка 
// otherBlock
Block.prototype.equal = function (otherBlock) {
  return this.col === otherBlock.col && this.row === otherBlock.row;
};
 
// Задаем конструктор Snake (змейка)
var Snake = function () {
  this.segments = [
    new Block(7, 5),
    new Block(6, 5),
    new Block(5, 5)
  ];
 
  this.direction = "right";
  this.nextDirection = "right";
};
 
// Рисуем квадратик для каждого сегмента тела змейки
Snake.prototype.draw = function () {
  for (var i = 0; i < this.segments.length; i++) {
    this.segments[i].drawSquare("#0cd3cd");
  }
};
 
// Создаем новую голову и добавляем ее к началу змейки,
// чтобы передвинуть змейку в текущем направлении
Snake.prototype.move = function () {
  var head = this.segments[0];
  var newHead;
 
  this.direction = this.nextDirection;
 
  if (this.direction === "right") {
    newHead = new Block(head.col + 1, head.row);
  } else if (this.direction === "down") {
    newHead = new Block(head.col, head.row + 1);
  } else if (this.direction === "left") {
    newHead = new Block(head.col - 1, head.row);
  } else if (this.direction === "up") {
    newHead = new Block(head.col, head.row - 1);
  }
 
  if (this.checkCollision(newHead)) {
    gameOver();
    return;
  }
  this.segments.unshift(newHead);
  if (newHead.equal(apple.position)) {
    score++;
    apple.move();
  } else {
    this.segments.pop();
  }
};

  if (score === 3) {  //При получении трёх яблок, игра должна остановиться и вывести сообщение о победе.
    Win();
    return;  //На это ругается браузер.
  };
 
// Проверяем, не столкнулась ли змейка со стеной или собственным 
// телом
Snake.prototype.checkCollision = function (head) {
  var leftCollision = (head.col === 0);
  var topCollision = (head.row === 0);
  var rightCollision = (head.col === widthInBlocks - 1);
  var bottomCollision = (head.row === heightInBlocks - 1);
  var wallCollision = leftCollision || topCollision || rightCollision || bottomCollision;
 
  var selfCollision = false;
  
  for (var i = 0; i < this.segments.length; i++) {
    if (head.equal(this.segments[i])) {
      selfCollision = true;
    }
  }
 
  return wallCollision || selfCollision;
};
 
// Задаем следующее направление движения змейки на основе нажатой 
// клавиши
Snake.prototype.setDirection = function (newDirection) {
  if (this.direction === "up" && newDirection === "down") {
    return;
  } else if (this.direction === "right" && newDirection === "left") {
    return;
  } else if (this.direction === "down" && newDirection === "up") {
    return;
  } else if (this.direction === "left" && newDirection === "right") {
    return;
  }
 
  this.nextDirection = newDirection;
};
 
// Задаем конструктор Apple (яблоко)
var Apple = function () {
  this.position = new Block(20, 20);
};
 
// Рисуем кружок в позиции яблока
Apple.prototype.draw = function () {
  this.position.drawCircle("Red");
};
 
// Перемещаем яблоко в случайную позицию
Apple.prototype.move = function () {
 var randomCol = Math.floor(Math.random() * (widthInBlocks - 2)) + 1;
 var randomRow = Math.floor(Math.random() * (heightInBlocks - 2)) + 1;
  this.position = new Block(randomCol, randomRow);
};
 
// Создаем объект-змейку и объект-яблоко
var snake = new Snake();
var apple = new Apple();
 
// Запускаем функцию анимации через setInterval
var intervalId = setInterval(function () {
  ctx.clearRect(0, 0, width, height);
  drawScore();
  snake.move();
  snake.draw();
  apple.draw();
  drawBorder();
}, 80);
 
// Преобразуем коды клавиш в направления
var directions = {
  65: "left",
  87: "up",
  68: "right",
  83: "down"
};
 
// Задаем обработчик события keydown (клавиши-стрелки)
$("body").keydown(function (event) {
  var newDirection = directions[event.keyCode];
  if (newDirection !== undefined) {
    snake.setDirection(newDirection);
  }
});
 
 $(document).on("click", ".update", function(){
    location.reload(true);
    });
    </script>
</body>
</html>

Ответы (1 шт):

Автор решения: Aziz Umarov

Немного подправил код, теперь работает.

Проблема была в следущей части кода:

  if (score === 3) {  
    Win();
    return;  //На это ругается браузер.
  };

Блок return находился вне функции.

// Настройка «холста»
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

// Получаем ширину и высоту элемента canvas
var width = canvas.width;
var height = canvas.height;
 
// Вычисляем ширину и высоту в ячейках
var blockSize = 10;
var widthInBlocks = width / blockSize;
var heightInBlocks = height / blockSize;
 
// Устанавливаем счет 0
var score = 0;
 
// Рисуем рамку
var drawBorder = function () {
  ctx.fillStyle = "#383838";
  ctx.fillRect(0, 0, width, blockSize);
  ctx.fillRect(0, height - blockSize, width, blockSize);
  ctx.fillRect(0, 0, blockSize, height);
  ctx.fillRect(width - blockSize, 0, blockSize, height);
};
 
// Выводим счет игры в левом верхнем углу
var drawScore = function () {
  ctx.font = "20px 'Press Start 2P'";
  ctx.fillStyle = "White";
  ctx.textAlign = "left";
  ctx.textBaseline = "top";
  ctx.fillText("Счет: " + score, blockSize, blockSize);
};
 
// Отменяем действие setInterval и печатаем сообщение «Конец игры»
var gameOver = function () {
  clearInterval(intervalId);
  ctx.font = "30px 'Press Start 2P'";
  ctx.fillStyle = "White";
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";
  ctx.fillText("Конец игры", width / 2, height / 2);
};

var Win = function () {   //Переменная Win с сообщением.
  clearInterval(intervalId);
  ctx.font = "30px 'Press Start 2P'";
  ctx.fillStyle = "White";
  ctx.textAlign = "center";
  ctx.textBaseline = "middle";
  ctx.fillText("Победа !", width / 2, height / 2);
};
 
// Рисуем окружность (используя функцию из главы 14)
var circle = function (x, y, radius, fillCircle) {
  ctx.beginPath();
  ctx.arc(x, y, radius, 0, Math.PI * 2, false);
  if (fillCircle) {
    ctx.fill();
  } else {
    ctx.stroke();
  }
};
 
// Задаем конструктор Block (ячейка)
var Block = function (col, row) {
  this.col = col;
  this.row = row;
};
 
// Рисуем квадрат в позиции ячейки
Block.prototype.drawSquare = function (color) {
  var x = this.col * blockSize;
  var y = this.row * blockSize;
  ctx.fillStyle = color;
  ctx.fillRect(x, y, blockSize, blockSize);
};
 
// Рисуем круг в позиции ячейки
Block.prototype.drawCircle = function (color) {
  var centerX = this.col * blockSize + blockSize / 2;
  var centerY = this.row * blockSize + blockSize / 2;
  ctx.fillStyle = color;
  circle(centerX, centerY, blockSize / 2, true);
};
 
// Проверяем, находится ли эта ячейка в той же позиции, что и ячейка 
// otherBlock
Block.prototype.equal = function (otherBlock) {
  return this.col === otherBlock.col && this.row === otherBlock.row;
};
 
// Задаем конструктор Snake (змейка)
var Snake = function () {
  this.segments = [
    new Block(7, 5),
    new Block(6, 5),
    new Block(5, 5)
  ];
 
  this.direction = "right";
  this.nextDirection = "right";
};
 
// Рисуем квадратик для каждого сегмента тела змейки
Snake.prototype.draw = function () {
  for (var i = 0; i < this.segments.length; i++) {
    this.segments[i].drawSquare("#0cd3cd");
  }
};
 
// Создаем новую голову и добавляем ее к началу змейки,
// чтобы передвинуть змейку в текущем направлении
Snake.prototype.move = function () {
  var head = this.segments[0];
  var newHead;
 
  this.direction = this.nextDirection;
 
  if (this.direction === "right") {
    newHead = new Block(head.col + 1, head.row);
  } else if (this.direction === "down") {
    newHead = new Block(head.col, head.row + 1);
  } else if (this.direction === "left") {
    newHead = new Block(head.col - 1, head.row);
  } else if (this.direction === "up") {
    newHead = new Block(head.col, head.row - 1);
  }
 
  if (this.checkCollision(newHead)) {
    gameOver();
    return;
  }
  this.segments.unshift(newHead);
  if (newHead.equal(apple.position)) {
    score++;
    apple.move();
  } else {
    this.segments.pop();
  }
  
  if (score === 3) {  //При получении трёх яблок, игра должна остановиться и вывести сообщение о победе.
    Win();
    return;
  };
};

  
 
// Проверяем, не столкнулась ли змейка со стеной или собственным 
// телом
Snake.prototype.checkCollision = function (head) {
  var leftCollision = (head.col === 0);
  var topCollision = (head.row === 0);
  var rightCollision = (head.col === widthInBlocks - 1);
  var bottomCollision = (head.row === heightInBlocks - 1);
  var wallCollision = leftCollision || topCollision || rightCollision || bottomCollision;
 
  var selfCollision = false;
  
  for (var i = 0; i < this.segments.length; i++) {
    if (head.equal(this.segments[i])) {
      selfCollision = true;
    }
  }
 
  return wallCollision || selfCollision;
};
 
// Задаем следующее направление движения змейки на основе нажатой 
// клавиши
Snake.prototype.setDirection = function (newDirection) {
  if (this.direction === "up" && newDirection === "down") {
    return;
  } else if (this.direction === "right" && newDirection === "left") {
    return;
  } else if (this.direction === "down" && newDirection === "up") {
    return;
  } else if (this.direction === "left" && newDirection === "right") {
    return;
  }
 
  this.nextDirection = newDirection;
};
 
// Задаем конструктор Apple (яблоко)
var Apple = function () {
  this.position = new Block(20, 20);
};
 
// Рисуем кружок в позиции яблока
Apple.prototype.draw = function () {
  this.position.drawCircle("Red");
};
 
// Перемещаем яблоко в случайную позицию
Apple.prototype.move = function () {
 var randomCol = Math.floor(Math.random() * (widthInBlocks - 2)) + 1;
 var randomRow = Math.floor(Math.random() * (heightInBlocks - 2)) + 1;
  this.position = new Block(randomCol, randomRow);
};
 
// Создаем объект-змейку и объект-яблоко
var snake = new Snake();
var apple = new Apple();
 
// Запускаем функцию анимации через setInterval
var intervalId = setInterval(function () {
  ctx.clearRect(0, 0, width, height);
  drawScore();
  snake.move();
  snake.draw();
  apple.draw();
  drawBorder();
}, 80);
 
// Преобразуем коды клавиш в направления
var directions = {
  65: "left",
  87: "up",
  68: "right",
  83: "down"
};
 
// Задаем обработчик события keydown (клавиши-стрелки)
$("body").keydown(function (event) {
  var newDirection = directions[event.keyCode];
  if (newDirection !== undefined) {
    snake.setDirection(newDirection);
  }
});
 
 $(document).on("click", ".update", function(){
    location.reload(true);
    });
canvas {
        /*background-color: #839C86;*/
        background-image: url(https://i.pinimg.com/originals/31/fe/12/31fe123182f2a5f956bf542af837ca12.jpg);
        margin-left: 35%;
        margin-top: 1%;
    }
    body {
        background-image: url(Snake/img/Background.jpg);
    }
    text {
        color: white;
    }
    button {
        margin-top: 4%;
        margin-left: 58%;
        font-family: 'Press Start 2P';
        font-size: 10px;
    }

    .gradient {
        background: rgb(255,0,0);
        background: linear-gradient(90deg, rgba(255,0,0,1) 7%, rgba(19,121,9,1) 27%);
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet">
<button class="update">
    Restart
</button>
<canvas id="canvas" width="400" height="400"></canvas>

→ Ссылка