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 }