Tirei uns comentários por conta do limite de caracteres, mas acho que deu pra entender.
<meta charset="UTF-8">
<canvas id="t1" width="600" height="400">
<script>
var tela = document.querySelector("canvas#t1");
var pincel = tela.getContext("2d");
var x = 300; // Determina o eixo X (horizontal) da nossa futura animação.
var y = 200; // Determina o eixo Y (vertical) da nossa futura animação.
var raio = 10; // Raio da nossa coroa circula (que é, praticamente, um círculo com um "buraco" no meio). Sempre que eu usar o termo "coroa", caso o seu objetivo seja apenas ver a resolução do exercício, trate a nossa coroa como se fosse o seu círculo. :)
var sentido = 1; // Variável que irá somar com o nosso raio no futuro, assim fazendo a animação de "pulsar" acontecer.
var area = [2500*Math.PI , 4900*Math.PI, (raio**2)*Math.PI]; // Área do limite menor, maior e da coroa circular, respetivamente. Lembrando que a área de uma circunferência é o quadrado do raio multiplicado por PI (ou 3.14).
function coroa(x, y, raio, cor){
pincel.strokeStyle = cor; // Dá cor ao stroke (borda) e recebe o "cor" do parâmetro da função.
pincel.lineWidth = 10; // Define o tamanho das linhas criadas pelo pincel.
pincel.beginPath(); // Inicia um caminho para que a coroa possa ser desenhada.
pincel.arc(x, y, raio, 0, 2*Math.PI); // Define a posição x, y, raio, ângulo inicial e final do nosso círculo.
pincel.stroke(); // Transforma o círculo em uma borda circular (devido a seleção de tamanho que fizemos, fica parecendo uma coroa circular).
}
function verifica(){
if (area[2] > area[0] && area[2] < area[1]+1){ // Para o acertou, a área da nossa coroa tem que ser inferior a do limite menor, mas superior do que a do limite maior. Atender a essas duas condições é o que fará o usuário acertar.
window.alert("Você acertou!"); // Mensagem de exibição caso o usuário consiga acertar.
} else { // "Else" para caso a condição anteriormente requisitada não aconteça.
window.alert("Você errou!"); // Mensagem para caso o usuário não acerte.
}
}
function limpa(){
pincel.clearRect(0, 0, 600 , 400); // Ao invés de desenhar um retângulo que nem o "pincel.fillRect", apaga no formato de um retângulo. Nesse caso, está apagando o canvas inteiro.
}
function limite(x, y, raio, cor){
pincel.strokeStyle = cor; // Apesar de desnecessário, já que os nossos limites serão pretos como o padrão, é bom para caso queira haver uma rápida mudança da coloração.
pincel.lineWidth = 1; // Volta o tamanho de nossas linhas para algo menor (como deveria ser o limite).
pincel.beginPath(); // Inicia o caminho para desenharmos outra borda circunferência.
pincel.arc(x, y, raio, 0, 2*3.14); // Mesma situação da construção da coroa, mas agora para os limites.
pincel.stroke(); // Desenha nossas circunferências-limites como um stroke.
}
function animacao(){
area = [2500*Math.PI , 4900*Math.PI, (raio**2)*Math.PI]; // Fará com que a variável área atualize os seus valores do raio à cada atualização deles feita ao decorrer da animação.
limpa(); // Limpará o nosso canvas constantemente e fará com que a repetição da função "animacao" seja realmente uma animação dinâmica.
limite(x, y, 50, "black"); // Desenha o nosso limite com raio 50.
limite(x, y, 70, "black"); // Desenha o nosso limite com raio 70.
if(raio > 100 ){ // Condição caso o raio seja maior do que 100 (limite imposto por mim para a nossa coroa).
sentido = -1; // Atribui "-1" a variável "sentido", assim podendo subtrair o raio no futuro e fazer a nossa coroa diminuir de tamanho
} else if (raio < 10 ){ // Condição caso o raio seja menor do que 10 (limite mínimo).
sentido = 1; // Já que a coroa estará indo abaixo do seu tamanho mínimo, sentido terá o valor "1" como atribuição e seu raio começará a ser somado - assim fazendo com que aumente de tamanho.
}
coroa(x, y, raio, "pink"); // Desenha a nossa coroa com as variáveis criadas no início dentro do parâmetro de nossa função.
raio += sentido; // Soma ou diminui o valor, dependendo do número atribuído ao "sentido". Algumas pessoas podem se confudir com o fato de somar algo com "-1", mas não esqueça que "10 + (-2)" é o mesmo que "10 - 2", e isso serve para qualquer outra operação parecida. Também não se esqueça que "raio += sentido" é o mesmo que "raio = sentido + raio". Isso é apenas mais um atalho, assim como raio++, para que possamos escrever menos.
}
setInterval(animacao, 15); // Cria um intervalo de 15 milissegundos para cada repetição da função "animacao", assim tornando uma velocidade apropriada para o olho humano. Dessa forma, essa repetição rápida e incessante se tornará uma animação.
tela.onclick= verifica; // Caso o usuário clique em nosso canvas, a função "verifica" checa as condições dentro dela e, caso a área da nossa coroa circular esteja batendo com os requisitos para ganhar, o usuário vencerá! Do contrário, o alerta exibido será o de erro.
</script>