Skip to content
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

module#2 (Mahmud) #38

Open
wants to merge 2 commits into
base: module-2
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 82 additions & 17 deletions pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const CellType = {
Snake: "snake",
Food: "food",
Empty: "empty",
Poison: "poison",
};

const Direction = {
Expand Down Expand Up @@ -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 {};
}
Expand Down Expand Up @@ -100,6 +110,7 @@ const useSnake = () => {
const [direction, setDirection] = useState(getInitialDirection());

const [foods, setFoods] = useState([]);
const [poisons, setPoisons] = useState([]);

const score = snake.length - 3;

Expand All @@ -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)=>{

Choose a reason for hiding this comment

The 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.

Copy link
Author

Choose a reason for hiding this comment

The 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.

Choose a reason for hiding this comment

The 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.

removeObject(type){
if(type===CellType.Food)//do something for food
else if (type===CellType.Poison)//do something for poison
}

it is much simpler.
Also, you may consider food or poison as an object. The only thing that differs between them is the type. All the functionalities differ according to the type(for example, adding or removing is the same process for different arrays). We can easily use the type to differentiate.

Choose a reason for hiding this comment

The 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
)
);
}, []);
},[]);

Choose a reason for hiding this comment

The 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),

Choose a reason for hiding this comment

The 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]
);

Copy link

@MahdiMurshed MahdiMurshed Apr 17, 2022

Choose a reason for hiding this comment

The 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(() => {
Expand All @@ -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();
}
Expand All @@ -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);

Choose a reason for hiding this comment

The 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) => {
Expand Down Expand Up @@ -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} />
Expand Down