Created
October 30, 2012 04:35
-
-
Save chemoish/3978317 to your computer and use it in GitHub Desktop.
A CodePen by Carey Hinoki. Tic-Tac-Toe - The first interview question I give out is to make TTT in 15 minutes. The only person that has finished it in my company / all interviewees is me. One day everyone decided to one up the basic TTT problem... So thi
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <canvas id="game" width="600" height="600"></canvas> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| TTT = (function() { | |
| var canvas = $('#game').get(0); | |
| var ctx = canvas.getContext('2d'); | |
| var height = canvas.height; | |
| var width = canvas.width; | |
| function drawBoard() { | |
| ctx.save(); | |
| ctx.lineWidth = 10; | |
| ctx.lineCap = 'round'; | |
| ctx.strokeStyle = '#AD5472'; | |
| ctx.beginPath(); | |
| ctx.moveTo(200, 20); | |
| ctx.lineTo(200, 580); | |
| ctx.stroke(); | |
| ctx.beginPath(); | |
| ctx.moveTo(400, 20); | |
| ctx.lineTo(400, 580); | |
| ctx.stroke(); | |
| ctx.beginPath(); | |
| ctx.moveTo(20, 200); | |
| ctx.lineTo(580, 200); | |
| ctx.stroke(); | |
| ctx.beginPath(); | |
| ctx.moveTo(20, 400); | |
| ctx.lineTo(580, 400); | |
| ctx.stroke(); | |
| ctx.restore(); | |
| } | |
| function drawDrop(x, y) { | |
| var segments = 30; | |
| var fromX = x; | |
| var fromY = y; | |
| var toX = x + Math.floor(Math.random() * 10) + 5; | |
| var toY = y + Math.floor(Math.random() * 20) + 5; | |
| var slope = ((toY - fromY) / (toX - fromX)) * -1; | |
| var slopeX = ((toX - fromX) / segments); | |
| var slopeY = ((toY - fromY) / segments); | |
| ctx.lineCap = 'round'; | |
| var segment_collection = []; | |
| for (var i = 0; i <= segments; i++) { | |
| toX = (i * slopeX) + x; | |
| toY = (i * slopeY) + y; | |
| segment_collection[i] = { | |
| fromX: fromX, | |
| fromY: fromY, | |
| toX: toX, | |
| toY: toY | |
| }; | |
| fromX = toX; | |
| fromY = toY; | |
| } | |
| var counter = 0; | |
| var tail = Math.floor(Math.random() * 10) + 5; | |
| (function animate() { | |
| var segment = segment_collection[counter]; | |
| var segment_tail = segment_collection[counter - tail]; | |
| counter++; | |
| if (segment_tail != undefined) { | |
| drop(segment_tail.fromX, segment_tail.fromY, segment_tail.toX, segment_tail.toY, '#FFFFFF', 5); | |
| } | |
| if (segment != undefined) { | |
| var color; | |
| if (Math.floor(Math.random() * 100) < 15) { | |
| color = '#A1B0FF'; | |
| } else { | |
| color = '#CAE6E8'; | |
| } | |
| drop(segment.fromX, segment.fromY, segment.toX, segment.toY, color, 3); | |
| } | |
| if (segment != undefined || segment_tail != undefined) { | |
| setTimeout(function() { | |
| animate(); | |
| }, 1000 / 60); | |
| } | |
| })(); | |
| function drop(fromX, fromY, toX, toY, color, lineWidth) { | |
| ctx.save(); | |
| ctx.beginPath(); | |
| ctx.moveTo(fromX, fromY); | |
| ctx.lineTo(toX, toY); | |
| ctx.lineWidth = lineWidth; | |
| ctx.strokeStyle = color; | |
| ctx.globalAlpha = 0.7; | |
| ctx.stroke(); | |
| ctx.restore(); | |
| } | |
| } | |
| function rain(x, y) { | |
| drawDrop(x + 15, y + 5); | |
| drawDrop(x + 25, y + 5); | |
| drawDrop(x + 41, y + 0); | |
| drawDrop(x + 46, y + 5); | |
| drawDrop(x + 60, y + 5); | |
| drawDrop(x + 70, y + 0); | |
| var timeout = setTimeout(function() { | |
| rain(x, y); | |
| }, 1000/5); | |
| if (shower == false) { | |
| clearTimeout(timeout); | |
| } | |
| }; | |
| // initialize game | |
| var board = [ | |
| [0, 0, 200, 200], | |
| [200, 0, 400, 200], | |
| [400, 0, 600, 200], | |
| [0, 200, 200, 400], | |
| [200, 200, 400, 400], | |
| [400, 200, 600, 400], | |
| [0, 400, 200, 600], | |
| [200, 400, 400, 600], | |
| [400, 400, 600, 600] | |
| ]; | |
| var moves = []; | |
| var turns = [ | |
| '9728', // Sun | |
| '9729' // Cloud | |
| ]; | |
| var turn = 0; | |
| var shower = true; | |
| // draw board | |
| drawBoard(); | |
| return { | |
| getBoard: function() { | |
| return moves; | |
| }, | |
| getWinner: function() { | |
| if (this.hasWon(0)) { | |
| return 1; // update zero index offset | |
| } else if (this.hasWon(1)) { | |
| return 2; // update zero index offset | |
| } else { | |
| return false; | |
| } | |
| }, | |
| hasWon: function(turn) { | |
| if ( | |
| (moves[0] == turn && moves[1] == turn && moves[2] == turn) || | |
| (moves[3] == turn && moves[4] == turn && moves[5] == turn) || | |
| (moves[6] == turn && moves[7] == turn && moves[8] == turn) || | |
| (moves[0] == turn && moves[3] == turn && moves[6] == turn) || | |
| (moves[1] == turn && moves[4] == turn && moves[7] == turn) || | |
| (moves[2] == turn && moves[5] == turn && moves[8] == turn) || | |
| (moves[0] == turn && moves[4] == turn && moves[8] == turn) || | |
| (moves[2] == turn && moves[4] == turn && moves[6] == turn) | |
| ) { | |
| return true; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| isCatsGame: function () { | |
| return this.getBoard().join('').length == 9 && this.getWinner() === false; | |
| }, | |
| isGameOver: function() { | |
| if (this.hasWon(0) || this.hasWon(1) || this.isCatsGame()) { | |
| return true; | |
| } | |
| }, | |
| move: function(x, y) { | |
| var num_slots = board.length; | |
| // check every slot to see if your mouse click matches a give areamap | |
| for (var i = 0; i < num_slots; i++) { | |
| // grab slot cordinates | |
| var x1 = board[i][0]; | |
| var y1 = board[i][1]; | |
| var x2 = board[i][2]; | |
| var y2 = board[i][3]; | |
| // check to see if slot is a valid move | |
| if ((x >= x1 && x <= x2 && y >= y1 && y <= y2) && moves[i] == undefined) { | |
| // store move | |
| moves[i] = turn; | |
| // generate position of text based on slot | |
| // offset is for text centering - based on font size | |
| var slot = board[i]; | |
| var offsetX = slot[0] + 50; | |
| var offsetY = slot[1] + 145; | |
| ctx.save(); | |
| ctx.font = '120px Futura, Helvetica, sans-serif'; | |
| ctx.lineCap = 'square'; | |
| ctx.lineWidth = 2; | |
| ctx.shadowBlur = 10; | |
| ctx.shadowColor = '#6C9380'; | |
| ctx.shadowOffsetX = 5; | |
| ctx.shadowOffsetY = 5; | |
| // change color based on turns | |
| if (turn == 0) { | |
| ctx.strokeStyle = '#F07C6C'; | |
| } else { | |
| ctx.strokeStyle = '#56626B'; | |
| } | |
| ctx.strokeText(String.fromCharCode(turns[turn]), offsetX, offsetY); | |
| ctx.restore(); | |
| if (turn == 1) { | |
| // add rain to turn 1 move - offset it to the text | |
| rain(offsetX + 10, offsetY - 8); | |
| } | |
| turn = (turn == 0) ? 1 : 0; // update turn | |
| } | |
| } | |
| }, | |
| restart: function() { | |
| shower = false; | |
| setTimeout(function() { | |
| ctx.save(); | |
| ctx.fillStyle = '#FFFFFF'; | |
| ctx.fillRect(0, 0, width, height); | |
| ctx.restore(); | |
| drawBoard(); | |
| // reset instance variables | |
| turn = 0; | |
| moves = []; | |
| shower = true; | |
| }, 300); | |
| } | |
| }; | |
| }()); | |
| $(function() { | |
| $('#game').on('click', function(event) { | |
| var element = $(this), | |
| eoffset = $(this).offset(), | |
| x = event.pageX - eoffset.left, | |
| y = event.pageY - eoffset.top; | |
| // if game is not over - let the player move | |
| if (!TTT.isGameOver()) { | |
| TTT.move(x, y); | |
| var winner = TTT.getWinner(), | |
| is_cats_game = TTT.isCatsGame(); | |
| if (winner !== false || is_cats_game === true) { | |
| var body = $('body'), | |
| msg; | |
| if (is_cats_game === true) { | |
| msg = 'Cats Game!'; | |
| } else { | |
| msg = 'Player ' + winner + ' has won!'; | |
| } | |
| body.append($('<h1 class="title">' + msg + '</h1>')); | |
| body.append($('<input type="button" class="reset" value="Reset Game">')); | |
| $('.reset').on('click', function() { | |
| TTT.restart(); | |
| $('h1.title').remove(); | |
| $(this).remove(); | |
| }); | |
| } | |
| } else { | |
| return false; | |
| } | |
| }); | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| body | |
| { | |
| padding: 100px 0; | |
| } | |
| #game | |
| { | |
| cursor: pointer; | |
| display: block; | |
| margin: 0 auto; | |
| position: relative; | |
| } | |
| h1.title | |
| { | |
| color: #404040; | |
| font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
| text-align: center; | |
| } | |
| input.reset | |
| { | |
| display: block; | |
| height: 35px; | |
| margin: 0px auto; | |
| width: 90px; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment