به پروژه ی سوم از این سری آموزشی خوش آمدید. در این پروژه می خواهیم یک بازی حدس عدد را بسازیم که به شکل زیر کار می کند:
ما در این پروژه ها سعی می کنیم از کتابخانه های مختلفی برای راه اندازی UI خود استفاده کنیم تا شما با انواع مختلف آن ها آشنا شویم. در این پروژه از کتابخانه ی Skeleton استفاده می کنیم که یک کتابخانه ی بسیار کم حجم و فشرده و البته بسیار ساده می باشد:
متاسفانه وب سایت رسمی این کتابخانه، ip های ایران را تحریم کرده اند بنابراین برای رجوع به سایت آن ها باید از ابزار های رفع تحریم استفاده کنید. من از CDN زیر برای بارگذاری در پروژه مان استفاده می کنم:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.css" integrity="sha256-ECB9bbROLGm8wOoEbHcHRxlHgzGqYpDtNTgDTyDz0wg=" crossorigin="anonymous" />
برای راه اندازی پروژه ابتدا یک پوشه به نام NumberGuesser ایجاد می کنیم و مثل همیشه درون آن دو فایل مختلف خواهیم داشت:
برای محتوای فایل html می توانید کدهای زیر را در آن کپی کنید:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.css" /> <title>Number Guesser</title> </head> <body> <div class="container"> <h1>Number Guesser</h1> <div id="game"> <p>Guess a number between <span class="min-num"></span> and <span class="max-num"></span></p> <input type="number" id="guess-input" placeholder="Enter your guess..."> <input type="submit" value="Submit" id="guess-btn"> <p class="message"></p> </div> </div> <script src="app.js"></script> </body> </html>
اگر دوست داشتید می توانید فایل HTML را بیشتر بررسی کنید اما کدهای آن بسیار ساده است و من توضیحاتی در مورد آن نمی دهم. حالا وارد فایل app.js می شویم تا کدهای جاوا اسکریپت آن را بنویسیم.
اولین کار ما تعریف برخی از متغیرهای مربوط به بازی است:
// Game values let min = 1, max = 10, winningNum = 2, guessesLeft = 3;
کد بالا خطا نیست بلکه روش بهتر تعریف متغیرهای مختلف است. شما می توانید کلیدواژه ی let را بنویسید و سپس متغیرها را با ویرگول از هم جدا کنید. عدد min قرار است حداقل و max حداکثر باشد. این دو عدد تعریف می کنند که برنامه بین چه بازه ای عدد را انتخاب کند. متغیر winningNum نیز عدد انتخاب شده توسط جاوا اسکریپت است که البته فعلا به صورت دستی آن را 2 قرار داده ایم تا بعدا کدهایش را تکمیل کنیم و به صورت تصادفی انتخاب شود. gussesLeft نیز به معنی حدس های باقی مانده برای کاربر است که در اولین اجرای برنامه باید 3 باشد (کاربر با 3 حدس بازی را شروع می کند). این متغیرها مربوط به خود بازی هستند و در طول بازی تغییر می کنند به همین دلیل از نوع let هستند اما باید متغیرهای مخصوص UI را نیز تعریف کنیم که از نوع const خواهند بود. بنابراین:
// UI Elements const game = document.querySelector('#game'), minNum = document.querySelector('.min-num'), maxNum = document.querySelector('.max-num'), guessBtn = document.querySelector('#guess-btn'), guessInput = document.querySelector('#guess-input'), message = document.querySelector('.message');
توضیح متغیرها:
حالا باید مقدار دو <span> ای را که عدد حداقل و حداکثر را مشخص می کنند با استفاده از جاوا اسکریپت تعیین کنیم بنابراین می گوییم:
// Assign UI min and max minNum.textContent = min; maxNum.textContent = max;
حالا به فایل html بروید و مقدار 1 و 10 را از درون آن دو تگ <span> حذف کنید چرا که جاوا اسکریپت این مقادیر را برایمان قرار خواهد داد. از این به بعد اگر مقدار متغیرهای min و max را تغییر دهید، مقدار این اعداد در span ها نیز تغییر می کند.
در قدم بعد باید event-listener خود را تعریف کنیم:
guessBtn.addEventListener('click', function () { });
اولین کاری که باید درون این تابع انجام دهیم دریافت مقدار تایپ شده توسط کاربر است اما برای آنکه مطمئن شویم مقدار تایپ شده توسط کاربر یک عدد خواهد بود از تابع parseInt استفاده می کنیم:
guessBtn.addEventListener('click', function () { let guess = parseInt(guessInput.value); });
برخی اوقات زمانی که کاربر مثلا عدد 2 را درون input وارد می کند، عدد 2 به صورت یک رشته (یعنی "2") ارسال می شود بنابراین با parseInt آن را به یک عدد تبدیل می کنیم. دلیل اینکه می خواهیم این مقدار حتما عدد باشد این است که بعدا می خواهیم آن را با عدد اصلی که جاوا اسکریپت انتخاب کرده است مقایسه کنیم و در این مقایسه هر دو باید از یک نوع باشند.
در مرحله ی بعد باید ورودی کاربر را ارزیابی کنیم که خارج از بازه ی تعیین شده (اعداد حداقل و حداکثر) نباشد بنابراین می گوییم:
guessBtn.addEventListener('click', function () { let guess = parseInt(guessInput.value); // Validate if (isNaN(guess) || guess < min || guess > max) { setMessage(`Please enter a number between ${min} and ${max}`, 'red'); } });
به نظر شما چرا داده ی کاربر را چک کرده ام تا NaN نباشد؟ در حالت عادی اگر کاربر فیلد را خالی بگذارد و فرم را ثبت کند، یک رشته ی خالی به ما ارسال می شود اما از آنجایی که داده های کاربر را با parseInt تبدیل به عدد کرده ایم، رشته ی خالی تبدیل به NaN می شود. به همین خاطر به جای چک کردن برای خالی بودن فیلد، NaN بودن ورودی را چک می کنیم. دو شرط بعدی هم می گویند که عدد وارد شده بیشتر از حداکثر و کمتر از حداقل نباشد. اگر شرط برقرار بود (یعنی داده ی کاربر نامعتبر بود) تابعی به نام setMessage اجرا می شود که به کاربر می گوید عددی بین بازه ی تعیین شده را وارد کند. پارامتر دوم این تابع یک رنگ است که رنگ متن را دریافت می کند. من برای این خطا رنگ قرمز را انتخاب کرده ام. حالا باید تابع setMessage را تعریف کنیم. ما خارج از event-listener خودمان آن را اینگونه تعریف می کنیم:
// Set message function setMessage(msg, color){ message.style.color = color; message.textContent = msg; }
در مرحله ی بعد باید ببینیم که آیا حدس کاربر صحیح است یا خیر. برای این کار از یک شرط if درون event-listener استفاده می کنیم:
// Listen for guess guessBtn.addEventListener('click', function () { let guess = parseInt(guessInput.value); // Validate if (isNaN(guess) || guess < min || guess > max) { setMessage(`Please enter a number between ${min} and ${max}`, 'red'); } // Check if won if (guess === winningNum) { // Disable input guessInput.disabled = true; // Change border color guessInput.style.borderColor = 'green'; // Set message setMessage(`${winningNum} is correct, YOU WIN!`, 'green'); } else { } });
در این شرط if می گوییم آیا حدس کاربر برابر با winingNum (عدد انتخاب شده توسط جاوا اسکریپت) است؟ اگر چنین بود ابتدا input را غیرفعال می کنیم تا کاربر چیز دیگری تایپ نکند (او برنده شده و باز تمام شده است). سپس رنگ حاشیه فیلد input را سبز می کنیم تا UI زیباتری داشته باشیم و در آخر با استفاده از همان تابع setMessage به کاربر می گوییم که برنده شده است. رنگ این پیام نیز باید سبز (green) باشد.
در قسمت بعدی باید کدهای باختن کاربر را بنویسیم (قسمت else در شرط if بالا)؛ مثلا چند حدس دیگر باقی مانده و مسائل از این قبیل...
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.