////////// Exercice 1 ////////// function node(_val, _children) { return { val: _val, children: _children }; } function val(tree) { return tree['val']; } function children(tree) { return tree['children']; } function leaf(_val) { return node(_val, []); } // Displays a state `s` function stateDisp(s) { return `----- |${s[0]}${s[1]}${s[2]}| |${s[3]}${s[4]}${s[5]}| |${s[6]}${s[7]}${s[8]}| -----`; } let aState = [ 'x', ' ', 'o', 'x', 'o', ' ', 'x', ' ', ' ' ]; console.log(`A state :\n${stateDisp(aState)}`); stateEmptySlots([ 'x', ' ', 'o', 'x', 'o', ' ', 'x', ' ', ' ' ]); // -> [ 1, 5, 7, 8 ] stateNexts(['x', 'o', 'x', ' ', ' ', ' ', 'x', 'o', 'x'], 'x'); // -> [ [ 'x', 'o', 'x', 'x', ' ', ' ', 'x', 'o', 'x' ], // [ 'x', 'o', 'x', ' ', 'x', ' ', 'x', 'o', 'x' ], // [ 'x', 'o', 'x', ' ', ' ', 'x', 'x', 'o', 'x' ] ] ////////// Exercice 2 ////////// // Displays a tree `root`. The `dispFun` parameter is optional, // but if provided is used to display the values in the tree. function treeDisp(root, dispFun) { function treeDispIndent(root, indent) { let valString = dispFun ? dispFun(root.val) : root.val; if (isFrozen(root)) { let winString = (root.winner) ? `, winner: '${root.winner}'` : ''; console.log(`${indent}{ val: ${valString}${winString} }`); } else { console.log(`${indent}{`); let winString = (root.winner) ? `, winner: '${root.winner}'` : ''; console.log(`${indent} val: ${valString}${winString}`); console.log(`${indent} children: [`); root.children.forEach((child) => treeDispIndent(child, indent + ' ')); console.log(`${indent} ],`); console.log(`${indent}}`); } }; treeDispIndent(root, ""); } function node(aVal, someChildren) { return { val: aVal, children: someChildren }; } function isFrozen(node) { return typeof node.children === 'function'; } let frozenTree = node("root", () => [ node("1st son", []), node("2nd son", []) ]); function treeThawAtDepth(root, depth) { if (depth === 0) return; else { if (isFrozen(root)) nodeThaw(root); root.children.forEach((child) => treeThawAtDepth(child, depth-1)); } } ////////// Exercice 3 ////////// // Returns ' ' if the game is not won, 'x' or 'o' if there is a // winner, 'D' in a draw, and '?' if both players have won. function stateWinner(s) { function lines(s) { return [0,1,2].map((i) => s.slice(3*i,3*i+3)); } function cols(s) { return [0,1,2].map((i) => [s[i], s[i+3], s[i+6]]); } function diags(s) { return [[s[0], s[4], s[8]], [s[2], s[4], s[6]]]; } function allEqual(arr) { return arr.every( v => v === arr[0] ); } const allLines = lines(s).concat(cols(s)).concat(diags(s)); const winLines = allLines .filter((l) => allEqual(l)) .map((l) => l[0]) .filter((e) => e !== ' '); if (winLines.length === 0) { if (stateEmptySlots(s).length === 0) return 'D'; else return ' '; } else if (allEqual(winLines)) return winLines[0]; else return '?'; } // Predicate telling if the state `s` corresponds to the end of // a game or not (either one player won, or the game is a draw). function stateIsFinal(s) { const possibleWinner = stateWinner(s); return (possibleWinner === 'o' || possibleWinner === 'x' || possibleWinner === 'D'); }