File indexing completed on 2024-05-05 15:53:06

0001 /* GCompris - fifteen.js
0002  *
0003  * SPDX-FileCopyrightText: 2014 Bruno Coudoin
0004  *
0005  * Authors:
0006  *   Bruno Coudoin <bruno.coudoin@gcompris.net> (GTK+ version)
0007  *   Bruno Coudoin <bruno.coudoin@gcompris.net> (Qt Quick port)
0008  *
0009  *   SPDX-License-Identifier: GPL-3.0-or-later
0010  */
0011 .pragma library
0012 .import QtQuick 2.12 as Quick
0013 .import "qrc:/gcompris/src/core/core.js" as Core
0014 
0015 var url = "qrc:/gcompris/src/activities/fifteen/resource/"
0016 
0017 var numberOfLevel = 13
0018 var items
0019 
0020 var palette = [
0021     "#D40000",
0022     "#FF0000",
0023     "#FF5555",
0024     "#FFAAAA",
0025     "#FFD5D5",
0026     "#FF6600",
0027     "#FFB380",
0028     "#D4AA00",
0029     "#FFCC00",
0030     "#FFE680",
0031     "#88AA00",
0032     "#AAD400",
0033     "#CCFF00",
0034     "#66FF00",
0035     "#7FFF2A",
0036     "#55FFDD"
0037 ]
0038 
0039 function start(items_) {
0040     items = items_
0041     items.currentLevel = Core.getInitialLevel(numberOfLevel)
0042     initLevel()
0043 }
0044 
0045 function stop() {
0046 }
0047 
0048 function initLevel() {
0049 
0050     // Create the initial array that holds the model data sorted
0051     var model = []
0052     for(var i = 1; i < 16; i++)
0053         model.push(i)
0054     model.push(0)
0055 
0056     scramble(model, [3, 3], (items.currentLevel + 2))
0057 
0058     items.model.clear()
0059     for(i = 0; i < 16; i++)
0060         items.model.append(
0061                     {"value": model[i],
0062                     "fcolor": palette[model[i]]}
0063                     )
0064 
0065 }
0066 
0067 function countBadPlaced(model) {
0068     var badPlaced = 0
0069     for(var i = 0; i < 15; i++) {
0070         if(model[i] !== i + 1)
0071             badPlaced++
0072     }
0073     return badPlaced
0074 }
0075 
0076 function swap(model, spot1, spot2) {
0077     var old = model[spot1[0] + spot1[1] * 4]
0078     model[spot1[0] + spot1[1] * 4] = model[spot2[0] + spot2[1] * 4]
0079     model[spot2[0] + spot2[1] * 4] = old
0080 }
0081 
0082 function getRandomMove(model, emptySpot) {
0083     var possibleMoves = []
0084     if(emptySpot[0] > 0)
0085         possibleMoves.push([emptySpot[0] - 1, emptySpot[1]])
0086     if(emptySpot[0] < 3)
0087         possibleMoves.push([emptySpot[0] + 1, emptySpot[1]])
0088     if(emptySpot[1] > 0)
0089         possibleMoves.push([emptySpot[0], emptySpot[1] - 1])
0090     if(emptySpot[1] < 3)
0091         possibleMoves.push([emptySpot[0], emptySpot[1] + 1])
0092 
0093     return Core.shuffle(possibleMoves)[0]
0094 }
0095 
0096 function scrambleOne(model, emptySpot) {
0097     var nextSpot = getRandomMove(model, emptySpot)
0098     swap(model, emptySpot, nextSpot)
0099     return nextSpot
0100 }
0101 
0102 // We loop until the scramble created the requested
0103 // numberOfExpectedBadPlaced items
0104 function scramble(model, emptySpot, numberOfExpectedBadPlaced) {
0105     do {
0106         emptySpot = scrambleOne(model, emptySpot)
0107     } while(countBadPlaced(model) < numberOfExpectedBadPlaced)
0108 }
0109 
0110 function checkAnswer() {
0111     for(var i = 0; i < 15; i++)
0112         if(items.model.get(i).value !== i + 1) {
0113             return false
0114         }
0115 
0116     return true
0117 }
0118 
0119 function onClick(value) {
0120     // Find the value in the model
0121     var done = false
0122     for(var x = 0; x < 4 && !done; x++)
0123         for(var y = 0; y < 4 && !done; y++)
0124             if(items.model.get(x + y * 4).value === value) {
0125                 // Find a free spot
0126                 if(x > 0 && items.model.get((x - 1) + y * 4).value === 0) {
0127                     items.model.move(x + y * 4, (x - 1) + y * 4, 1)
0128                     done = true
0129                 } else if(x < 3 && items.model.get((x + 1) + y * 4).value === 0) {
0130                     items.model.move(x + y * 4, (x + 1) + y * 4, 1)
0131                     done = true
0132                 } else if(y > 0 && items.model.get(x + (y - 1) * 4).value === 0) {
0133                     items.model.move(x + y * 4, x + (y - 1) * 4, 1)
0134                     items.model.move(x + 1 + (y - 1) * 4, x + y * 4, 1)
0135                     done = true
0136                 } else if(y < 3 && items.model.get(x + (y + 1) * 4).value === 0) {
0137                     items.model.move(x + (y + 1) * 4, x + y * 4, 1)
0138                     items.model.move(x + 1 + y * 4, x + (y + 1) * 4, 1)
0139                     done = true
0140                 }
0141             }
0142 }
0143 
0144 // Return the index in the model of the empty spot
0145 function getEmptySpot()
0146 {
0147     for(var i=0; i < items.model.count; i++) {
0148         if(items.model.get(i).value === 0)
0149             return i
0150     }
0151 }
0152 
0153 function processPressedKey(event) {
0154     var emptySpot = getEmptySpot()
0155 
0156     /* Move the player */
0157     switch (event.key) {
0158     case Qt.Key_Right:
0159         if(emptySpot % 4 != 0) {
0160             items.model.move(emptySpot - 1, emptySpot, 1)
0161             event.accepted = true
0162         }
0163         break
0164     case Qt.Key_Left:
0165         if(emptySpot % 4 != 3) {
0166             items.model.move(emptySpot + 1, emptySpot, 1)
0167             event.accepted = true
0168         }
0169         break
0170     case Qt.Key_Up:
0171         if(emptySpot < items.model.count - 4) {
0172             items.model.move(emptySpot + 4, emptySpot, 1)
0173             items.model.move(emptySpot + 1, emptySpot + 4, 1)
0174             event.accepted = true
0175         }
0176         break
0177     case Qt.Key_Down:
0178         if(emptySpot >= 4) {
0179             items.model.move(emptySpot, emptySpot - 4, 1)
0180             items.model.move(emptySpot - 3, emptySpot, 1)
0181             event.accepted = true
0182         }
0183         break
0184     }
0185 
0186     /* Check if success */
0187     if(checkAnswer())
0188         items.bonus.good('flower')
0189     else if(event.accepted)
0190         items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/flip.wav")
0191 
0192 }
0193 
0194 function nextLevel() {
0195     items.currentLevel = Core.getNextLevel(items.currentLevel, numberOfLevel);
0196     initLevel();
0197 }
0198 
0199 function previousLevel() {
0200     items.currentLevel = Core.getPreviousLevel(items.currentLevel, numberOfLevel);
0201     initLevel();
0202 }