jQuery Flip Puzzle Game

JavaScriptJavaScriptBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

Dieses Projekt, das "jQuery Flip Puzzle Game", bietet eine praktische Erfahrung im Web-Entwicklung, mit einem Schwerpunkt auf JavaScript, jQuery und Bootstrap. Es beinhaltet objektorientiertes Programmieren in JavaScript und behandelt das häufige Problem der "this" Bindung im Kontext der Web-Entwicklung. Das Spiel wird mit jQuery und Bootstrap 3 für die Benutzeroberfläche implementiert. Während eine Vertrautheit mit Bootstrap hilfreich ist, wird die Kernlogik des Projekts mit jQuery und JavaScript aufgebaut.

Im Spiel beginnen die Spieler mit einem Gitter aus orangenen Blöcken. Jeder Block hat eine orangene Seite und eine blaue Seite. Wenn ein Spieler auf einen Block klickt, wechselt seine Farbe, und die Farben der angrenzenden Blöcke ändern sich ebenfalls. Das Ziel ist, alle Blöcke blau zu machen, um das Spiel zu gewinnen.

👀 Vorschau

jQuery Flip Puzzle Game

🎯 Aufgaben

In diesem Projekt lernen Sie:

  • Wie man objektorientiertes Programmieren in JavaScript implementiert und das Problem der "this" Bindung löst.
  • Wie man die Kernlogik des Spiels mit jQuery und JavaScript aufbaut.
  • Wie man ein interaktives Puzzle-Spiel erstellt, in dem die Spieler die Blockfarben umkehren, um zu gewinnen.

🏆 Errungenschaften

Nach Abschluss dieses Projekts werden Sie in der Lage sein:

  • Objektorientierte Programmierungsprinzipien in JavaScript anzuwenden.
  • Die "this" Bindung in JavaScript für die Ereignisbehandlung und Objektmethoden zu behandeln.
  • Interaktive Webbspiele mit jQuery zu entwickeln.
  • Bootstrap 3 nutzen, um visuell ansprechende und benutzerfreundliche Oberflächen zu erstellen.

Grundlegende HTML-Struktur

Basierend auf dem Vorschaubild wird ein vorläufiges Webseitenlayout erstellt. In Bootstrap gibt es einen Modal-Dialog, der ähnlich wie das alert-Pop-up-Fenster ist, und der Stil von Modal ist im Vergleich ästhetischer.

Wir müssen die CSS-Stile aus Bootstrap, unsere benutzerdefinierten CSS-Stile, die jQuery-Datei, die Bootstrap-JavaScript-Datei und die Haupt-JavaScript-Datei des Spiels in das Projekt einbinden. Schreiben Sie folgenden Code im head-Tag der HTML-Seite:

<head>
  <meta charset="utf-8" />
  <title>Blue Puzzle</title>
  <!-- Fügen Sie die Bootstrap-CSS ein -->
  <link
    rel="stylesheet"
    href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
  />
  <!-- Fügen Sie die benutzerdefinierte CSS ein -->
  <link rel="stylesheet" href="style.css" />

  <!-- Fügen Sie jQuery und die Bootstrap-JavaScript ein -->
  <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
  <!-- Fügen Sie die Haupt-JavaScript-Datei des Spiels ein -->
  <script src="game.js"></script>
</head>
✨ Lösung prüfen und üben

Spielbereich einrichten

Um den Spielbereich einzurichten, einschließlich der Buttons für das Zurücksetzen des Spiels und andere Funktionen, fügen Sie folgenden Code in den body-Tag ein:

<div class="container">
  <div class="heading">
    <h1 class="title">jQuery Flip Puzzle Game</h1>
    <div class="scoresContainer">
      <!-- Zeige das aktuelle Spiellevel an -->
      <div class="currLevel">Aktuelles Level: <b>1</b></div>
    </div>
  </div>
  <div class="aboveGame">
    <!-- Spielbuttons -->
    <a
      class="instruct btn btn-primary"
      data-toggle="modal"
      data-target="#instructions"
      >Spielanleitung</a
    >
    <a
      class="newgame btn btn-primary"
      data-toggle="modal"
      data-target="#newGame"
      >Neustart</a
    >
    <a
      class="reset btn btn-primary"
      data-toggle="modal"
      data-target="#restartLevel"
      >Level zurücksetzen</a
    >
  </div>
  <div class="board">
    <!-- Spielbereich -->
    <div class="gamerow">
      <div class="gamesquare coord0q0"></div>
    </div>
  </div>
</div>
✨ Lösung prüfen und üben

Bearbeiten Sie den Inhalt des Popups, das dem Button "Edit Game Instructions" entspricht. Schreiben Sie folgenden Code unter dem Code für den Spielbereich:

<!-- Spielgeschehen Modal -->
<div
  class="modal fade"
  id="instructions"
  tabindex="-1"
  role="dialog"
  aria-hidden="true"
>
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title">Spielgeschehen</h4>
      </div>
      <div class="modal-body">
        <p>Wie man gewinnt: Machen Sie alle Puzzle-Stücke blau.</p>
        <p>
          Spielgeschehen: Jedes Quadrat hat eine orangene Seite und eine blaue
          Seite. Wenn Sie auf ein Quadrat klicken, wechselt seine Farbe, und die
          Farben der angrenzenden Quadrate werden ebenfalls umgeschaltet.
        </p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-primary" data-dismiss="modal">
          Spiel starten
        </button>
      </div>
    </div>
  </div>
</div>
✨ Lösung prüfen und üben

Layout für das Neustart-Modal

Bearbeiten Sie den Inhalt des Modals, das dem Button "Restart" entspricht. Schreiben Sie folgenden Code unter dem Code für die Spiel-Logik:

<!-- Neustart Modal -->
<div
  class="modal fade"
  id="newGame"
  tabindex="-1"
  role="dialog"
  aria-hidden="true"
>
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title">Neustart</h4>
      </div>
      <div class="modal-body">
        <p>Sind Sie sicher, dass Sie einen Neustart wünschen?</p>
      </div>
      <div class="modal-footer">
        <button
          type="button"
          class="btn btn-primary"
          id="newGameConfirm"
          data-dismiss="modal"
        >
          Spiel starten
        </button>
      </div>
    </div>
  </div>
</div>
✨ Lösung prüfen und üben

Bestätigungsmodallayout für das Level zurücksetzen

Ändern Sie den Inhalt des Popups, das dem Button "Reset Level" entspricht. Fügen Sie folgenden Code unter dem Code "Restart Level" hinzu:

<!-- Bestätigungsmodal für das Level zurücksetzen -->
<div
  class="modal fade"
  id="restartLevel"
  tabindex="-1"
  role="dialog"
  aria-hidden="true"
>
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title">Bestätigung für das Level zurücksetzen</h4>
      </div>
      <div class="modal-body">
        <p>Sind Sie sicher, dass Sie das Level zurücksetzen möchten?</p>
      </div>
      <div class="modal-footer">
        <button
          type="button"
          class="btn btn-primary"
          id="resetLevelConfirm"
          data-dismiss="modal"
        >
          Zurücksetzen
        </button>
      </div>
    </div>
  </div>
</div>
✨ Lösung prüfen und üben

CSS-Stile

Die CSS-Stile des Spiels sind relativ einfach. Der Code in style.css ist unten gezeigt:

.container {
  width: 600px;
  margin: 0 auto;
}

/* Spiellevel */
.scoresContainer {
  float: right;
  text-align: right;
  font-size: 18px;
}

/* Spielbuttons */
.aboveGame:after {
  display: block;
  margin: 20px 0;
  content: "";
  clear: both;
}

/* Spielbereich */
.board {
  position: absolute;
  background-color: #5f5f5f;
  border-radius: 4px;
}

.gamesquare {
  float: left;
  margin-right: 15px;
  border-radius: 3px;
}
✨ Lösung prüfen und üben

Einrichten der Spielszene

Die Kacheln im Spielpanel werden als zweidimensionales Array gespeichert, wobei jedes Element einen Wert von 0 (auf orange gesetzt) oder 1 (auf blau gesetzt) hat. Am Anfang werden alle Werte auf 0 gesetzt. Wenn eine Kachel angeklickt wird, wechselt ihre Farbe, und die Koordinaten der angrenzenden Kacheln werden bestimmt, um auch ihre Farben zu wechseln, während gleichzeitig die Werte im zweidimensionalen Array geändert werden. Das Spiel ist beendet, wenn alle Werte im Array 1 werden (d.h., alle Kacheln sind blau).

Hauptlogik:

  1. Die Beziehung zwischen der Größe der Spielszene, der Schwierigkeitsstufe und der Größe und Anzahl der Kacheln.
  2. Anklicken einer Kachel und Änderung des Zustands der angrenzenden Kacheln.
  3. Überprüfen, ob alle Kachelzustände 1 sind.
function SetStyle() {}
SetStyle.prototype.setGridSize = function (level) {
  var margin = this.getMargin(level);
  var res = ($(".container").width() - margin * level) / level;

  // Setze die Größe und den Abstand der Kacheln
  $(".gamesquare").css("margin-right", margin);
  $(".gamesquare").css("width", res);
  $(".gamesquare").css("height", res);

  // Setze die Höhe, den rechten Rand und den unteren Rand jeder Zeile
  $(".gamerow").css("height", res);
  $(".gamerow").css("margin-right", margin * -1);
  $(".gamerow").css("margin-bottom", margin);

  // Setze den Innenabstand des Spielbereichs
  $(".board").css("padding", margin);
  $(".board").css("padding-bottom", 0);
};
SetStyle.prototype.getMargin = function (level) {
  if (level <= 6) return 15;
  if (level > 15) return 5;
  return 20 - level;
};
✨ Lösung prüfen und üben

Erstellen des Game-Konstruktors

// Game-Konstruktor
function Game() {
  // Spielstufe
  this.level = 1;
  // Objekte zur Steuerung des Spiels erstellen
  this.gb;
  this.sh = new SetStyle();
}

Der Game-Konstruktor soll Instanzen eines Spiels mit Eigenschaften erstellen, um den Spielzustand zu verfolgen, und Methoden, um Spielfunktionen wie das Starten des Spiels, das Aktualisieren seines Zustands und das Rendern von Visuals zu behandeln. Die tatsächliche Logik für diese Funktionen (innerhalb der start-, update- und render-Methoden) wird derzeit nicht bereitgestellt, und Platzhalter sind für die zukünftige Implementierung vorhanden.

✨ Lösung prüfen und üben

Einstellen von Spieldetails

Setzen Sie die Spieldetails in den Prototypenmethoden der Game-Klasse:

// Prototypenmethode der Game-Klasse, die die spezifische Spiellogik steuert, stellen Sie sicher, dass die 'this'-Referenz zurückgesetzt wird
Game.prototype = {
  processClick: function (w, h) {
    this.gb.processClick(w, h);
    this.updateCounts();
    if (this.gb.isGameWin()) {
      this.gameEnd();
    }
  },
  // Spiel starten
  beginGame: function () {
    this.setupLevel();
  },
  // Spielende
  gameEnd: function () {
    this.level++;
    this.resetGame();
  },
  // Spiel zurücksetzen, leiten Sie 'this' über bind um
  resetGame: function () {
    $("#levelDescriptor").html("Enter Level " + this.level);
    setTimeout(
      function () {
        this.setupLevel(); // Wenn 'this' nicht zurückgesetzt wird, bezieht es sich auf das window-Objekt
      }.bind(this),
      500
    ); // Verwenden Sie bind, um 'this' von window auf die Instanz umzuleiten
  },
  // Schwierigkeitsstufe einstellen
  setupLevel: function () {
    this.gb = new GameBoard(this.level, this.level);
    $(".board").html(""); // Spielfeld leeren
    this.gb.populate(); // Alle Kacheln auf orange setzen
    this.gb.renderBoard(); // Spielfeld rendern und Kacheln erstellen
    this.sh.setGridSize(this.level); // Größe der Kacheln im Spielbereich steuern
    this.updateCounts(); // Aktuelle Stufe anzeigen aktualisieren
    this.applyBindings(); // Farben der Kacheln um die angeklickte Kachel herum umkehren
  },
  // Aktuelle Stufe anzeigen aktualisieren
  updateCounts: function () {
    $(".currLevel").html("Current Level: <b>" + this.level + "</b>");
  },
  applyBindings: function () {
    var that = this; // Speichern Sie 'this' als Variable vor dem DOM-Ereignis-Callback für einfache Referenz
    $(".gamesquare").click(function () {
      // Position der angeklickten Kachel abrufen
      var cname = $(this).attr("class").split(" ")[1];
      var coord = cname.substring(5).split("q");
      var height = parseInt(coord[1]);
      var width = parseInt(coord[0]);
      that.processClick(width, height);
    });
  },
  onNewGameClick: function () {
    this.level = 1;
    this.setupLevel();
  }
};

Dieser Code erweitert die Funktionalität des Game-Konstruktors, indem er Prototypenmethoden hinzufügt. Diese Methoden definieren die primäre Spiellogik und Interaktionen.

✨ Lösung prüfen und üben

Festlegen der Koordinaten der Blöcke

Dieser Code definiert eine Konstruktorfunktion namens GameBoard, die verwendet wird, um Spielfeldobjekte zu erstellen.

// xPos, yPos sind die Koordinaten des Blocks
function GameBoard(xPos, yPos) {
  // Spielfeld
  // Kachelkoordinaten
  this.high = yPos - 1; // Der Index beginnt bei 0
  this.wide = xPos - 1; // Der Index beginnt bei 0
  this.count = 0;
  // Die horizontale Koordinate ist wide, und die vertikale Koordinate ist high
  //    [0][0] |  [0][1]
  //  - - - - - - - - - - - -
  //    [1][0] |  |[1][1]

  // Erstellen eines zweidimensionalen Arrays von Kacheln
  this.board = new Array(xPos);
  for (var i = 0; i <= this.wide; i++) {
    this.board[i] = new Array(yPos);
  }
}
✨ Lösung prüfen und üben

Einstellen der Spielregeln

Der Codeausschnitt, den Sie bereitgestellt haben, erweitert die Funktionalität des GameBoard-Konstruktors, indem er Prototypenmethoden hinzufügt, die die Kernspielregeln und das Rendern der Logik definieren.

// Implementierung der Spielregeln
GameBoard.prototype = {
  renderBoard: function () {
    var htmlString = ""; // Struktur der Spielkacheln
    for (var j = 0; j <= this.high; j++) {
      htmlString += "<div class='gamerow'>";
      for (var i = 0; i <= this.wide; i++) {
        htmlString += "<div class='gamesquare coord" + i + "q" + j + "'></div>";
      }
      htmlString += "</div>";
    }
    $(".board").html(htmlString);

    for (var i = 0; i <= this.wide; i++) {
      for (var j = 0; j <= this.high; j++) {
        this.processClickView(i, j);
      }
    }
  },
  processClick: function (w, h) {
    //
    // Wechselt die Farben der Blöcke um den angeklickten Block herum
    //

    // Finde die umliegenden Blöcke, die umgedreht werden müssen
    var lowx = w - 1;
    var highx = w + 1;
    var lowy = h - 1;
    var highy = h + 1;

    // Überprüfe, ob der angeklickte Block ein Randblock ist
    if (w == 0) lowx = 0;
    if (w == this.wide) highx = this.wide;
    if (h == 0) lowy = 0;
    if (h == this.high) highy = this.high;

    // Wechsle die vertikal angrenzenden Blöcke des angeklickten Blocks
    for (var i = lowy; i <= highy; i++) {
      if (this.board[w][i] == 0) {
        this.board[w][i] = 1;
        this.count++;
      } else {
        this.board[w][i] = 0;
        this.count--;
      }
      this.processClickView(w, i);
    }

    // Wechsle die horizontal angrenzenden Blöcke des angeklickten Blocks
    for (var i = lowx; i <= highx; i++) {
      if (i == w) continue;
      if (this.board[i][h] == 0) {
        this.board[i][h] = 1;
        this.count++;
      } else {
        this.board[i][h] = 0;
        this.count--;
      }
      this.processClickView(i, h);
    }
  },
  // Wechselt die Farbe eines Blocks
  processClickView: function (w, h) {
    var coord = ".coord" + w + "q" + h;
    if (this.board[w][h] == 0) {
      $(coord).css("background-color", "#e8BB39");
    } else {
      $(coord).css("background-color", "#6060e0");
    }
  },

  // Setze alle Blöcke auf orange
  populate: function () {
    for (var i = 0; i <= this.wide; i++) {
      for (var j = 0; j <= this.high; j++) {
        this.board[i][j] = 0;
      }
    }
  },

  // Gewinnbedingung des Spiels
  isGameWin: function () {
    return this.count == (this.wide + 1) * (this.high + 1);
  }
};
✨ Lösung prüfen und üben

Initialisierung des Spiels

Dieser Code setzt das Spiel zusammen, wenn die Seite geladen ist. Er initialisiert das Spiel, startet die erste Stufe und legt auch Event-Listener für das Zurücksetzen der aktuellen Stufe oder das Starten eines neuen Spiels fest.

// Initialisiere das Spiel
$(document).ready(function () {
  // Erstelle das Spiel
  var game = new Game();
  // Beginne das Spiel
  game.beginGame();

  // Setze die Stufenkacheln zurück
  $("#resetLevelConfirm").click(function () {
    game.setupLevel();
  });

  // Starte ein neues Spiel
  $("#newGameConfirm").click(function () {
    game.onNewGameClick();
  });
});
✨ Lösung prüfen und üben

Ausführen der App

  • Öffnen Sie index.html in einem Webbrowser.
    open web
  • Der Effekt der Seite ist wie folgt:
    Image description
✨ Lösung prüfen und üben

Zusammenfassung

Beim Entwicklung dieses Spiels sind wir auf folgende Aspekte gestoßen:

  • Objektorientierte Methoden in JavaScript
  • Die interne this-Referenz und -Umleitung in JavaScript
  • Wie man mit jQuery das DOM manipuliert
  • Matrixbeziehungsfragen

Wir müssen diese Logik tatsächlich nicht implementieren, aber wir sollten die Denkweise lernen. Um ein Problem zu lösen, müssen wir es zuerst analysieren und die beteiligten logischen Beziehungen klären. Das ist der Schlüssel zum Problemlösen.