خبر و ترفند روز

خبر و ترفند های روز را اینجا بخوانید!

نحوه ساخت کلون Wordle با جاوا اسکریپت

حتما بازی Wordle را بازی کرده اید. در اینجا نحوه ایجاد نسخه Wordle خود با استفاده از جاوا اسکریپت آمده است.

Worlde یک بازی محبوب است که در اوایل سال 2022 جهان را در معرض طوفان قرار داد. ایجاد مجدد بازی Wordle یا حداقل ساختن نسخه ساده تر آن چیزی است که توسعه دهندگانی که تازه وارد جاوا اسکریپت شده اند باید در نظر بگیرند.

Wordle چگونه کار می کند

در Wordle یک کلمه مخفی پنج حرفی وجود دارد. بازیکن شش تلاش دارد و باید کلمات پنج حرفی مختلف را حدس بزند تا ببیند چقدر به کلمه مخفی نزدیک هستند.

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

رنگ سبز به کاربر می گوید که حرف در کلمه مخفی و در موقعیت درست قرار دارد، در حالی که رنگ خاکستری به بازیکن می گوید که حرف در کلمه نیست.

توضیح وردل

راه اندازی سرور توسعه

کد مورد استفاده در این پروژه در یک مخزن GitHub موجود است و برای استفاده شما تحت مجوز MIT رایگان است. اگر می‌خواهید نگاهی به نسخه زنده این پروژه بیندازید، می‌توانید این دمو را مشاهده کنید.

این پروژه از ابزار Vite build از طریق Command Line Interface (CLI) برای داربست استفاده می کند. مطمئن شوید که Yarn را روی رایانه خود نصب کرده اید زیرا به طور کلی سریعتر از Node Package Manager (NPM) است. ترمینال خود را باز کنید و دستور زیر را اجرا کنید:

yarn create vite

این یک پروژه جدید Vite ایجاد می کند. چارچوب باید Vanilla باشد و نوع آن باید به جاوا اسکریپت تنظیم شود. حالا اجرا کنید:

yarn

این همه وابستگی های لازم برای کارکرد پروژه را نصب می کند. پس از این نصب، دستور زیر را برای راه اندازی سرور توسعه اجرا کنید:

yarn dev

راه اندازی بازی و طراحی صفحه کلید

پروژه را در ویرایشگر کد خود باز کنید، محتویات فایل main.js را پاک کنید و مطمئن شوید که پوشه پروژه شما به شکل زیر است:

ساختار پروژه

حال محتویات فایل index.html را با کد boilerplate زیر جایگزین کنید:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>JS Wordle</title>
</head>

<body>
  <div id="app">
    <div>
      <h1>Wordle Clone</h1>
      <div id="controls">
        <button id="restart-btn">Replay</button>
        <button id="show-btn">Show Answer</button>
      </div>
      <div id="message">Please wait. The Game is loading...</div>
    </div>
    <div id="interface">
      <div id="board"></div>
        <div class="keyboard"></div>
    </div>
  </div>
  <script type="module" src="/main.js"></script>
</body>

</html>

برای CSS، به مخزن GitHub این پروژه بروید و محتویات فایل style.css را در فایل style.css خود کپی کنید.

مطلب مرتبط:   16 بازی محبوب Nintendo DS در تمام دوران

اکنون در ترمینال، بسته Toastify NPM را با اجرای دستور زیر نصب کنید:

yarn add toastify -S

Toastify یک بسته جاوا اسکریپت محبوب است که به شما امکان می دهد هشدارها را به کاربر نشان دهید. سپس، در فایل main.js، فایل style.css و ابزار toastify را وارد کنید.

import "./style.css"
import Toastify from 'toastify-js'

متغیرهای زیر را برای تسهیل تعامل با عناصر DOM تعریف کنید:

let board = document.querySelector("#board");
let message = document.querySelector("#message");
let keys = "QWERTYUIOPASDFGHJKLZXCVBNM".split("");
let restartBtn = document.querySelector("#restart-btn");
let showBtn = document.querySelector("#show-btn");
showBtn.setAttribute("disabled", "true");
keys.push("Backspace");
let keyboard = document.querySelector(".keyboard");

راه اندازی صفحه بازی

از آنجایی که Wordle یک بازی است که در آن کاربر باید یک کلمه پنج حرفی را در شش تلاش حدس بزند، متغیری به نام boardContent تعریف کنید که آرایه ای از شش آرایه را در خود جای دهد. سپس متغیرهای currentRow و currentBox را تعریف کنید تا عبور از boardContent آسانتر شود.

let boardContent = [
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0],
];
let currentRow = 0;
let currentBox = 0;
let secretWord;

برای رندر کردن تابلو با پنج کادر در هر یک از شش ردیف با استفاده از عناصر HTML، از حلقه‌های تودرتو برای تکرار و ایجاد عناصر استفاده کنید. در نهایت آنها را به تابلو اضافه کنید.

for (let i = 0; i <= 5; i++) {
    let row = document.createElement('div')
    for (let y = 0; y <= 4; y++) {
        let box = document.createElement('span');
        row.appendChild(box);
        row.className = `row-${i + 1}`
    }
    board.appendChild(row);
}

افزودن صفحه کلید و گوش دادن به ورودی صفحه کلید

برای ایجاد صفحه کلید، با استفاده از forEach از میان کلیدها تکرار کنید و برای هر ورودی یک عنصر دکمه ایجاد کنید. اگر ورودی * است، متن دکمه را روی Backspace قرار دهید، در غیر این صورت آن را روی مقدار ورودی تنظیم کنید.

کلاس کلید را به دکمه اختصاص دهید و ویژگی data-key را روی مقدار ورودی بزرگ تنظیم کنید. سپس، شنونده رویداد کلیکی را به دکمه ای اضافه کنید که تابع insertKey را با مقدار ورودی بزرگ فراخوانی می کند.

keys.forEach(entry => {
    let key = document.createElement("button");
    if (entry === "*") {
        key.innerText = "Backspace";
    } else {
        key.innerText = entry;
    }
    key.className = "key";
    key.setAttribute("data-key", entry.toUpperCase());
    key.addEventListener("click", () => {
        insertKey(entry.toUpperCase())
        setTimeout(() => {
            document.querySelector(`button[data-key=${entry.toUpperCase()}]`).blur();
        }, 250)
    })
    keyboard.append(key);
})

دریافت یک کلمه جدید از یک API

هنگامی که کاربر برای اولین بار بازی را بارگذاری می کند، بازی باید یک کلمه پنج حرفی جدید از API کلمه تصادفی دریافت کند. سپس این کلمه در متغیر secretWord ذخیره می شود.

function getNewWord() {
    async function fetchWord() {
        try {
            const response = await fetch("https://random-word-api.herokuapp.com/word?length=5");
            if (response.ok) {
                const data = await response.json();
                return data;
            } else {
                throw new Error("Something went wrong!")
            }
        } catch (error) {
            message.innerText = `Something went wrong. \n${error}\nCheck your internet connection.`;
        }
    }
    fetchWord().then(data => {
        secretWord = data[0].toUpperCase();
        main();
    })

}

در بلوک کد بالا، اگر کلمه تصادفی با موفقیت واکشی شود، تابع اصلی اجرا می شود. یک تابع اصلی درست در زیر تابع getNewWord تعریف کنید:

function main(){

}

برای استایل دادن به هر کادر روی تابلو، به لیستی از تمام کادرهای هر ردیف نیاز دارید. یک متغیر، ردیفی که تمام سطرهای DOM را می گیرد، اعلام کنید. همچنین سبک نمایش پیام را روی none تنظیم کنید:

    rows.forEach(row => [...row.children].forEach(child => boxes.push(child)))
    boxes.forEach((box) => {
        box.classList.add("empty");
    })
    message.style.display = "none";

سپس، شنونده رویداد keyup را به شی پنجره اضافه کنید و بررسی کنید که آیا کلید منتشر شده معتبر است یا خیر. اگر معتبر است، روی دکمه مربوطه تمرکز کنید، یک کلیک را شبیه‌سازی کنید و بعد از 250 میلی‌ثانیه تأخیر آن را محو کنید:

    window.addEventListener('keyup', (e) => {
        if (isValidCharacter(e.key)) {
            document.querySelector(`button[data-key=${e.key.toUpperCase()}]`).focus();
            document.querySelector(`button[data-key=${e.key.toUpperCase()}]`).click();
            setTimeout(() => {
                document.querySelector(`button[data-key=${e.key.toUpperCase()}]`).blur();
            }, 250)
        }
    })

در زیر شنونده رویداد keyup، شنوندگان رویداد را برای دو دکمه تنظیم کنید: showBtn و restartBtn. وقتی بازیکن روی showBtn کلیک کرد، یک اعلان نان تست با مقدار متغیر secretWord نمایش دهید.

مطلب مرتبط:   جدول ASCII چیست و چگونه از آن استفاده می کنید؟

با کلیک بر روی restartBtn صفحه دوباره بارگیری می شود. همچنین، مطمئن شوید که یک تابع isValidCharacter برای بررسی اینکه آیا یک کلید یک کاراکتر معتبر است یا خیر، اضافه کنید.

    showBtn.addEventListener('click', () => {
        Toastify({
            text: `Alright fine! the answer is ${secretWord}`,
            duration: 2500,
            className: "alert",
        }).showToast();
    })

    restartBtn.addEventListener('click', () => {
        location.reload();
    })
    function isValidCharacter(val) {
        return (val.match(/^[a-zA-Z]+$/) && (val.length === 1 || val === "Backspace"))
    }

خارج از تابع اصلی، یک تابع renderBox ایجاد کنید و سه پارامتر را ارائه دهید: ردیف (شماره ردیف)، کادر (شاخص کادر داخل ردیف)، و داده (محتوای متنی که باید به‌روزرسانی شود).

function renderBox(row, box, data) {
    [...document.querySelector(`.row-${row}`).children][box].innerText = data;
}

مدیریت ورودی صفحه کلید با یک عملکرد

برای مدیریت ورودی های کلید و به روز رسانی برد، یک تابع insertKey با یک پارامتر کلیدی ایجاد کنید. تابع باید مطابق با پارامتر ارسال شده رفتار کند.

function insertKey(key) {
    if (key === "Backspace".toUpperCase() && currentRow < boardContent.length) {
        boardContent[currentRow][currentBox] = 0;
        if (currentBox !== 0) {
            currentBox--;
            renderBox(currentRow + 1, currentBox, "");
        }
    } else {
        if (currentRow < boardContent.length) {
            boardContent[currentRow][currentBox] = key;
            renderBox(currentRow + 1, currentBox, key);
            currentBox++;
        }
        if (currentRow < boardContent.length && boardContent[currentRow][currentBox] !== 0) {
            evaluate(currentRow, key);
            currentBox = 0;
            currentRow++;
        }
    }
}

ارزیابی حدس بازیکن

یک تابع ارزیابی ایجاد کنید که پارامتر ردیف را بپذیرد. این تابع مسئول ارزیابی حدس بازیکن است.

function evaluate(row){

}

هر بازی دارای یک دکمه نمایش پاسخ است که تنها پس از اینکه کاربر چهار حدس زد ظاهر می شود. بنابراین، در تابع، عملکردی را پیاده سازی کنید که دقیقاً این کار را انجام می دهد:

if (currentRow === 4) {
    showBtn.removeAttribute('disabled')
}

سپس متغیر حدس و یک متغیر پاسخ تعریف کنید که بررسی کند آیا حروف در موقعیت صحیح قرار دارند یا خیر.

let guess = boardContent[row].join('').toUpperCase();
let answer = secretWord.split("");

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

مطلب مرتبط:   چگونه عبارات if را در جاوا اسکریپت ساده کنیم

اگر کاشی در کلمه باشد اما در نقطه اشتباه باشد، کاشی زرد است و در نهایت رنگ خاکستری برای کاشی هایی است که در کلمه نیستند.

let colors = guess
    .split("")
    .map((letter, idx) => letter == answer[idx] ? (answer[idx] = false) : letter)
    .map((letter, idx) =>
        letter
            ? (idx = answer.indexOf(letter)) < 0
                ? "grey"
                : (answer[idx] = "yellow")
            : "green"
);

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

در مرحله بعد، یک تابع setColors تعریف کنید که بتواند آرایه رنگ ها را به عنوان پارامتر در نظر بگیرد و کاشی ها را به طور مناسب رنگ کند:

function setColor(colors) {
        colors.forEach((color, index) => {
            document.querySelector(`button[data-key=${guess[index].toUpperCase()}]`).style.backgroundColor = color;
            document.querySelector(`button[data-key=${guess[index].toUpperCase()}]`).style.color= "black";
            [...document.querySelector(`.row-${row + 1}`).children][index].style.backgroundColor = color;
        })
}

بازی در حال حاضر کامل است. اکنون تنها کاری که باید انجام دهید این است که تابع getNewWord را فراخوانی کنید، و شما آماده هستید.

getNewWord();

تبریک می‌گویم، شما فقط Wordle را بازسازی کردید.

تصویر بازی کامل شده

با بازآفرینی بازی ها، مهارت های جاوا اسکریپت خود را به سطح بعدی ببرید

یادگیری یک زبان جدید به عنوان یک مبتدی آسان نیست. بازآفرینی بازی‌هایی مانند Tic-tac-toe، Hangman و Wordle در زبانی مانند جاوا اسکریپت، می‌تواند به مبتدیان کمک کند تا مفاهیم زبان را با عملی کردن آنها تسلط یابند.