برای آشنایی با قالب صورت سوال در Quera اینجا را مشاهده کنید و برای آشنایی با نحوه‌ی داوری فرانت‌اند، اینجا را ببینید. برای کسب اطلاعات بیشتر درباره نحوه برگزاری مسابقه و پخش جوایز هم اینجا را ببینید.

دو سوال آخر مسابقه مربوط به React هستند.

مین‌روب دو نفره


مین‌روب

می‌خواهیم بازی مین‌روب را به شکل سه‌بعدی و دونفره با استفاده از ReactJS پیاده‌سازی کنیم.

این بازی به صورت دونفره بین دو نفر به شکل نوبتی بازی می‌شود که یک مکعب n×n×n n \times n \times n داریم که هر خانه از این مکعب یا امن است یا حاوی یک مین است. با کلیک روی هر خانه، آن خانه باز می‌شود؛ بازشدن یک‌خانه به این معنی است که در صورتی که در آن خانه بمب باشد، بازیکنی که آن را باز کرده یک امتیاز گرفته و در غیر این‌صورت تعداد مین‌های اطراف این خانه شمرده می‌شوند، اگر صفر نبود تعداد این مین‌ها روی آن خانه نمایش داده می‌شوند و در صورتی که صفر بود، مشخص‌است که کل خانه‌های مجاور با این خانه نیز بدون مین هستند، آن خانه‌ها هم باز می‌شوند و این بازشدن تا جایی ادامه پیدا می‌کند تا به خانه‌های بدون بمبی که اطرافشان حداقل یک مین است برسیم.

برای پایان بازی باید همه‌ی خانه‌هایی که در آن مین قرار گرفته توسط یکی از دو نفر باز شود، سپس اگر امتیاز دونفر نابرابر بود کسی که امتیاز بیشتری کسب کرده برنده‌ی بازی و در غیراین‌صورت تساوی رخ می‌دهد.

چون بازی ۳ بعدی است و تنها می‌توانیم دو بعد را در کامپیوتر ببینیم، صفحه‌ی نمایش بازی را به دو بخش تقسیم می‌کنیم، بخش اول شامل یک صفحه‌ی دوبعدی از بازی است که نشان‌دهنده‌ی همه‌ی خانه‌های یک عمق خاص از مکعب است و بخش دوم شامل نمای کوچکی از همه‌ی عمق‌هاست که با کلیک بر روی هر عمق کدام، آن عمق روی بخش اول به نمایش در می‌آید.

دو خانه در مکعب مجاورند اگر رأس مشترک داشته باشند. یعنی یک خانه می‌تواند حداکثر ۲۶ خانه‌ی مجاور داشته باشد.

پروژه اولیه🔗

پروژه اولیه را از اینجا دانلود کنید.

ساختار فایل‌های پروژه‌ی اولیه
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
Plain text

راه‌اندازی پروژه🔗

برای اجرای پروژه، باید NodeJS و npm (یا pnpm) را از قبل نصب کرده باشید.

  • در پوشه‌ی minroob ، دستور npm install را برای نصب نیازمندی‌ها اجرا کنید.
    • نکته: برای نصب سریع‌تر از pnpm install استفاده کنید.
  • در همین پوشه، دستور npm start را برای راه‌اندازی پروژه اجرا کنید.
  • با مراجعه به http://localhost:3000/ می‌توانید نتیجه را ببینید.
  • برای اجرای تست‌های نمونه npm test را اجرا کنید.

جزئیات🔗

پروژه تعدادی مؤلفه تعریف شده که در جدول زیر مشاهده می‌کنید. همچنین حالت بازی در بالاترین مؤلفه یعنی App قرار دارد:

مؤلفه توضیحات
App مؤلفه‌ی اصلی بازی است و حالت بازی در آن قرار دارد.
State مؤلفه‌ی بدون حالت برای اینکه نوبت کدام یک از دو نفر است و اینکه اگر بازی تمام شده، برنده‌ی بازی کیست
Layers مؤلفه‌ی بدون حالت برای لیست عمق‌های مکعب بازی
Board مؤلفه‌ی بدون حالت برای نمایش یک عمق از مکعب بازی
Cell مؤلفه‌ی بدون حالت برای نمایش یک خانه از بازی

حالت بازی (حالت مؤلفه‌ی App) به صورت زیر است.

{
  n: 5,
  currentLayer: 0,
  turn: 1, // turn is 1 or 2
  board: [
    [
      {
        hasBomb: true,
        visible: false,
        owner: null
      },
      {
        hasBomb: false,
        visible: false,
        owner: null
      },
      ...
    ],
    ...
  ]
}
JavaScript

همان‌طور که مشخص است، اندازه‌ی مکعب، لایه‌ای از مکعب که در حال مشاهده‌ی آن هستیم، کسی که نوبت اوست و اطلاعات مکعب در حالت قرار دارد.

  • شماره‌ی لایه‌ای که آن‌را می‌بینیم currentLayer از صفر شروع می‌شود.
  • مقدار turn یک یا دو است و اینکه نوبت نفر اول است یا دوم را نشان می‌دهد.
  • board شامل اطلاعات مکعب بازی است که یک آرایه است که هر عضو آن مربوط به یک عمق است که آن یک آرایه‌ی با n×nn \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 در فایل ارسالی نباشد.
ارسال پاسخ برای این سؤال
در حال حاضر شما دسترسی ندارید.