ظاهر کلی برنامه بدین صورت است:
![ظاهر برنامه](https://quera.ir/qbox/view/us7L0GX2aX/nested-selector-screely.png)
# پروژه اولیه
پروژه اولیه را از
[این لینک](/contest/assignments/20209/download_problem_initial_project/65889/)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
```
nested-selector
├── index.html
└── styles.css
```
<details class="brown">
<summary>
راهاندازی پروژه
</summary>
- ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
- سپس فایل `index.html` را در مرورگر خود باز کنید.
</details>
# جزئیات
در فایل `html` داده شده دو تگ `p` در داخل یک `div` با ایدی `container` و یک تگ `p` دیگر بیرون از آن قرار گرقته است.
شما باید با استفاده از انتخابکنندههای مناسب استایلی بسازید که باعث شود تگهای داخل `container` دارای رنگ `indigo` و تگ خارج از آن دارای رنگ `indianred` باشد.
# نکات
- شما تنها مجاز به اعمال تغییرات در فایل `styles.css` هستید.
- فقط فایلی را که مجاز به تغییر هستید باید آپلود نمایید.
# قسمت آموزشی
در این قسمت راهنماییهای سوال، به مرور اضافه میشود. مشکلاتتان در راستای حل سوال را میتوانید از بخش ["سوال بپرسید"](https://quera.ir/contest/clarification/20209/) مطرح کنید.
<details class="blue">
<summary>
راهنمایی ۱
</summary>
مقدار یک ویژگی المان ممکن است چندین بار تغییر کند ولی هربار مقدار جدیدی بگیرد. برای مثال رنگ یک تگ `p` یکبار مشکی است و یکبار قرمز.
درباره این موضوع یک سری قواعد وجود دارد که هرکدام اولویتی دارند و بسته به اولویت آنها، استایلها داده میشود.
یکی از این موارد قرار گرفتن استایل جدید بعد از استایل ما میباشد.
یکی دیگر از این موارد استفاده از `!important` در هنگام استایلدهی میباشد که صرف از نظر از تقدم استایلها، آن استایل که دارای `!important` میباشد، انتخاب میشود.
**درنهایت ترکیب اولویتها و انتخابکنندهها منجر به انتخاب استایل توسط مرورگر میشود.**
</details>
<details class="blue">
<summary>
راهنمایی ۲
</summary>
مهمترین و پرکاربردترین قواعد انتخاب استایل توسط مرورگر این است که هرچه انتخابکننده (*selector*) خاصتر باشد، آن انتخاب میشود.
```
a {
color: yellow;
}
nav > a {
color: green;
}
```
در مثال بالا رنگ تگهای `a` سبز انتخاب میشود چرا که انتخابکننده خاصتر است.
**ترکیب این قاعده با قاعده قبلی منجر به انتخاب استایل توسط مرورگر میشود.**
</details>
<details class="blue">
<summary>
راهنمایی۳
</summary>
استایلهای داخل *HTML* به استایلهای داخل فایلهای *CSS* مقدم هستند. این تقدم را میتوان با استفاده از `important!` از بین برد.
برای تغییر تقدم `important!` میتوان سلکتور را مشخصتر کرد. در این حالت استایلی که سلکتور آن خاصتر باشد، انتخاب میشود.
</details>
انتخابکننده تودرتو
ظاهر کلی برنامه بدین صورت است:
![ظاهر برنامه](https://quera.ir/qbox/view/X1L7blUCq5/mahsolat.gif)
# پروژه اولیه
پروژه اولیه را از
[این لینک](/contest/assignments/20209/download_problem_initial_project/65887/)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
```
products
├── assets
│ └── Vazir.ttf
├── cypress
│ ├── fixtures
│ │ └── example.json
│ ├── integration
│ │ └── sample.spec.js
│ ├── plugins
│ │ └── index.js
│ └── support
│ ├── commands.js
│ └── index.js
├── cypress.json
├── index.html
├── package-lock.json
├── package.json
├── script.js
└── styles.css
```
<details class="brown">
<summary>
راهاندازی پروژه
</summary>
- ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
- سپس فایل `index.html` را در مرورگر خود باز کنید.
</details>
# جزئیات
در این سوال میخواهیم تغییراتی را در لیست داده شده ایجاد کنیم و لیست جدید را رندر کنیم. در پروژه اولیه در فایل `script.js` تابعی با نام `changeProducts` وجود داره که کد شما در آن قسمت قرار میگیرد. شما باید در این تابع لیست جدیدی با تغییرات خواسته شده ایجاد کنید و تابع `renderProducts` را با لیست جدید صدا بزنید. تابع `changeProducts` وقتی صدا زده میشود که دکمه "اعمال تغییرات" کلیک شود. (کد این قسمت در پروژه اولیه وجود دارد)
**تغییرات خواسته شده**
- قیمت محصولات باید نصف شود.
- تاریخ با استفاده از `Date` و متد `toLocaleDateString` فرمت شود. (راهنمایی: `timestamp` داده شده در فیلد `date` محصولات به صورت ثانیه است اما `Date` نیاز به میلی ثانیه دارد. این تبدیل باید انجام شود)
# نکات
- شما تنها مجاز به اعمال تغییرات در فایل `script.js` هستید.
- تعدادی تست نمونه در پروژه اولیه وجود دارد که با استفاده از آنها میتوانید کد خود را تست کنید.
- فقط فایلی را که مجاز به تغییر هستید باید آپلود نمایید.
# قسمت آموزشی
در این قسمت راهنماییهای سوال، به مرور اضافه میشود. مشکلاتتان در راستای حل سوال را میتوانید از بخش ["سوال بپرسید"](https://quera.ir/contest/clarification/20209/) مطرح کنید.
<details class="blue">
<summary>
راهنمایی ۱
</summary>
با استفاده از map روی لیست محصولات داده شده میتوانید لیست جدید با تغییرات خواسته شده را ایجاد کنید.
</details>
<details class="blue">
<summary>
راهنمایی ۲
</summary>
تغییر خواسته شده برای تاریخ به این صورت است که ابتدا `date` را ضرب در ۱۰۰۰ میکنیم که به میلی ثانیه تبدیل شود بعد آن را به *new Date* میدهیم و متد `toLocaleDateString` رو آن صدا میزنیم.
</details>
<details class="blue">
<summary>
راهنمایی۳
</summary>
برای خواندن مطالب بیشتر در مورد `map` و `Date` میتوانید از این لینکها استفاده کنید:
[لینک برای مپ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
[لینک برای تاریخ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date)
</details>
محصولات
ظاهر کلی برنامه بدین صورت است:
![ظاهر برنامه](https://quera.ir/qbox/view/HbOZvuLKdT/tic-tac-toe.gif)
# پروژه اولیه
پروژه اولیه را از
[این لینک](/contest/assignments/20209/download_problem_initial_project/65888/)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
```
tic-tac-toe
├── cypress
│ ├── fixtures
│ │ └── example.json
│ ├── integration
│ │ └── sample.spec.js
│ ├── plugins
│ │ └── index.js
│ └── support
│ ├── commands.js
│ └── index.js
├── cypress.json
├── index.html
├── package-lock.json
├── package.json
├── script.js
└── style.css
```
<details class="brown">
<summary>
راهاندازی پروژه
</summary>
- ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
- سپس فایل `index.html` را در مرورگر خود باز کنید.
</details>
# جزئیات
این سوال یکی از تمرینهای دوره فرانتاند و بخش سوم ساخت بازی *XO* است. تا این بخش کلیات بازی ساخته شده اما بازی هیچگاه برنده ندارد. در این بخش میخواهیم این قوانین را به بازی اضافه کنیم.
نکاتی که برای اضافه کردن عملکرد برد و باخت و مساوی به بازی باید به آنها توجه کنید:
- اگر سه سلول افقی یا عمودی یا قطری یکی باشند، بازی برنده دارد. اگر این سه سلول `X` باشند، این بازیکن برنده بازی است و در قسمت وضعیت بازی باید "Player X has won" نوشته شود و اگر `O` باشند، باید در قسمت وضعیت بازی "Player O has won" نوشته شود.
- هرگاه بازی برنده داشت ادامه بازی ممکن نیست یعنی وقتی روی سلولهای خالی کلیک شود، اتفاقی نیفتد (با `X` یا `O` پر نشود).
- اگر بازی برنده نداشت و تمام سلولها پر شدند، بازی مساوی است و داخل قسمت وضعیت بازی باید " Game ended in a draw" نوشته شود.
# نکات
- شما تنها مجاز به اعمال تغییرات در فایل `script.js` هستید.
- تعدادی تست نمونه در پروژه اولیه وجود دارد که با استفاده از آنها میتوانید کد خود را تست کنید.
- فقط فایلی را که مجاز به تغییر هستید باید آپلود نمایید.
# قسمت آموزشی
در این قسمت راهنماییهای سوال، به مرور اضافه میشود. مشکلاتتان در راستای حل سوال را میتوانید از بخش ["سوال بپرسید"](https://quera.ir/contest/clarification/20209/) مطرح کنید.
<details class="blue">
<summary>
راهنمایی ۱
</summary>
با استفاده از `gameState` میتوانید تمام شدن بازی و برنده یا مساوی بودن بازی را مشخص کنید. اگر بازی برنده داشت بازی را متوقف کنید.
</details>
<details class="blue">
<summary>
راهنمایی ۲
</summary>
بعداز اینکه بازی برنده یا مساوی شد، `gameActive` باید `false` شود و موقع کلیک چک شود که اگر `gameActive` برابر `false` بود حرکت انجام نشود. `gameActive` بعداز کلیک شدن روی شروع دوباره `true` میشود.
</details>
<details class="blue">
<summary>
راهنمایی ۳
</summary>
برای تشخیص برد میتوانید یک آرایه به این صورت تعریف کنید: (لیست زیر کامل نیست و فقط شامل حالتهای افقی برای برد است)
```javascript
const winningConditions = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
...
];
```
شامل تمام حالتهای برد و با یک حلقه روی `winningConditions` اگر این سه تا نقطه در *gameState* برابر بودند، یعنی بازی برنده دارد.
</details>
بازی XO
**مهارتهای لازم:**
- آشنایی با state
--------------------------------------------------
ظاهر کلی برنامه بدین صورت است:
![ظاهر برنامه](https://quera.ir/qbox/view/Ar3ncTfRIr/input_mask.gif)
# پروژه اولیه
پروژه اولیه را از
[این لینک](/contest/assignments/20209/download_problem_initial_project/65884/)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
```
input-mask
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── __tests__
│ │ └── sample.test.js
│ ├── App.js
│ ├── Input.js
│ ├── cities.json
│ ├── index.css
│ └── index.js
├── package-lock.json
└── package.json
```
<details class="brown">
<summary>
راهاندازی پروژه
</summary>
**برای اجرای پروژه، باید `NodeJS` و `npm` را از قبل نصب کرده باشید.**
- ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
- در پوشهی `input-mask` ، دستور `npm install` را برای نصب نیازمندیها اجرا کنید.
- در همین پوشه، دستور `npm start` را برای راهاندازی پروژه اجرا کنید.
- پس از انجام موفق این مراحل، با مراجعه به آدرس `http://localhost:3000/`
میتوانید نتیجه را ببینید.
</details>
# جزئیات
در این سوال شما باید:
1. شهر ها را از فایل `cities.json` بخوانید
2. کامپوننت `Input` را داخل div رندر کنید
3. با استفاده از تابعی که به `handleChange` اینپوت میدهید، اولین شهری که با حروف ورودی اینپوت شروع میشود را پیدا کنید و شهر پیدا شده را به `hint` اینپوت بدهید
- اگر اینپوت خالی باشد، `hint` هم باید خالی شود
- اگر شهری پیدا نشد `hint` باید خالی باشد
- به حروف بزرگ و کوچک حساس است
# نکات
- شما تنها مجاز به اعمال تغییرات در فایل `App.js` هستید.
- تعدادی تست نمونه در پروژه اولیه وجود دارد که با استفاده از آنها میتوانید کد خود را تست کنید.
- پس از اعمال تغییرات، پروژه را _ZIP_ کرده و ارسال کنید. دقت کنید که پوشهی `node_modules` در فایل ارسالی نباشد.
# قسمت آموزشی
در این قسمت راهنماییهای سوال، به مرور اضافه میشود. مشکلاتتان در راستای حل سوال را میتوانید از بخش ["سوال بپرسید"](https://quera.ir/contest/clarification/20209/) مطرح کنید.
<details class="blue">
<summary>
راهنمایی ۱
</summary>
در جاوااسکریپت تابعی وجود دارد به اسم startsWith که وظیفهاش چک کردن اینکه یک string با string دیگر شروع شده باشد.
```javascript
"test".startsWith("te") // true
```
</details>
<details class="blue">
<summary>
راهنمایی ۲
</summary>
برای `hint` از هوک `useState` استفاده کنید که در ابتدا یک رشته خالی "" است. وقتی شهر را پیدا کردید مقدارش را به مقدار آن شهر تغییر دهید و وفتی متن داخل اینپوت خالی شد مقدارش را به خالی "" تغییر دهید.
</details>
<details class="blue">
<summary>
راهنمایی۳
</summary>
مقدار اینپوت را میتوانید به وسیله تابعی که به کامپوننت `Input` میدهید بدست آورید. این تابعی که تعریف میکنید یک *event* میگیرد و با `event.target.value` میتوانید به مقدار اینپوت دسترسی پیدا کنید.
</details>
Input Mask
**مهارتهای لازم:**
- آشنایی با context
- آشنایی با fetch
- کار با فرم
--------------------------------------------------
ظاهر کلی برنامه بدین صورت است:
![ظاهر برنامه](https://quera.ir/qbox/view/BwSU1r4udj/auth_context.gif)
# پروژه اولیه
پروژه اولیه را از
[این لینک](/assignment/20076/download_problem_initial_project/65819/)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
```
auth-context
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── __tests__
│ │ └── sample.test.js
│ ├── components
│ │ ├── login.js
│ │ └── register.js
│ ├── context
│ │ └── auth-context.js
│ ├── hacks
│ │ ├── hack-fetch.js
│ │ └── users.js
│ ├── app.js
│ ├── authenticated-app.js
│ ├── index.css
│ ├── index.js
│ └── unauthenticated-app.js
├── .env
├── package-lock.json
└── package.json
```
<details class="brown">
<summary>
راهاندازی پروژه
</summary>
**برای اجرای پروژه، باید `NodeJS` و `npm` را از قبل نصب کرده باشید.**
- ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
- در پوشهی `auth-context` ، دستور `npm install` را برای نصب نیازمندیها اجرا کنید.
- در همین پوشه، دستور `npm start` را برای راهاندازی پروژه اجرا کنید.
- پس از انجام موفق این مراحل، با مراجعه به آدرس `http://localhost:3000/`
میتوانید نتیجه را ببینید.
</details>
# جزئیات
در این سوال شما باید در فایل `auth-context.js` کانتکس و *provider* بسازید که وظیفه آن بهاشتراکگذاری کاربر و لاگین یا لاگاوت بودن آن در تمام کامپوننتها است. کامپوننتهای `login` و `register` را طوری کامل کنید که هنگام *submit* فرم موجود، اطلاعات کاربر به صورت درخواست *POST* به آدرس سرور مورد نظر ارسال شود. اگر درخواست فرستاده شده موفقیتآمیز بود کاربر باید در کانتکست ثبت شود و اگر ایراد داشت باید هندل شود و ارور برگشت داده شده در *div* با کلاس *error-message* نشان داده شود.
آدرس سرور برای ثبت نام:
http://localhost:8989/api/register
آدرس سرور برای لاگین:
http://localhost:8989/api/login
برای دانستن بیشتر در مورد *fetch* میتوانید از این لینک استفاده کنید:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
# نکات
شما تنها مجاز به اعمال تغییر در فایلهای زیر هستید:
src/context/auth-context.js
src/components/login.js
src/components/register.js
- نیازی به تغییر یا دیدن فایلهای موجود در پوشه hacks ندارید.
- تعدادی تست نمونه در پروژه اولیه وجود دارد که با استفاده از آنها میتوانید کد خود را تست کنید.
- پس از اعمال تغییرات، پروژه را _ZIP_ کرده و ارسال کنید. دقت کنید که پوشهی `node_modules` در فایل ارسالی نباشد.
# قسمت آموزشی
در این قسمت راهنماییهای سوال، به مرور اضافه میشود. مشکلاتتان در راستای حل سوال را میتوانید از بخش ["سوال بپرسید"](https://quera.ir/contest/clarification/20209/) مطرح کنید.
<details class="blue">
<summary>
راهنمایی ۱
</summary>
برای قسمت مقدار `AuthProvider` نیاز به ابجکت با سه تا فیلد: *user* که ابجکت کاربر، *login* تابعی که کاربر را ثبت میکند و و *logout* که کاربر را *null* قرار میدهد. هنگام ثبتنام و لاگین بعداز ارسال درخواست تابع *login* از این *context* صدا زده میشود.
</details>
<details class="blue">
<summary>
راهنمایی ۲
</summary>
در صفحات لاگین و ثبتنام هنگام *submit* فرم باید یک درخواست *POST* بوسیله *fetch* به آدرس گفته شده ارسال شود. داده ارسالی یک آبجکت شامل *username* و *password* است. این *username* و *password* را میتوانید به دو صورت بگیرید. اگر از *onSubmit* روی فرم استفاده میکنید میتوانید از `event.target.elements` بگیرید که برای مثال مقدار *username* به صورت `event.target.elements.username.value` است یا میتوانید از استیت استفاده کنید.
</details>
<details class="blue">
<summary>
راهنمایی۳
</summary>
**نکته**: مقدار *value* اینپوتها داخل فرمها را تغییر ندهید، نیازی به اینکار نیست و با *value* تستها تداخل ایجاد میکند.
</details>
Auth Context
**مهارتهای لازم:**
- تسلط به hook
- کار کاردن با state و reducer
- آشنایی با قوانین بازی مار
--------------------------------------------------
ظاهر کلی برنامه بدین صورت است:
![ظاهر برنامه](https://quera.ir/qbox/view/jN9tR8ZuMW/bazi_mar.gif)
# پروژه اولیه
پروژه اولیه را از
[این لینک](/contest/assignments/20209/download_problem_initial_project/65885/)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
```
snake-game
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── __tests__
│ │ └── sample.test.js
│ ├── assets
│ │ └── index.css
│ ├── components
│ │ ├── apple.js
│ │ ├── game.js
│ │ └── snake.js
│ ├── hooks
│ │ └── use-snake.js
│ ├── index.js
│ ├── initialState.js
│ └── logic.js
├── package-lock.json
└── package.json
```
<details class="brown">
<summary>
راهاندازی پروژه
</summary>
**برای اجرای پروژه، باید `NodeJS` و `npm` را از قبل نصب کرده باشید.**
- ابتدا پروژهی اولیه را دانلود و از حالت فشرده خارج کنید.
- در پوشهی `snake-game` ، دستور `npm install` را برای نصب نیازمندیها اجرا کنید.
- در همین پوشه، دستور `npm start` را برای راهاندازی پروژه اجرا کنید.
- پس از انجام موفق این مراحل، با مراجعه به آدرس `http://localhost:3000/`
میتوانید نتیجه را ببینید.
</details>
# جزئیات
در این سوال شما باید هوک *useSnake* که در فایل `hooks/use-snake.js` تعریف شده را کامل کنید. این هوک در کامپوننت `game.js` استفاده شده و آبجکتی شامل تمام اعضای وضعیت اولیه بازی برمیگرداند که در ابتدا برابر با آن است و سپس براساس موارد زیر تغییر میکند. شما در این سوال باید تغییرات لازم را در هر ۱۰۰ میلیثانیه (سرعت بازی) و کلیک شدن دکمههای w s a d در کیبورد روی وضعیت بازی اعمال کنید. (وضعیت اولیه بازی را حتما از فایل `initialState.js` بخوانید)
- مار و غذا در ابتدا در مکان اولیه تعریف شده هستند.
- در شروع کار مار به سمت راست شروع به حرکت میکند.
- حرکتها یک لیست است که در حالت اولیه یک آیتم دارد، با فشار دادن دکمه های w s a d اگر حرکت مخالف اولین حرکت تو این لیست نباشد به لیست اضافه میشود. وقتی حرکتها داخل لیست بیشتر از یکی باشد به ترتیب از اولین حرکت، رفته و از لیست خارج میشوند تا به یک آیتم در لیست برسد. (مسیر حرکت مار اولین ایتم لیست حرکتها است و این لیست همواره حداقل یک آیتم دارد)
- مار بعد از خوردن غذا رشد میکند.
- غذا بعد از خورده شدن تو مکان رندمی از بورد ظاهر میشود که حتما داخل بورد است.
- بازی با خوردن مار با خودش دوباره از وضعیت اولیه شروع میشود.
**وضعیت اولیه بازی**
```json
{
<mark title="تعداد ستون های بورد بازی">cols</mark>: 20,
<mark title="تعداد ردیف های بورد بازی">rows</mark>: 14,
<mark title="طول و عرض بورد بازی">board</mark>: {width: 700, height: 500},
<mark title="سرعتی که مار با ان حرکت میکند">speed</mark>: 100,
<mark title=" ارایه ای از حرکت ها، اگر یک حرکت وجود داشته باشد مار با همان حرکت برای همیشه ادامه میدهد تا وقتی که دکمه های wasd زده میشود و حرکت ها در این ارایه به صورت صف وارد میشوند و به ترتیب انجام میشوند">moves</mark>: [EAST],
<mark title="ارایه ای از مختصاتهای نقطه های مار">snake</mark>: [{x: 2, y: 2}],
<mark title="مختصات غذا که اولین بار با `initialState` پر میشود و دفعات بعد به صورت رندم است">apple</mark>: {x: 16, y: 2},
}
```
**مختصات**
مختصاتها در بازی مار به صورت یه ابجکت هستند. مبدا مخصات `{x: 0, y: 0}` گوشه بالا سمت چپ بورد بازی است.
![نمودار](https://quera.ir/qbox/view/ZrVA8RlEx5/bazi_mart_chart2.png)
مربع ابی نشان داده شده در مختصات `{x: 2, y: 1}` است.
# نکات
- شما تنها مجاز به اعمال تغییرات در فایلهای`hooks/use-snake.js` و `logic.js` هستید.
- فایل `logic.js` فقط یک فایل اضافه است که بتوانید توابعی که مربوط به *logic* بازی است را در آن تعریف کنید. این فایل میتواند خالی باشد
- تعدادی تست نمونه در پروژه اولیه وجود دارد که با استفاده از آنها میتوانید کد خود را تست کنید.
- پس از اعمال تغییرات، پروژه را _ZIP_ کرده و ارسال کنید. دقت کنید که پوشهی `node_modules` در فایل ارسالی نباشد.
# قسمت آموزشی
در این قسمت راهنماییهای سوال، به مرور اضافه میشود. مشکلاتتان در راستای حل سوال را میتوانید از بخش ["سوال بپرسید"](https://quera.ir/contest/clarification/20209/) مطرح کنید.
<details class="blue">
<summary>
راهنمایی ۱
</summary>
از `useReducer` برای مدیریت استیت بازی استفاده کنید و `INIT_STATE` را به عنوان استیت اولیه به آن بدهید.
</details>
<details class="blue">
<summary>
راهنمایی ۲
</summary>
بعداز تعریف `useReducer` از یک `useEffect` برای تعریف یک *interval* استفاده میکنیم که در هر ۱۰۰ میلی ثانیه *dispatch* را با یک اسمی مانند *move* صدا میزند این *interval* را در یک متغیر میذاریم تا هنگام `return`، بتوانیم `clearInterval` را روی آن صدا بزنیم.
از یک `useEffect` دیگر برای تعریف دکمههای w a s d استفاده میکنیم و dispatch را با اسمی مانند *change_direction* و البته جهت جدید صدا میزنیم.
بقیه برنامه، فقط منطق برنامه است که داخل *reducer* نوشته میشوند.
**توجه**: این فقط یکی از روشهای ساخت این بازی است و قطعا روشهای دیگری هم وجود دارد.
</details>
<details class="blue">
<summary>
راهنمایی۳
</summary>
**قوانین بازی مار:**
اگر *head* بعدی مار که قراره حرکت کنیم را *nextHead* در نظر بگیریم
- **برخورد**: برخورد وقتی اتفاق میفتد که مختصات *nextHead* با مختصات یکی از نقطههای مار برابر باشد.
- **حرکت مار**: اگر مار برخورد داشت به حالت اولیه برمیگردد، اگر برخورد نداشت با اضافه کردن *nextHead* به نقطههای مار به جز آخرین نقطه بدست میآید اما در صورت خوردن سیب آخرین نقطه هم اضافه میشود.
- سیب در یک نقطه رندوم یعنی *x* باید عدد صحیح رندوم بین ۰ و اندازه *cols* (که از *INIT_STATE* میاد) و *y* باید عدد صحیح رندوم بین ۰ و *rows* (که از *INIT_STATE* میاد) باشد.
</details>