diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1117462 --- /dev/null +++ b/.gitignore @@ -0,0 +1,91 @@ +# WebStorm +.idea/ + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ diff --git a/package.json b/package.json new file mode 100644 index 0000000..ec95e04 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "javascript-pyramid-solitaire-solver", + "version": "1.0.0", + "description": "A brute force solver for pyramid solitaire written in javascript", + "main": "solver.js", + "scripts": { + "test": "mocha" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/IgniparousTempest/javascript-pyramid-solitaire-solver.git" + }, + "author": "Courtney Pitcher", + "license": "ISC", + "bugs": { + "url": "https://github.com/IgniparousTempest/javascript-pyramid-solitaire-solver/issues" + }, + "homepage": "https://github.com/IgniparousTempest/javascript-pyramid-solitaire-solver#readme", + "devDependencies": { + "mocha": "^6.2.0" + } +} diff --git a/solver.js b/solver.js index 04beb5e..68cae35 100644 --- a/solver.js +++ b/solver.js @@ -79,9 +79,18 @@ class MoveString { static resetStock() {return "Reset stock.";} } -const GameStates = Object.freeze({"won": 1, "lost": 2, "inProgress": 3}); +const GameStates = Object.freeze({"won": true, "lost": false}); -function solve(pyramidArray, stockArray, stockIndex, remainingStocks, moveArray) { +/** + * Solves a Pyramid solitaire game. + * @param pyramidArray The cards in the pyramid, starting in the top card. The cards are in left-to-right, then top-to-bottom order. + * @param stockArray The cards in the stock. + * @param stockIndex The index of the top stock card. + * @param remainingStocks The number of times the stock can be reset. + * @param moveArray The list of moves that have been made to get a deck in this configuration. + * @returns {*[]|[*, *]|[*, *]|[*, *]|[*, *]|*} + */ +function solve(pyramidArray, stockArray, stockIndex = 0, remainingStocks = 3, moveArray = []) { let newMoveArray = JSON.parse(JSON.stringify(moveArray)); let pyramid = new Pyramid(pyramidArray); @@ -197,5 +206,7 @@ function solve(pyramidArray, stockArray, stockIndex, remainingStocks, moveArray) } // This node was useless - return [GameStates.inProgress, moveArray]; + return [GameStates.lost, moveArray]; } + +exports.solve = solve; diff --git a/test.js b/test.js new file mode 100644 index 0000000..bf6b5a4 --- /dev/null +++ b/test.js @@ -0,0 +1,15 @@ +const assert = require('assert'); +const solver = require('./solver'); + +const solvable_games = [ + "4C 8C 6S 7H 4D 6C 8S JH 2S 8H 4H KC AS 6H KD 7D JS TH AH 8D 9D AD 9S QS 7S TC 2D 5C 2C 9C TD 5S QC AC KH 9H 3C 7C 3S 3H 2H JD 5H 4S 6D QD 3D KS QH JC TS 5D" +]; + +it('should solve known games', () => { + assert.equal(true, true); + solvable_games.forEach(function (i) { + const array = i.split(' '); + const result = solver.solve(array.slice(0, 28), array.slice(28, 52), 0, 3, []); + assert.equal(result[0], true); + }); +});