after running a lint + format

This commit is contained in:
Adam Piontek 2022-09-07 08:49:25 -04:00
parent 1a47184c29
commit 2b2e1ec0c9
4 changed files with 131 additions and 111 deletions

View file

@ -8,5 +8,5 @@ module.exports = {
node: true, node: true,
mocha: true, mocha: true,
}, },
extends: ["eslint:recommended", "prettier"] extends: ["eslint:recommended", "prettier"],
}; };

View file

@ -1,4 +1,5 @@
# javascript-tri-peaks-solitaire-solver # javascript-tri-peaks-solitaire-solver
A brute force solver for Microsoft Tri-Peaks solitaire written in javascript. A brute force solver for Microsoft Tri-Peaks solitaire written in javascript.
You can see it in action on my [website](https://igniparoustempest.github.io/tri-peaks-solitaire-solver/): You can see it in action on my [website](https://igniparoustempest.github.io/tri-peaks-solitaire-solver/):
@ -10,4 +11,3 @@ You can see it in action on my [website](https://igniparoustempest.github.io/tri
## Notes ## Notes
This is probably quite a poor implementation. Please don't fault me, I am teaching myself javascript. This is probably quite a poor implementation. Please don't fault me, I am teaching myself javascript.

View file

@ -18,7 +18,10 @@ class Card {
* @returns {boolean} True if sequential, false otherwise. * @returns {boolean} True if sequential, false otherwise.
*/ */
isSequential(card) { isSequential(card) {
return (this.integerValue + 1) % 13 === card.integerValue || (this.integerValue - 1) % 13 === card.integerValue; return (
(this.integerValue + 1) % 13 === card.integerValue ||
(this.integerValue - 1) % 13 === card.integerValue
);
} }
get toString() { get toString() {
@ -33,8 +36,7 @@ class Pyramid {
get isCleared() { get isCleared() {
for (let i = 0; i < this.array.length; i++) { for (let i = 0; i < this.array.length; i++) {
if (this.array[i] !== 0) if (this.array[i] !== 0) return false;
return false;
} }
return true; return true;
} }
@ -42,20 +44,33 @@ class Pyramid {
get freeCardIndices() { get freeCardIndices() {
let freeIndices = []; let freeIndices = [];
for (let i = this.array.length - 1; i >= 0; i--) { for (let i = this.array.length - 1; i >= 0; i--) {
if (this.array[i] === 0) if (this.array[i] === 0) continue;
continue;
const secondOffset = Math.floor((i - 3) / 2); const secondOffset = Math.floor((i - 3) / 2);
// This is the last row // This is the last row
if (i >= 18) if (i >= 18) freeIndices.push(i);
freeIndices.push(i);
// Third row // Third row
else if (i <= 17 && i >= 9 && this.array[i + 9] === 0 && this.array[i + 10] === 0) else if (
i <= 17 &&
i >= 9 &&
this.array[i + 9] === 0 &&
this.array[i + 10] === 0
)
freeIndices.push(i); freeIndices.push(i);
// Second row // Second row
else if (i <= 8 && i >= 3 && this.array[i + 6 + secondOffset] === 0 && this.array[i + 7 + secondOffset] === 0) else if (
i <= 8 &&
i >= 3 &&
this.array[i + 6 + secondOffset] === 0 &&
this.array[i + 7 + secondOffset] === 0
)
freeIndices.push(i); freeIndices.push(i);
// First row // First row
else if (i <= 2 && i >= 0 && this.array[i + 3 + i] === 0 && this.array[i + 4 + i] === 0) else if (
i <= 2 &&
i >= 0 &&
this.array[i + 3 + i] === 0 &&
this.array[i + 4 + i] === 0
)
freeIndices.push(i); freeIndices.push(i);
} }
return freeIndices; return freeIndices;
@ -63,13 +78,21 @@ class Pyramid {
} }
class MoveString { class MoveString {
static gameWon() {return "You have won.";} static gameWon() {
static gameLost() {return "There are no more valid moves.";} return "You have won.";
static match(cardA) {return "Move " + cardA + " onto the stock.";} }
static flipStock() {return "Draw a new stock card.";} static gameLost() {
return "There are no more valid moves.";
}
static match(cardA) {
return "Move " + cardA + " onto the stock.";
}
static flipStock() {
return "Draw a new stock card.";
}
} }
const GameStates = Object.freeze({"won": true, "lost": false}); const GameStates = Object.freeze({ won: true, lost: false });
/** /**
* Solves a Tri Peaks solitaire game. * Solves a Tri Peaks solitaire game.
@ -101,8 +124,7 @@ function solve(pyramidArray, stockArray, stockIndex = 0, moveArray = []) {
// match free cards with stock // match free cards with stock
for (let i = 0; i < freeCardsIndices.length; i++) { for (let i = 0; i < freeCardsIndices.length; i++) {
let cardA = new Card(pyramidArray[freeCardsIndices[i]]); let cardA = new Card(pyramidArray[freeCardsIndices[i]]);
if (!cardA.isSequential(topStock)) if (!cardA.isSequential(topStock)) continue;
continue;
let newStock = JSON.parse(JSON.stringify(stockArray)); let newStock = JSON.parse(JSON.stringify(stockArray));
newStock.splice(stockIndex + 1, 0, cardA.toString); newStock.splice(stockIndex + 1, 0, cardA.toString);
stockIndex++; stockIndex++;
@ -114,16 +136,14 @@ function solve(pyramidArray, stockArray, stockIndex = 0, moveArray = []) {
newPyramidArray[freeCardsIndices[i]] = 0; newPyramidArray[freeCardsIndices[i]] = 0;
let result = solve(newPyramidArray, newStock, stockIndex, newMoveArray); let result = solve(newPyramidArray, newStock, stockIndex, newMoveArray);
if (result[0] === GameStates.won) if (result[0] === GameStates.won) return result;
return result;
} }
// Flip over a new card // Flip over a new card
newMoveArray = JSON.parse(JSON.stringify(moveArray)); newMoveArray = JSON.parse(JSON.stringify(moveArray));
newMoveArray.push(MoveString.flipStock()); newMoveArray.push(MoveString.flipStock());
let result = solve(pyramidArray, stockArray, stockIndex + 1, newMoveArray); let result = solve(pyramidArray, stockArray, stockIndex + 1, newMoveArray);
if (result[0] === GameStates.won) if (result[0] === GameStates.won) return result;
return result;
// This node was useless // This node was useless
return [GameStates.lost, moveArray]; return [GameStates.lost, moveArray];

10
test.js
View file

@ -1,15 +1,15 @@
const assert = require('assert'); const assert = require("assert");
const solver = require('./solver'); const solver = require("./solver");
const solvable_games = [ const solvable_games = [
"8S TS 4D 7S 5D 7C 2D JH AC 3S 2H 3H 9H KC QC TD 8D 9C 7H 9D JS QS 4H 5C 5S 4C 2C QD 8C KD 3D KS JD 2S 7D KH AH 5H 9S 4S QH 6S 6D 3C JC TC 8H 6C TH AS AD 6H", "8S TS 4D 7S 5D 7C 2D JH AC 3S 2H 3H 9H KC QC TD 8D 9C 7H 9D JS QS 4H 5C 5S 4C 2C QD 8C KD 3D KS JD 2S 7D KH AH 5H 9S 4S QH 6S 6D 3C JC TC 8H 6C TH AS AD 6H",
"5D 9C 5S QS 8S 9D AS 5C 2S QD KC 9H 4H QC 2H 8D 4C 4D JC TS 6D 7H QH 3S 5H JH 6H 2D AC 7S 7C 3D KD 9S 3C TH 6C AH 8H TC 4S 8C AD 3H KS 6S JS 7D JD TD 2C KH" "5D 9C 5S QS 8S 9D AS 5C 2S QD KC 9H 4H QC 2H 8D 4C 4D JC TS 6D 7H QH 3S 5H JH 6H 2D AC 7S 7C 3D KD 9S 3C TH 6C AH 8H TC 4S 8C AD 3H KS 6S JS 7D JD TD 2C KH",
]; ];
it('should solve known games', () => { it("should solve known games", () => {
assert.equal(true, true); assert.equal(true, true);
solvable_games.forEach(function (i) { solvable_games.forEach(function (i) {
const array = i.split(' '); const array = i.split(" ");
const result = solver.solve(array.slice(0, 28), array.slice(28, 52), 0, []); const result = solver.solve(array.slice(0, 28), array.slice(28, 52), 0, []);
assert.equal(result[0], true); assert.equal(result[0], true);
}); });