From bee70f211e0cf7284df9577d67a85da12c924a18 Mon Sep 17 00:00:00 2001 From: owishi Date: Sun, 27 Mar 2022 23:29:03 +0600 Subject: [PATCH 01/11] half --- pages/index.js | 98 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 28 deletions(-) diff --git a/pages/index.js b/pages/index.js index de83024..56b4368 100644 --- a/pages/index.js +++ b/pages/index.js @@ -1,10 +1,10 @@ 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 = { - height: 25, - width: 25, + height: 15, + width: 15, cellSize: 32, }; @@ -61,9 +61,12 @@ 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()*100), }); -const Snake = () => { +//custom hook +//controller +const UseSnake = () => { const getDefaultSnake = () => [ { x: 8, y: 12 }, { x: 7, y: 12 }, @@ -75,67 +78,106 @@ 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([]); + const score = snake.length - 3; + + // ?. 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 = () => { 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, isFood, isSnake, resetGame]); // update score whenever head touches a food useEffect(() => { const head = snake[0]; if (isFood(head)) { - setScore((score) => { - return score + 1; - }); + setFoods((currentFoods) => + currentFoods.filter((food) => food.x !== head.x && food.y !== head.y) + ); + } + }, [isFood, snake]); + //food after 3s + useEffect(() => { + const interval = setInterval(() => { let newFood = getRandomCell(); - while (isSnake(newFood)) { + while (isSnake(newFood) || isFood(newFood)) { newFood = getRandomCell(); } + setFoods((currentFoods) => [...currentFoods, newFood]); + // setTimeout(() => { + // setFoods((f) => + // f.filter( + // (e) => + // e.start!==newFood.start + // ) + // ); + // },10*1000); + }, 3000); + return () => clearInterval(interval); + }, []); - setFood(newFood); - } - }, [snake]); + const changeDir = (checkDir, newDir) => { + setDirection((direction) => { + if (direction != checkDir) return newDir; + return direction; + }); + }; useEffect(() => { const handleNavigation = (event) => { switch (event.key) { case "ArrowUp": - setDirection(Direction.Top); + changeDir(Direction.Bottom, Direction.Top); break; case "ArrowDown": - setDirection(Direction.Bottom); + changeDir(Direction.Top, Direction.Bottom); break; case "ArrowLeft": - setDirection(Direction.Left); + changeDir(Direction.Right, Direction.Left); break; case "ArrowRight": - setDirection(Direction.Right); + changeDir(Direction.Left, Direction.Right); break; } }; @@ -144,13 +186,13 @@ const Snake = () => { return () => window.removeEventListener("keydown", handleNavigation); }, []); - // ?. 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 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 cf27ed266c7eb592434a9fc65fac93c9d9ef3e2d Mon Sep 17 00:00:00 2001 From: owishi Date: Mon, 28 Mar 2022 01:06:47 +0600 Subject: [PATCH 02/11] half complete --- pages/index.js | 123 +++++++++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 56 deletions(-) diff --git a/pages/index.js b/pages/index.js index 56b4368..698e7b2 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()*100), + start: Date.now(), }); //custom hook @@ -81,49 +81,62 @@ const UseSnake = () => { const [foods, setFoods] = useState([]); const score = snake.length - 3; - // ?. 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]); + // ?. 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] + ); + //restart the game const resetGame = useCallback(() => { 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, - }; - - // make a new snake by extending head - const newSnake = [newHead, ...snake]; - - // remove tail when head doesnt eat food - if (!isFood(newHead)) { - newSnake.pop(); - } - if (isSnake(newHead)) { - resetGame(); - } - - return newSnake; - }); - }; - - runSingleStep(); - const timer = setInterval(runSingleStep, 300); + }, []); + //moving the snake + const runSingleStep = useCallback(() => { + 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, + }; + + // make a new snake by extending head + const newSnake = [newHead, ...snake]; + + // remove tail when head doesnt eat food + if (!isFood(newHead)) { + newSnake.pop(); + } + if (isSnake(newHead)) { + resetGame(); + } - return () => clearInterval(timer); - }, [direction, isFood, isSnake, resetGame]); + return newSnake; + }); + }, [direction.x, direction.y, isFood, isSnake, resetGame]); + //add new food + const addFood = () => { + let newFood = getRandomCell(); + while (isSnake(newFood) || isFood(newFood)) { + newFood = getRandomCell(); + } + setFoods((currentFoods) => [...currentFoods, newFood]); + }; +//remove food +const removeFood = useCallback(()=>{ + setFoods((currentFoods)=> { + currentFoods.filter((food) => Date.now() - food.start <10000) + }) +},[setFoods]) // update score whenever head touches a food useEffect(() => { const head = snake[0]; @@ -134,25 +147,24 @@ const UseSnake = () => { } }, [isFood, snake]); - //food after 3s - useEffect(() => { - const interval = setInterval(() => { - let newFood = getRandomCell(); - while (isSnake(newFood) || isFood(newFood)) { - newFood = getRandomCell(); + const UseInterval = (func, dir) => { + const timer = useRef(Date.now()); + const createCallback = useCallback(() => { + if (Date.now() - timer.current > dir) { + timer.current = Date.now(); + func(); } - setFoods((currentFoods) => [...currentFoods, newFood]); - // setTimeout(() => { - // setFoods((f) => - // f.filter( - // (e) => - // e.start!==newFood.start - // ) - // ); - // },10*1000); - }, 3000); - return () => clearInterval(interval); - }, []); + }, [dir, func]); + + useEffect(() => { + const interval = setInterval(createCallback, 1000 / 60); + return () => clearInterval(interval); + }, [createCallback]); + }; + + UseInterval(addFood, 3000); + UseInterval(runSingleStep, 300); + UseInterval(removeFood,5000); const changeDir = (checkDir, newDir) => { setDirection((direction) => { @@ -186,7 +198,6 @@ const UseSnake = () => { return () => window.removeEventListener("keydown", handleNavigation); }, []); - return { score, isFood, isSnake }; }; From ec21c5ab26a268c70f34bee7e5481cb02624d514 Mon Sep 17 00:00:00 2001 From: owishi Date: Tue, 29 Mar 2022 03:32:36 +0600 Subject: [PATCH 03/11] removing bug --- pages/index.js | 85 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 17 deletions(-) diff --git a/pages/index.js b/pages/index.js index 698e7b2..89060d6 100644 --- a/pages/index.js +++ b/pages/index.js @@ -1,5 +1,5 @@ import dynamic from "next/dynamic"; -import { useEffect, useState, useRef, useCallback, useMemo } from "react"; +import { useEffect, useState, useRef, useCallback } from "react"; import styles from "../styles/Snake.module.css"; const Config = { @@ -39,6 +39,14 @@ const Cell = ({ x, y, type }) => { height: 32, }; + case CellType.Poison: + return { + backgroundColor: "red", + borderRadius: 20, + width: 32, + height: 32, + }; + default: return {}; } @@ -77,8 +85,8 @@ const UseSnake = () => { // snake[0] is head and snake[snake.length - 1] is tail const [snake, setSnake] = useState(getDefaultSnake()); const [direction, setDirection] = useState(Direction.Right); - const [foods, setFoods] = useState([]); + const [poisons, setPoison] = useState([]); const score = snake.length - 3; // ?. is called optional chaining @@ -88,17 +96,26 @@ const UseSnake = () => { [foods] ); + const isPoison = useCallback( + ({ x, y }) => + poisons.find((position) => position.x === x && position.y === y), + [poisons] + ); + const isSnake = useCallback( ({ x, y }) => snake.find((position) => position.x === x && position.y === y), [snake] ); + //restart the game const resetGame = useCallback(() => { setSnake(getDefaultSnake()); setDirection(Direction.Right); setFoods([]); + setPoison([]); }, []); + //moving the snake const runSingleStep = useCallback(() => { setSnake((snake) => { @@ -115,37 +132,67 @@ const UseSnake = () => { if (!isFood(newHead)) { newSnake.pop(); } - if (isSnake(newHead)) { + //remove again when eats poison + if (isPoison(newHead)) { + newSnake.pop(); + } + if (isSnake(newHead) || score < 0) { resetGame(); } return newSnake; }); - }, [direction.x, direction.y, isFood, isSnake, resetGame]); + }, [direction.x, direction.y, isFood, isPoison, isSnake, resetGame, score]); //add new food const addFood = () => { let newFood = getRandomCell(); - while (isSnake(newFood) || isFood(newFood)) { + while (isSnake(newFood) || isFood(newFood) || isPoison(newFood)) { newFood = getRandomCell(); } setFoods((currentFoods) => [...currentFoods, newFood]); }; -//remove food -const removeFood = useCallback(()=>{ - setFoods((currentFoods)=> { - currentFoods.filter((food) => Date.now() - food.start <10000) - }) -},[setFoods]) - // update score whenever head touches a food + + //add poison + const addPoison = () => { + let newPoison = getRandomCell(); + while (isSnake(newPoison) || isFood(newPoison) || isPoison(newPoison)) { + newPoison = getRandomCell(); + } + setPoison((currentPoison) => [...currentPoison, newPoison]); + }; + + //remove food + const removeFood = useCallback(() => { + console.log("delete"); + setFoods((currentFoods) => + currentFoods.filter((food) => Date.now() - food.start < 10000) + ); + }, []); + //remove poison + const removePoison = useCallback(() => { + setPoison((currentPoison) => + currentPoison.filter((poison) => Date.now() - poison.start < 10000) + ); + }, []); + + // update foods and poisons whenever head touches a food or a poison useEffect(() => { const head = snake[0]; if (isFood(head)) { + console.log("ate food"); setFoods((currentFoods) => currentFoods.filter((food) => food.x !== head.x && food.y !== head.y) ); } - }, [isFood, snake]); + if (isPoison(head)) { + setPoison((currentPoison) => + currentPoison.filter( + (poison) => poison.x !== head.x && poison.y !== head.y + ) + ); + } + }, [isFood, isPoison, snake]); const UseInterval = (func, dir) => { const timer = useRef(Date.now()); @@ -162,9 +209,11 @@ const removeFood = useCallback(()=>{ }, [createCallback]); }; - UseInterval(addFood, 3000); + UseInterval(addFood, 2000); UseInterval(runSingleStep, 300); - UseInterval(removeFood,5000); + UseInterval(removeFood, 50); + UseInterval(addPoison, 4000); + UseInterval(removePoison, 100); const changeDir = (checkDir, newDir) => { setDirection((direction) => { @@ -198,12 +247,12 @@ const removeFood = useCallback(()=>{ return () => window.removeEventListener("keydown", handleNavigation); }, []); - return { score, isFood, isSnake }; + return { score, isFood, isSnake, isPoison }; }; //view const Snake = () => { - const { score, isFood, isSnake } = UseSnake(); + const { score, isFood, isSnake, isPoison } = UseSnake(); const cells = []; for (let x = 0; x < Config.width; x++) { for (let y = 0; y < Config.height; y++) { @@ -212,6 +261,8 @@ const Snake = () => { type = CellType.Food; } else if (isSnake({ x, y })) { type = CellType.Snake; + } else if (isPoison({ x, y })) { + type = CellType.Poison; } cells.push(); } From 9721681a1a7f3efdfbae34f622eda91472e0c606 Mon Sep 17 00:00:00 2001 From: owishi Date: Tue, 29 Mar 2022 03:36:40 +0600 Subject: [PATCH 04/11] bugs in removing --- pages/index.js | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/pages/index.js b/pages/index.js index 89060d6..6f81d01 100644 --- a/pages/index.js +++ b/pages/index.js @@ -74,6 +74,20 @@ const getRandomCell = () => ({ //custom hook //controller +const UseInterval = (func, dir) => { + const timer = useRef(Date.now()); + const createCallback = useCallback(() => { + if (Date.now() - timer.current > dir) { + timer.current = Date.now(); + func(); + } + }, [dir, func]); + + useEffect(() => { + const interval = setInterval(createCallback, 1000 / 60); + return () => clearInterval(interval); + }, [createCallback]); +}; const UseSnake = () => { const getDefaultSnake = () => [ { x: 8, y: 12 }, @@ -194,21 +208,6 @@ const UseSnake = () => { } }, [isFood, isPoison, snake]); - const UseInterval = (func, dir) => { - const timer = useRef(Date.now()); - const createCallback = useCallback(() => { - if (Date.now() - timer.current > dir) { - timer.current = Date.now(); - func(); - } - }, [dir, func]); - - useEffect(() => { - const interval = setInterval(createCallback, 1000 / 60); - return () => clearInterval(interval); - }, [createCallback]); - }; - UseInterval(addFood, 2000); UseInterval(runSingleStep, 300); UseInterval(removeFood, 50); From 66aec44156b6625c96c8dc15cab822e215bd9fd6 Mon Sep 17 00:00:00 2001 From: owishi Date: Tue, 29 Mar 2022 03:46:53 +0600 Subject: [PATCH 05/11] bug while eating --- pages/index.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pages/index.js b/pages/index.js index 6f81d01..567a160 100644 --- a/pages/index.js +++ b/pages/index.js @@ -178,15 +178,16 @@ const UseSnake = () => { //remove food const removeFood = useCallback(() => { - console.log("delete"); + // console.log("delete food auto"); setFoods((currentFoods) => - currentFoods.filter((food) => Date.now() - food.start < 10000) + currentFoods.filter((food) => (Date.now() - food.start) < 10000) ); }, []); //remove poison const removePoison = useCallback(() => { + // console.log("delete poison auto"); setPoison((currentPoison) => - currentPoison.filter((poison) => Date.now() - poison.start < 10000) + currentPoison.filter((poison) => (Date.now() - poison.start) < 10000) ); }, []); @@ -200,6 +201,7 @@ const UseSnake = () => { ); } if (isPoison(head)) { + console.log("ate poison"); setPoison((currentPoison) => currentPoison.filter( (poison) => poison.x !== head.x && poison.y !== head.y @@ -208,7 +210,7 @@ const UseSnake = () => { } }, [isFood, isPoison, snake]); - UseInterval(addFood, 2000); + UseInterval(addFood, 3000); UseInterval(runSingleStep, 300); UseInterval(removeFood, 50); UseInterval(addPoison, 4000); From 5c03c11277570f556898720b39e8eb4da0d9bb5c Mon Sep 17 00:00:00 2001 From: owishi Date: Sat, 16 Apr 2022 22:40:24 +0600 Subject: [PATCH 06/11] added removeObject and addObject --- pages/index.js | 68 +++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/pages/index.js b/pages/index.js index 567a160..85462e7 100644 --- a/pages/index.js +++ b/pages/index.js @@ -158,37 +158,31 @@ const UseSnake = () => { }); }, [direction.x, direction.y, isFood, isPoison, isSnake, resetGame, score]); - //add new food - const addFood = () => { - let newFood = getRandomCell(); - while (isSnake(newFood) || isFood(newFood) || isPoison(newFood)) { - newFood = getRandomCell(); - } - setFoods((currentFoods) => [...currentFoods, newFood]); - }; - - //add poison - const addPoison = () => { - let newPoison = getRandomCell(); - while (isSnake(newPoison) || isFood(newPoison) || isPoison(newPoison)) { - newPoison = getRandomCell(); - } - setPoison((currentPoison) => [...currentPoison, newPoison]); - }; - - //remove food - const removeFood = useCallback(() => { - // console.log("delete food auto"); - setFoods((currentFoods) => - currentFoods.filter((food) => (Date.now() - food.start) < 10000) - ); - }, []); - //remove poison - const removePoison = useCallback(() => { - // console.log("delete poison auto"); - setPoison((currentPoison) => - currentPoison.filter((poison) => (Date.now() - poison.start) < 10000) - ); + const isBlocked = useCallback( + (cell) => isSnake(cell) || isFood(cell) || isPoison(cell), + [isFood, isPoison, isSnake] + ); + const addObject = useCallback( + (flag) => { + let newObject = getRandomCell(); + while (isBlocked(newObject)) { + newObject = getRandomCell(); + } + if (flag === "food") + setFoods((currentFoods) => [...currentFoods, newObject]); + else setPoison((currentPoison) => [...currentPoison, newObject]); + }, + [isBlocked] + ); + const removeObject = useCallback((type) => { + if (type === "food") + setFoods((currentFoods) => + currentFoods.filter((food) => Date.now() - food.start < 10000) + ); + else + setPoison((currentPoison) => + currentPoison.filter((poison) => Date.now() - poison.start < 10000) + ); }, []); // update foods and poisons whenever head touches a food or a poison @@ -197,24 +191,24 @@ const UseSnake = () => { if (isFood(head)) { console.log("ate food"); setFoods((currentFoods) => - currentFoods.filter((food) => food.x !== head.x && food.y !== head.y) + currentFoods.filter((food) => !(food.x === head.x && food.y === head.y)) ); } if (isPoison(head)) { console.log("ate poison"); setPoison((currentPoison) => currentPoison.filter( - (poison) => poison.x !== head.x && poison.y !== head.y + (poison) => !(poison.x === head.x && poison.y === head.y) ) ); } }, [isFood, isPoison, snake]); - UseInterval(addFood, 3000); + UseInterval(() => addObject("food"), 3000); + UseInterval(() => addObject("poison"), 1000); UseInterval(runSingleStep, 300); - UseInterval(removeFood, 50); - UseInterval(addPoison, 4000); - UseInterval(removePoison, 100); + UseInterval(() => removeObject("food"),50); + UseInterval(()=> removeObject("poison"), 100); const changeDir = (checkDir, newDir) => { setDirection((direction) => { From 2b4d230d30d5c83a5f0d8becb785bf4dfbfa8a1d Mon Sep 17 00:00:00 2001 From: owishi Date: Sat, 16 Apr 2022 23:26:00 +0600 Subject: [PATCH 07/11] cannot set remaining --- pages/index.js | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/pages/index.js b/pages/index.js index 85462e7..dfbca8d 100644 --- a/pages/index.js +++ b/pages/index.js @@ -21,7 +21,7 @@ const Direction = { Bottom: { x: 0, y: 1 }, }; -const Cell = ({ x, y, type }) => { +const Cell = ({ x, y, type, remaining }) => { const getStyles = () => { switch (type) { case CellType.Snake: @@ -33,10 +33,11 @@ const Cell = ({ x, y, type }) => { case CellType.Food: return { - backgroundColor: "darkorange", + backgroundColor: "tomato", borderRadius: 20, width: 32, height: 32, + transform: `scale(${0.5 + remaining / 20})`, }; case CellType.Poison: @@ -45,6 +46,7 @@ const Cell = ({ x, y, type }) => { borderRadius: 20, width: 32, height: 32, + transform: `scale(${0.5 + remaining / 20})`, }; default: @@ -61,7 +63,9 @@ const Cell = ({ x, y, type }) => { height: Config.cellSize, }} > -
+
+ {remaining} +
); }; @@ -207,8 +211,8 @@ const UseSnake = () => { UseInterval(() => addObject("food"), 3000); UseInterval(() => addObject("poison"), 1000); UseInterval(runSingleStep, 300); - UseInterval(() => removeObject("food"),50); - UseInterval(()=> removeObject("poison"), 100); + UseInterval(() => removeObject("food"), 50); + UseInterval(() => removeObject("poison"), 100); const changeDir = (checkDir, newDir) => { setDirection((direction) => { @@ -241,28 +245,36 @@ const UseSnake = () => { return () => window.removeEventListener("keydown", handleNavigation); }, []); - - return { score, isFood, isSnake, isPoison }; -}; - -//view -const Snake = () => { - const { score, isFood, isSnake, isPoison } = UseSnake(); const cells = []; for (let x = 0; x < Config.width; x++) { for (let y = 0; y < Config.height; y++) { - let type = CellType.Empty; + let type = CellType.Empty, + remaining = undefined; if (isFood({ x, y })) { type = CellType.Food; + remaining = + 10 - + Math.round( + (Date.now() - + foods.find((food) => food.x === x && food.y === y).createdAt) / + 1000 + ); } else if (isSnake({ x, y })) { type = CellType.Snake; } else if (isPoison({ x, y })) { type = CellType.Poison; } - cells.push(); + cells.push( + + ); } } + return { score, isFood, isSnake, isPoison, cells }; +}; +//view +const Snake = () => { + const { score, cells } = UseSnake(); return (
Date: Sun, 17 Apr 2022 01:00:02 +0600 Subject: [PATCH 08/11] complete --- pages/index.js | 59 +++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/pages/index.js b/pages/index.js index dfbca8d..f532aa3 100644 --- a/pages/index.js +++ b/pages/index.js @@ -98,8 +98,6 @@ const UseSnake = () => { { x: 7, y: 12 }, { x: 6, y: 12 }, ]; - const grid = useRef(); - // snake[0] is head and snake[snake.length - 1] is tail const [snake, setSnake] = useState(getDefaultSnake()); const [direction, setDirection] = useState(Direction.Right); @@ -107,23 +105,17 @@ const UseSnake = () => { const [poisons, setPoison] = useState([]); const score = snake.length - 3; - // ?. is called optional chaining - const isFood = useCallback( - ({ x, y }) => - foods.find((position) => position.x === x && position.y === y), - [foods] - ); - - const isPoison = useCallback( - ({ x, y }) => - poisons.find((position) => position.x === x && position.y === y), - [poisons] - ); + const finding = ({ x, y }, arr) => { + return arr.find((position) => position.x === x && position.y === y); + }; - const isSnake = useCallback( - ({ x, y }) => - snake.find((position) => position.x === x && position.y === y), - [snake] + const isObject = useCallback( + ({ x, y }, type) => { + if (type === "food") return finding({ x, y }, foods); + else if (type === "poison") return finding({ x, y }, poisons); + else if (type === "snake") return finding({ x, y }, snake); + }, + [foods, poisons, snake] ); //restart the game @@ -147,24 +139,27 @@ const UseSnake = () => { const newSnake = [newHead, ...snake]; // remove tail when head doesnt eat food - if (!isFood(newHead)) { + if (!isObject(newHead, "food")) { newSnake.pop(); } //remove again when eats poison - if (isPoison(newHead)) { + if (isObject(newHead, "poison")) { newSnake.pop(); } - if (isSnake(newHead) || score < 0) { + if (isObject(newHead, "snake") || score < 0) { resetGame(); } return newSnake; }); - }, [direction.x, direction.y, isFood, isPoison, isSnake, resetGame, score]); + }, [direction.x, direction.y, isObject, resetGame, score]); const isBlocked = useCallback( - (cell) => isSnake(cell) || isFood(cell) || isPoison(cell), - [isFood, isPoison, isSnake] + (cell) => + isObject(cell, "snake") || + isObject(cell, "food") || + isObject(cell, "poison"), + [isObject] ); const addObject = useCallback( (flag) => { @@ -192,13 +187,13 @@ const UseSnake = () => { // update foods and poisons whenever head touches a food or a poison useEffect(() => { const head = snake[0]; - if (isFood(head)) { + if (isObject(head, "food")) { console.log("ate food"); setFoods((currentFoods) => currentFoods.filter((food) => !(food.x === head.x && food.y === head.y)) ); } - if (isPoison(head)) { + if (isObject(head, "poison")) { console.log("ate poison"); setPoison((currentPoison) => currentPoison.filter( @@ -206,7 +201,7 @@ const UseSnake = () => { ) ); } - }, [isFood, isPoison, snake]); + }, [isObject, snake]); UseInterval(() => addObject("food"), 3000); UseInterval(() => addObject("poison"), 1000); @@ -250,18 +245,18 @@ const UseSnake = () => { for (let y = 0; y < Config.height; y++) { let type = CellType.Empty, remaining = undefined; - if (isFood({ x, y })) { + if (isObject({ x, y }, "food")) { type = CellType.Food; remaining = 10 - Math.round( (Date.now() - - foods.find((food) => food.x === x && food.y === y).createdAt) / + foods.find((food) => food.x === x && food.y === y).start) / 1000 ); - } else if (isSnake({ x, y })) { + } else if (isObject({ x, y }, "snake")) { type = CellType.Snake; - } else if (isPoison({ x, y })) { + } else if (isObject({ x, y }, "poison")) { type = CellType.Poison; } cells.push( @@ -269,7 +264,7 @@ const UseSnake = () => { ); } } - return { score, isFood, isSnake, isPoison, cells }; + return { score, isObject, cells }; }; //view From 48ca4d23b5ae0f2b64804ee4b9146b95e545e0b2 Mon Sep 17 00:00:00 2001 From: owishi Date: Sun, 17 Apr 2022 12:51:29 +0600 Subject: [PATCH 09/11] complete 01 --- pages/index.js | 99 ++++++++++++++++++----------------------- styles/Snake.module.css | 6 ++- 2 files changed, 48 insertions(+), 57 deletions(-) diff --git a/pages/index.js b/pages/index.js index f532aa3..f08cc80 100644 --- a/pages/index.js +++ b/pages/index.js @@ -12,6 +12,7 @@ const CellType = { Snake: "snake", Food: "food", Empty: "empty", + Poison: "poison", }; const Direction = { @@ -70,10 +71,11 @@ const Cell = ({ x, y, type, remaining }) => { ); }; -const getRandomCell = () => ({ +const getRandomCell = (type) => ({ x: Math.floor(Math.random() * Config.width), y: Math.floor(Math.random() * Config.width), start: Date.now(), + type: type, }); //custom hook @@ -101,29 +103,30 @@ const UseSnake = () => { // snake[0] is head and snake[snake.length - 1] is tail const [snake, setSnake] = useState(getDefaultSnake()); const [direction, setDirection] = useState(Direction.Right); - const [foods, setFoods] = useState([]); - const [poisons, setPoison] = useState([]); + // const [foods, setFoods] = useState([]); + // const [poisons, setPoison] = useState([]); + const [objects, setObjects] = useState([]); const score = snake.length - 3; - const finding = ({ x, y }, arr) => { - return arr.find((position) => position.x === x && position.y === y); + const finding = ({ x, y }, arr, type) => { + return arr.find((position) => position.x === x && position.y === y && position.type===type); }; + //checking cells const isObject = useCallback( ({ x, y }, type) => { - if (type === "food") return finding({ x, y }, foods); - else if (type === "poison") return finding({ x, y }, poisons); - else if (type === "snake") return finding({ x, y }, snake); + if (type === CellType.Food) return finding({ x, y }, objects,type); + else if (type === CellType.Poison) return finding({ x, y }, objects, type); + else if (type === CellType.Snake) return finding({ x, y }, snake); }, - [foods, poisons, snake] + [objects, snake] ); //restart the game const resetGame = useCallback(() => { setSnake(getDefaultSnake()); setDirection(Direction.Right); - setFoods([]); - setPoison([]); + setObjects([]); }, []); //moving the snake @@ -139,14 +142,14 @@ const UseSnake = () => { const newSnake = [newHead, ...snake]; // remove tail when head doesnt eat food - if (!isObject(newHead, "food")) { + if (!isObject(newHead, CellType.Food)) { newSnake.pop(); } //remove again when eats poison - if (isObject(newHead, "poison")) { + if (isObject(newHead, CellType.Poison)) { newSnake.pop(); } - if (isObject(newHead, "snake") || score < 0) { + if (isObject(newHead, CellType.Snake) || score < 0) { resetGame(); } @@ -156,58 +159,44 @@ const UseSnake = () => { const isBlocked = useCallback( (cell) => - isObject(cell, "snake") || - isObject(cell, "food") || - isObject(cell, "poison"), + isObject(cell, CellType.Snake) || + isObject(cell, CellType.Food) || + isObject(cell, CellType.Poison), [isObject] ); const addObject = useCallback( - (flag) => { - let newObject = getRandomCell(); + (type) => { + let newObject = getRandomCell(type); while (isBlocked(newObject)) { - newObject = getRandomCell(); + newObject = getRandomCell(type); } - if (flag === "food") - setFoods((currentFoods) => [...currentFoods, newObject]); - else setPoison((currentPoison) => [...currentPoison, newObject]); + console.log(newObject.type) + setObjects((currentObjects) => [...currentObjects, newObject]); }, [isBlocked] ); - const removeObject = useCallback((type) => { - if (type === "food") - setFoods((currentFoods) => - currentFoods.filter((food) => Date.now() - food.start < 10000) - ); - else - setPoison((currentPoison) => - currentPoison.filter((poison) => Date.now() - poison.start < 10000) + const removeObject = useCallback(() => { + setObjects((currentObjects) => + currentObjects.filter((currentObject) => Date.now() - currentObject.start < 10000) ); }, []); // update foods and poisons whenever head touches a food or a poison useEffect(() => { const head = snake[0]; - if (isObject(head, "food")) { - console.log("ate food"); - setFoods((currentFoods) => - currentFoods.filter((food) => !(food.x === head.x && food.y === head.y)) - ); - } - if (isObject(head, "poison")) { - console.log("ate poison"); - setPoison((currentPoison) => - currentPoison.filter( - (poison) => !(poison.x === head.x && poison.y === head.y) - ) + if (isObject(head, CellType.Food)) { + console.log("ate object"); + setObjects((currentObjects) => + currentObjects.filter((currentObject) => !(currentObject.x === head.x && currentObject.y === head.y)) ); } }, [isObject, snake]); - UseInterval(() => addObject("food"), 3000); - UseInterval(() => addObject("poison"), 1000); + UseInterval(() => addObject(CellType.Food), 3000); + UseInterval(() => addObject(CellType.Poison), 1000); UseInterval(runSingleStep, 300); - UseInterval(() => removeObject("food"), 50); - UseInterval(() => removeObject("poison"), 100); + UseInterval(() => removeObject(CellType.Food), 50); + UseInterval(() => removeObject(CellType.Poison), 100); const changeDir = (checkDir, newDir) => { setDirection((direction) => { @@ -245,19 +234,17 @@ const UseSnake = () => { for (let y = 0; y < Config.height; y++) { let type = CellType.Empty, remaining = undefined; - if (isObject({ x, y }, "food")) { + if (isObject({ x, y }, CellType.Food)) { type = CellType.Food; remaining = - 10 - - Math.round( - (Date.now() - - foods.find((food) => food.x === x && food.y === y).start) / - 1000 - ); - } else if (isObject({ x, y }, "snake")) { + 10 - Math.round((Date.now() - finding({ x, y }, objects, type).start) / 1000); + } else if (isObject({ x, y }, CellType.Snake)) { type = CellType.Snake; - } else if (isObject({ x, y }, "poison")) { + } else if (isObject({ x, y }, CellType.Poison)) { type = CellType.Poison; + remaining = + 10 - + Math.round((Date.now() - finding({ x, y }, objects, type).start) / 1000); } cells.push( diff --git a/styles/Snake.module.css b/styles/Snake.module.css index b4f0f28..e9b527a 100644 --- a/styles/Snake.module.css +++ b/styles/Snake.module.css @@ -34,4 +34,8 @@ .cell { width: 100%; height: 100%; -} + display: flex; + justify-content: center; + align-items: center; + color: white; +} \ No newline at end of file From 4ba03c313d87e63a375da187e6d08ea19b0ce2d5 Mon Sep 17 00:00:00 2001 From: owishi Date: Sun, 17 Apr 2022 12:53:20 +0600 Subject: [PATCH 10/11] complete 02 --- pages/index.js | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/pages/index.js b/pages/index.js index f08cc80..b0cef5f 100644 --- a/pages/index.js +++ b/pages/index.js @@ -103,20 +103,22 @@ const UseSnake = () => { // snake[0] is head and snake[snake.length - 1] is tail const [snake, setSnake] = useState(getDefaultSnake()); const [direction, setDirection] = useState(Direction.Right); - // const [foods, setFoods] = useState([]); - // const [poisons, setPoison] = useState([]); const [objects, setObjects] = useState([]); const score = snake.length - 3; const finding = ({ x, y }, arr, type) => { - return arr.find((position) => position.x === x && position.y === y && position.type===type); + return arr.find( + (position) => + position.x === x && position.y === y && position.type === type + ); }; //checking cells const isObject = useCallback( ({ x, y }, type) => { - if (type === CellType.Food) return finding({ x, y }, objects,type); - else if (type === CellType.Poison) return finding({ x, y }, objects, type); + if (type === CellType.Food) return finding({ x, y }, objects, type); + else if (type === CellType.Poison) + return finding({ x, y }, objects, type); else if (type === CellType.Snake) return finding({ x, y }, snake); }, [objects, snake] @@ -170,15 +172,17 @@ const UseSnake = () => { while (isBlocked(newObject)) { newObject = getRandomCell(type); } - console.log(newObject.type) - setObjects((currentObjects) => [...currentObjects, newObject]); + console.log(newObject.type); + setObjects((currentObjects) => [...currentObjects, newObject]); }, [isBlocked] ); const removeObject = useCallback(() => { - setObjects((currentObjects) => - currentObjects.filter((currentObject) => Date.now() - currentObject.start < 10000) - ); + setObjects((currentObjects) => + currentObjects.filter( + (currentObject) => Date.now() - currentObject.start < 10000 + ) + ); }, []); // update foods and poisons whenever head touches a food or a poison @@ -187,7 +191,10 @@ const UseSnake = () => { if (isObject(head, CellType.Food)) { console.log("ate object"); setObjects((currentObjects) => - currentObjects.filter((currentObject) => !(currentObject.x === head.x && currentObject.y === head.y)) + currentObjects.filter( + (currentObject) => + !(currentObject.x === head.x && currentObject.y === head.y) + ) ); } }, [isObject, snake]); @@ -237,14 +244,19 @@ const UseSnake = () => { if (isObject({ x, y }, CellType.Food)) { type = CellType.Food; remaining = - 10 - Math.round((Date.now() - finding({ x, y }, objects, type).start) / 1000); + 10 - + Math.round( + (Date.now() - finding({ x, y }, objects, type).start) / 1000 + ); } else if (isObject({ x, y }, CellType.Snake)) { type = CellType.Snake; } else if (isObject({ x, y }, CellType.Poison)) { type = CellType.Poison; remaining = 10 - - Math.round((Date.now() - finding({ x, y }, objects, type).start) / 1000); + Math.round( + (Date.now() - finding({ x, y }, objects, type).start) / 1000 + ); } cells.push( From b5a4648222ab8324f990ef9fdd9c882171682f55 Mon Sep 17 00:00:00 2001 From: owishi Date: Sun, 17 Apr 2022 19:20:26 +0600 Subject: [PATCH 11/11] fixed redundancy --- pages/index.js | 67 +++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/pages/index.js b/pages/index.js index b0cef5f..2b62d72 100644 --- a/pages/index.js +++ b/pages/index.js @@ -80,7 +80,7 @@ const getRandomCell = (type) => ({ //custom hook //controller -const UseInterval = (func, dir) => { +const useInterval = (func, dir) => { const timer = useRef(Date.now()); const createCallback = useCallback(() => { if (Date.now() - timer.current > dir) { @@ -94,7 +94,7 @@ const UseInterval = (func, dir) => { return () => clearInterval(interval); }, [createCallback]); }; -const UseSnake = () => { +const GetSnake = () => { const getDefaultSnake = () => [ { x: 8, y: 12 }, { x: 7, y: 12 }, @@ -107,6 +107,9 @@ const UseSnake = () => { const score = snake.length - 3; const finding = ({ x, y }, arr, type) => { + //for snake + if (type === undefined) + return arr.find((position) => position.x === x && position.y === y); return arr.find( (position) => position.x === x && position.y === y && position.type === type @@ -114,12 +117,10 @@ const UseSnake = () => { }; //checking cells - const isObject = useCallback( + const isObjectOrSnake = useCallback( ({ x, y }, type) => { - if (type === CellType.Food) return finding({ x, y }, objects, type); - else if (type === CellType.Poison) - return finding({ x, y }, objects, type); - else if (type === CellType.Snake) return finding({ x, y }, snake); + if (type === CellType.Snake) return finding({ x, y }, snake); + else return finding({ x, y }, objects, type); }, [objects, snake] ); @@ -144,38 +145,38 @@ const UseSnake = () => { const newSnake = [newHead, ...snake]; // remove tail when head doesnt eat food - if (!isObject(newHead, CellType.Food)) { + if (!isObjectOrSnake(newHead, CellType.Food)) { newSnake.pop(); } //remove again when eats poison - if (isObject(newHead, CellType.Poison)) { + if (isObjectOrSnake(newHead, CellType.Poison)) { newSnake.pop(); } - if (isObject(newHead, CellType.Snake) || score < 0) { + if (isObjectOrSnake(newHead, CellType.Snake) || score < 0) { resetGame(); } return newSnake; }); - }, [direction.x, direction.y, isObject, resetGame, score]); + }, [direction.x, direction.y, isObjectOrSnake, resetGame, score]); - const isBlocked = useCallback( - (cell) => - isObject(cell, CellType.Snake) || - isObject(cell, CellType.Food) || - isObject(cell, CellType.Poison), - [isObject] - ); const addObject = useCallback( (type) => { let newObject = getRandomCell(type); - while (isBlocked(newObject)) { + while ( + isObjectOrSnake( + newObject, + CellType.Snake || + isObjectOrSnake(newObject, CellType.Food) || + isObjectOrSnake(isObjectOrSnake, CellType.Poison) + ) + ) { newObject = getRandomCell(type); } console.log(newObject.type); setObjects((currentObjects) => [...currentObjects, newObject]); }, - [isBlocked] + [isObjectOrSnake] ); const removeObject = useCallback(() => { setObjects((currentObjects) => @@ -188,8 +189,8 @@ const UseSnake = () => { // update foods and poisons whenever head touches a food or a poison useEffect(() => { const head = snake[0]; - if (isObject(head, CellType.Food)) { - console.log("ate object"); + if (isObjectOrSnake(head, CellType.Food)) { + console.log("ate food"); setObjects((currentObjects) => currentObjects.filter( (currentObject) => @@ -197,13 +198,13 @@ const UseSnake = () => { ) ); } - }, [isObject, snake]); + }, [isObjectOrSnake, snake]); - UseInterval(() => addObject(CellType.Food), 3000); - UseInterval(() => addObject(CellType.Poison), 1000); - UseInterval(runSingleStep, 300); - UseInterval(() => removeObject(CellType.Food), 50); - UseInterval(() => removeObject(CellType.Poison), 100); + useInterval(() => addObject(CellType.Food), 3000); + useInterval(() => addObject(CellType.Poison), 1000); + useInterval(runSingleStep, 300); + useInterval(() => removeObject(), 50); + useInterval(() => removeObject(), 100); const changeDir = (checkDir, newDir) => { setDirection((direction) => { @@ -241,16 +242,16 @@ const UseSnake = () => { for (let y = 0; y < Config.height; y++) { let type = CellType.Empty, remaining = undefined; - if (isObject({ x, y }, CellType.Food)) { + if (isObjectOrSnake({ x, y }, CellType.Food)) { type = CellType.Food; remaining = 10 - Math.round( (Date.now() - finding({ x, y }, objects, type).start) / 1000 ); - } else if (isObject({ x, y }, CellType.Snake)) { + } else if (isObjectOrSnake({ x, y }, CellType.Snake)) { type = CellType.Snake; - } else if (isObject({ x, y }, CellType.Poison)) { + } else if (isObjectOrSnake({ x, y }, CellType.Poison)) { type = CellType.Poison; remaining = 10 - @@ -263,12 +264,12 @@ const UseSnake = () => { ); } } - return { score, isObject, cells }; + return { score, isObjectOrSnake, cells }; }; //view const Snake = () => { - const { score, cells } = UseSnake(); + const { score, cells } = GetSnake(); return (