Змейка JS. Искуственный интелект
Хочу сделать змейку на js вместе с ИИ.
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const game = Array.apply(null, {length:40}).map(el=>Array.apply(null,{length:40}).map(el=>0))
let snake = [{x:1,y:1}]
let snakeDirection = {Ox:1,Oy:0}
const grid = 20;
let apple = {x:0, y:0};
let color = "white";
class Neuron{
constructor(value){
this._value=value;
this._weight = random(10,0,false);
}
get value(){return this._value*this._weight }
set weight(value){this._weight-=value}
}
class Brain{
constructor (length){
this._neurons = Array.apply(null,{length}).map(el=>new Neuron(0));
}
set neuron({id, value}) {
this._neurons[id]=value;
}
get neurons (){return this._neurons}
}
const snakeAi = new Brain(13);
function log(text){
const p = document.querySelector("p");
p.innerHTML=text;
}
function random(max,min, floor = true){
let value = Math.random()*(max-min+1)+min;
if(floor){
return Math.floor(value)
}
return value
}
document.addEventListener("keydown",(e)=>{
const key = e.code;
switch(key){
case "KeyW":
if(snakeDirection.Oy===0){snakeDirection.Oy=-1;snakeDirection.Ox=0;}
break;
case "KeyS":
if(snakeDirection.Oy===0){snakeDirection.Oy=1;snakeDirection.Ox=0;}
break;
case "KeyD":
if(snakeDirection.Ox===0){snakeDirection.Ox=1;snakeDirection.Oy=0;}
break;
case "KeyA":
if(snakeDirection.Ox===0){snakeDirection.Ox=-1;snakeDirection.Oy=0;}
break;
case "KeyE":
tik = 4;
break;
case "KeyQ":
tik = 0;
break;
}
})
for(let i = 0; i <10; i++){
snake.push({x:0,y:0})
}
let befforeSnake = snake;
let tik = 0;
function collision(){
if(snake[0].x===apple.x && snake[0].y===apple.y ){
snake.push({x:snake[snake.length-1].x,y:snake[snake.length-1].y})
apple.x=random(game[0].length-1,0);
apple.y=random(game.length-1,0);
}
for(let i = 1; i < snake.length; i++){
if(snake[i].x===snake[0].x && snake[i].y===snake[0].y){
return true
}
}
if(snake[0].x+snakeDirection.Ox === game.length || snake[0].x+snakeDirection.Ox < 0 || snake[0].y+snakeDirection.Oy == game.length || snake[0].y+snakeDirection.Oy < 0 ) return true
}
function move(){
for(let i = 0, befforeEl={}; i<snake.length;i++){
if(i===0){
[befforeEl.x,befforeEl.y]=[snake[i].x,snake[i].y];
snake[i].x+=snakeDirection.Ox;
snake[i].y+=snakeDirection.Oy;
game[snake[i].x][snake[i].y]="h";
}else if(i===snake.length-1){
game[snake[i].x][snake[i].y]=0;
let el = snake[i];
snake[i] = befforeEl;
befforeEl = el;
}else{
let el = snake[i];
snake[i] = befforeEl;
befforeEl = el;
game[snake[i].x][snake[i].y]=1;
}
}
}
let [w,h]=[canvas.width,canvas.height]=[800,800];
apple.x=random(game[0].length-1,0);
apple.y=random(game.length-1,0);
let fps = 0;
function render(){
if(tik++===2){
[w,h]=[canvas.width,canvas.height]=[window.innerWidth,window.innerHeight];
game[apple.x][apple.y]=2;
if(!collision()) tik=0;
move();
ctx.fillStyle = "black";
ctx.fillRect(0,0,w,h);
ctx.strokeStyle="#fffefe";
ctx.fillStyle = "white";
for(let i = 0; i<game.length; i++){
const row = game[i];
for(let j = 0; j<row.length;j++){
if(row[j]===1){
ctx.fillRect(50+i*20,50+j*20,20,20);
}else if(row[j]==="h"){
ctx.fillStyle = "yellow";
ctx.fillRect(50+i*20,50+j*20,20,20);
ctx.fillStyle = "white";
}else if(row[j]===2){
ctx.fillStyle = "green";
ctx.fillRect(50+i*20,50+j*20,20,20);
ctx.fillStyle = "white";
}
}
}
ctx.beginPath();
ctx.rect(50,50,game.length*20,game[0].length*20)
ctx.stroke();
}
fps++;
requestAnimationFrame(render);
}
requestAnimationFrame(render);
setInterval(()=>{log(fps);fps=0;},1000)
body{
margin:0;
}
p{
color:white;
position:absolute;
top: 20px;
left:20px;
}
<p></p>
<canvas></canvas>
Использовал массив в виде карты, предполагалось что так будет менее затратной операция поиска области которую сможет видеть змейка.
Вопрос - как указать змейке область начиная из головы, область обзора должна быть 3 на 5
ооо
гоо - где г- голова, о - область которую видит змейка.
ооо
Желательно, область должна отображаться на игровом поле