mirror of
https://github.com/tiennm99/pikachu.git
synced 2026-08-10 16:22:28 +00:00
fix: Z-pattern logic, eliminate code duplication, fix tests
- Fix Z-pattern to use proper 2-turn path (H-V-H and V-H-V scanning) instead of single midpoint which only duplicated L-pattern behavior - Eliminate ~390 lines of duplicated pattern-matching code from PikachuGame.js by delegating to PikachuGameLogic via shared board ref - Fix removeCards to reset type=0 so pattern matching works after removal - Fix Jest config: remove invalid preset, add ESM support for Windows - Rename log.js to log.cjs for CommonJS compatibility with ESM project - Fix test expectations to account for pattern priority and border routing
This commit is contained in:
@@ -2,77 +2,77 @@ import { PikachuBaseTest } from '../base/PikachuBaseTest.js';
|
||||
|
||||
describe('Z-Pattern Tests', () => {
|
||||
let tester;
|
||||
|
||||
|
||||
beforeEach(() => {
|
||||
tester = new PikachuBaseTest();
|
||||
});
|
||||
|
||||
describe('Basic Z-Shapes', () => {
|
||||
test('should connect cards through intermediate point', () => {
|
||||
test('should connect cards through two turns', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 1, 1);
|
||||
tester.placeCard(matrix, 3, 3, 1);
|
||||
// Block L-pattern possibilities
|
||||
// Block L-pattern corners
|
||||
tester.placeCard(matrix, 1, 3, 2);
|
||||
tester.placeCard(matrix, 3, 1, 2);
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Basic Z-pattern with intermediate point',
|
||||
'Basic Z-pattern with two turns',
|
||||
matrix,
|
||||
1, 1, 3, 3,
|
||||
true,
|
||||
'Z-pattern'
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
|
||||
test('should find multiple possible intermediate points', () => {
|
||||
test('should find path with distant cards', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 1, 1);
|
||||
tester.placeCard(matrix, 5, 5, 1);
|
||||
// Block L-pattern possibilities
|
||||
// Block L-pattern corners
|
||||
tester.placeCard(matrix, 1, 5, 2);
|
||||
tester.placeCard(matrix, 5, 1, 2);
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Z-pattern with multiple intermediate points',
|
||||
'Z-pattern with distant cards',
|
||||
matrix,
|
||||
1, 1, 5, 5,
|
||||
true,
|
||||
'Z-pattern'
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
|
||||
test('should work with intermediate point at border', () => {
|
||||
test('should work with connecting column between cards', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 2, 2, 1);
|
||||
tester.placeCard(matrix, 4, 4, 1);
|
||||
// Block L-pattern possibilities
|
||||
// Block L-pattern corners
|
||||
tester.placeCard(matrix, 2, 4, 2);
|
||||
tester.placeCard(matrix, 4, 2, 2);
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Z-pattern with border intermediate point',
|
||||
'Z-pattern with connecting column',
|
||||
matrix,
|
||||
2, 2, 4, 4,
|
||||
true,
|
||||
'Z-pattern'
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Blocked Scenarios', () => {
|
||||
test('should fail when no intermediate point is available', () => {
|
||||
test('should fail when no path is available', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 1, 1);
|
||||
tester.placeCard(matrix, 3, 3, 1);
|
||||
|
||||
// Block all possible intermediate points
|
||||
|
||||
// Block all possible paths
|
||||
for (let row = 1; row <= 8; row++) {
|
||||
for (let col = 1; col <= 20; col++) {
|
||||
if (!((row === 1 && col === 1) || (row === 3 && col === 3))) {
|
||||
@@ -80,35 +80,35 @@ describe('Z-Pattern Tests', () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Z-pattern blocked - no intermediate point',
|
||||
'Z-pattern blocked - no path available',
|
||||
matrix,
|
||||
1, 1, 3, 3,
|
||||
false
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
|
||||
test('should fail when paths to intermediate point are blocked', () => {
|
||||
test('should fail when all connecting columns and rows are blocked', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 1, 1);
|
||||
tester.placeCard(matrix, 3, 3, 1);
|
||||
|
||||
// Block paths to potential intermediate points
|
||||
|
||||
// Block paths to potential connecting points
|
||||
tester.placeCard(matrix, 1, 2, 2);
|
||||
tester.placeCard(matrix, 2, 1, 2);
|
||||
tester.placeCard(matrix, 2, 3, 2);
|
||||
tester.placeCard(matrix, 3, 2, 2);
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Z-pattern blocked - paths to intermediate blocked',
|
||||
'Z-pattern blocked - connecting paths blocked',
|
||||
matrix,
|
||||
1, 1, 3, 3,
|
||||
false
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
});
|
||||
@@ -118,10 +118,10 @@ describe('Z-Pattern Tests', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 1, 1);
|
||||
tester.placeCard(matrix, 8, 20, 1);
|
||||
// Block simpler patterns
|
||||
// Block L-pattern corners
|
||||
tester.placeCard(matrix, 1, 20, 2);
|
||||
tester.placeCard(matrix, 8, 1, 2);
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Z-pattern at board edges',
|
||||
matrix,
|
||||
@@ -129,74 +129,74 @@ describe('Z-Pattern Tests', () => {
|
||||
true,
|
||||
'Z-pattern'
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
|
||||
test('should handle Z-pattern along board boundaries', () => {
|
||||
test('should handle Z-pattern with same-row cards and blocker', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 2, 1);
|
||||
tester.placeCard(matrix, 1, 8, 1);
|
||||
// Block direct horizontal path
|
||||
tester.placeCard(matrix, 1, 5, 2);
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Z-pattern along board boundary',
|
||||
'Z-pattern with same-row cards',
|
||||
matrix,
|
||||
1, 2, 1, 8,
|
||||
true,
|
||||
'Z-pattern'
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Complex Intermediate Points', () => {
|
||||
test('should use specific intermediate point', () => {
|
||||
describe('Complex Connecting Points', () => {
|
||||
test('should use specific connecting column', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 2, 2, 1);
|
||||
tester.placeCard(matrix, 6, 6, 1);
|
||||
// Block L-pattern possibilities
|
||||
// Block L-pattern corners
|
||||
tester.placeCard(matrix, 2, 6, 2);
|
||||
tester.placeCard(matrix, 6, 2, 2);
|
||||
// Ensure intermediate point at (4,4) is available
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Z-pattern with specific intermediate point',
|
||||
'Z-pattern with specific connecting column',
|
||||
matrix,
|
||||
2, 2, 6, 6,
|
||||
true,
|
||||
'Z-pattern'
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
|
||||
test('should work in dense board with limited intermediate points', () => {
|
||||
test('should work in dense board with limited paths', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 1, 1);
|
||||
tester.placeCard(matrix, 4, 4, 1);
|
||||
|
||||
// Fill most of the board but leave some Z-pattern paths
|
||||
tester.placeCard(matrix, 2, 2, 1);
|
||||
tester.placeCard(matrix, 5, 5, 1);
|
||||
|
||||
// Fill most of the board but leave a Z-pattern corridor through col 3:
|
||||
// (2,2) -> (2,3) -> (5,3) -> (5,5)
|
||||
for (let row = 1; row <= 8; row++) {
|
||||
for (let col = 1; col <= 20; col++) {
|
||||
if (!((row === 1 && col === 1) || (row === 4 && col === 4) ||
|
||||
(row === 1 && col === 4) || (row === 4 && col === 1) ||
|
||||
(row === 2 && col === 2) || (row === 3 && col === 3))) {
|
||||
if (!((row === 2 && col === 2) || (row === 5 && col === 5) ||
|
||||
(row === 2 && col === 3) || (row === 5 && col === 3) ||
|
||||
(row === 3 && col === 3) || (row === 4 && col === 3) ||
|
||||
(row === 5 && col === 4))) {
|
||||
tester.placeCard(matrix, row, col, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Z-pattern in dense board',
|
||||
matrix,
|
||||
1, 1, 4, 4,
|
||||
2, 2, 5, 5,
|
||||
true,
|
||||
'Z-pattern'
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
});
|
||||
@@ -204,37 +204,35 @@ describe('Z-Pattern Tests', () => {
|
||||
describe('Same Row/Column Scenarios', () => {
|
||||
test('should handle Z-pattern with cards in same row', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 1, 1);
|
||||
tester.placeCard(matrix, 1, 10, 1);
|
||||
tester.placeCard(matrix, 4, 1, 1);
|
||||
tester.placeCard(matrix, 4, 10, 1);
|
||||
// Block direct horizontal path
|
||||
tester.placeCard(matrix, 1, 5, 2);
|
||||
|
||||
tester.placeCard(matrix, 4, 5, 2);
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Z-pattern with cards in same row',
|
||||
matrix,
|
||||
1, 1, 1, 10,
|
||||
true,
|
||||
'Z-pattern'
|
||||
4, 1, 4, 10,
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
|
||||
test('should handle Z-pattern with cards in same column', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 1, 1);
|
||||
tester.placeCard(matrix, 6, 1, 1);
|
||||
tester.placeCard(matrix, 1, 5, 1);
|
||||
tester.placeCard(matrix, 6, 5, 1);
|
||||
// Block direct vertical path
|
||||
tester.placeCard(matrix, 3, 1, 2);
|
||||
|
||||
tester.placeCard(matrix, 3, 5, 2);
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Z-pattern with cards in same column',
|
||||
matrix,
|
||||
1, 1, 6, 1,
|
||||
true,
|
||||
'Z-pattern'
|
||||
1, 5, 6, 5,
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
});
|
||||
@@ -244,7 +242,7 @@ describe('Z-Pattern Tests', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 1, 1);
|
||||
tester.placeCard(matrix, 1, 5, 1);
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Should prefer I-pattern over Z-pattern',
|
||||
matrix,
|
||||
@@ -252,7 +250,7 @@ describe('Z-Pattern Tests', () => {
|
||||
true,
|
||||
'I-pattern'
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
|
||||
@@ -260,7 +258,7 @@ describe('Z-Pattern Tests', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 1, 1);
|
||||
tester.placeCard(matrix, 3, 3, 1);
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Should prefer L-pattern over Z-pattern',
|
||||
matrix,
|
||||
@@ -268,7 +266,7 @@ describe('Z-Pattern Tests', () => {
|
||||
true,
|
||||
'L-pattern'
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
|
||||
@@ -276,11 +274,10 @@ describe('Z-Pattern Tests', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 1, 1);
|
||||
tester.placeCard(matrix, 3, 3, 1);
|
||||
// Block I-pattern (not applicable)
|
||||
// Block L-pattern corners
|
||||
tester.placeCard(matrix, 1, 3, 2);
|
||||
tester.placeCard(matrix, 3, 1, 2);
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Should use Z-pattern when L-pattern blocked',
|
||||
matrix,
|
||||
@@ -288,7 +285,7 @@ describe('Z-Pattern Tests', () => {
|
||||
true,
|
||||
'Z-pattern'
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
});
|
||||
@@ -301,7 +298,7 @@ describe('Z-Pattern Tests', () => {
|
||||
// Block L-pattern paths
|
||||
tester.placeCard(matrix, 1, 7, 2);
|
||||
tester.placeCard(matrix, 5, 1, 2);
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Z-pattern with two distinct turns',
|
||||
matrix,
|
||||
@@ -309,26 +306,26 @@ describe('Z-Pattern Tests', () => {
|
||||
true,
|
||||
'Z-pattern'
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
|
||||
test('should handle Z-pattern with intermediate point far from both cards', () => {
|
||||
test('should handle Z-pattern across full board', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 1, 1);
|
||||
tester.placeCard(matrix, 8, 20, 1);
|
||||
// Block other patterns by placing strategic obstacles
|
||||
// Block L-pattern corners
|
||||
tester.placeCard(matrix, 1, 20, 2);
|
||||
tester.placeCard(matrix, 8, 1, 2);
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Z-pattern with distant intermediate point',
|
||||
'Z-pattern across full board',
|
||||
matrix,
|
||||
1, 1, 8, 20,
|
||||
true,
|
||||
'Z-pattern'
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
});
|
||||
@@ -341,7 +338,7 @@ describe('Z-Pattern Tests', () => {
|
||||
// Block L-pattern
|
||||
tester.placeCard(matrix, 2, 8, 2);
|
||||
tester.placeCard(matrix, 6, 3, 2);
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Asymmetric Z-pattern',
|
||||
matrix,
|
||||
@@ -349,7 +346,7 @@ describe('Z-Pattern Tests', () => {
|
||||
true,
|
||||
'Z-pattern'
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
|
||||
@@ -357,10 +354,10 @@ describe('Z-Pattern Tests', () => {
|
||||
const matrix = tester.createEmptyMatrix();
|
||||
tester.placeCard(matrix, 1, 5, 1);
|
||||
tester.placeCard(matrix, 7, 15, 1);
|
||||
// Block other patterns
|
||||
// Block L-pattern corners
|
||||
tester.placeCard(matrix, 1, 15, 2);
|
||||
tester.placeCard(matrix, 7, 5, 2);
|
||||
|
||||
|
||||
const testCase = tester.createTestCase(
|
||||
'Z-pattern with varying distances',
|
||||
matrix,
|
||||
@@ -368,8 +365,8 @@ describe('Z-Pattern Tests', () => {
|
||||
true,
|
||||
'Z-pattern'
|
||||
);
|
||||
|
||||
|
||||
tester.expectTestCase(testCase);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user