JQuery und JSON

24.07.2017 10:31 Uhr

Version B –

Erweiterte JQuery Version

var player = "X";
var lock = null;

$( document ).ready(function() {
    console.log( "document ready! ( DOM loaded )" );

    

    $(".btn-field").click(function(){ 
      if(lock != null) {
        alert("Dieses Spiel ist beendet - beginne ein Neues!");
      } else if($(this).val() === ""){
        $(this).val(player);
        endRound();
      } else {
        alert("Schon besetzt!");
      }
    });

    $("#clear").click(function(){ 
      clear();
    });

});



function endRound(){  
    checkForWin();
    switch(player) {
        case "X":
            player = "O";
            break;
        case "O":
            player = "X";
            break;
        default:
            alert("We're sorry: Some unexpexted error occoured - Game will reset!");
            clear();
            break;
    }
}  
        
function checkForWin() {  
    if (winningCondition("#b0", "#b1", "#b2")) return true;
    if (winningCondition("#b3", "#b4", "#b5")) return true;
    if (winningCondition("#b6", "#b7", "#b8")) return true;
    if (winningCondition("#b0", "#b3", "#b6")) return true;
    if (winningCondition("#b1", "#b4", "#b7")) return true;
    if (winningCondition("#b2", "#b5", "#b8")) return true;
    if (winningCondition("#b0", "#b4", "#b8")) return true;
    if (winningCondition("#b2", "#b4", "#b6")) return true;
    else return false;
}

function winningCondition(a, b, c) { 
    if ($(a).val() == player && $(b).val() == player && $(c).val() == player){
      $(a).addClass("mark-green");
      $(b).addClass("mark-green");
      $(c).addClass("mark-green");
      lock = "locked!"; // lockes up the game if a player wins
      alert("Spieler " + player + " gewinnt die Runde!");
      return true;
    } else {
      return false;
    }

}

function clear() {
  player = "X";
  for (var i = 0; i <= 8; i++) {
    //clear all fields from #b0 to #b9
    $("#b"+i).val("");        
  }    
  lock = null;
  alert("Alles klar - neue Runde!");
}


Version C –

Erweiterte jQuery & JSON Version

Diese Version verwendet JSON-Objekte, um dynamische Spielfelder von potenziell beliebiger Größe zu generieren.

+ HTML: tictactoe.html

JS: tictactoe.js

var gameState = null; //holds meta data of the game
var gameField = null; //holds current game (values of each field)
var gameMode = "3x3"; //holds current gamemode setting
var debug = false;    //displays sth in the console. just an example how to use this.

$( document ).ready(function() {
    console.log( "document ready! ( DOM loaded )" );

    loadFieldFromJSON(gameMode); //initializes the first round

    $("#tab").on('click', '.field', function(){ //fires whenever a field is clicked!
      fieldClicked(this);
    });

    $("#3x3").click(function(){ //fires whenever the 3x3-btn clicked!
      gameMode = '3x3';
      loadFieldFromJSON(gameMode);
    });
    $("#5x5").click(function(){ //fires whenever the 5x5-btn clicked!
      gameMode = '5x5';
      loadFieldFromJSON(gameMode);
    });

});


/*
 *  FUNCTIONS LIBRARY
 */

/*
 *  loads gamemode specific data from .jsons
 */
function loadFieldFromJSON(string){ 
  if(string != "3x3" && string != "5x5"){ return alert("CONFIG ERROR: Only 3x3 or 4x4 field implemented.") }
  $.ajax({ 
    type: 'GET', 
    url: './' + string + '.json', 
    dataType: 'text',
    success: function (data) { 
      var obj = JSON.parse(data);
      prepareField(obj);
      gameState = obj.state;
      gameField = obj.rows;
      updateView();
      return obj;
    }
  }); 
}

/*
 *  assembles the table which serves as visual representation of the current game
 */
function prepareField(data){  
  if(debug===true) console.log(data);
  var html = '';
  var rows = data.rows;
  for (var i = 0; i < rows.length; i++) {          
    if(i===0){  // generates rows
      html += '';   
      for (var j = 0; j < rows[i].fields.length; j++) html += '' + j + '';
      html += ''; 
    }
    html += ''; 
    html += '' + rows[i].rowId + '';
    for (var j = 0; j < rows[i].fields.length; j++) {  // generates fields within rows
        html += '';
        html += ''; 
        html += '';
    }
    html += ''; 
  }
  $('#tab').html(html);
}

/*
 *  handles the action fired by a click-event on a field
 */
function fieldClicked(field){
  $(field).val(gameState.currentPlayer);
  updateGameState(); // every click forces the game to update
}

/*
 *  updates the viewer above the table which holds current player and counters
 */
function updateView(){
  $('#currentPlayer').text(gameState.currentPlayer);
  $('#countX').text(gameState.count.playerX);
  $('#countO').text(gameState.count.playerO);
}

/*
 *  central update-function, keeps json-object and visual representation (talbe) sync, 
 *  checks for a winner, swaps the player each round and updates the view
 */
function updateGameState(){
  syncFields();
  if(checkForEndConditions()===true) return endRound();
  swapPlayer();
  updateView();
}

/*
 *  Checks if one of the conditions is fulfilled, if yes: current player wins 
 */
function checkForEndConditions(){
  if(evaluateRows() || evaluateCols() || evaluateDiagonalUp() || evaluateDiagonalDown()){
    return true;
  }
  return false;
}

/*
 *  grabs values of the visual representation - which changes while gaming - an updates the json-obj
 */
function syncFields(){
  for (var i = 0; i < gameField.length; i++) {          
    for (var j = 0; j < gameField[i].fields.length; j++) { 
      var id = gameField[i].rowId+j;
      var val = $('#'+id).val();
      gameField[i].fields[j].value = val;
    }
  }
}

/*
 *  checks all rows for a match
 */
function evaluateRows(){
  for (var i = 0; i < gameField.length; i++) {
    if(evaluateRow(i)===true) return true; 
  }
  return false;  
}

/*
 *  checks all cols for a match
 */
function evaluateCols(){
  for (var i = 0; i < gameField[0].fields.length; i++) {
    if(evaluateCol(i)===true) return true; 
  }
  return false;  
}
 
/*
 *  checks if a specific row is a match
 */  
function evaluateRow(row){
  for (var i = 0; i < gameField[row].fields.length; i++) {
    if(    gameField[row].fields[0].value != gameField[row].fields[i].value 
        || gameField[row].fields[0].value == null
        || gameField[row].fields[0].value == '' ) return false;
  }
  return true;
}

/*
 *  checks if a specific col is a match
 */
function evaluateCol(col){
  for (var i = 0; i < gameField.length; i++) {
    if(    gameField[0].fields[col].value != gameField[i].fields[col].value 
        || gameField[0].fields[col].value == null
        || gameField[0].fields[col].value == '' ) return false;
  } 
  return true;
}

/*
 *  checks if the diagonal 'line' form top left to bottom right is a match
 */
function evaluateDiagonalUp(){
  for (var i = 0; i < gameField[0].fields.length; i++) {
    if(    gameField[0].fields[0].value != gameField[i].fields[i].value 
        || gameField[0].fields[0].value == null
        || gameField[0].fields[0].value == '' ) return false;
  } 
  return true;
}

/*
 *  checks if the diagonal 'line' form bottom left to top right is a match
 */
function evaluateDiagonalDown(){
  var maxRows = gameField.length - 1;
  var maxCols = gameField[0].fields.length - 1;
  var j = maxCols;
  for (var i = 0; i < gameField[0].fields.length; i++) {
    if(    gameField[maxRows].fields[0].value != gameField[i].fields[j].value 
        || gameField[maxRows].fields[0].value == null
        || gameField[maxRows].fields[0].value == '' ) return false;
    j--;
  } 
  return true;
}

/*
 *  swaps the player
 */
function swapPlayer(){
  if(gameState.currentPlayer == "X") gameState.currentPlayer = 'O';
  else if(gameState.currentPlayer == "O") gameState.currentPlayer = 'X';
  return gameState.currentPlayer
}

/*
 *  counts up for the current player (winner), alerts winner and clears for next round, counter stays!
 */
function endRound(){
  if(gameState.currentPlayer == "X") gameState.count.playerX += 1;
  else if(gameState.currentPlayer == "O") gameState.count.playerO += 1;
  alert('Spieler ' + gameState.currentPlayer + ' gewinnt das Spiel.');
  clearFields();
  updateView();
}

/*
 *  clears the visual and json for the next round
 */
function clearFields(){
  for (var i = 0; i < gameField.length; i++) {          
    for (var j = 0; j < gameField[i].fields.length; j++) { 
      var id = gameField[i].rowId+j;
      $('#'+id).val(null);
      gameField[i].fields[j].value = null;
    }
  } 
}

JSON: 3x3.json

JSON für ein 3x3-Spielfeld.

{ 
	"state": {
		"name":"3x3 field", 
		"currentPlayer":"X",
		"winner": null,
		"count":{
			"playerX": 0,
			"playerO": 0,
			"remis": 0
		}
	},
	"rows":[
		{ 
			"rowId": "A", 
			"fields": [
				{ "val": null },
				{ "val": null },
				{ "val": null }
			] 
		},{ 
			"rowId": "B", 
			"fields": [
				{ "val": null },
				{ "val": null },
				{ "val": null }
			] 
		},{ 
			"rowId": "C", 
			"fields": [
				{ "val": null },
				{ "val": null },
				{ "val": null }
			] 
		}
	] 
}

JSON: 5x5.json

JSON für ein 5x5-Spielfeld.

{ 
	"state": {
		"name":"5x5 field", 
		"currentPlayer":"X",
		"winner": null,
		"count":{
			"playerX": 0,
			"playerO": 0,
			"remis": 0
		}
	},
	"rows":[
		{ 
			"rowId": "A", 
			"fields": [
				{ "val": null },
				{ "val": null },
				{ "val": null },
				{ "val": null },
				{ "val": null }
			] 
		},{ 
			"rowId": "B", 
			"fields": [
				{ "val": null },
				{ "val": null },
				{ "val": null },
				{ "val": null },
				{ "val": null }
			] 
		},{ 
			"rowId": "C", 
			"fields": [
				{ "val": null },
				{ "val": null },
				{ "val": null },
				{ "val": null },
				{ "val": null }
			] 
		},{ 
			"rowId": "D", 
			"fields": [
				{ "val": null },
				{ "val": null },
				{ "val": null },
				{ "val": null },
				{ "val": null }
			] 
		},{ 
			"rowId": "E", 
			"fields": [
				{ "val": null },
				{ "val": null },
				{ "val": null },
				{ "val": null },
				{ "val": null }
			] 
		}
	] 
}

+ CSS: tictactoe.css

+ JS: jquery.min.js

An der CSS Instanz hat sich im Vergleich zu Version B nichts verändert. jQuery wird dieses Mal lokal eingebunden.

Download: tictactoe_jQuery_JSON.zip

Schlagwörter: