From ef464ae4d8906114d7f79ac4b7cac7fb72c46b41 Mon Sep 17 00:00:00 2001 From: Craig Copeland Date: Thu, 24 Aug 2017 05:39:07 -0500 Subject: [PATCH 1/4] Initial push. Controlling turns. Added message. --- 07week/ticTacToe/script.js | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/07week/ticTacToe/script.js b/07week/ticTacToe/script.js index d0bc4bd52..0ced0dd1c 100644 --- a/07week/ticTacToe/script.js +++ b/07week/ticTacToe/script.js @@ -1,28 +1,48 @@ 'use strict'; class TicTacToe extends React.Component { + constructor(props) { super(props); + this.state = { + turn: 'X', + }; + this.message = ''; } + handleClick=(cell)=>{ + const state = {...this.state}; + const // this.state.turn? 'X' : 'O'; + if (!state[cell]) { + state[cell] = this.state.turn; + state['turn'] = this.state.turn === 'X'? 'O' : 'X'; // Switch between X and O + this.message = ''; + } else { + this.message = 'Square occupied. Please select a different square'; + } + // toggleTurn(); + // this.state.turn? 'X' : 'O'; + this.setState(state) + }; render() { return (
-
-
-
+
this.handleClick('cell0')}>{this.state.cell0}
+
this.handleClick('cell1')}>{this.state.cell1}
+
this.handleClick('cell2')}>{this.state.cell2}
-
-
-
+
this.handleClick('cell3')}>{this.state.cell3}
+
this.handleClick('cell4')}>{this.state.cell4}
+
this.handleClick('cell5')}>{this.state.cell5}
-
-
-
+
this.handleClick('cell6')}>{this.state.cell6}
+
this.handleClick('cell7')}>{this.state.cell7}
+
this.handleClick('cell8')}>{this.state.cell8}
+
{this.message}
); } From cf0a06e0b88e0d3054d6c796ce508f9590bf8691 Mon Sep 17 00:00:00 2001 From: Craig Copeland Date: Sun, 27 Aug 2017 12:38:42 -0500 Subject: [PATCH 2/4] Ability to click and control stacks internally via object of 3 arrays. --- 07week/towersOfHanoi/script.js | 118 +++++++++++++++++++++++++++++++-- 07week/towersOfHanoi/style.css | 17 +++-- 2 files changed, 123 insertions(+), 12 deletions(-) diff --git a/07week/towersOfHanoi/script.js b/07week/towersOfHanoi/script.js index 9b156e880..12d647e4c 100644 --- a/07week/towersOfHanoi/script.js +++ b/07week/towersOfHanoi/script.js @@ -1,22 +1,128 @@ 'use strict'; +/****************** WHITE BOARD NOTES ********************** +// Given: the board, stacks and blocks. Board Display. +// +// create object with 3 arrays? +// +// Click on a block (and stack) +// Test for popped block. +// If popped block then +// If validMove() then +// *** Comparing last block in current stack, test +// movePiece() +// if checkForWin() then +// Announce winner! +// else +// Continue playing the game. +// else +// alert user, 'Cannot move larger block onto smaller one' +// end if +// else +// If !popOffBlock() then +// alert user, 'select a stack with a block' +// End if +// +// validMove(sourceStack, targetStack) // the tests expect this function to take in 2 values. +// if source stack array.last < target stack array.last then +// return true +// end if +// return false +// +// movePiece() +// target stack array.push(source stack array.pop) +// return +// +// checkForWin() +// if b.array.length === 4 || c.array.length === 4 then +// return true +// end if +// return false +// +// popOffBlock(sourceStack) +// if sourceStack > 0 // has blocks +// Pop off top block. +// return true; +// else +// return false; +// end if + +***********************************************************/ class TowersOfHanoi extends React.Component { constructor(props) { super(props); + this.state = { + stacks: { + 1: [100,75,50,25], + 2: [], + 3: [] + }, + popped: { + stack: null, + block: null + } + } + } // Constructor + + popOffBlock(stacks, sKey, popped) { + // popped + console.log('in popOffBlock'); + popped['stack'] = sKey; + popped['block'] = stacks[sKey][stacks[sKey].length-1]; + return popped; + } + + handleClick(sKey) { + // Creating an exact copy of stacks... one that is not by reference. + const stacks = {1:[],2:[],3:[]}; + stacks[1] = this.state.stacks[1].slice(); + stacks[2] = this.state.stacks[2].slice(); + stacks[3] = this.state.stacks[3].slice(); + let popped = {stack:null,block:null}; + popped['stack'] = this.state.popped['stack']; + popped['block'] = this.state.popped['block']; + console.log('popped before change', popped); + if (popped['block']) { //block was already popped. Now I want to push block + // if (sKey) { + // console.log('you clicked on me: '+ sKey); + // } + // else { + // console.log('you clicked on nothing'); + // } + popped['stack'] = null; + popped['block'] = null; + + // No block was popped. Therefore, we are clicking stack to pop a + // block off. Let's make sure stack has blocks to pop off. + } else if (stacks[sKey].length > 0) { // Ok, no block was popped + console.log('stacks length', stacks[sKey].length); + popped = this.popOffBlock(stacks, sKey, popped); + console.log('popped after', popped); + // No popped block. User click empty stack. Tell User + // he is a complete dolt. + } else { + console.log('Please select a stack with blocks.'); + } + this.setState({stacks: stacks, popped: popped,}); + } + + checkForWin() { + console.log('in checkForWin'); } render() { + // let block; return (
-
+
this.handleClick(1)}>
-
-
-
+
+
+
-
+
this.handleClick(2)}>
-
+
this.handleClick(3)}>
); diff --git a/07week/towersOfHanoi/style.css b/07week/towersOfHanoi/style.css index 2fc698923..8096709e4 100644 --- a/07week/towersOfHanoi/style.css +++ b/07week/towersOfHanoi/style.css @@ -1,34 +1,39 @@ -[data-stack] { +#towers-of-hanoi { + display: flex; + + } + [data-stack] { display: flex; justify-content: flex-start; align-items: center; height: 101px; background-color: aliceblue; margin: 25px; + flex-direction: column-reverse; } [data-block] { - width: 25px; + height: 25px; float: left; } [data-block="25"] { - height: 25px; + width: 25px; background-color: blue; } [data-block="50"] { - height: 50px; + width: 50px; background-color: green; } [data-block="75"] { - height: 75px; + width: 75px; background-color: red; } [data-block="100"] { - height: 100px; + width: 100px; background-color: yellow; } From 871696b31bcbbdc76559daa59dd8894b436f9db1 Mon Sep 17 00:00:00 2001 From: Craig Copeland Date: Sun, 27 Aug 2017 22:03:44 -0500 Subject: [PATCH 3/4] TOH react COMPLETE! It is broken up more React like with components, leveraging state, and passing values through props. Need to run through linter though. --- 07week/towersOfHanoi/Block.js | 11 +++ 07week/towersOfHanoi/Pop.js | 9 ++ 07week/towersOfHanoi/Stack.js | 25 ++++++ 07week/towersOfHanoi/index.html | 5 ++ 07week/towersOfHanoi/script.js | 142 ++++++++++++++++++++------------ 07week/towersOfHanoi/style.css | 16 +++- 6 files changed, 153 insertions(+), 55 deletions(-) create mode 100644 07week/towersOfHanoi/Block.js create mode 100644 07week/towersOfHanoi/Pop.js create mode 100644 07week/towersOfHanoi/Stack.js diff --git a/07week/towersOfHanoi/Block.js b/07week/towersOfHanoi/Block.js new file mode 100644 index 000000000..fdb3a8e3a --- /dev/null +++ b/07week/towersOfHanoi/Block.js @@ -0,0 +1,11 @@ +// import React from 'react'; + +// This functional component renders a block. We pass the size +// of the block in props. +const Block = (props) => { + return ( +
+ ); +}; + +// export default Block; diff --git a/07week/towersOfHanoi/Pop.js b/07week/towersOfHanoi/Pop.js new file mode 100644 index 000000000..fad743029 --- /dev/null +++ b/07week/towersOfHanoi/Pop.js @@ -0,0 +1,9 @@ +// This functional component renders the Popped block line. +const Pop = (props) => { + return ( +
+
Popped Block: 
+
+
+ ); +}; diff --git a/07week/towersOfHanoi/Stack.js b/07week/towersOfHanoi/Stack.js new file mode 100644 index 000000000..ffaa6a5e9 --- /dev/null +++ b/07week/towersOfHanoi/Stack.js @@ -0,0 +1,25 @@ +// import React from 'react'; +// import Block from './Block.js'; + +// This functional component renders the Stacks. It uses an array map to display +// all the blocks assigned in stacks arrays. +const Stack = (props) => { + + const updateMe = () => props.click(props.id); + + return ( +
+ { + props.blocks.map((blockSize,index) => + + ) + } +
+ ); + +}; + +// export default Stack; diff --git a/07week/towersOfHanoi/index.html b/07week/towersOfHanoi/index.html index 37d057527..9955c4445 100644 --- a/07week/towersOfHanoi/index.html +++ b/07week/towersOfHanoi/index.html @@ -10,6 +10,11 @@ + + + + + diff --git a/07week/towersOfHanoi/script.js b/07week/towersOfHanoi/script.js index 12d647e4c..e685a9081 100644 --- a/07week/towersOfHanoi/script.js +++ b/07week/towersOfHanoi/script.js @@ -5,7 +5,9 @@ // // create object with 3 arrays? // -// Click on a block (and stack) +// Create functional components: Stack and Block +// +// Click on a stack // Test for popped block. // If popped block then // If validMove() then @@ -48,85 +50,117 @@ // end if ***********************************************************/ + +// Main driver class. class TowersOfHanoi extends React.Component { - constructor(props) { - super(props); + constructor() { + super(); + const startArr = [100,75,50,25]; + const winCount = startArr.length; this.state = { - stacks: { - 1: [100,75,50,25], - 2: [], - 3: [] + stacks: { // My stacks object has 3 arrays for each stack + 1: startArr.slice(), // a place to store the popped block and the + 2: [], // winning count. + 3: [], + popped: null, + winCount: winCount }, - popped: { - stack: null, - block: null - } + message: '', // message used to display messages to the user. + youWon: false // Used to shut game down after win. } } // Constructor - popOffBlock(stacks, sKey, popped) { - // popped - console.log('in popOffBlock'); - popped['stack'] = sKey; - popped['block'] = stacks[sKey][stacks[sKey].length-1]; - return popped; + // Need to ensure player is not placing a larger block on top of a smaller one. + validMove(popped, stack) { + if (stack.length === 0 || popped < stack[stack.length - 1]) { + return true; + } + return false; } + // Check for a win. If stack 2 or 3 has all the blocks, then WIN. + checkForWin(stacks) { + // console.log('in checkForWin'); + // console.log('Win criteria',stacks.winCount, stacks[2].length, stacks[3].length); + if (stacks[2].length === stacks.winCount || stacks[3].length === stacks.winCount) { + return true; + } + return false; + } // checkForWin() + + // All the TOH logic is in here. handleClick(sKey) { + console.log('In handleClick!'); // Creating an exact copy of stacks... one that is not by reference. - const stacks = {1:[],2:[],3:[]}; + const stacks = {1:[],2:[],3:[],popped:null,winCount:null}; stacks[1] = this.state.stacks[1].slice(); stacks[2] = this.state.stacks[2].slice(); stacks[3] = this.state.stacks[3].slice(); - let popped = {stack:null,block:null}; - popped['stack'] = this.state.popped['stack']; - popped['block'] = this.state.popped['block']; - console.log('popped before change', popped); - if (popped['block']) { //block was already popped. Now I want to push block - // if (sKey) { - // console.log('you clicked on me: '+ sKey); - // } - // else { - // console.log('you clicked on nothing'); - // } - popped['stack'] = null; - popped['block'] = null; + stacks['popped'] = this.state.stacks['popped']; + stacks['winCount'] = this.state.stacks['winCount']; - // No block was popped. Therefore, we are clicking stack to pop a - // block off. Let's make sure stack has blocks to pop off. - } else if (stacks[sKey].length > 0) { // Ok, no block was popped - console.log('stacks length', stacks[sKey].length); - popped = this.popOffBlock(stacks, sKey, popped); - console.log('popped after', popped); - // No popped block. User click empty stack. Tell User - // he is a complete dolt. - } else { - console.log('Please select a stack with blocks.'); + let message = this.state.message; + let youWon = this.state.youWon; + + if(stacks['popped']) { // We have a popped block. Need to push block + if (this.validMove(stacks['popped'], stacks[sKey])) { + stacks[sKey].push(stacks['popped']); + stacks['popped'] = null; + message = ''; + if (this.checkForWin(stacks) && !youWon) { + message = 'Congratulations, you solved Towers of Hanoi!'; + youWon = true; + this.setState({stacks: stacks, message: message, youWon: youWon}); + } + } else { + message = 'Invalid move. Cannot place larger block on smaller one'; + } + } else { // We need to pop a block off the selected stack. + if (stacks[sKey].length > 0) { + stacks['popped'] = stacks[sKey].pop(); + message = ''; + } else { + message = 'You selected an empty stack. Please try again.'; + } } - this.setState({stacks: stacks, popped: popped,}); - } + youWon? null : this.setState({stacks: stacks, message: message, youWon: youWon}); - checkForWin() { - console.log('in checkForWin'); - } + } // handleClick() + // This is the main display for the game. I display a Stack object. + // The stack objects display the block objects. render() { - // let block; return (
-
this.handleClick(1)}> -
-
-
-
+
+

Towers of Hanoi by Craig... React version!

+
-
this.handleClick(2)}> +
+ + +
-
this.handleClick(3)}> +
+

{this.state.message}

+
); } } +// Rendering TowersOfHanoi class within div id=towers-of-hanoi ReactDOM.render(, document.getElementById('towers-of-hanoi')); diff --git a/07week/towersOfHanoi/style.css b/07week/towersOfHanoi/style.css index 8096709e4..6dad59966 100644 --- a/07week/towersOfHanoi/style.css +++ b/07week/towersOfHanoi/style.css @@ -1,12 +1,26 @@ #towers-of-hanoi { display: flex; + font-family: Arial; + } + +#board { + display: flex; } + +#pop { + display: flex; + flex-wrap: nowrap; + justify-content: center; + height: 30px; + align-items: center; +} [data-stack] { display: flex; justify-content: flex-start; align-items: center; - height: 101px; + height: 150px; + width: 200px; background-color: aliceblue; margin: 25px; flex-direction: column-reverse; From 772112e67b9e83e3ab35f65404ef8d832e3c2a07 Mon Sep 17 00:00:00 2001 From: Craig Copeland Date: Tue, 29 Aug 2017 19:10:57 -0500 Subject: [PATCH 4/4] moving click code directly to stack element --- 07week/towersOfHanoi/Stack.js | 7 +++++-- 07week/towersOfHanoi/script.js | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/07week/towersOfHanoi/Stack.js b/07week/towersOfHanoi/Stack.js index ffaa6a5e9..e088f8327 100644 --- a/07week/towersOfHanoi/Stack.js +++ b/07week/towersOfHanoi/Stack.js @@ -5,10 +5,13 @@ // all the blocks assigned in stacks arrays. const Stack = (props) => { - const updateMe = () => props.click(props.id); + // const updateMe = ; return ( -
+
props.handleStackClick(props.id)} + > { props.blocks.map((blockSize,index) =>