যদি তুমি এই বার্তা দেখে থাক, তার মানে বাইরের উপকরণ লোড করতে সমস্যা হচ্ছে।

If you're behind a web filter, please make sure that the domains *.kastatic.org and *.kasandbox.org are unblocked.

মূল বিষয়বস্তু

Memory game: Drawing a grid of tiles

প্রথমে "স্মৃতিশক্তি" গেমে, টাইলসগুলোকে এলোমেলোভাবে একটি আয়তক্ষেত্রাকার ছকে নিম্নমুখীভাবে সাজানো হয়, কারণ এভাবে সাজালে টাইলসের উল্টো পাশের কার্টুন চিত্র দেখা যায় না।

নিম্নমুখী টাইলস

শুরুতে প্রোগ্রামিং করার জন্য, শুধু নিম্নমুখী টাইলস তৈরি করি এবং বাকিটা পরে করবো।
The "tile" is an important enough object in the game of "Memory" that we will use object-oriented principles to define a Tile object and then create multiple instances of it. Then we'll be able to associate both properties (like location and image) as well as behavior (like drawing them) with each of the Tiles.
শুরুতে, আমরা Tile এর কন্সট্রাক্টর ফাংশনকে সংজ্ঞায়িত করবো। আমরা এখনও চিত্র নিয়ে কাজ করছি না, এজন্য শুধু x এবং y আর্গুমেন্ট পাঠাই। অবজেক্টের একটি বৈশিষ্ট্যে (tile) টাইলের প্রস্থ (একটি ধ্রুবক) সংরক্ষণ করি।
var Tile = function(x, y) {
  this.x = x;
  this.y = y;
  this.width = 50;
};
Now that we've defined the constructor, we can use that in a loop to create tiles at appropriate x and y positions. In fact, we'll use two for loops - a nested for loop - as that makes it conceptually easy to generate coordinates for a grid.
First we need to declare an empty tiles array, to store all those tiles:
var tiles = [];
বাহিরের লুপটি কলাম (column) নির্দেশ করে, ভেতরের লুপটি সারি (row) নির্দেশ করে এবং প্রত্যেকটি নতুন Tile এ একটি x এবং y থাকে যা সারি (row) এবং কলামকে (column) নির্দেশ করে।
var NUM_COLS = 5;
var NUM_ROWS = 4;
for (var i = 0; i < NUM_COLS; i++) {
  for (var j = 0; j < NUM_ROWS; j++) {
    var tileX = i * 54 + 5;
    var tileY = j * 54 + 40;
    tiles.push(new Tile(tileX, tileY));
  }
}
কিন্তু, এই যে, টাইলসগুলো দেখতে কেমন তা বোঝা যায় না, কারণ তাদের আঁকানোর জন্য এখনও কোড করা হয়নি! সত্যি বলতে, এটা আমাদের আগে করা উচিত ছিল। অনেক সময়, প্রোগ্রামিং এ, প্রথমে কি কোড করা উচিত তা বোঝা যায় না, তাই না? ক্যানভাসে একটি টাইলকে নিম্নমুখীভাবে আঁকার জন্য Tile অবজেক্টে একটি মেথড যোগ করি। নির্ধারিত অবস্থানে আমরা খান একাডেমির একটি সবুজ পাতা আয়তক্ষেত্রাকার টাইলের উপর আঁকবো।
Tile.prototype.draw = function() {
  fill(214, 247, 202);
  strokeWeight(2);
  rect(this.x, this.y, this.width, this.width, 10);
  image(getImage("avatars/leaf-green"),
        this.x, this.y, this.width, this.width);
};
We're so close to being able to check how our tiles look! Let's add a new for loop that iterates through all the tiles and calls the drawing method on them:
for (var i = 0; i < tiles.length; i++) {
    tiles[i].draw();
}
সকল কোড সহ, আমাদের প্রোগ্রামটি এমন হয়। নেস্টেড for লুপের সংখ্যা পরিবর্তন করে দেখা যায় এটা কীভাবে ছকে টাইলসের সংখ্যার পরিবর্তন ঘটায়।

ঊর্ধ্বমুখী টাইলস

এখন আমাদের নিম্নমুখী টাইলসের ছক আছে, তাহলে এবার আরেকটি জটিল কাজ করি: প্রত্যেকটি টাইলসে চিত্র যোগ করি, এমনভাবে যোগ করি যেন অ্যারেতে প্রত্যেকটি চিত্র 2 বার থাকে, কিন্তু যেন চিত্রগুলো এলোমেলোভাবে টাইলসে সাজানো থাকে। এটা করার অনেক উপায় আছে, কিন্তু আমরা নিম্নরূপে করবো:
  1. We create an array of the possible images, using the getImage function to pick ones from our library.
  2. We'll only need 10 images for the faces of our 20 tiles, so then we create a new array that holds 2 copies of 10 randomly selected images from that first array.
  3. We shuffle the selected images array, so that the pairs of images are no longer next to each other in an array.
  4. In the nested for loop where we create the tiles, we'll assign an image from that array to each tile.
প্রত্যেকটি ধাপ বোধগম্য নাও হতে পারে - এজন্য প্রত্যেকটি ধাপ অনুযায়ী কাজ সম্পাদন করে দেখি কেমন হয়।
ধাপ 1: আমাদের লাইব্রেরি থেকে getImage ব্যবহার করে, সম্ভাব্য চিত্রগুলোর অ্যারে তৈরি করবো:
var faces = [
    getImage("avatars/leafers-seed"),
    getImage("avatars/leafers-seedling"),
    getImage("avatars/leafers-sapling"),
    getImage("avatars/leafers-tree"),
    getImage("avatars/leafers-ultimate"),
    getImage("avatars/marcimus"),
    getImage("avatars/mr-pants"),
    getImage("avatars/mr-pink"),
    getImage("avatars/old-spice-man"),
    getImage("avatars/robot_female_1"),
    getImage("avatars/piceratops-tree"),
    getImage("avatars/orange-juice-squid")
];
আমি কয়েকটি avatars (প্রতিরূপ) বাছাই করেছি, কিন্তু চাইলে এটা পরিবর্তন করা যায়। সবচেয়ে গুরুত্বপূর্ণ বিষয় হল অ্যারেতে 10 টি চিত্র রাখা, যেন 20 টি টাইলসের জন্য চিত্র ফুরিয়ে না যায়। অবশ্য গেমে বৈচিত্র্য আনার জন্য আমরা 10 টি চিত্রের চেয়েও বেশি চিত্র ব্যবহার করতে পারি, এখন পরবর্তী ধাপটি করবো।
ধাপ 2: আমাদের 20 টি টাইলসের জন্য শুধুমাত্র 10 টি চিত্র লাগবে, এজন্য প্রথম অ্যারে থেকে 10 টি চিত্রের 2 টি কপি নিয়ে নতুন একটি অ্যারে তৈরি করি।
এটা করার জন্য, একটি for লুপ তৈরি করব যা 10 বার ক্রিয়া করে। প্রতিবার ক্রিয়ায়, আমরা faces অ্যারে থেকে যে কোন একটি মান বাছাই করি, সেটা দুইবার selected অ্যারেতে পাঠাই এবং তারপর splice মেথড ব্যবহার করে faces অ্যারে থেকে সেগুলো বাদ দিয়ে দেই, যাতে দুইবার একই জিনিস বাছাই না হয়। শেষের ধাপটি খুবই গুরুত্বপূর্ণ!
var selected = [];
for (var i = 0; i < 10; i++) {
    // faces অ্যারে থেকে যে কোন একটি বাছাই করা
    var randomInd = floor(random(faces.length));
    var face = faces[randomInd];
    // অ্যারেতে 2 টি কপি পাঠানো
    selected.push(face);
    selected.push(face);
    // অ্যারে থেকে বাদ দেয়া
    faces.splice(randomInd, 1);
}
Step 3: We shuffle the selected images array, so that the pairs of images are no longer next to each other in an array.
You've probably shuffled a deck of cards in your life, but have you ever shuffled an array in JavaScript? The most popular technique for shuffling in any programming language is called the Fisher-Yates Shuffle, and that's what we'll use here.
The Fisher-Yates Shuffle starts by first selecting a random element anywhere in the array, and swapping it with the last element in the array. In the next step, it selects a random element from anywhere in the array besides the last element, and swaps it with the second to last element. It keeps going until it has swapped every element.
You can click through this visualization to see what I mean:
To implement that in JavaScript, let's make a shuffleArray function that takes in an array and shuffles its elements, changing the original array:
var shuffleArray = function(array) {
    var counter = array.length;

    // While there are elements in the array
    while (counter > 0) {
        // Pick a random index
        var ind = Math.floor(Math.random() * counter);
        // Decrease counter by 1
        counter--;
        // And swap the last element with it
        var temp = array[counter];
        array[counter] = array[ind];
        array[ind] = temp;
    }
};
If the algorithm doesn't quite make sense yet after stepping through the visualization and reading the code, you could try it with an actual deck of cards in the real world or watch how Adam Khoury does it in his Youtube video.
After defining that function, we need to actually call it:
shuffleArray(selected);
And now we have an array of 10 pairs of images, randomly shuffled!
ধাপ 4: যে নেস্টেড for লুপে টাইলস তৈরি করা হয়েছিল, সেই অ্যারে থেকে চিত্রগুলো নিয়ে টাইলসে বসাবো।
We have 20 images in our selected array, and we're iterating 20 times to instantiate new tiles at locations in the grid. To select a random image for each tile, we can call the pop method on the array. That method removes the last element from the array and returns it, and is the easiest way to make sure we assign all the images but don't double assign them.
for (var i = 0; i < NUM_COLS; i++) {
  for (var j = 0; j < NUM_ROWS; j++) {
    var tileX = i * 54 + 5;
    var tileY = j * 54 + 40;
    var tileFace = selected.pop();
    var tile = new Tile(tileX, tileY, tileFace);
    tiles.push(tile);
  }
}
Notice how that code passes tileFace as the third parameter to the Tileconstructor? Our constructor originally only had 2 parameters, x and y, but now we modify it so that we can also remember the image of each tile face, plus whether it's face up:
var Tile = function(x, y, face) { this.x = x; this.y = y; this.width = 70; this.face = face; this.isFaceUp = false; };
So we now theoretically have images assigned to each tile, but we're not displaying them yet! Let's modify the Tile.draw method so that it can draw tiles that are face up:
Tile.prototype.draw = function() {
    fill(214, 247, 202);
    strokeWeight(2);
    rect(this.x, this.y, this.width, this.width, 10);
    if (this.isFaceUp) {
        image(this.face, this.x, this.y,
              this.width, this.width);
    } else {
        image(getImage("avatars/leaf-green"),
              this.x, this.y, this.width, this.width);
    }
};
Finally, to test it all works, we can change our for loop to set each tile's isFaceUp property to true before drawing it:
for (var i = 0; i < tiles.length; i++) {
  tiles[i].isFaceUp = true;
  tiles[i].draw();
}
সবকিছু, একসাথে নিচে দেওয়া হল। পুনরায় চালু করলে প্রতিবার টাইলসের পরিবর্তন দেখা যায়।

আলোচনায় অংশ নিতে চাও?

কোন আলাপচারিতা নেই।
ইংরেজি জানো? খান একাডেমির ইংরেজি সাইটে আরো আলোচনা দেখতে এখানে ক্লিক কর।