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 1 commit
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
62 changes: 55 additions & 7 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,6 +121,7 @@ const useSnake = () => {
const resetGame = useCallback(() => {
setFoods([]);
setDirection(getInitialDirection());
setPoisons([]);
}, []);

const removeFoods = useCallback(() => {
Expand All @@ -119,26 +131,50 @@ const useSnake = () => {
);
}, []);

const removePoisons = useCallback(() => {
setPoisons((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 isAllowedCell = useCallback(
(newCell) => isSnake(newCell) || isFood(newCell || isPoison(newCell)),
[isFood, isPoison, isSnake]
);
const addFood = useCallback(() => {
let newFood = getRandomCell();
while (isSnake(newFood) || isFood(newFood)) {
while (isAllowedCell(newFood)) {
newFood = getRandomCell();
}
setFoods((currentFoods) => [...currentFoods, newFood]);
}, [isFood, isSnake]);
}, [isAllowedCell]);

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 addPoison = useCallback(() => {
let newPoison = getRandomCell();
while (isAllowedCell(newPoison)) {
newPoison = getRandomCell();
}
setPoisons((currentPoisons) => [...currentPoisons, newPoison]);
}, [isAllowedCell]);

// move the snake
const runSingleStep = useCallback(() => {
Expand All @@ -156,8 +192,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 +212,13 @@ const useSnake = () => {

return newSnake;
});
}, [direction, isFood, isSnake, resetGame]);
}, [direction.x, direction.y, isFood, isPoison, isSnake, resetGame]);

useInterval(runSingleStep, 200);
useInterval(runSingleStep, 1);
useInterval(addFood, 3000);
useInterval(removeFoods, 100);
useInterval(addPoison, 3000);
useInterval(removePoisons, 100);

useEffect(() => {
const handleDirection = (direction, oppositeDirection) => {
Expand Down Expand Up @@ -231,6 +269,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