Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular-cookies.min.js"></script>
  <meta charset="utf-8">
  <title>Ænigma #19</title>
</head>
<body ng-app="app" ng-controller="gridder" class="well">
  <div class="body">
  <h1>
    Ænigma #19
    <small class="btn btn-warning"
           ng-click="persist.clear();">
      Clear
    </small>
  </h1>
  <h1 ng-hide="true">
    playing with cookies
    <small ng-click="state.save();" class="btn btn-default">save</small>
    <small ng-click="state.load();" class="btn btn-default">load</small>
  </h1>
  
  <div>
    
    <div id="puzzle-container">
      
      <div ng-repeat="row in verticals" class="row" ng-init="rowIndex = $index;">
        <div ng-repeat="state in row track by $index" 
             class="vertical-container"
             ng-click="row[$index] = nextState[state];
                       persist.save();"
             ng-style="{
               top: (rowIndex * spacing + vOffset) + 'px',
               left: ($index * spacing + hOffset) + 'px',
               height: spacing + 'px',
             }">
          <div class="vertical" ng-class="state"></div>
        </div>
      </div>
      <div ng-repeat="row in horizontals" class="row" ng-init="rowIndex = $index;">
        <div ng-repeat="state in row track by $index" 
             class="horizontal-container"
             ng-click="row[$index] = nextState[state];
                       persist.save();"
             ng-style="{
               top: (rowIndex * spacing + vOffset - 6) + 'px',
               left: ($index * spacing + hOffset + 6) + 'px',
               width: spacing + 'px',
             }">
          <div class="horizontal" ng-class="state"></div>
        </div>
      </div>  
      
      <img src="http://www.pavelspuzzles.com/adas/19/grid.png">
    </div>
    
    <div>
      <h1>
        <a href="http://www.pavelspuzzles.com/adas/19/" target="_blank">
          Adalogical Ænigma #19
        </a>
      </h1>
      <p>
      A simple playable web version of Pavel's most recent puzzle. Hover and click on the path segments at left to build up a single path. All rights reserved to Pavel Curtis. Also, as this is a jsBin (similar to jsFiddle, CodePen, etc.), you can hack this up as much as you like.
      </p>
    </div>
  </div>
    
  
 <h4>Some other fun things to do...</h4>
<ul>
    <li>Add another color for "guessing"</li>
    <li>keyboard navigation and shortcuts</li>
    <li>touch support</li>
    <li>highlight rule mistakes (e.g. going straight through black)</li>
    <li>history: undo, redo, replay previous steps (e.g. would be great to demonstrate the example puzzle)</li>
    <li>validate when puzzle is done</li>
    <li>can modify or add colors</li>
  </ul>
<h4>Changes &amp; Fixes</h4>
<ul>
  <li>Scrolling no longer moves the grid off the background puzzle image</li>
  <li>Save to browser cookie for persistent play</li>
</ul>
    
</div>
</body>
</html>
 
angular
.module('app', ['ngCookies'])
.controller('gridder', ['$scope', '$cookies', function($scope, $cookies) {
  var numColumns = 20;
  var numRows = 11;
  $scope.vOffset = 13;
  $scope.hOffset = 8;
  $scope.spacing = 28;
  
  var nextState = {
    blank: 'green',
    green: 'blank',
    //green: 'gray',
    //gray: 'blank'
  };
  var compactStateLookup = {
    blank: 0,
    green: 1
  };
  var uncompactStateLookup = [
    'blank',
    'green'
  ];
  
  $scope.nextState = nextState;
  
  function generateStates(x, y) {
    var states = [];
    while (x >= 0) {
      states[x] = [];
      var y_copy = y;
      while (y_copy >= 0) {
//         states[x][y_copy] = 'blank';
        states[x][y_copy] = 'blank';
        y_copy--; 
      }
      x--;
    }
    return states;
  }
  
  var persistentState = {
    save: function() {
      console.log('saving state');
      var state = { time: new Date() };
      ['horizontals', 'verticals'].forEach(function(type) {
        state[type] = persistentState.transform(compactStateLookup, $scope[type]);
      });
      $cookies.state = JSON.stringify(state);
      //persistentState.load();
    },
    load: function() {
//       var data = $cookies.state && JSON.parse($cookies.state);
       var data = $cookies.state;
       data = data && JSON.parse(data);
      if (!data) {return;}
      console.log('loading data');
      ['horizontals', 'verticals'].forEach(function(type) {
        if (!data[type]) {return;}
        $scope[type] = persistentState.transform(uncompactStateLookup, data[type]);
      });
    },
    transform: function(lookup, rows) {
      return rows.map(function(row) {
        return row.map(function(val) {
          return persistentState.apply(lookup, val);
        });
      });
    },
    apply: function(lookup, value) {
      return lookup[value];
    },
    clear: function() {
      var sure = confirm('Are you sure you want to clear current puzzle progress?');
      if (!sure) { return; }
      delete $cookies.state;
      delete $scope.horizontals;
      delete $scope.verticals;
      setUpBoard();
    }
  };
  
  persistentState.load(); // load data if it exists
  
  $scope.persist = persistentState;
  
  function setUpBoard() {
    $scope.verticals = $scope.verticals || generateStates(numRows-1, numColumns);
    $scope.horizontals = $scope.horizontals || generateStates(numRows, numColumns-1);
  }
  setUpBoard();
  
}]);
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
hryanjonespro
0viewers