-
Notifications
You must be signed in to change notification settings - Fork 15
module#2 (Mahmud) #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: module-2
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,7 @@ const CellType = { | |
| Snake: "snake", | ||
| Food: "food", | ||
| Empty: "empty", | ||
| Poison: "poison", | ||
| }; | ||
|
|
||
| const Direction = { | ||
|
|
@@ -40,6 +41,15 @@ const Cell = ({ x, y, type, remaining }) => { | |
| transform: `scale(${0.5 + remaining / 20})`, | ||
| }; | ||
|
|
||
| case CellType.Poison: | ||
| return { | ||
| backgroundColor: "blue", | ||
| borderRadius: 20, | ||
| width: 32, | ||
| height: 32, | ||
| transform: `scale(${0.5 + remaining / 20})`, | ||
| }; | ||
|
|
||
| default: | ||
| return {}; | ||
| } | ||
|
|
@@ -100,6 +110,7 @@ const useSnake = () => { | |
| const [direction, setDirection] = useState(getInitialDirection()); | ||
|
|
||
| const [foods, setFoods] = useState([]); | ||
| const [poisons, setPoisons] = useState([]); | ||
|
|
||
| const score = snake.length - 3; | ||
|
|
||
|
|
@@ -110,35 +121,76 @@ const useSnake = () => { | |
| const resetGame = useCallback(() => { | ||
| setFoods([]); | ||
| setDirection(getInitialDirection()); | ||
| setPoisons([]); | ||
| }, []); | ||
|
|
||
| const removeFoods = useCallback(() => { | ||
| // only keep those foods which were created within last 10s. | ||
| setFoods((currentFoods) => | ||
| currentFoods.filter((food) => Date.now() - food.createdAt <= 10 * 1000) | ||
| // const removeFoods = useCallback(() => { | ||
| // // only keep those foods which were created within last 10s. | ||
| // setFoods((currentFoods) => | ||
| // currentFoods.filter((food) => Date.now() - food.createdAt <= 10 * 1000) | ||
| // ); | ||
| // }, []); | ||
|
|
||
| // const removePoisons = useCallback(() => { | ||
| // setPoisons((currentPoisons) => | ||
| // currentPoisons.filter( | ||
| // (poison) => Date.now() - poison.createdAt <= 10 * 1000 | ||
| // ) | ||
| // ); | ||
| // }, []); | ||
|
|
||
| const removeObject = useCallback((setState)=>{ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't need to send the setStates as they're already available in this function. It would be better to use cellType to decide which setState you want to call.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But this call the same addFood or addPoison function inside that. I wanted to generalize the adding and removing process for food and poison both. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, and we can easily do it by checking the type of the object. it is much simpler. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @owishiboo in your code you almost did the same thing . You passed array as an argument for checking types in findings function . |
||
| setState((currentPoisons) => | ||
| currentPoisons.filter( | ||
| (poison) => Date.now() - poison.createdAt <= 10 * 1000 | ||
| ) | ||
| ); | ||
| }, []); | ||
| },[]); | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can create a reusable removeObject(type) function like addObject |
||
| // ?. is called optional chaining | ||
| // see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining | ||
| const isFood = useCallback( | ||
| ({ x, y }) => foods.some((food) => food.x === x && food.y === y), | ||
| ({ x, y }) => foods.find((food) => food.x === x && food.y === y), | ||
| [foods] | ||
| ); | ||
| const isPoison = useCallback( | ||
| ({ x, y }) => poisons.find((poison) => poison.x === x && poison.y === y), | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. food and poison are basically the same but different types. We can check food or poison with the same function. |
||
| [poisons] | ||
| ); | ||
|
|
||
| const isSnake = useCallback( | ||
| ({ x, y }) => | ||
| snake.find((position) => position.x === x && position.y === y), | ||
| [snake] | ||
| ); | ||
|
|
||
| const addFood = useCallback(() => { | ||
| let newFood = getRandomCell(); | ||
| while (isSnake(newFood) || isFood(newFood)) { | ||
| newFood = getRandomCell(); | ||
| const isAllowedCell = useCallback( | ||
| (newCell) => isSnake(newCell) || isFood(newCell || isPoison(newCell)), | ||
| [isFood, isPoison, isSnake] | ||
| ); | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. basically addFood and addPoison does the same job .So we can make a reusable function like const addObject= useCallback((type) => {
let newObj= getRandomCell();
while (isAllowedCell(newObj)) {
newObj= getRandomCell();
}
if(type===CellType.Food){
setFoods((currentFoods) => [...currentFoods, newObj]);
}else{
setPoisons(currentPoison=>[...currentPoison,newObj]);
}
}, [isAllowedCell]);when calling useInterval(()=>addObject(CellType.Food), 3000);
useInterval(()=>addObject(CellType.Poison), 3000); |
||
| const getEmptyCell = useCallback(() =>{ | ||
| let newCell = getRandomCell(); | ||
| while (isAllowedCell(newCell)) { | ||
| newCell = getRandomCell(); | ||
| } | ||
| setFoods((currentFoods) => [...currentFoods, newFood]); | ||
| }, [isFood, isSnake]); | ||
| return newCell; | ||
| },[isAllowedCell]); | ||
|
|
||
| // const addFood = useCallback(() => { | ||
| // const newFood = getEmptyCell(); | ||
| // setFoods((currentFoods) => [...currentFoods, newFood]); | ||
| // }, [getEmptyCell]); | ||
|
|
||
| // const addPoison = useCallback(() => { | ||
| // const newPoison = getEmptyCell(); | ||
| // setPoisons((currentPoisons) => [...currentPoisons, newPoison]); | ||
| // }, [getEmptyCell]); | ||
|
|
||
| const addObject = useCallback((setState)=>{ | ||
| const newObject = getEmptyCell(); | ||
| setState((currentPoisons) => [...currentPoisons, newObject]); | ||
| },[getEmptyCell]) | ||
|
|
||
| // move the snake | ||
| const runSingleStep = useCallback(() => { | ||
|
|
@@ -156,8 +208,8 @@ const useSnake = () => { | |
| // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax | ||
| const newSnake = [newHead, ...snake]; | ||
|
|
||
| // reset the game if the snake hit itself | ||
| if (isSnake(newHead)) { | ||
| // reset the game if the snake hit itself or poison | ||
| if (isSnake(newHead) || isPoison(newHead)) { | ||
| resetGame(); | ||
| return getDefaultSnake(); | ||
| } | ||
|
|
@@ -176,11 +228,14 @@ const useSnake = () => { | |
|
|
||
| return newSnake; | ||
| }); | ||
| }, [direction, isFood, isSnake, resetGame]); | ||
| }, [direction.x, direction.y, isFood, isPoison, isSnake, resetGame]); | ||
|
|
||
|
|
||
| useInterval(runSingleStep, 200); | ||
| useInterval(addFood, 3000); | ||
| useInterval(removeFoods, 100); | ||
| useInterval(()=>addObject(setFoods), 3000); | ||
| useInterval(()=>removeObject(setFoods), 100); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can identify food or poison as an object, the only difference will be the type(the type of an object will be food or poison) and it will be less hassle to handle. |
||
| useInterval(()=>addObject(setPoisons), 3000); | ||
| useInterval(()=>removeObject(setPoisons), 100); | ||
|
|
||
| useEffect(() => { | ||
| const handleDirection = (direction, oppositeDirection) => { | ||
|
|
@@ -231,6 +286,16 @@ const useSnake = () => { | |
| ); | ||
| } else if (isSnake({ x, y })) { | ||
| type = CellType.Snake; | ||
| } else if (isPoison({ x, y })) { | ||
| type = CellType.Poison; | ||
| remaining = | ||
| 10 - | ||
| Math.round( | ||
| (Date.now() - | ||
| poisons.find((poison) => poison.x === x && poison.y === y) | ||
| .createdAt) / | ||
| 1000 | ||
| ); | ||
| } | ||
| cells.push( | ||
| <Cell key={`${x}-${y}`} x={x} y={y} type={type} remaining={remaining} /> | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.