From 10af4e9ff87e220ebdcab9a0408c4881cefd9be4 Mon Sep 17 00:00:00 2001 From: owishi Date: Sun, 13 Mar 2022 02:06:05 +0600 Subject: [PATCH 1/6] bug with 3s --- pages/index.js | 88 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 18 deletions(-) diff --git a/pages/index.js b/pages/index.js index de83024..6ce2634 100644 --- a/pages/index.js +++ b/pages/index.js @@ -63,7 +63,9 @@ const getRandomCell = () => ({ y: Math.floor(Math.random() * Config.width), }); -const Snake = () => { +//custom hook +//controller +const UseSnake = () => { const getDefaultSnake = () => [ { x: 8, y: 12 }, { x: 7, y: 12 }, @@ -75,67 +77,109 @@ const Snake = () => { const [snake, setSnake] = useState(getDefaultSnake()); const [direction, setDirection] = useState(Direction.Right); - const [food, setFood] = useState({ x: 4, y: 10 }); - const [score, setScore] = useState(0); + const [foods, setFoods] = useState([{ x: 4, y: 10 }]); + const score = snake.length-3; + const resetGame = () => { + setSnake(getDefaultSnake()) + setDirection(Direction.Right) + setFoods([{ x: 4, y: 10 }]) + } // move the snake useEffect(() => { const runSingleStep = () => { setSnake((snake) => { const head = snake[0]; - const newHead = { x: head.x + direction.x, y: head.y + direction.y }; + const newHead = { x: (head.x + direction.x + Config.width) % Config.width, + y: (head.y + direction.y + Config.height) % Config.height }; // make a new snake by extending head - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax const newSnake = [newHead, ...snake]; - // remove tail - newSnake.pop(); + // remove tail when head doesnt eat food + if(!isFood(newHead)){ + newSnake.pop(); + } + if(isSnake(newHead)){ + resetGame() + } return newSnake; }); }; runSingleStep(); - const timer = setInterval(runSingleStep, 500); + const timer = setInterval(runSingleStep, 300); return () => clearInterval(timer); - }, [direction, food]); + }, [direction, foods]); // update score whenever head touches a food useEffect(() => { const head = snake[0]; if (isFood(head)) { - setScore((score) => { - return score + 1; - }); let newFood = getRandomCell(); while (isSnake(newFood)) { newFood = getRandomCell(); } - setFood(newFood); + setFoods(currentFoods => { + currentFoods.filter(food => food.x!==head.x && food.y!==head.y) + return [...currentFoods,newFood]//? + }); } }, [snake]); + //food after 3s + useEffect(() => { + const interval = setInterval(()=> { + let newFood = getRandomCell(); + while (isSnake(newFood) || isFood(newFood)) { + newFood = getRandomCell(); + } + setFoods(currentFoods => [...currentFoods,newFood]); + },3000); + + return ( () => + clearInterval(interval) + ) + + },[foods]) + useEffect(() => { const handleNavigation = (event) => { switch (event.key) { case "ArrowUp": - setDirection(Direction.Top); + setDirection((direction) =>{ + if(direction!==Direction.Bottom) + return Direction.Top; + return direction; + }) break; case "ArrowDown": - setDirection(Direction.Bottom); + setDirection((direction) =>{ + if(direction!==Direction.Top) + return Direction.Bottom; + return direction; + }) break; case "ArrowLeft": - setDirection(Direction.Left); + setDirection((direction) =>{ + if(direction!==Direction.Right) + return Direction.Left; + return direction; + }) break; case "ArrowRight": - setDirection(Direction.Right); + setDirection((direction) =>{ + if(direction!==Direction.Left) + return Direction.Right; + return direction; + }) break; } }; @@ -146,11 +190,19 @@ const Snake = () => { // ?. is called optional chaining // see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining - const isFood = ({ x, y }) => food?.x === x && food?.y === y; + const isFood = ({ x, y }) => + foods.find((position)=> position.x === x && position.y === y); const isSnake = ({ x, y }) => snake.find((position) => position.x === x && position.y === y); + + return {score,isFood, isSnake} +} + +//view +const Snake = () => { + const {score, isFood, isSnake} = UseSnake() const cells = []; for (let x = 0; x < Config.width; x++) { for (let y = 0; y < Config.height; y++) { From 75bb8db606c3376480b5860cc604542b06564e5f Mon Sep 17 00:00:00 2001 From: owishi Date: Mon, 14 Mar 2022 23:38:20 +0600 Subject: [PATCH 2/6] bug in removing after 10s --- pages/index.js | 62 +++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/pages/index.js b/pages/index.js index 6ce2634..3b61515 100644 --- a/pages/index.js +++ b/pages/index.js @@ -112,22 +112,15 @@ const UseSnake = () => { const timer = setInterval(runSingleStep, 300); return () => clearInterval(timer); - }, [direction, foods]); + }, [direction]); // update score whenever head touches a food useEffect(() => { const head = snake[0]; if (isFood(head)) { - - let newFood = getRandomCell(); - while (isSnake(newFood)) { - newFood = getRandomCell(); - } - - setFoods(currentFoods => { + setFoods(currentFoods => currentFoods.filter(food => food.x!==head.x && food.y!==head.y) - return [...currentFoods,newFood]//? - }); + );//doesnt work with return } }, [snake]); @@ -147,39 +140,47 @@ const UseSnake = () => { },[foods]) + //food after 10s + //doesnt work + useEffect(() => { + const interval = setInterval(()=> { + setFoods(currentFoods => currentFoods.slice(1)) + // currentFoods.shift(); --> doesnt work + + },10000); + + return ( () => + clearInterval(interval) + ) + + },[foods]) + + const changeDir = (checkDir, newDir) => { + setDirection((direction) => { + if(direction!=checkDir) + return newDir; + return direction; + }) + + } + useEffect(() => { const handleNavigation = (event) => { switch (event.key) { case "ArrowUp": - setDirection((direction) =>{ - if(direction!==Direction.Bottom) - return Direction.Top; - return direction; - }) + changeDir(Direction.Bottom,Direction.Top); break; case "ArrowDown": - setDirection((direction) =>{ - if(direction!==Direction.Top) - return Direction.Bottom; - return direction; - }) + changeDir(Direction.Top,Direction.Bottom); break; case "ArrowLeft": - setDirection((direction) =>{ - if(direction!==Direction.Right) - return Direction.Left; - return direction; - }) + changeDir(Direction.Right,Direction.Left); break; case "ArrowRight": - setDirection((direction) =>{ - if(direction!==Direction.Left) - return Direction.Right; - return direction; - }) + changeDir(Direction.Left,Direction.Right); break; } }; @@ -189,7 +190,6 @@ const UseSnake = () => { }, []); // ?. is called optional chaining - // see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining const isFood = ({ x, y }) => foods.find((position)=> position.x === x && position.y === y); From 138d2ceeeb5fc4a859ae58ae38b90ea9e7be9307 Mon Sep 17 00:00:00 2001 From: owishi Date: Thu, 17 Mar 2022 12:48:05 +0600 Subject: [PATCH 3/6] complete snake --- pages/index.js | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/pages/index.js b/pages/index.js index 3b61515..c07206f 100644 --- a/pages/index.js +++ b/pages/index.js @@ -77,13 +77,13 @@ const UseSnake = () => { const [snake, setSnake] = useState(getDefaultSnake()); const [direction, setDirection] = useState(Direction.Right); - const [foods, setFoods] = useState([{ x: 4, y: 10 }]); + const [foods, setFoods] = useState([]); const score = snake.length-3; const resetGame = () => { setSnake(getDefaultSnake()) setDirection(Direction.Right) - setFoods([{ x: 4, y: 10 }]) + setFoods([]) } // move the snake useEffect(() => { @@ -118,9 +118,9 @@ const UseSnake = () => { useEffect(() => { const head = snake[0]; if (isFood(head)) { - setFoods(currentFoods => - currentFoods.filter(food => food.x!==head.x && food.y!==head.y) - );//doesnt work with return + setFoods(currentFoods =>currentFoods.filter(food => food.x!==head.x && food.y!==head.y) + + ); } }, [snake]); @@ -132,20 +132,23 @@ const UseSnake = () => { newFood = getRandomCell(); } setFoods(currentFoods => [...currentFoods,newFood]); + setTimeout(() => { + setFoods((f) => f.filter(e => e.x !=newFood.x && e.y !=newFood.y)) + }, 10*1000) },3000); return ( () => clearInterval(interval) ) - },[foods]) + },[]) //food after 10s //doesnt work useEffect(() => { const interval = setInterval(()=> { - setFoods(currentFoods => currentFoods.slice(1)) - // currentFoods.shift(); --> doesnt work + // setFoods(currentFoods => currentFoods.slice(1)) + // currentFoods.shift(); --> doesnt work either },10000); @@ -153,7 +156,7 @@ const UseSnake = () => { clearInterval(interval) ) - },[foods]) + },[]) const changeDir = (checkDir, newDir) => { setDirection((direction) => { From 8668a1176a04ebd98d6ef2862a31e807fd79d9bb Mon Sep 17 00:00:00 2001 From: owishi Date: Sat, 19 Mar 2022 21:37:48 +0600 Subject: [PATCH 4/6] bug in removing after 10s --- pages/index.js | 100 +++++++++++++++++++++---------------------------- 1 file changed, 43 insertions(+), 57 deletions(-) diff --git a/pages/index.js b/pages/index.js index c07206f..b227ada 100644 --- a/pages/index.js +++ b/pages/index.js @@ -3,8 +3,8 @@ import { useEffect, useState, useRef } from "react"; import styles from "../styles/Snake.module.css"; const Config = { - height: 25, - width: 25, + height: 15, + width: 15, cellSize: 32, }; @@ -61,6 +61,7 @@ const Cell = ({ x, y, type }) => { const getRandomCell = () => ({ x: Math.floor(Math.random() * Config.width), y: Math.floor(Math.random() * Config.width), + start: Math.floor(Math.random()), }); //custom hook @@ -78,30 +79,32 @@ const UseSnake = () => { const [direction, setDirection] = useState(Direction.Right); const [foods, setFoods] = useState([]); - const score = snake.length-3; + const score = snake.length - 3; const resetGame = () => { - setSnake(getDefaultSnake()) - setDirection(Direction.Right) - setFoods([]) - } + setSnake(getDefaultSnake()); + setDirection(Direction.Right); + setFoods([]); + }; // move the snake useEffect(() => { const runSingleStep = () => { setSnake((snake) => { const head = snake[0]; - const newHead = { x: (head.x + direction.x + Config.width) % Config.width, - y: (head.y + direction.y + Config.height) % Config.height }; + const newHead = { + x: (head.x + direction.x + Config.width) % Config.width, + y: (head.y + direction.y + Config.height) % Config.height, + }; // make a new snake by extending head const newSnake = [newHead, ...snake]; // remove tail when head doesnt eat food - if(!isFood(newHead)){ + if (!isFood(newHead)) { newSnake.pop(); } - if(isSnake(newHead)){ - resetGame() + if (isSnake(newHead)) { + resetGame(); } return newSnake; @@ -118,72 +121,56 @@ const UseSnake = () => { useEffect(() => { const head = snake[0]; if (isFood(head)) { - setFoods(currentFoods =>currentFoods.filter(food => food.x!==head.x && food.y!==head.y) - - ); + setFoods((currentFoods) => + currentFoods.filter((food) => food.x !== head.x && food.y !== head.y) + ); } }, [snake]); //food after 3s useEffect(() => { - const interval = setInterval(()=> { + const interval = setInterval(() => { let newFood = getRandomCell(); while (isSnake(newFood) || isFood(newFood)) { newFood = getRandomCell(); } - setFoods(currentFoods => [...currentFoods,newFood]); - setTimeout(() => { - setFoods((f) => f.filter(e => e.x !=newFood.x && e.y !=newFood.y)) - }, 10*1000) - },3000); - - return ( () => - clearInterval(interval) - ) - - },[]) - - //food after 10s - //doesnt work - useEffect(() => { - const interval = setInterval(()=> { - // setFoods(currentFoods => currentFoods.slice(1)) - // currentFoods.shift(); --> doesnt work either - - },10000); - - return ( () => - clearInterval(interval) - ) - - },[]) + setFoods((currentFoods) => [...currentFoods, newFood]); + setTimeout(() => { + setFoods((f) => + f.filter( + (e) => + e.start!==newFood.start + ) + ); + },10*1000); + }, 3000); + return () => clearInterval(interval); + }, []); const changeDir = (checkDir, newDir) => { setDirection((direction) => { - if(direction!=checkDir) - return newDir; + if (direction != checkDir) return newDir; return direction; - }) - - } + }); + }; useEffect(() => { const handleNavigation = (event) => { switch (event.key) { case "ArrowUp": - changeDir(Direction.Bottom,Direction.Top); + changeDir(Direction.Bottom, Direction.Top); break; case "ArrowDown": - changeDir(Direction.Top,Direction.Bottom); + changeDir(Direction.Top, Direction.Bottom); break; case "ArrowLeft": - changeDir(Direction.Right,Direction.Left); + changeDir(Direction.Right, Direction.Left); break; case "ArrowRight": - changeDir(Direction.Left,Direction.Right); + changeDir(Direction.Left, Direction.Right); break; } }; @@ -193,19 +180,18 @@ const UseSnake = () => { }, []); // ?. is called optional chaining - const isFood = ({ x, y }) => - foods.find((position)=> position.x === x && position.y === y); + const isFood = ({ x, y }) => + foods.find((position) => position.x === x && position.y === y); const isSnake = ({ x, y }) => snake.find((position) => position.x === x && position.y === y); - - return {score,isFood, isSnake} -} + return { score, isFood, isSnake }; +}; //view const Snake = () => { - const {score, isFood, isSnake} = UseSnake() + const { score, isFood, isSnake } = UseSnake(); const cells = []; for (let x = 0; x < Config.width; x++) { for (let y = 0; y < Config.height; y++) { From d1d21adbc7a8adcb3b45d996e9144e6e810da0e0 Mon Sep 17 00:00:00 2001 From: owishi Date: Sat, 19 Mar 2022 21:41:10 +0600 Subject: [PATCH 5/6] bug in 10s --- pages/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/index.js b/pages/index.js index b227ada..b513968 100644 --- a/pages/index.js +++ b/pages/index.js @@ -61,7 +61,7 @@ const Cell = ({ x, y, type }) => { const getRandomCell = () => ({ x: Math.floor(Math.random() * Config.width), y: Math.floor(Math.random() * Config.width), - start: Math.floor(Math.random()), + start: Math.floor(Math.random()*100), }); //custom hook From a12e1d28c05e35ebac568e2f729158f913698e56 Mon Sep 17 00:00:00 2001 From: owishi Date: Sun, 27 Mar 2022 15:06:45 +0600 Subject: [PATCH 6/6] use callback half --- pages/index.js | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/pages/index.js b/pages/index.js index b513968..56b4368 100644 --- a/pages/index.js +++ b/pages/index.js @@ -1,5 +1,5 @@ import dynamic from "next/dynamic"; -import { useEffect, useState, useRef } from "react"; +import { useEffect, useState, useRef, useCallback, useMemo } from "react"; import styles from "../styles/Snake.module.css"; const Config = { @@ -81,11 +81,18 @@ const UseSnake = () => { const [foods, setFoods] = useState([]); const score = snake.length - 3; - const resetGame = () => { + // ?. is called optional chaining + const isFood = useCallback(({ x, y }) => + foods.find((position) => position.x === x && position.y === y),[foods]); + + const isSnake = useCallback(({ x, y }) => + snake.find((position) => position.x === x && position.y === y),[snake]); + + const resetGame = useCallback(() => { setSnake(getDefaultSnake()); setDirection(Direction.Right); setFoods([]); - }; + },[]); // move the snake useEffect(() => { const runSingleStep = () => { @@ -115,7 +122,7 @@ const UseSnake = () => { const timer = setInterval(runSingleStep, 300); return () => clearInterval(timer); - }, [direction]); + }, [direction, isFood, isSnake, resetGame]); // update score whenever head touches a food useEffect(() => { @@ -125,7 +132,7 @@ const UseSnake = () => { currentFoods.filter((food) => food.x !== head.x && food.y !== head.y) ); } - }, [snake]); + }, [isFood, snake]); //food after 3s useEffect(() => { @@ -135,14 +142,14 @@ const UseSnake = () => { newFood = getRandomCell(); } setFoods((currentFoods) => [...currentFoods, newFood]); - setTimeout(() => { - setFoods((f) => - f.filter( - (e) => - e.start!==newFood.start - ) - ); - },10*1000); + // setTimeout(() => { + // setFoods((f) => + // f.filter( + // (e) => + // e.start!==newFood.start + // ) + // ); + // },10*1000); }, 3000); return () => clearInterval(interval); }, []); @@ -179,12 +186,6 @@ const UseSnake = () => { return () => window.removeEventListener("keydown", handleNavigation); }, []); - // ?. is called optional chaining - const isFood = ({ x, y }) => - foods.find((position) => position.x === x && position.y === y); - - const isSnake = ({ x, y }) => - snake.find((position) => position.x === x && position.y === y); return { score, isFood, isSnake }; };