Jquery UI Dragabble is not enabled



class Cell {

constructor(game, index) {
this.isEmpty = false;
this.game = game;
this.index = index;
this.height = (game.height / game.dimension);
this.width = (game.width / game.dimension);  
this.id = "cell-" + index;
this.cell = this.createCell();
$("#content").append(this.cell);
if (this.index === this.game.dimension * this.game.dimension - 1) {
this.isEmpty = true;
return;
}
this.setImage();
this.setPosition(this.index)
}

createCell() {
const cell = document.createElement("div");    
$(cell).css({
"width": this.height + "px",
"height": this.width + "px",
"position": "absolute",
"border": "1px solid #fff"
})
$(cell).attr("id", this.id);
//On click Move to the Empty Space
$(cell).on("click", () => {
if (this.game.gameStarted) {
let validCells = this.game.checkValidCells();
let compareCells = [];
if (validCells.right) {
compareCells.push(this.game.cells[validCells.right].cell);
}
if (validCells.left || validCells.left === 0) {
compareCells.push(this.game.cells[validCells.left].cell);
}
if (validCells.top || validCells.top === 0) {
compareCells.push(this.game.cells[validCells.top].cell);
}
if (validCells.bottom) {
compareCells.push(this.game.cells[validCells.bottom].cell);
}
let i = this.game.cells.findIndex(item => item.cell === cell);
let j = this.game.findEmptyCell();
if (compareCells.indexOf(cell) != -1) {
[this.game.cells[i], this.game.cells[j]] = [this.game.cells[j], this.game.cells[i]];  
this.game.cells[i].setPosition(i);
this.game.cells[j].setPosition(j);
if (this.game.checkWin()) {
alert("you won the game!!");
this.game.numberOfMoves = 0; 
this.game.gameStarted = false;
}
this.game.numberOfMoves++;
$("#moves").html("Moves: " + this.game.numberOfMoves);
}
this.game.dragTheTile();
}
})
return cell;
}

setImage() {
const left = this.width * (this.index % this.game.dimension);
const top = this.height * Math.floor(this.index / this.game.dimension);
const bgPosition = -left + "px" + " " + -top + "px";
const bgSize = this.game.width + "px " + this.game.height + "px" 
$(this.cell).css({
"background": 'url(' + this.game.imageSrc + ')',
"background-position" : bgPosition,
"background-size": bgSize
})      
}

setPosition(index) {
const {left, top} = this.getPosition(index);
$(this.cell).css({
"left": left + "px",
"top": top + "px"
})
}

makeDraggable(index) {
let emptyCellIndex = this.game.findEmptyCell();
$(this.cell).draggable({
containment: "parent",
snap: this.game.cells[emptyCellIndex],
cursor: "move",
snapMode: "inner",
snapTolerance: 20,
helper: "clone",
opacity: 0.5
})
}

makeDroppable(index) {
$(this.cell).droppable({
drop: (event, ui) => {
let draggedCell;
draggedCell = ui.draggable;
let i = this.game.cells.findIndex(item => item.cell === draggedCell[0]);
let j = this.game.findEmptyCell();
[this.game.cells[i], this.game.cells[j]] = [this.game.cells[j], this.game.cells[i]];  
this.game.cells[i].setPosition(i);
this.game.cells[j].setPosition(j);
this.game.clearDrag();
this.game.numberOfMoves++;
$("#moves").html("Moves: " + this.game.numberOfMoves);
if (this.game.checkWin()) {
alert("you won the game!!");
this.game.numberOfMoves = 0;
this.game.gameStarted = false;
} else {
this.game.dragTheTile();
}
}
})
}

getPosition(index) {
return {
left: this.width * (index % this.game.dimension),
top: this.height * Math.floor(index / this.game.dimension)
}
}

}
class GameBoard {
constructor(dimension){
this.dimension = dimension;
this.imageSrc = 'https://i.ibb.co/1XfXq6S/image.jpg'
this.cells = [];
let length = Math.min(window.innerHeight, window.innerWidth);
this.width = length - 100;
this.height = length - 100;
this.setup();
this.gameStarted = false;
this.numberOfMoves = 0;
}

setup() {
for(let i = 0;i < this.dimension * this.dimension; i++) {
this.cells.push(new Cell(this, i));
}
}
shuffle() {
for (let i = this.cells.length -1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[this.cells[i], this.cells[j]] = [this.cells[j], this.cells[i]];  
this.cells[i].setPosition(i);
this.cells[j].setPosition(j);
}
}

findEmptyCell() {
return this.cells.findIndex(cell => cell.isEmpty)
}

checkValidCells() {
const emptyCell = this.findEmptyCell(),
topCell = emptyCell - this.dimension,
leftCell = emptyCell - 1,
rightCell = emptyCell + 1,
bottomCell = emptyCell + this.dimension;
const mod = emptyCell % this.dimension;
let left, right, top, bottom;
if (mod != 0) {
left = leftCell;
} 
if (mod != this.dimension -1) {
right = rightCell;
}
if (emptyCell >= this.dimension) {
top = topCell;
}
if (emptyCell < this.dimension * (this.dimension - 1)) {
bottom = bottomCell
}
return {right: right, left: left, top: top, bottom: bottom};
}
findPosition(index) {
return this.cells.findIndex(cell => cell.index === index);
}

checkWin() {
for (let i = 0; i < this.cells.length; i++) {
if (i != this.cells[i].index) {
return false;
}
}
return true;
}
clearDrag() {
this.cells.forEach(cell => {  
if($(cell.cell).data('ui-draggable')) $(cell.cell).draggable("destroy");
})
}
dragTheTile() {
this.clearDrag();
const validCells = this.checkValidCells();
let availableCells = [];
if (validCells.right) {
availableCells.push(this.cells[this.findPosition(validCells.right)].index);
}
if (validCells.left || validCells.left === 0) {
availableCells.push(this.cells[this.findPosition(validCells.left)].index);
}
if (validCells.top || validCells.top === 0) {
availableCells.push(this.cells[this.findPosition(validCells.top)].index);  
}
if (validCells.bottom) {
availableCells.push(this.cells[this.findPosition(validCells.bottom)].index);   
}
let emptyCellIndex = this.findEmptyCell();
availableCells.forEach(cell => {
this.cells[cell].makeDraggable(cell);
this.cells[emptyCellIndex].makeDroppable(cell);
})
}
solve() {
let i;
for (i = 0; i < this.cells.length; i++) {
let j = this.cells[i].index;
if (i != j) {
[this.cells[i], this.cells[j]] = [this.cells[j], this.cells[i]];  
this.cells[i].setPosition(i);
this.cells[j].setPosition(j);
i--;
}
if (i === this.cells.length - 1) {
[this.cells[i], this.cells[i - 1]] = [this.cells[i - 1], this.cells[i]];  
this.cells[i].setPosition(i);
this.cells[i - 1].setPosition(i - 1);
}
}
}

}
$(document).ready(() => {
let gb;
$("#startGame").on("click", () => {
gb.gameStarted = true;
gb.shuffle();
gb.numberOfMoves = 0;
$("#moves").html("Moves: " + gb.numberOfMoves);
gb.clearDrag();
gb.dragTheTile();
})
$("#solve").on("click", () => {
if (gb.gameStarted) {
gb.solve();
gb.clearDrag();
gb.dragTheTile();
}
})
$("#generate-puzzle").on("click", () => {
let number = parseInt($("#dimension").val());
if(number >= 3 && Number.isInteger(number)) {
gb = new GameBoard(number);
$("#content").css("display", "block");
$("#solve").css("display", "block");
$("#startGame").css("display", "block");
$("#enter-dimension").css("display", "none");
$("#content").css({
width: gb.width + "px",
height : gb.height + "px"
})
} else {
$("#alert").css("display", "block");
}
})
})
body {
background-color: #3d3d3d;
}
#content {
width: 400px;
height : 400px;
background-color: #fff;
margin:  auto;
position: relative;
display: none;
}
#startGame {
margin: auto;
display: none;
}
#solve {
margin: auto;
display: none;
}
#alert {
display: none;
}
#moves {
margin: auto;
padding:  5px;
text-align: center;
color: #FFFF00;
}
#enter-dimension {
margin: auto; 
}
#label-dimension {
color: #ddd;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- JQuery -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<!-- Bootstrap -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js" integrity="sha512-uto9mlQzrs59VwILcLiRYeLKPPbS/bT71da/OEBYEwcdNUk8jYIy+D176RYoop1Da+f9mvkYrmj5MCLZWEtQuA==" crossorigin="anonymous"></script>
<title>Image Puzzle</title>

</head>

<body>

<div class="container col-md-6">
<div id="moves">
Moves : 0
</div>
<div class="d-flex justify-content-center row">
<div class="col-md-6">
<div class="mt-5" id="enter-dimension">
<form>
<div class="form-group">
<label id="label-dimension" for="dimension">Enter the Dimension of the puzzle</label>
<input type="number" class="form-control" id="dimension">
</div>
<div class="alert alert-danger" id="alert" role="alert">
Enter a Valid Positive Integer Greater than or Equal to 3
</div>
<button type="button" class="btn btn-primary" id="generate-puzzle">Generate the Puzzle</button>
</form>
</div>
</div>
</div>
<div class="row">
<!--The GRid Layout and the tiles -->
<div class="mt-3"  id="content">
</div>
</div>
<!--Button to Start the Game -->
<div class="row buttons">
<button type="button" class="btn btn-info mt-2" id="startGame">Start Game</button>
<button type="button" class="btn btn-success mt-2" id="solve">Solve This!</button>
</div>   
</div>

</body>

</html>

这个谜题很完美,但有一个问题。如果将一个单元格拖放到一个空单元格,则无法将该平铺块再次拖放到其上一个位置,即当前空单元格。在我看来,makeDraggable((和dragTheTile((函数中存在问题。当我用鼠标点击移动一个单元格时,我可以将同一个单元格拖放到它的上一个位置(即当前空单元格(,或者如果我将单元格拖放到一个空白处,我可以用鼠标点击将其移动到它的前一个位置(即当前的空单元格(。但拖动后,无法再次拖动同一单元格。看起来该特定单元格的draggable((已禁用。一旦一个单元格被拖动,下一步它应该是一个可拖动的单元格(因为它是空单元格的相邻单元格(当我使其可拖动时;ui可拖动";类被添加到它,但是";ui可拖动手柄";类丢失

问题出在我清除可拖动属性的函数上:

clearDrag() {
this.cells.forEach(cell => {  
if($(cell.cell).data('ui-draggable')) $(cell.cell).draggable("destroy");
})
}

";销毁";方法给出了一些冲突。我找到的另一种方法是首先用draggable属性初始化所有单元格,但在开始时禁用它,并在需要时再次启用它。这里使用的属性是";disabled:true";以及";disabled:false";。

我没有使用dragTheTile((函数,而是编写了一个名为dragTile(((的新函数,如下所示:

dragTile() {
this.cells.forEach(cell => {
cell.makeDraggable();
})
const validCells = this.checkValidCells();
let availableCells = [];
if (validCells.right) {
availableCells.push(this.cells[this.findPosition(validCells.right)].index);
}
if (validCells.left || validCells.left === 0) {
availableCells.push(this.cells[this.findPosition(validCells.left)].index);
}
if (validCells.top || validCells.top === 0) {
availableCells.push(this.cells[this.findPosition(validCells.top)].index);  
}
if (validCells.bottom) {
availableCells.push(this.cells[this.findPosition(validCells.bottom)].index);   
}
let emptyCellIndex = this.findEmptyCell();
availableCells.forEach(cell => {
$(this.cells[cell].cell).draggable({disabled: false});
})
this.cells[emptyCellIndex].makeDroppable(availableCells);
}

这很容易就解决了问题。

最新更新