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

Եթե գտնվում ես վեբ զտիչի հետևում, խնդրում ենք համոզվել, որ *.kastatic.org և *.kasandbox.org տիրույթները հանված են արգելափակումից։

Հիմնական նյութ

Հիշողության խաղ․ շրջել սալիկները

Այժմ ունենք մի շարք սալիկներ, որ կարող ենք ցուցադրել և՛ դեմքով շրջված, և՛ դեմքով հակառակ ձևերով, սակայն այս պահին խաղը խաղալու որևէ հստակ տարբերակ չունենք։ Հուշում, թե ինչպես պետք է խաղը խաղաս՝
  • Երբ խաղը սկսվում է, բոլոր սալիկները դեմքով հակառակ շրջված են լինում։
  • Հետո խաղացողը ընտրում է երկու խաղաքարտ՝ դրանց վրա սեղմելով մկնիկով։
  • Եթե այդ երկու սալիկների խաղաքարտերն ունեն նույն պատկերը, ապա դրանք մնում են դեմքով շրջված, իսկ եթե տարբեր պատկերներ ես ընտրում, ապա դրանք որոշակի դադարից հետո կրկին շրջվում են դեմքով հակառակ։

Սալիկների սեղմում-շրջում

Այժմ ունենք մի ծրագիր, որը նկարում է մի շարք սալիկներ և հետո այլևս ոչինչ չի նկարում։ Առաջ ընթանալով՝ մեր ծրագիրը պետք է կարողանա տարբեր պատկերներ նկարել։ Ժամանակի ընթացքում այն կսկսի նկարել դեմքով հակառակ կողմ թեքված սալիկներ, սակայն հետո այն կցուցադրի մկնիկով սեղմված սալիկներ և, եթե ամեն ինչ լավ ընթանա խաղացողի համար, ապա էկրանի վրա ցույց կտա, որ նա հաղթել է։
Այսպիսով՝ արի մեր նկարելու կոդը ամբողջությամբ ProcessingJS-ի draw ֆունկցիա տեղափոխենք։ Համակարգիչը կշարունակի կանչել draw(), մինչդեռ ծրագիրն աշխատում է, այսպիսով սալիկները կշարունակեն նկարվել՝ համապատասխան իրենց դիրքի՝ դեմքով վերև կամ դեմքով ներքև:
draw = function() {
    background(255, 255, 255);
    for (var i = 0; i < tiles.length; i++) {
        tiles[i].draw();
    }
};
Արի սալիկների մի մասը դեմքով շրջենք դեպի վեր։ Սալիկը շրջելու համար խաղացողը պետք է սեղմի դրա վրա։ ProcessingJS ծրագրի սեղմմանը պատասխանելու համար կարող ենք սահմանել mouseClicked ֆունկցիան, և համակարգիչը մկնիկի ամեն սեղմման հետ կգործարկի այդ կոդը։
mouseClicked = function() {
  // process click somehow
};
Երբ մեր ծրագիրը տեսնում է, որ խաղացողը ինչ-որ տեղ սեղմել է, պետք է ստուգենք՝ սեղմել է արդյոք նա սալիկի վրա՝ օգտագործելով mouseX և mouseY։ Արի սկսենք՝ ավելացնելով isUnderMouse մեթոդը Tile-ին, որը վերադարձնում է true, եթե տրված է x և y սալիկի տարածքում։
Համաձայն մեր նկարած սալիկների՝ դրանց x-ը և y-ը համապատասխանում են սալիկի վերևի ձախ անկյունին, այսպիսով մենք պետք է վերադարձնենք true-ն միայն այն դեպքում, եթե տրված x-ը this.x-ի և this.x + this.width-ի միջև է, և եթե տրված y -ըthis.y-ի և this.y + this.width-ի միջև է՝
Tile.prototype.isUnderMouse = function(x, y) {
    return x >= this.x && x <= this.x + this.width  &&
        y >= this.y && y <= this.y + this.width;
};
Այժմ այս մեթոդի առկայության շնորհիվ կարող ենք mouseClicked-ում օգտագործել forցիկլ, որպեսզի ստուգենք՝ արդյոք յուրաքանչյուր սալիկ գտնվում է mouseX-ի և mouseY-ի ներքո։ Եթե այդպես լինի, ապա կարող ենք սալիկի isFaceUp հատկությանը սահմանել true.
mouseClicked = function() {
  for (var i = 0; i < tiles.length; i++) {
    if (tiles[i].isUnderMouse(mouseX, mouseY)) {
      tiles[i].isFaceUp = true;
    }
  }
};
Ահա ինչպիսի տեսք այն պետք է ունենա։ Սեղմիր մի քանի սալիկների վրա և ինքդ տես, թե ինչ է կատարվում.

Սալիկի շրջումների սահմանափակում

Ինչ-որ բացթողում նկատեցի՞ր։ Մենք իրականցրել ենք խաղի միայն մեկ հատվածը, որով խաղացողը կարող է շրջել սալիկները, սակայն մի կարևոր սահմանափակում է պակասում այստեղ. խաղացողը չպետք է կարողանա միաժամանակ շրջել երկուսից ավելի սալիկներ:
Պետք է շրջված սալիկների քանակը ինչ-որ կերպ փորձենք հաշվել։ Հեշտ տարբերակներից մեկը գլոբալ numFlipped փոփոխականը կլինի, որը կմեծանա, երբ խաղացողը խաղաքարտը դեմքով վերև շրջի։ Սալիկը կարելի է շրջել այն դեպքում, եթե numFlipped-ը 2-ից փոքր է, և սալիկը դեռևս դեմքով վերև շրջված չէ։
var numFlipped = 0;
mouseClicked = function() {
    for (var i = 0; i < tiles.length; i++) {
        var tile = tiles[i];
        if (tiles.isUnderMouse(mouseX, mouseY)) {
            if (numFlipped < 2 && !tile.isFaceUp) { 
              tile.isFaceUp = true;
              numFlipped++;
            }
        }
    }
};

Ուշացումով շրջվող սալիկներ

Մեր երկու սալիկների շրջման տրամաբանությունն ամբողջական է։ Ո՞րն է հաջորդ քայլը։ Արի վերհիշենք խաղի կանոնները.
Եթե երկու սալիկները ունեն նույն պատկերը, ապա դրանք կշարունակեն մնալ դեմքով վերև շրջված։ Հակառակ դեպքում սալիկները որոշ ժամանակ անց հետ կշրջվեն դեմքի հակառակ կողմով։
Սկզբում կկիրառենք երկրորդ հատվածը, որը ավտոմատ կերպով ետ է շրջում սալիկները, քանի որ առաջին հատվածը ստուգելը դժվար կլինի, երբ չենք կարողանում հեշտորեն գտնել համապատասխան նոր զույգեր։
isFaceUp-ը դարձնելով false, կարող ենք սալիկները հետ շրջել։ Սակայն ինչպե՞ս դա պետք է անենք որոշակի դադարից հետո։ Յուրաքանչյուր լեզու և միջավայր ունի իր յուրահատուկ, տարբերվող մոտեցումը կոդի ուշացման իրականացման հարցում, և հարկավոր է պարզել՝ ինչպես կատարել վերջինս ProcessingJS-ում։ Նախ՝ հարկավոր է ժամանակի պահպանման ինչ-որ տարբերակ՝ արդյոք ժամանակը լրացել է, և հետո՝ անհրաժեշտ է կոդը կանչելու նախընտրելի տարբերակ, երբ այդ որոշ ժամանակն արդեն անցել է։ Ահա թե ինչ ենք առաջարկում.
  • Ստեղծում ենք գլոբալ delayStartFC փոփոխականը՝ սկզբնական արժեքը սահմանելով զրոյական։
  • Մեր mouseClicked ֆունկցիայում, հենց երկրորդ սալիկն արդեն շրջել ենք, frameCount-ի ընթացիկ արժեքը պահպանում ենք delayStartFC -ում։Այդ փոփոխականը տեղեկացնում է, թե քանի շրջանակ է անցկացվել ծրագրի աշխատանքից ի վեր, և այն մեր ծրագրերում տեղեկացնում է նաև ժամանակի մասին։
  • Իսկ մեր draw ֆունկցիայում ստուգում ենք՝ frameCount-ի նոր արժեքը ակնհայտորեն ավելի բարձր չէ արդյոք, քան նախորդը, և եթե դա այդպես է, ապա շրջում ենք բոլոր սալիկները և սահմանում numFlipped-ը 0-ական արժեքի, \ ինչպես նաև delayStartFC-ը զրոյականացնում ենքnull։
Սա հրաշալի լուծում է, որը չի պահանջում չափազանց շատ և տարբեր կոդերի իրականացում։ Կատարողականության բարելավման համար կարող ենք օգտագործել loop և noLoop ֆունկցիաները՝ համոզվելու համար, որ draw կոդը կանչվում է միայն այն ժամանակ, երբ կա ուշացում։ Ամբողջը կարող ես տեսնել այստեղ՝
var numFlipped = 0;
var delayStartFC = null;

mouseClicked = function() {
  for (var i = 0; i < tiles.length; i++) {
    var tile = tiles[i];
    if (tile.isUnderMouse(mouseX, mouseY)) {
      if (numFlipped < 2 && !tile.isFaceUp) {
        tile.isFaceUp = true;
        numFlipped++;
        if (numFlipped === 2) {
          delayStartFC = frameCount;
        }
        loop();
      } 
    }
  }
};

draw = function() {
  if (delayStartFC &&
     (frameCount - delayStartFC) > 30) {
    for (var i = 0; i < tiles.length; i++) {
      tiles[i].isFaceUp = false;
    }
    numFlipped = 0;
    delayStartFC = null;
    noLoop();
  }

  background(255, 255, 255);
  for (var i = 0; i < tiles.length; i++) {
    tiles[i].draw();
  }
};
Հրաշալի է, ինչպես են ներքևում գտնվող մի քանի սալիկներ ավտոմատ կերպով հետ շրջվում։ Ավելի լավ հասկանալու համար փորձիր փոխել ուշացման տևողությունը, և թե քանի սալիկ պետք է շրջվի մինչ ուշացումը։

Համապատասխան զույգերի ստուգում

Եթե ստացվեց համապատասխան զույգեր գտնել բոլոր սալիկների համար, ամենայն հավանականությամբ, դու մի փոքր տխրում էիր, երբ դրանք հետ էին շրջվում, որովհետև դու զույգեր էիր ստեղծում։ Այժմ ժամանակն է կատարել խաղի այս կանոնը։
Եթե երկու սալիկ համապատասխան զույգ են ստեղծում, ապա նրանք պետք է դեմքով շրջված մնան։
Նշանակում է՝ միշտ, երբ երկու սալիկ շրջվում են, պետք է անպայման ստուգենք դրանց զույգի համապատասխանությունը՝ նախքան ուշացման սահմանումը։ Կեղծ կոդում դա այսպես կլիներ.
if there are two tiles flipped over:
    if first tile has same face as second tile:
       keep the tiles face up
Մենք արդեն ունենք երկու սալիկի շրջումը ստուգելու տարբերակ (numFlipped === 2), և հիմա պետք է ստուգենք՝ արդյոք սալիկները նույն պատկերն ունեն։ Նախ հարկավոր է այդ երկու շրջված սալիկներին հասնելու ինչ-որ տարբերակ։ Ինչպե՞ս կարող ենք գտնել դա։
Կարող ենք ամեն անգամ կրկնօրինակենք մեր զանգվածը, փնտրենք բոլոր ճիշտ սահմանված isFaceUp սալիկները և հետո պահեստավորենք վերջիններս զանգվածում։
Ահա կրճատ ուղին. հեշտ հասանելիության համար շրջված սալիկները միշտ պահեստավորիր զանգվածում։ Այս կերպ ասած՝ կարիք չի լինի կրկնօրինակել ողջ tiles զանգվածը ամեն անգամ, երբ խաղացողը շրջում է մեկ սալիկ։
Առաջին քայլում պետք էnumFlipped-ը փոխարինել զանգվածով և հետո ամենուր օգտագործել flippedTiles.length, որը նախկինում օգտագործել ենք այսպես՝ numFlipped։ Մեր mouseClick-ն այսպիսի տեսք ունի.
var flippedTiles = [];
var delayStartFC = null;

mouseClicked = function() {
  for (var i = 0; i < tiles.length; i++) {
    var tile = tiles[i];
    if (tile.isUnderMouse(mouseX, mouseY)) {
      if (flippedTiles.length < 2 && !tile.isFaceUp) {
        tile.isFaceUp = true;
        flippedTiles.push(tile);
        if (flippedTiles.length === 2) {
          delayStartFC = frameCount;
          loop();
        }
      } 
    }
  }
};
Այժմ պետք է մի տարբերակ մտածենք, որպեսզի պարզենք՝ արդյոք flippedTiles զանգվածում առկա երկու սալիկները նույն պատկերն ունեն, թե ոչ։ Նախ՝ին՞չ է faceհատկությունը։ Այն օբյեկտ է, և զույգերով համապատասխան սալիկների դեմքը պետք է միանգամայն նույն առարկան լինի, ինչպես, օրինակ, երբ փոփոխականը երկուսի դեպքում էլ մատնանշում է համակարգչի հիշողության նույն վայրը։ Վերջինիս պատճառն այն է, որ մենք յուրաքանչյուր պատկերի օբյեկտը ստեղծել ենք միայն մեկ անգամ (օրինակ՝ getImage("avatars/old-spice-man")-ով, այնուհետև երկու անգամ տեղադրել ենք նույն նկար-օբյեկտը զանգվածի պատկերներին՝
var face = possibleFaces[randomInd];
selected.push(face);
selected.push(face);
Առնվազն JavaScript-ում հավասարության նշանը կդառնա ճիշտ, եթե այն օգտագործվի երկու փոփոխականների վրա, որոնք մատնանշում են օբյեկտները, և որ այդ փոփոխականներից երկուսն էլ հիշողության մեջ հղում կատարեն նույն օբյեկտին։ Նշանակում է, որ մեր ստուգման գործընթացը կարող է բավականին պարզ լինել՝ պարզապես օգտագործիր հավասարության նշանը յուրաքանչյուր սալիկի face հատկության վրա։
if (flippedTiles[0].face === flippedTiles[1].face) {
  ...
}
Այժմ, երբ գիտենք սալիկների համապատասխան զույգերի մասին, անհրաժեշտ է պահպանել դրանք։ Այս պահի դրությամբ, որոշ ժամանակ ուշացումից հետո, դրանք բոլորը պետք է հետ շրջվեին։ Այս դեպքում կարող ենք պարզապես չսահմանել անիմացիա, բայց չպետք է մոռանանք, որ հետագա փորձերի ընթացքում անիմացիան առկա կլինի, այդ իսկ պատճառով չենք կարող վերջինիս վստահել։
Փոխարենը անհրաժեշտ է մի ծրագիր մշակել, որը կհայտնի մեզ՝ «երբ այդ բոլոր սալիկները հետ շրջենք, այդ հատուկ համապատասխան զույգերը չենք շրջի»։ Սա բուլյան հատկության համար շատ լավ գործածություն կլինի։ Եկեք սալիկ կոնստրուկտորին ավելացնենք համապատասխան isMatch հատկություն և հետո սահմանենք isMatchtrue -ի՝ միայն այդ if պայմանում՝
if (flippedTiles[0].face === flippedTiles[1].face) {
  flippedTiles[0].isMatch = true;
  flippedTiles[1].isMatch = true;
}
Այժմ կարող ենք օգտագործել այդ հատկությունը, որպեսզի որոշենք՝ արդյոք հետ շրջենք սալիկները ուշացումից հետո։
for (var i = 0; i < tiles.length; i++) {
  var tile = tiles[i];
  if (!tile.isMatch) {
    tile.isFaceUp = false;
  }
}
Կարող ես ինքդ փորձարկումներ կատարել ներքևում։ Երբ ներքևում գտնես երկու համապատասխան սալիկների զույգ, դրանք պետք է շարունակեն մնալ դեմքով շրջված ուշացումից հետո (և հաջորդ փորձերից հետո)՝

Ուզո՞ւմ ես միանալ խոսակցությանը։

Առայժմ հրապարակումներ չկան։
Անգլերեն հասկանո՞ւմ ես: Սեղմիր այստեղ և ավելի շատ քննարկումներ կգտնես «Քան» ակադեմիայի անգլերեն կայքում: