If you're seeing this message, it means we're having trouble loading external resources on our website.

თუ ვებფილტრს იყენებთ, დარწმუნდით, რომ *.kastatic.org და *.kasandbox.org დომენები არ არის დაბლოკილი.

ძირითადი მასალა

მეხსიერების თამაში: ფილების ბადის დახატვა

„მეხსიერების“ თამაშის პირველი ნაბიჯი არის ყველა ფილის შემთხვევითად არევა და შემდეგ მათი მართკუთხა ბადედ დალაგება პირდაღმა, რათა ვერ ვნახოთ, რომელი სურათია თითოეული ფილის მეორე მხარეს.

პირდაღმა მყოფი ფილები

თამაშის დაპროგრამების დასაწყებად, ვიფიქროთ პირდაღმა მყოფი ფილების შექმნაზე, ხოლო სხვადასხვა სურათის გაკეთების გზებზე მოგვიანებით ვიმსჯელოთ.
„ფილა“ საკმარისად მნიშვნელოვანი ობიექტია თამაშში საიმისოდ, რომ გამოვიყენოთ ობიექტზე ორიენტირებული პრინციპები Tile (ფილა) ობიექტის განსასაზღვრად და შემდეგ მისი ბევრი ნიმუშის შესაქმნელად. შემდეგ შევძლებთ, ერთმანეთთან დავაკავშიროთ ორივე თვისება (მაგალითად, ადგილმდებარეობა და სურათი) და ქცევა (მაგალითად, მათი დახატვა) თითოეული Tile-ისთვის.
დასაწყისისთვის, განვსაზღვროთ Tile კონსტრუქტორი ფუნქცია. ვინაიდან ჯერ სურათებს არ ვეხებით, მას გადავცემთ მხოლოდ x და y არგუმენტებს. გარდა ამისა, დავიმახსოვრებთ ფილის სიგანეს (მუდმივას) ობიექტის თვისებაში.
var Tile = function(x, y) {
  this.x = x;
  this.y = y;
  this.width = 50;
};
ახლა, როცა კონსტრუქტორი განსაზღვრული გვაქვს, შეგვიძლია, ის გამოვიყენოთ ციკლში, რათა შევქმნათ ფილები ადეკვატურ x და y მდებარეობებზე. ჩვენ გამოვიყენებთ ორ for ციკლს — ჩასმულ for ციკლს — რადგან ეს აზრობრივად ამარტივებს ბადის კოორდინატების გენერირებას.
პირველ ყოვლისა, უნდა გამოვაცხადოთ ცარიელი tiles მასივი, რათა შევინახოთ ყველა ფილა:
var tiles = [];
ჩვენი გარე ციკლი გადაუყვება იმდენ სვეტს, რამდენიც გვინდა. ჩვენი შიდა ციკლი გადაუყვება თითოეულ მწკრივს და ყოველი ახალი Tile (ფილა) ინიციალიზდება x-ითა და y-ით, რომელიც შეესაბამება ამ მწკრივსა და სვეტს.
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);
};
ძალიან ახლოს ვართ იმის შემოწმებასთან, თუ როგორ გამოიყურება ჩვენი ფილები! დავამატოთ ახალი for ციკლი, რომელიც გადაუყვება ყველა ფილას და მათზე გამოიძახებს დახატვის მეთოდს:
for (var i = 0; i < tiles.length; i++) {
    tiles[i].draw();
}
აი, როგორ გამოიყურება ჩვენი პროგრამა მთელი ამ კოდით. სცადეთ სხვადასხვა რიცხვები ჩასმულ for ციკლში და ნახეთ, როგორ შეცვლის ის ბადეს, ან შეცვალეთ მათი დახატვის გზა (იქნებ სხვა ლოგო გეცადათ?)

პირაღმა მყოფი ფილები

ახლა, როცა გვაქვს უკუღმა დადებული ფილების ბადე, უფრო რთულ პრობლემას შევეხოთ: თითოეულ მათგანს სურათი მივანიჭოთ ისე, რომ თითოეული სურათი ორჯერ იყოს მასივში, თან შემთხვევითად განაწილებული. ალბათ, მრავალი გზა არსებობს ამის მისაღწევად, მაგრამ მე ამას გირჩევთ:
  1. ვქმნით შესაძლო სურათების მასივს getImage ფუნქციის გამოყენებით, რათა ამოვირჩიოთ ჩვენი ბიბლიოთეკიდან.
  2. დაგვჭირდება მხოლოდ 10 სურათი 20 ფილისათვის, ასე რომ, შემდეგ ვქმნით მასივს, რომელიც ინახავს პირველი მასივიდან შემთხვევითად შერჩეული 10 სურათის ორ ასლს.
  3. შერჩეული სურათების მასივს ავრევთ, რათა სურათები თავიანთი ასლების გვერდით აღარ იყვნენ მასივში.
  4. ჩასმულ for ციკლში, რომელშიც ფილებს ვქმნით, თითოეულ ფილას მივანიჭებთ სურათს ამ მასივიდან.
ალბათ, ამ ნაბიჯების აზრს ჯერ ვერ ხვდებით — მოდით, შევასრულოთ თითოეული და ვნახოთ, რა იქნება.
ნაბიჯი 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")
];
მე შევარჩიე რამდენიმე ავატარი, მაგრამ თქვენ შეგიძლიათ, შეცვალოთ ისინი თქვენთვის საყვარელი სურათებით. მნიშვნელოვანია, რომ ამ მასივს ჰქონდეს მინიმუმ 10 სურათი, რათა არ მოგვაკლდეს სურათები ოცი ფილისთვის. მიუხედავად ამისა, შეგვიძლია, 10-ზე ბევრად მეტი სურათი დავამატოთ, რათა ჩვენს თამაშს მრავალფეროვნება შევძინოთ ყოველი თამაშისას, რადგან შემდეგ ნაბიჯში სიას შევამცირებთ.
ნაბიჯი 2: დაგვჭირდება მხოლოდ 10 სურათი ჩვენი 20 ფილისათვის, ასე რომ, ვქმნით ახალ მასივს, რომელიც ინახავს პირველი მასივიდან შემთხვევითად შერჩეული 10 სურათის ორ ასლს.
ამის გასაკეთებლად ვქმნით for ციკლს, რომელიც 10 ელემენტს გადაუყვება. ყოველ ჯერზე შემთხვევითად ვირჩევთ ინდექსს faces მასივიდან, ორჯერ ვამატებთ მას selected მასივში და შემდეგ ვიყენებთ splice მეთოდს მის faces მასივიდან ამოსაღებად, რათა ის ორჯერ არ ავირჩიოთ. ეს ბოლო ნაბიჯი ძალიან მნიშვნელოვანია!
var selected = [];
for (var i = 0; i < 10; i++) {
    // სახეების მასივიდან აირჩიეთ ერთი შემთხვევითი 
    var randomInd = floor(random(faces.length));
    var face = faces[randomInd];
    // Push 2 copies onto array
    selected.push(face);
    selected.push(face);
    // ამოიღეთ სახეების მასივებიდან, რათა შემდეგ ცდაზე არ ავირჩიოთ იგივე სახე
    faces.splice(randomInd, 1);
}
ნაბიჯი 3: შერჩეული სურათების მასივს ავრევთ, რათა სურათები თავიანთი ასლების გვერდით აღარ იყვნენ მასივში.
ალბათ, კარტი აგირევიათ (აგიჩეხავთ), მაგრამ აგირევიათ თუ არა მასივი JavaScript-ში? არევის ყველა პოპულარულ ტექნიკას პროგრამირების ნებისმიერ ენაში ეწოდება ფიშერ-იეტსის არევა (ინგლ. Fisher–Yates Shuffle) და სწორედ მას გამოვიყენებთ აქ.
ფიშერ-იეტსის არევა იწყება მასივის ნებისმიერი შემთხვევითი ელემენტის არჩევით და მასივის ბოლო ელემენტთან მისი ადგილის გაცვლით. შემდეგი ნაბიჯია ბოლო ელემენტის გარდა ნებისმიერი ელემენტის შერჩევა და მისი ადგილის გაცვლა ბოლოსწინა ელემენტთან. ის ასე აგრძელებს მანამ, სანამ ყველა ელემენტს არ გაუცვლის ადგილს.
შეგიძლიათ, დააწკაპუნოთ ამ ვიზუალიზაციას, რათა ნახოთ, რას ვგულისხმობ:
ამის JavaScript-ში იმპლემენტაციისათვის, მოდით, შევქმნათ shuffleArray ფუნქცია, რომელიც იღებს მასივს და მის ელემენტებს რევს, რითაც თავდაპირველ მასივს შეცვლის:
var shuffleArray = function(array) {
    var counter = array.length;

    // სანამ მასივში არის ელემენტები
    while (counter > 0) {
        // შემთხვევითად ვირჩევთ ინდექსს
        var ind = Math.floor(Math.random() * counter);
        // შევამციროთ მთვლელი ცვლადი (counter) 1-ით
        counter--;
        // და ბოლო ელემენტს ადგილი გავუცვალოთ მასთან
        var temp = array[counter];
        array[counter] = array[ind];
        array[ind] = temp;
    }
};
თუ ალგორითმი ჯერ არ გეჩვენებათ აზრიანად ვიზუალიზაციის ნახვისა და კოდის წაკითხვის შემდეგ, შეგიძლიათ, სცადოთ ის ნამდვილი კარტით ან ნახოთ, როგორ აკეთებს ამას ადამ ხოური თავის YouTube ვიდეოში.
ამ ფუნქციის განსაზღვრის შემდეგ ის უნდა გამოვიძახოთ:
shuffleArray(selected);
და ახლა ჩვენ გვაქვს 10 სურათის წყვილის მასივი, რომელიც შემთხვევითად არის არეული!
ნაბიჯი 4: ჩასმულ for ციკლში, რომელშიც ფილებს ვქმნით, თითოეულ ფილას მივანიჭებთ სურათს ამ მასივიდან.
გვაქვს 20 სურათი ჩვენს selected მასივში და გადავუყვებით 20-ჯერ, რათა ინიციალიზაცია გავუკეთოთ ახალ ფილებს ბადეში მდებარეობებზე. თითოეული ფილისათვის შემთხვევითი სურათის შესარჩევად შეგვიძლია, გამოვიძახოთ pop მეთოდი მასივზე. და ეს ყველაზე იოლი გზაა იმისთვის, რომ ყველა სურათი მივანიჭოთ, მაგრამ ეს ორჯერ არ გავაკეთოთ.
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);
  }
}
შენიშნეთ, როგორ გადასცემს ეს კოდი tileFace-ს მესამე პარამეტრად Tile კონსტრუქტორს? ჩვენს კონსტრუქტორს თავდაპირველად ჰქონდა მხოლოდ ორი პარამეტრი, x და y, მაგრამ ახლა ჩვენ ვცვლით მას, რათა დავიმახსოვროთ თითოეული ფილის სურათი და ისიც, არის თუ არა ის წაღმა:
var Tile = function(x, y, face) { this.x = x; this.y = y; this.width = 70; this.face = face; this.isFaceUp = false; };
ასე რომ, ჩვენ თეორიულად მივანიჭეთ სურათები ფილებს, მაგრამ ჯერ მათ არ ვაჩვენებთ ეკრანზე! შევცვალოთ Tile.draw მეთოდი ისე, რომ მას შეეძლოს წაღმა დადებული ფილების დახატვა:
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);
    }
};
საბოლოოდ, ამ ყველაფრის მუშაობის დასატესტად შეგვიძლია, შევცვალოთ ჩვენი for ციკლი ისე, რომ ყოველი ფილის isFaceUp თვისება დააყენოს true-ზე მის დახატვამდე:
for (var i = 0; i < tiles.length; i++) {
  tiles[i].isFaceUp = true;
  tiles[i].draw();
}
აი, ყველაფერი ერთად. სცადეთ გადატვირთვა იმის სანახავად, თუ როგორ იცვლება ფილები ყოველ ჯერზე.

გსურთ, შეუერთდეთ დისკუსიას?

პოსტები ჯერ არ არის.
გესმით ინგლისური? დააწკაპუნეთ აქ და გაეცანით განხილვას ხანის აკადემიის ინგლისურენოვან გვერდზე.