var map, player = { x: 1, y: 8 }, i, maze = document.getElementById('maze'), win, playerDirection = 'north'; function mapToHTML(map) { var html = '', x, y, dictionary = { 'H': '<span class="tile wall">H</span>', '.': '<span class="tile floor">.</span>', '@': '<span class="tile player ' + playerDirection + '">@</span>', 'X': '<span class="tile goal">X</span>' }; for (y = 0; y < map.length; y += 1) { for (x = 0; x < map[y].length; x += 1) { html += dictionary[map[y][x]]; } html += '<br>'; } return html; } function updateMap() { var displayMap = [], x, y; for (y = 0; y < map.length; y += 1) { displayMap[y] = displayMap[y] || []; for (x = 0; x < map[y].length; x += 1) { displayMap[y][x] = map[y][x]; } } displayMap[player.y][player.x] = '@'; for (y = 0; y < displayMap.length; y += 1) { displayMap[y] = displayMap[y].join(''); } maze.innerHTML = mapToHTML(displayMap); } function playerMove(x, y) { var toX = player.x + x, toY = player.y + y; if (map[toY][toX] === '.' || map[toY][toX] === 'X') { player.x = toX; player.y = toY; updateMap(); if (document.body.className !== 'ready') { // this is a bit kludgey, but if we set the className every time it breaks the animation (at least in safari) document.body.className = 'ready'; } } if (map[toY][toX] === 'X') { maze.innerHTML = 'YOU WIN'; document.getElementById('buttons').innerHTML = ''; } } function updateDisplay(type) { maze.className = 'display-' + type; } map = [ 'HHHHHHHHHH', 'HH......XH', 'HH.H.H.H.H', 'HH.HHHHH.H', 'H........H', 'HHHHH.H.HH', 'H...H.H.HH', 'H.H...H.HH', 'H.H.HHH.HH', 'HHHHHHHHHH' ]; for (i = 0; i < map.length; i += 1) { map[i] = map[i].split(''); } document.getElementById('button-north').onclick = function() { playerDirection = "north"; playerMove(0, -1); }; document.getElementById('button-south').onclick = function() { playerDirection = "south"; playerMove(0, 1); }; document.getElementById('button-east').onclick = function() { playerDirection = "east"; playerMove(1, 0); }; document.getElementById('button-west').onclick = function() { playerDirection = "west"; playerMove(-1, 0); }; (function() { var i, displaySwitches = document.getElementsByClassName('switch-display'); for (i = 0; i < displaySwitches.length; i += 1) { displaySwitches[i].onchange = function(event) { updateDisplay(event.target.value); } } }()); updateDisplay('enhanced'); updateMap();
<div> <fieldset> <legend>Display mode:</legend> <label><input type="radio" class="switch-display" name="switch-display" value="ascii">ASCII</label> <label><input type="radio" class="switch-display" name="switch-display" value="simple">Simple</label> <label><input type="radio" class="switch-display" name="switch-display" value="enhanced" checked="checked">Enhanced</label> </fieldset> </div> <pre id="maze"></pre> <div id="buttons"> <button id="button-north" class="button">NORTH</button> <button id="button-west" class="button">WEST</button> <button id="button-east" class="button">EAST</button> <button id="button-south" class="button">SOUTH</button> </div>
#maze { width: 10em; margin: 1em; display: inline-block; } #buttons { text-align: center; display: inline-block; margin-left: 1em; } .button { padding: 1em 0.5em; background: lightblue; display: inline-block; width: 5em; } #button-north, #button-south { display: block; margin: 0 auto; } .display-simple .tile, .display-enhanced .tile { color: transparent; width: 1em; height: 1em; float: left; } .display-simple .wall { background: gray; } .display-simple .floor { background: darkgray; } .display-simple .player { background: yellow; } .display-simple .goal { background: red; } .display-simple br, .display-enhanced br { display: none; } html.backgroundsize .display-enhanced .tile { background-size: 100% 100%; background-repeat: no-repeat; background-color: transparent; } html.backgroundsize #maze.display-enhanced { color: #ccc; text-align: center; font-weight: bold; background-size: 1em 1em; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAD1BMVEULCwslJSUKCgoVFRUbGxvoRClcAAAAOElEQVQIHWMwhgIGExcXZyB2YDBxdHECYQYTQSADiEFSTiCMYBi5uCiBMIOxkpISCDOgm+NMnjkAAascBi14w+MAAAAASUVORK5CYII='); } #buttons { vertical-align: top; margin-left: 0; margin-top: 1em; } html.backgroundsize .display-enhanced .wall { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAABGdBTUEAALGPC/xhBQAAAAxQTFRFEQoHb19XMCYgT0E7gu+CdAAAAChJREFUCNdj4GrgamC4Gnc1juH/v///IARQiIsBKHSVAcj7DyGIVAcAvq4tuTilersAAAAASUVORK5CYII='); } html.backgroundsize .display-enhanced .goal { background-image: url('data:image/gif;base64,R0lGODlhEAAQAJAAANhA8P///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgABACwAAAAAEAAQAAACkUyYMGFAhAkTJkyYMCHCgAkTJkyYMGDChAgTJkyYEGHChAETJkwYMGHChAkRJkyIMGHChAkDJgyYMGHChAkTIkSYMGHChAkTBkSYMGHChAkTBgyYMGHChAkTIkyIMGHChAkDJkwYMGHChAkRJkyYEGHChAETJkyYMGDChAgTJkyYMCHCgAkTJkyYMGFAhAkTJgUAIfkECQoAAQAsAAAAABAAEAAAApFMmDBhwoQJEyZMmDBhQIQJEyZMmDAhwoAJEyZMmDBgwoQIEyZMmBBhwoQBEyZMGDBhwoQJESZMiDBhwoQJAyYMmDBhwoQJEyIMmDBhwoQJEyJMiDBhwoQJAyZMGDBhwoQJESZMmBBhwoQBEyZMmDBgwoQIEyZMmDAhwoAJEyZMmDBhQIQJEyZMmDBhwoQJEyYFACH5BAkKAAEALAAAAAAQABAAAAKRTJgwYcKECRMmTJgwYcKECRMmTJgwYUCECRMmTJgwIcKACRMmTJgwYMKECBMmTJgQYcKEARMmTBgwYcKECREmTIgwYcKECQMmTIgwYcKECQMmTBgwYcKECREmTJgQYcKEARMmTJgwYMKECBMmTJgwIcKACRMmTJgwYUCECRMmTJgwYcKECRMmTJgwYcKECRMmBQAh+QQJCgABACwAAAAAEAAQAAACkUyYMGHChAkTJkyYMGHChAkTJkyYMGHChAkTJkyYMGFAhAkTJkyYMCHCgAkTJkyYMGDChAgTJkyYEGHChAETJkwYMGHChAkRJkwYMGHChAkRJkyYEGHChAETJkyYMGDChAgTJkyYMCHCgAkTJkyYMGFAhAkTJkyYMGHChAkTJkyYMGHChAkTJkyYMGHChAkTJgUAIfkECQoAAQAsAAAAABAAEAAAApFMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhQIQJEyZMmDAhwoAJEyZMmDBgwoQIEyZMmBBhwoQBEyZMmBBhwoQBEyZMmDBgwoQIEyZMmDAhwoAJEyZMmDBhQIQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyYFACH5BAkKAAEALAAAAAAQABAAAAKRTJgwYcKECRMmTJgwYcKECRMmTJgwYcKECRMmTJgwYcKECRMmTJgwYcKECRMmTJgwYUCECRMmTJgwIcKACRMmTJgwYMKECBMmTJgwYMKECBMmTJgwIcKACRMmTJgwYUCECRMmTJgwYcKECRMmTJgwYcKECRMmTJgwYcKECRMmTJgwYcKECRMmTJgwYcKECRMmBQAh+QQJCgABACwAAAAAEAAQAAACkUyYMGHChAkTJkyYMGHChAkTJkyYMGHChAkTJkyYMGHChAkTJkyYMGHChAkTJkyYMGHChAkTJkyYMGFAhAkTJkyYMCHCgAkTJkyYMCHCgAkTJkyYMGFAhAkTJkyYMGHChAkTJkyYMGHChAkTJkyYMGHChAkTJkyYMGHChAkTJkyYMGHChAkTJkyYMGHChAkTJgUAIfkECQoAAQAsAAAAABAAEAAAApFMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhQIQJEyZMmDBhQIQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyZMmDBhwoQJEyYFADs='); } html.backgroundsize .display-enhanced .player { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAHlBMVEUAAABNNRKFjZGRZSRSV1ouMTLa5+3G0dexu8Gbo6gjp+WyAAAAAXRSTlMAQObYZgAAADRJREFUCFtjYMAO2FEZjAwMbGCGQQArmME81a0kEsQQmKlWNBMs1V45vQLM4OjoaAAzyAAAQZIHzWFT0LUAAAAASUVORK5CYII='); } @-webkit-keyframes north { 0% { -webkit-transform: rotate(0deg) translate(0%, 100%); } 100% { -webkit-transform: rotate(0deg) translate(0%, 0%); } } @-moz-keyframes north { 0% { -moz-transform: rotate(0deg) translate(0%, 100%); } 100% { -moz-transform: rotate(0deg) translate(0%, 0%); } } @-ms-keyframes north { 0% { -ms-transform: rotate(0deg) translate(0%, 100%); } 100% { -ms-transform: rotate(0deg) translate(0%, 0%); } } @-o-keyframes north { 0% { -o-transform: rotate(0deg) translate(0%, 100%); } 100% { -o-transform: rotate(0deg) translate(0%, 0%); } } @keyframes north { 0% { transform: rotate(0deg) translate(0%, 100%); } 100% { transform: rotate(0deg) translate(0%, 0%); } } @-webkit-keyframes south { 0% { -webkit-transform: rotate(180deg) translate(0%, 100%); } 100% { -webkit-transform: rotate(180deg) translate(0%, 0%); } } @-moz-keyframes south { 0% { -moz-transform: rotate(180deg) translate(0%, 100%); } 100% { -moz-transform: rotate(180deg) translate(0%, 0%); } } @-ms-keyframes south { 0% { -ms-transform: rotate(180deg) translate(0%, 100%); } 100% { -ms-transform: rotate(180deg) translate(0%, 0%); } } @-o-keyframes south { 0% { -o-transform: rotate(180deg) translate(0%, 100%); } 100% { -o-transform: rotate(180deg) translate(0%, 0%); } } @keyframes south { 0% { transform: rotate(90deg) translate(0%, 100%); } 100% { transform: rotate(90deg) translate(0%, 0%); } } @-webkit-keyframes east { 0% { -webkit-transform: rotate(90deg) translate(0%, 100%); } 100% { -webkit-transform: rotate(90deg) translate(0%, 0%); } } @-moz-keyframes east { 0% { -moz-transform: rotate(90deg) translate(0%, 100%); } 100% { -moz-transform: rotate(90deg) translate(0%, 0%); } } @-ms-keyframes east { 0% { -ms-transform: rotate(90deg) translate(0%, 100%); } 100% { -ms-transform: rotate(90deg) translate(0%, 0%); } } @-o-keyframes east { 0% { -o-transform: rotate(90deg) translate(0%, 100%); } 100% { -o-transform: rotate(90deg) translate(0%, 0%); } } @keyframes east { 0% { transform: rotate(90deg) translate(0%, 100%); } 100% { transform: rotate(90deg) translate(0%, 0%); } } @-webkit-keyframes west { 0% { -webkit-transform: rotate(270deg) translate(0%, 100%); } 100% { -webkit-transform: rotate(270deg) translate(0%, 0%); } } @-moz-keyframes west { 0% { -moz-transform: rotate(270deg) translate(0%, 100%); } 100% { -moz-transform: rotate(270deg) translate(0%, 0%); } } @-ms-keyframes west { 0% { -ms-transform: rotate(270deg) translate(0%, 100%); } 100% { -ms-transform: rotate(270deg) translate(0%, 0%); } } @-o-keyframes west { 0% { -o-transform: rotate(270deg) translate(0%, 100%); } 100% { -o-transform: rotate(270deg) translate(0%, 0%); } } @keyframes west { 0% { transform: rotate(270deg) translate(0%, 100%); } 100% { transform: rotate(270deg) translate(0%, 0%); } } html.backgroundsize.csstransforms .display-enhanced .player.north { -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); -o-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } html.backgroundsize.csstransforms.cssanimations .display-enhanced .player.north { -moz-animation: north 0.5s; -webkit-animation: north 0.5s; -ms-animation: north 0.5s; -o-animation: north 0.5s; animation: north 0.5s; } html.backgroundsize.csstransforms .display-enhanced .display-enhanced .player.south { -moz-transform: rotate(180deg); -webkit-transform: rotate(180deg); -o-transform: rotate(180deg); -ms-transform: rotate(180deg); transform: rotate(180deg); } html.backgroundsize.csstransforms.cssanimations .display-enhanced .player.south { -moz-animation: south 0.5s; -webkit-animation: south 0.5s; -ms-animation: south 0.5s; -o-animation: south 0.5s; animation: south 0.5s; } html.backgroundsize.csstransforms .display-enhanced .player.east { -moz-transform: rotate(90deg); -webkit-transform: rotate(90deg); -o-transform: rotate(90deg); -ms-transform: rotate(90deg); transform: rotate(90deg); } html.backgroundsize.csstransforms.cssanimations .display-enhanced .player.east { -moz-animation: east 0.5s; -webkit-animation: east 0.5s; -ms-animation: east 0.5s; -o-animation: east 0.5s; animation: east 0.5s; } html.backgroundsize.csstransforms .display-enhanced .player.west { -moz-transform: rotate(270deg); -webkit-transform: rotate(270deg); -o-transform: rotate(270deg); -ms-transform: rotate(270deg); transform: rotate(270deg); } html.backgroundsize.csstransforms.cssanimations .display-enhanced .player.west { -moz-animation: west 0.5s; -webkit-animation: west 0.5s; -ms-animation: west 0.5s; -o-animation: west 0.5s; animation: west 0.5s; } html.backgroundsize.csstransforms.cssanimations body.not-ready .display-enhanced .player { -moz-animation: none; -webkit-animation: none; -ms-animation: none; -o-animation: none; animation: none; } @-webkit-keyframes spin { 0% { -webkit-transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); } } @-moz-keyframes spin { 0% { -moz-transform: rotate(0deg); } 100% { -moz-transform: rotate(359deg); } } @-ms-keyframes spin { 0% { -ms-transform: rotate(0deg); } 100% { -ms-transform: rotate(359deg); } } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(359deg); } } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(359deg); } } html.backgroundsize.csstransforms.cssanimations .display-enhanced .goal { -moz-animation: spin 0.5s linear infinite; -webkit-animation: spin 0.5s linear infinite; -ms-animation: spin 0.5s linear infinite; -o-animation: spin 0.5s linear infinite; animation: spin 0.5s linear infinite; } label { display: block; }