![مینروب](https://quera.ir/qbox/view/ZYevn8BMGB/photo_2019-07-12_13-40-11.jpg)
میخواهیم بازی مینروب را به شکل سهبعدی و دونفره با استفاده از ReactJS پیادهسازی کنیم.
این بازی به صورت دونفره بین دو نفر به شکل نوبتی بازی میشود که یک مکعب $ n \times n \times n$ داریم که هر خانه از این مکعب یا امن است یا حاوی یک مین است. با کلیک روی هر خانه، آن خانه باز میشود؛ بازشدن یکخانه به این معنی است که در صورتی که در آن خانه بمب باشد، بازیکنی که آن را باز کرده یک امتیاز گرفته و در غیر اینصورت تعداد مینهای اطراف این خانه شمرده میشوند، اگر صفر نبود تعداد این مینها روی آن خانه نمایش داده میشوند و در صورتی که صفر بود، مشخصاست که کل خانههای مجاور با این خانه نیز بدون مین هستند، آن خانهها هم باز میشوند و این بازشدن تا جایی ادامه پیدا میکند تا به خانههای بدون بمبی که اطرافشان حداقل یک مین است برسیم.
برای پایان بازی باید همهی خانههایی که در آن مین قرار گرفته توسط یکی از دو نفر باز شود، سپس اگر امتیاز دونفر نابرابر بود کسی که امتیاز بیشتری کسب کرده برندهی بازی و در غیراینصورت تساوی رخ میدهد.
چون بازی ۳ بعدی است و تنها میتوانیم دو بعد را در کامپیوتر ببینیم، صفحهی نمایش بازی را به دو بخش تقسیم میکنیم، بخش اول شامل یک صفحهی دوبعدی از بازی است که نشاندهندهی همهی خانههای یک عمق خاص از مکعب است و بخش دوم شامل نمای کوچکی از همهی عمقهاست که با کلیک بر روی هر عمق کدام، آن عمق روی بخش اول به نمایش در میآید.
دو خانه در مکعب مجاورند اگر رأس مشترک داشته باشند. یعنی یک خانه میتواند حداکثر ۲۶ خانهی مجاور داشته باشد.
# پروژه اولیه
پروژه اولیه را از [اینجا](https://quera.ir/qbox/download/phBnP2Qfit/minroob.zip) دانلود کنید.
<details>
<summary>
ساختار فایلهای پروژهی اولیه
</summary>
```
minroob
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── components
│ │ ├── board
│ │ │ ├── Board.css
│ │ │ ├── Board.js
│ │ │ ├── Cell.css
│ │ │ ├── Cell.js
│ │ │ └── bomb.svg
│ │ ├── menu
│ │ │ ├── Layers.css
│ │ │ ├── Layers.js
│ │ │ ├── State.css
│ │ │ └── State.js
│ │ ├── App.css
│ │ └── App.js
│ ├── constants.js
│ ├── index.css
│ └── index.js
├── README.md
├── package.json
├── pnpm-debug.log
└── pnpm-lock.yaml
```
</details>
# راهاندازی پروژه
**برای اجرای پروژه، باید `NodeJS` و `npm` (یا `pnpm`) را از قبل نصب کرده باشید.**
- در پوشهی `minroob` ، دستور `npm install` را برای نصب نیازمندیها اجرا کنید.
- **نکته:** برای نصب سریعتر از `pnpm install` استفاده کنید.
- در همین پوشه، دستور `npm start` را برای راهاندازی پروژه اجرا کنید.
- با مراجعه به `http://localhost:3000/` میتوانید نتیجه را ببینید.
- برای اجرای تستهای نمونه `npm test` را اجرا کنید.
# جزئیات
پروژه تعدادی مؤلفه تعریف شده که در جدول زیر مشاهده میکنید.
همچنین حالت بازی در بالاترین مؤلفه یعنی `App` قرار دارد:
| مؤلفه | توضیحات |
|:-----------:|---------------------------------------------------------------------------|
| **`App`** | مؤلفهی اصلی بازی است و حالت بازی در آن قرار دارد. |
| **`State`** | مؤلفهی بدون حالت برای اینکه نوبت کدام یک از دو نفر است و اینکه اگر بازی تمام شده، برندهی بازی کیست |
| **`Layers`** | مؤلفهی بدون حالت برای لیست عمقهای مکعب بازی |
| **`Board`** | مؤلفهی بدون حالت برای نمایش یک عمق از مکعب بازی |
| **`Cell`** | مؤلفهی بدون حالت برای نمایش یک خانه از بازی |
حالت بازی (حالت مؤلفهی `App`) به صورت زیر است.
```js
{
n: 5,
currentLayer: 0,
turn: 1, // turn is 1 or 2
board: [
[
{
hasBomb: true,
visible: false,
owner: null
},
{
hasBomb: false,
visible: false,
owner: null
},
...
],
...
]
}
```
همانطور که مشخص است، اندازهی مکعب، لایهای از مکعب که در حال مشاهدهی آن هستیم، کسی که نوبت اوست و اطلاعات مکعب در حالت قرار دارد.
- شمارهی لایهای که آنرا میبینیم `currentLayer` از صفر شروع میشود.
- مقدار `turn` یک یا دو است و اینکه نوبت نفر اول است یا دوم را نشان میدهد.
- `board` شامل اطلاعات مکعب بازی است که یک آرایه است که هر عضو آن مربوط به یک عمق است که آن یک آرایهی با $n \times n$ درایه است که وضعیت خانهها را صورت سطر به سطر از چپ به راست نشان میدهد.
هر خانه از مکعب شامل ۳ داده است:
- مقدار `hasBomb` که نشان میدهد آیا در این خانه مین قرار دارد یا امن است.
- مقدار `visible` که نشان میدهد آیا این خانه باز شدهاست یا خیر.
- مقدار `owner` که نشان میدهد اگر در خانه مین است، این مین را کدام یک از دو نفر تصاحب کردهاند، مقدار `owner` برای خانههای امن یا بازنشده `null` و برای بقیهی خانهها ۱ یا ۲ است.
مواردی که باید پیادهسازی کنید:
## ۱. نمایش اولیه
در نمایش اولیهی بازی، باید حالت کنونی بازی در مؤلفهی `Board` نمایش دادهشود دقت کنید مؤلفهی `Board` هم نمایش بورد اصلی بازی را بر عهده دارد و هم نمایش بوردهای کوچک در مؤلفهی `Layers` را، خصوصهی `type` به همین منظور استفاده شدهاست.
همچنین بورد عمقی که در حال نمایش است از `Layers` باید کلاس `current` را داشتهباشد.
همچنین `Cell` ها براساس کلاسهای تعریفشده در `Cell.css` کلاس داشتهباشند، مثلا اگر خانه باز نشدهاست، `.cell.unknown` باشد، اگر مین دارد و متعلق به نفر اول است `.cell.bomb.user1` باشد و اگر باز شده و روی آن عدد ۳ است `.cell.number.number-3` را داشتهباشد.
## ۲. عملکرد صحیح انتخاب بوردها
با کلیک بر روی `.layerMask` هر بورد در `Layers`، باید آن بورد برای نمایش داده شدن در بورد اصلی انتخاب شود.
## ۳. عملکرد صحیح کلیک روی خانهها
با کلیک بر روی یک `Cell` در بورد اصلی، در صورتی که بازی تمام نشدهباشد و خانه قبلا باز نشدهباشد، باید خانه باز شده و نوبت به نفر دیگر دادهشود.
## ۴. عملکرد صحیح `State`
در صورتی که بازی تمام نشده (تمام مینها باز نشدهاند.) و یکی از دو کلاس `.state.turn-1` یا `.state.turn-2` را بر حسب کسی که نوبتش است داشتهباشد و در صورت پایان بازی، یکی از ۳ کلاس `.state.win-1`, `.state.win-2` یا `.state.win-0` در صورت برد نفر اول یا دوم یا مساوی داشتهباشد.
# نکات
- میتوانید در صورت نیاز دادههای دیگری نیز در حالت مؤلفه ذخیره کنید.
اما مجاز به تغییر ساختار دادههای فعلی نیستید.
- شما تنها مجاز به اعمال تغییر در فایلهای `App.js`، `Layers.js`، `Board.js`، `State.js` و `Cell.js` هستید.
- پس از اعمال تغییرات، پروژه را _Zip_ کرده و ارسال کنید.
دقت کنید که پوشهی `node_modules` در فایل ارسالی نباشد.