#javascript #html #jquery #css #jquery-ui
#javascript #HTML #jquery #css #jquery-ui
Вопрос:
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 amp;amp; 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(). Когда я перемещаю ячейку щелчком мыши, я могу перетащить эту же ячейку в ее предыдущую позицию (которая является текущей пустой ячейкой) или, если я перетаскиваю ячейку в пустое место, я могу переместить ее в предыдущую позицию (которая является текущей пустой ячейкой) щелчком мыши. Но после перетаскивания ту же ячейку нельзя перетащить снова. похоже, что функция перетаскивания () отключена для этой конкретной ячейки. После перетаскивания ячейки следующим перемещением должна быть перетаскиваемая ячейка (поскольку это соседняя ячейка с пустой ячейкой) Когда я делаю его перетаскиваемым, к нему добавляется класс «ui-draggable», но класс «ui-draggable-handle» отсутствует.
Комментарии:
1. Где ваш HTML?
2. Просто добавлены HTML и CSS
3. Вам трудно помочь, когда вы ссылаетесь на локальные файлы, которые вы не включаете здесь, в stackoverflow. понравилось <script src=»Scripts/Cell.js»></script> <script src=»Scripts/Gameboard.js»></script> <script src=»Scripts/game.js»></script>
4. в этом контексте нет необходимости в game.js . Как вы можете видеть Cell.js и Gameboard.js это файлы для классов, которые я упомянул в вопросе.
5. Нажмите Cltr-M или нажмите кнопку Javacript / HTML / CSS snippet и разрешите запускать этот код здесь, в Stackoverflow.
Ответ №1:
Проблема была с функцией, в которой я очистил перетаскиваемое свойство:
clearDrag() {
this.cells.forEach(cell => {
if($(cell.cell).data('ui-draggable')) $(cell.cell).draggable("destroy");
})
}
Метод «destroy» приводит к некоторым конфликтам.
Альтернативный метод, который я нашел, состоял в том, чтобы сначала инициализировать все ячейки с помощью перетаскиваемого свойства, но отключить его в начале и включить его снова, когда мне нужно.
здесь использовалось свойство «отключено: true» и «отключено: 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);
}
Это решило проблему очень легко.