made new snake and index and liberary improvements
This commit is contained in:
671
sketches/snakeAIEvolution.js
Normal file
671
sketches/snakeAIEvolution.js
Normal file
@@ -0,0 +1,671 @@
|
||||
let grid = [];
|
||||
let snake = [];
|
||||
let alive = true;
|
||||
let snakeDirection = 0;
|
||||
let AItype = "random";
|
||||
let gridSize = 20;
|
||||
let gridColumns = 10;
|
||||
let gridRows = 10;
|
||||
let eatenApples = 0;
|
||||
let _textSize = 16;
|
||||
let appleAmount = 1;
|
||||
let gameSpeed = 10;
|
||||
let buttonAddColoums = null;
|
||||
let buttonAddRows = null;
|
||||
let buttonUpgradeAI = null;
|
||||
let buttonAddMoreApples = null;
|
||||
let buttonSpeedUpgrade = null;
|
||||
let SpeedUpgradePrice = 5;
|
||||
let AddMoreApplesPrice = 1;
|
||||
let AddColoumsPrice = 1;
|
||||
let AddRowsPrice = 1;
|
||||
let UpgradeAIPrice = 1;
|
||||
let buttonSnifferUP = null;
|
||||
let buttonSnifferDown = null;
|
||||
let sniffingDistance = 1;
|
||||
let buttonEyeUp = null;
|
||||
let buttonEyeDown = null;
|
||||
let eyeDistance = 1;
|
||||
let snifferUpgradePrice = 1;
|
||||
let eyeUpgradePrice = 1;
|
||||
let snifferLevel = 1;
|
||||
let eyeLevel = 1;
|
||||
let sniffingIncrement = 1;
|
||||
let eyeIncrement = 2;
|
||||
let sniffingPriceIncrement = 2;
|
||||
let eyePriceIncrement = 2;
|
||||
let moulthOpenDistance = 2;
|
||||
|
||||
|
||||
function setup() {
|
||||
buttonAddColoums = createButton("Add coloums");
|
||||
buttonAddRows = createButton("Add rows");
|
||||
buttonAddMoreApples = createButton("Add more apples");
|
||||
buttonSpeedUpgrade = createButton("Increase speed");
|
||||
buttonSnifferUP = createButton("SnifferUp");
|
||||
buttonSnifferDown = createButton("SnifferDown");
|
||||
buttonEyeUp = createButton("EyeUp");
|
||||
buttonEyeDown = createButton("EyeDown");
|
||||
createCanvas(windowWidth, windowHeight);
|
||||
background(255, 255, 255);
|
||||
for (let i = 0; i < gridColumns; i++) {
|
||||
grid[i] = [];
|
||||
for (let j = 0; j < gridRows; j++) {
|
||||
grid[i][j] = 0;
|
||||
}
|
||||
}
|
||||
buttonAddColoums.mousePressed(buttonAddColoumsPressed);
|
||||
buttonAddRows.mousePressed(buttonAddRowsPressed);
|
||||
buttonAddMoreApples.mousePressed(buttonAddMoreApplesPressed);
|
||||
buttonSpeedUpgrade.mousePressed(buttonSpeedUpgradePressed);
|
||||
buttonSnifferUP.mousePressed(buttonSnifferUPPressed);
|
||||
buttonSnifferDown.mousePressed(buttonSnifferDownPressed);
|
||||
buttonEyeUp.mousePressed(buttonEyeUpPressed);
|
||||
buttonEyeDown.mousePressed(buttonEyeDownPressed);
|
||||
frameRate(gameSpeed);
|
||||
summonSnake();
|
||||
summonApple();
|
||||
drawGrid();
|
||||
}
|
||||
|
||||
|
||||
function buttonSnifferUPPressed(){
|
||||
if (sniffingDistance > gridRows) {
|
||||
return;
|
||||
}
|
||||
if (snifferUpgradePrice > eatenApples) {
|
||||
return;
|
||||
}
|
||||
if (!(snifferLevel * sniffingIncrement > sniffingDistance)) {
|
||||
eatenApples -= snifferUpgradePrice;
|
||||
snifferUpgradePrice += sniffingPriceIncrement;
|
||||
snifferLevel ++;
|
||||
}
|
||||
|
||||
sniffingDistance += sniffingIncrement;
|
||||
}
|
||||
function buttonSnifferDownPressed(){
|
||||
if (sniffingDistance < 1) {
|
||||
return;
|
||||
}
|
||||
sniffingDistance -= sniffingIncrement;
|
||||
}
|
||||
|
||||
function buttonSpeedUpgradePressed(){
|
||||
|
||||
if (eatenApples < SpeedUpgradePrice) {
|
||||
return;
|
||||
}
|
||||
|
||||
eatenApples -= SpeedUpgradePrice;
|
||||
|
||||
gameSpeed += 2;
|
||||
|
||||
frameRate(gameSpeed);
|
||||
|
||||
SpeedUpgradePrice += 5;
|
||||
}
|
||||
|
||||
function buttonEyeUpPressed(){
|
||||
if (eyeDistance > gridColumns) {
|
||||
return;
|
||||
}
|
||||
if (!(eyeLevel * eyeIncrement + 1 >= eyeDistance) && eyeUpgradePrice <= eatenApples) {
|
||||
eatenApples -= eyeUpgradePrice;
|
||||
eyeUpgradePrice += eyePriceIncrement;
|
||||
eyeLevel ++;
|
||||
}else if(eyeUpgradePrice > eatenApples){
|
||||
return;
|
||||
}
|
||||
|
||||
eyeDistance += eyeIncrement;
|
||||
}
|
||||
function buttonEyeDownPressed(){
|
||||
if (eyeDistance < 1) {
|
||||
return;
|
||||
}
|
||||
eyeDistance -= eyeIncrement;
|
||||
}
|
||||
|
||||
function buttonAddColoumsPressed(){
|
||||
if (eatenApples < AddColoumsPrice) {
|
||||
return;
|
||||
}
|
||||
eatenApples -= AddColoumsPrice;
|
||||
gridColumns++;
|
||||
grid.push([]);
|
||||
for (let i = 0; i < gridRows; i++) {
|
||||
grid[grid.length - 1][i] = 0;
|
||||
}
|
||||
}
|
||||
function buttonAddRowsPressed(){
|
||||
if (eatenApples < AddRowsPrice) {
|
||||
return;
|
||||
}
|
||||
eatenApples -= AddRowsPrice;
|
||||
gridRows++;
|
||||
for (let i = 0; i < gridColumns; i++) {
|
||||
grid[i].push(0);
|
||||
}
|
||||
}
|
||||
|
||||
function buttonAddMoreApplesPressed(){
|
||||
if (eatenApples < AddMoreApplesPrice) {
|
||||
return;
|
||||
}
|
||||
eatenApples -= AddMoreApplesPrice;
|
||||
if (appleAmount < 5){
|
||||
AddMoreApplesPrice += 1;
|
||||
}else if (appleAmount < 10){
|
||||
AddMoreApplesPrice += 2;
|
||||
}else if (appleAmount < 20){
|
||||
AddMoreApplesPrice += 3;
|
||||
}else if (appleAmount < 50){
|
||||
AddMoreApplesPrice += 4;
|
||||
}else{
|
||||
AddMoreApplesPrice += ceil(AddMoreApplesPrice*0.15);
|
||||
}
|
||||
summonApple();
|
||||
appleAmount++;
|
||||
}
|
||||
|
||||
function summonApple(){
|
||||
if (appleAmount >= gridColumns * gridRows - snake.length ) {
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
for (let j = 0; j < grid[0].length; j++) {
|
||||
if (grid[i][j] == 2) {
|
||||
grid[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
let x = grid.length - floor(random(1, grid.length +1));
|
||||
let y = grid[0].length - floor(random(1, grid[0].length +1));
|
||||
if(grid[x][y] == 2 || grid[x][y] == 1){
|
||||
summonApple();//best practice coding right here
|
||||
return;
|
||||
}
|
||||
grid[x][y] = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function dontMoveBackwards(lastSnakeX, lastSnakeY, currentSnakeX, currentSnakeY, direction){
|
||||
if (direction == 0) {
|
||||
return lastSnakeX < currentSnakeX;
|
||||
}else if (direction == 1) {
|
||||
return lastSnakeY < currentSnakeY;
|
||||
}else if (direction == 2) {
|
||||
return lastSnakeX > currentSnakeX;
|
||||
}else if (direction == 3) {
|
||||
return lastSnakeY > currentSnakeY;
|
||||
}
|
||||
}
|
||||
|
||||
function restartGame(){
|
||||
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
for (let j = 0; j < grid[0].length; j++) {
|
||||
|
||||
if (grid[i][j] == 2 || grid[i][j] == 1) {
|
||||
grid[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snake = [];
|
||||
|
||||
summonSnake();
|
||||
|
||||
for (let i = 0; i < appleAmount; i++) {
|
||||
summonApple();
|
||||
}
|
||||
|
||||
alive = true;
|
||||
}
|
||||
|
||||
function runSnake(){
|
||||
let x = snake[0][0];
|
||||
let y = snake[0][1];
|
||||
for (let i = snake.length - 1; i > 0; i--) {
|
||||
snake[i][0] = snake[i - 1][0];
|
||||
snake[i][1] = snake[i - 1][1];
|
||||
}
|
||||
snakeAI();
|
||||
let lastSnakeX = snake[1][0]
|
||||
let lastSnakeY = snake[1][1];
|
||||
if (dontMoveBackwards(lastSnakeX, lastSnakeY, x, y, snakeDirection)) {
|
||||
snakeDirection = (snakeDirection + 2) % 4;
|
||||
}
|
||||
if (snakeDirection == 0) {
|
||||
snake[0][0] += 1;
|
||||
}else if (snakeDirection == 1) {
|
||||
snake[0][1] += 1;
|
||||
}else if (snakeDirection == 2) {
|
||||
snake[0][0] -= 1;
|
||||
}else if (snakeDirection == 3) {
|
||||
snake[0][1] -= 1;
|
||||
}
|
||||
if (snake[0][1] >= grid[0].length || snake[0][1] < 0 || snake[0][0] >= grid.length || snake[0][0] < 0) {
|
||||
alive = false;
|
||||
return;
|
||||
}
|
||||
if (grid[snake[0][0]][snake[0][1]] == 2) {
|
||||
alive = false;
|
||||
return;
|
||||
}
|
||||
if (grid[snake[0][0]][snake[0][1]] == 1) {
|
||||
snake.push([snake[snake.length - 1][0], snake[snake.length - 1][1]]);
|
||||
summonApple();
|
||||
eatenApples++;
|
||||
}
|
||||
if (
|
||||
snake.length >=
|
||||
(gridColumns * gridRows) - appleAmount
|
||||
){
|
||||
restartGame();
|
||||
return;
|
||||
}
|
||||
drawSnakeOnGrid();
|
||||
}
|
||||
|
||||
function summonSnake(){
|
||||
let x = grid.length - floor(random(1, grid.length));
|
||||
let y = grid[0].length - floor(random(1, grid[0].length));
|
||||
snake.push([x, y]);
|
||||
snake.push([x - 1, y]);
|
||||
snake.push([x - 2, y]);
|
||||
drawSnakeOnGrid();
|
||||
}
|
||||
|
||||
function drawSnakeOnGrid(){
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
for (let j = 0; j < grid[0].length; j++) {
|
||||
if (grid[i][j] == 2) {
|
||||
grid[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < snake.length; i++) {
|
||||
|
||||
let x = snake[i][0];
|
||||
let y = snake[i][1];
|
||||
|
||||
// prevent crash
|
||||
if (
|
||||
x < 0 ||
|
||||
y < 0 ||
|
||||
x >= grid.length ||
|
||||
y >= grid[0].length
|
||||
){
|
||||
alive = false;
|
||||
return;
|
||||
}
|
||||
|
||||
grid[x][y] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
function drawGrid() {
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
for (let j = 0; j < grid[0].length; j++) {
|
||||
switch (grid[i][j]) {
|
||||
case 1:
|
||||
strokeWeight(0)
|
||||
fill(255, 0, 0);
|
||||
circle(i*gridSize+gridSize/2, j*gridSize+gridSize/2, gridSize-2);
|
||||
break;
|
||||
case 2:
|
||||
if (i == snake[0][0] && j == snake[0][1]) {
|
||||
strokeWeight(0)
|
||||
fill(0, 233, 0);
|
||||
rect(i * gridSize, j * gridSize, gridSize, gridSize);
|
||||
fill(100, 255, 100);
|
||||
circle(i*gridSize+gridSize/2, j*gridSize+gridSize/2, gridSize-2);
|
||||
switch (snakeDirection) {
|
||||
case 0://right
|
||||
makeEye(i*gridSize+gridSize/4, j*gridSize+gridSize/4);
|
||||
makeEye(i*gridSize+gridSize/4, j*gridSize+gridSize/4*3);
|
||||
break;
|
||||
case 1://down
|
||||
makeEye(i*gridSize+gridSize/4, j*gridSize+gridSize/4);
|
||||
makeEye(i*gridSize+gridSize/4*3, j*gridSize+gridSize/4);
|
||||
break;
|
||||
case 2://left
|
||||
makeEye(i*gridSize+gridSize/4*3, j*gridSize+gridSize/4);
|
||||
makeEye(i*gridSize+gridSize/4*3, j*gridSize+gridSize/4*3);
|
||||
break;
|
||||
case 3://up
|
||||
makeEye(i*gridSize+gridSize/4, j*gridSize+gridSize/4*3);
|
||||
makeEye(i*gridSize+gridSize/4*3, j*gridSize+gridSize/4*3);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid snakeDirection: " + snakeDirection);
|
||||
break;
|
||||
}
|
||||
makeMoulth(snakeDirection,i,j);
|
||||
}else{
|
||||
const snakeIndex = getSnakePartIndex(i, j);
|
||||
if (snakeIndex == -1) {
|
||||
console.error("Snake part not found: " + i + ", " + j);
|
||||
}
|
||||
let SnakeGreen = 255-snakeIndex*10;
|
||||
let SnakeBlue = 0;
|
||||
let SnakeRed = 0;
|
||||
if (SnakeGreen < 0) {
|
||||
SnakeBlue = abs(SnakeGreen);
|
||||
}
|
||||
if (SnakeBlue > 255) {
|
||||
SnakeRed = SnakeBlue-255;
|
||||
}
|
||||
|
||||
strokeWeight(0)
|
||||
fill(SnakeRed, SnakeGreen, SnakeBlue);
|
||||
rect(i * gridSize, j * gridSize, gridSize, gridSize);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
strokeWeight(0.3)
|
||||
fill(255, 255, 255);
|
||||
rect(i * gridSize, j * gridSize, gridSize, gridSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeEye(x,y){
|
||||
if (countFreeNeighbors(snake[0][0], snake[0][1]) == 0) {
|
||||
//make dead eyes
|
||||
fill(0, 0, 0);
|
||||
strokeWeight(2);
|
||||
line(x-gridSize/16, y-gridSize/16, x+gridSize/16, y+gridSize/16);
|
||||
line(x-gridSize/16, y+gridSize/16, x+gridSize/16, y-gridSize/16);
|
||||
return;
|
||||
}
|
||||
fill(255, 255, 255);
|
||||
circle(x, y, gridSize/4);
|
||||
fill(25, 255, 25);
|
||||
circle(x, y, gridSize/8);
|
||||
fill(0, 0, 0);
|
||||
circle(x, y, gridSize/16);
|
||||
}
|
||||
function makeMoulth(direction,i,j){
|
||||
let x, y, w, h;
|
||||
fill(0, 0, 0);
|
||||
if (moulthOpenDistance >= getClosestAppleDistanceToSnake()) {
|
||||
switch (direction) {
|
||||
case 0://right
|
||||
x = gridSize*i+gridSize/16*11;
|
||||
y = gridSize*j+gridSize/2;
|
||||
w = gridSize/8*5;
|
||||
h = gridSize/4*3;
|
||||
break;
|
||||
case 1://down
|
||||
x = gridSize*i+gridSize/2;
|
||||
y = gridSize*j+gridSize/16*11;
|
||||
w = gridSize/4*3;
|
||||
h = gridSize/8*5;
|
||||
break;
|
||||
case 2://left
|
||||
x = gridSize*i+gridSize/16*5;
|
||||
y = gridSize*j+gridSize/2;
|
||||
w = gridSize/8*5;
|
||||
h = gridSize/4*3;
|
||||
break;
|
||||
case 3://up
|
||||
x = gridSize*i+gridSize/2;
|
||||
y = gridSize*j+gridSize/16*5;
|
||||
w = gridSize/4*3;
|
||||
h = gridSize/8*5;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid direction SnakeDirection: " + snakeDirection);
|
||||
break;
|
||||
|
||||
}
|
||||
ellipse(x, y, w, h)
|
||||
}else{
|
||||
switch (direction) {
|
||||
case 0://right
|
||||
x = gridSize*i+gridSize/16*13;
|
||||
y = gridSize*j+gridSize/2;
|
||||
w = gridSize/16;
|
||||
h = gridSize/4*3;
|
||||
break;
|
||||
case 1://down
|
||||
x = gridSize*i+gridSize/2;
|
||||
y = gridSize*j+gridSize/16*13;
|
||||
w = gridSize/4*3;
|
||||
h = gridSize/16;
|
||||
break;
|
||||
case 2://left
|
||||
x = gridSize*i+gridSize/16;
|
||||
y = gridSize*j+gridSize/2;
|
||||
w = gridSize/16;
|
||||
h = gridSize/4*3;
|
||||
break;
|
||||
case 3://up
|
||||
x = gridSize*i+gridSize/2;
|
||||
y = gridSize*j+gridSize/16;
|
||||
w = gridSize/4*3;
|
||||
h = gridSize/16;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Invalid direction SnakeDirection: " + snakeDirection);
|
||||
break;
|
||||
}
|
||||
ellipse(x, y, w, h)
|
||||
}
|
||||
}
|
||||
|
||||
function getSnakePartIndex(x, y){
|
||||
for (let i = 0; i < snake.length; i++) {
|
||||
if (snake[i][0] == x && snake[i][1] == y) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function draw() {
|
||||
|
||||
if (alive == false){
|
||||
restartGame();
|
||||
}
|
||||
|
||||
background(255);
|
||||
|
||||
runSnake();
|
||||
drawGrid();
|
||||
|
||||
fill(0, 0, 0);
|
||||
textSize(_textSize);
|
||||
|
||||
text("₴ " + eatenApples, gridColumns * gridSize + gridSize + _textSize*3, _textSize * 1);
|
||||
text("More apples: " + appleAmount, gridColumns * gridSize + gridSize, _textSize * 2);
|
||||
|
||||
buttonAddMoreApples.html("Add more apples ₴ " + AddMoreApplesPrice);
|
||||
buttonAddMoreApples.position(gridColumns * gridSize + gridSize + _textSize*7, _textSize * 1.1);
|
||||
|
||||
text("AI Upgrades ", gridColumns * gridSize + gridSize, _textSize * 3);
|
||||
text("Better Eyes: " + eyeLevel, gridColumns * gridSize + gridSize, _textSize * 4);
|
||||
|
||||
buttonEyeUp.html("Upgrade Eyes ₴ " + eyeUpgradePrice);
|
||||
buttonEyeUp.position(gridColumns * gridSize + gridSize + _textSize*7, _textSize * 3.1);
|
||||
buttonEyeDown.html("Downgrade Eyes");
|
||||
buttonEyeDown.position(gridColumns * gridSize + gridSize + _textSize*13, _textSize * 3.1);
|
||||
|
||||
text("Better Sniffer: " + snifferLevel, gridColumns * gridSize + gridSize, _textSize * 5);
|
||||
|
||||
buttonSnifferUP.mousePressed(buttonSnifferUPPressed);
|
||||
buttonSnifferUP.html("Upgrade Sniffer ₴ " + snifferUpgradePrice);
|
||||
buttonSnifferUP.position(gridColumns * gridSize + gridSize + _textSize*8, _textSize * 4.1);
|
||||
buttonSnifferDown.html("Downgrade Sniffer");
|
||||
buttonSnifferDown.position(gridColumns * gridSize + gridSize + _textSize*14, _textSize * 4.1);
|
||||
}
|
||||
function mousePressed() {
|
||||
}
|
||||
|
||||
function snakeAI(){
|
||||
direction = floor(random(0, 4));
|
||||
count = 0;
|
||||
while (!isDirectionSafe(direction)) {
|
||||
count++;
|
||||
if (count > 20) {
|
||||
snakeDirection =0;
|
||||
return;
|
||||
}
|
||||
direction = floor(random(0, 4));
|
||||
if (sniffingDistance >= getClosestAppleDistanceToSnake()) {
|
||||
console.log("sniffing apple");
|
||||
direction = pathSnakeToPoint(getClosestApple()[0], getClosestApple()[1]);
|
||||
|
||||
}
|
||||
if (isAppleInView(snakeDirection, eyeDistance)) {
|
||||
console.log("apple in view");
|
||||
direction = snakeDirection;
|
||||
}
|
||||
}
|
||||
snakeDirection = direction;
|
||||
}
|
||||
|
||||
function directionToVector(direction){
|
||||
|
||||
switch(direction){
|
||||
case 0:
|
||||
return [1, 0];
|
||||
|
||||
case 1:
|
||||
return [0, 1];
|
||||
|
||||
case 2:
|
||||
return [-1, 0];
|
||||
|
||||
case 3:
|
||||
return [0, -1];
|
||||
}
|
||||
}
|
||||
|
||||
function pathSnakeToPoint(x,y){
|
||||
let vec = [x - snake[0][0], y - snake[0][1]];
|
||||
|
||||
if (vec[0] > 0){
|
||||
return 0;
|
||||
}else if (vec[0] < 0){
|
||||
return 2;
|
||||
}else if (vec[1] > 0){
|
||||
return 1;
|
||||
}else if (vec[1] < 0){
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
function isDirectionSafe(direction){
|
||||
|
||||
let vec = directionToVector(direction);
|
||||
|
||||
let newX = snake[0][0] + vec[0];
|
||||
let newY = snake[0][1] + vec[1];
|
||||
|
||||
if (
|
||||
newX < 0 ||
|
||||
newY < 0 ||
|
||||
newX >= grid.length ||
|
||||
newY >= grid[0].length
|
||||
){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (grid[newX][newY] == 2){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function getClosestApple(){
|
||||
|
||||
let bestApple = null;
|
||||
let bestDistance = Infinity;
|
||||
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
for (let j = 0; j < grid[0].length; j++) {
|
||||
|
||||
if (grid[i][j] == 1){
|
||||
|
||||
let distance =
|
||||
abs(snake[0][0] - i) +
|
||||
abs(snake[0][1] - j);
|
||||
|
||||
if (distance < bestDistance){
|
||||
bestDistance = distance;
|
||||
bestApple = [i, j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestApple;
|
||||
}
|
||||
|
||||
function getClosestAppleDistanceToPoint(x, y){
|
||||
let apple = getClosestApple();
|
||||
if (apple == null){
|
||||
return Infinity;
|
||||
}
|
||||
return abs(x - apple[0]) + abs(y - apple[1]);
|
||||
}
|
||||
|
||||
function getClosestAppleDistanceToSnake(){
|
||||
return getClosestAppleDistanceToPoint(snake[0][0], snake[0][1]);
|
||||
}
|
||||
|
||||
function isAppleInView(snakeDirection, viewDistance){
|
||||
|
||||
let vec = directionToVector(snakeDirection);
|
||||
|
||||
for (let i = 0; i < viewDistance; i++) {
|
||||
if (i >= grid.length || i >= grid[0].length|| snake[0][0]+(vec[0] *i) >= grid.length || snake[0][0]+(vec[0] *i) < 0 || snake[0][1]+(vec[1] *i) >= grid[0].length || snake[0][1]+(vec[1] *i) < 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
if (grid[snake[0][0] + (vec[0] * i)][snake[0][1] + (vec[1] * i)] == 1){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function countFreeNeighbors(x, y){
|
||||
|
||||
let count = 0;
|
||||
|
||||
let dirs = [
|
||||
[1,0],
|
||||
[0,1],
|
||||
[-1,0],
|
||||
[0,-1]
|
||||
];
|
||||
|
||||
for (let i = 0; i < dirs.length; i++) {
|
||||
|
||||
let nx = x + dirs[i][0];
|
||||
let ny = y + dirs[i][1];
|
||||
|
||||
if (
|
||||
nx >= 0 &&
|
||||
ny >= 0 &&
|
||||
nx < grid.length &&
|
||||
ny < grid[0].length &&
|
||||
grid[nx][ny] != 2
|
||||
){
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
Reference in New Issue
Block a user