working ios game

This commit is contained in:
2026-05-01 09:21:43 -04:00
commit 89b2e779f5
17 changed files with 2892 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
import XCTest
@testable import Shikaku
final class ShikakuCoreTests: XCTestCase {
func testGeneratedPuzzlesAreCoveredAndValidated() throws {
let cases: [(size: Int, seeds: ClosedRange<UInt64>)] = [
(5, 1...20),
(7, 1...20),
(10, 1...5),
(15, 1...5),
(20, 1...2),
(25, 1...2)
]
for testCase in cases {
for seed in testCase.seeds {
let size = testCase.size
let puzzle = try ShikakuGenerator.generate(size: size, seed: seed)
var covered: Set<GridPoint> = []
XCTAssertEqual(puzzle.size, size)
XCTAssertEqual(puzzle.clues.count, puzzle.solution.count)
for rect in puzzle.solution {
XCTAssertGreaterThanOrEqual(rect.area, 2)
for cell in rect.cells {
XCTAssertTrue((0..<size).contains(cell.row))
XCTAssertTrue((0..<size).contains(cell.col))
XCTAssertTrue(covered.insert(cell).inserted, "Cell \(cell) was covered more than once")
}
let cluesInside = rect.cells.compactMap { puzzle.clues[$0] }
XCTAssertEqual(cluesInside, [rect.area])
}
XCTAssertEqual(covered.count, size * size)
let playerRects = puzzle.solution.map {
PlayerRect(
startRow: $0.row,
startCol: $0.col,
endRow: $0.row + $0.height - 1,
endCol: $0.col + $0.width - 1
)
}
let validation = ShikakuValidation.verify(size: size, playerRects: playerRects, clues: puzzle.clues)
XCTAssertTrue(validation.isSolved)
}
}
}
func testSeededGenerationIsRepeatable() throws {
let first = try ShikakuGenerator.generate(size: 10, seed: 123_456_789)
let second = try ShikakuGenerator.generate(size: 10, seed: 123_456_789)
XCTAssertEqual(first.seed, second.seed)
XCTAssertEqual(first.clues, second.clues)
XCTAssertEqual(first.solution, second.solution)
}
func testValidationRejectsOverlappingRectangles() {
let clues = [
GridPoint(row: 0, col: 0): 2,
GridPoint(row: 1, col: 1): 2
]
let playerRects = [
PlayerRect(startRow: 0, startCol: 0, endRow: 0, endCol: 1),
PlayerRect(startRow: 0, startCol: 1, endRow: 1, endCol: 1)
]
let validation = ShikakuValidation.verify(size: 2, playerRects: playerRects, clues: clues)
XCTAssertFalse(validation.isSolved)
XCTAssertEqual(validation.message, "Cells overlap between two rectangles")
}
@MainActor
func testPlacingARectangleRemovesOverlappingPlayerRects() {
let game = ShikakuGame(size: 5)
game.placeRect(PlayerRect(startRow: 0, startCol: 0, endRow: 0, endCol: 1))
game.placeRect(PlayerRect(startRow: 0, startCol: 1, endRow: 1, endCol: 1))
XCTAssertEqual(game.playerRects.count, 1)
XCTAssertTrue(game.playerRects[0].contains(GridPoint(row: 0, col: 1)))
XCTAssertTrue(game.playerRects[0].contains(GridPoint(row: 1, col: 1)))
}
@MainActor
func testSingleCellPlacementIsRejected() {
let game = ShikakuGame(size: 5)
game.placeRect(PlayerRect(startRow: 0, startCol: 0, endRow: 0, endCol: 0))
XCTAssertTrue(game.playerRects.isEmpty)
XCTAssertEqual(game.message, "Drag over at least 2 cells")
}
@MainActor
func testGameCanStartFromRequestedSeed() {
let game = ShikakuGame(size: 5)
game.newPuzzle(seed: 987_654_321)
XCTAssertEqual(game.currentSeed, 987_654_321)
XCTAssertEqual(game.size, 5)
XCTAssertTrue(game.playerRects.isEmpty)
}
func testValidationAcceptsKnownSolution() {
let clues = [
GridPoint(row: 0, col: 0): 2,
GridPoint(row: 1, col: 0): 2
]
let playerRects = [
PlayerRect(startRow: 0, startCol: 0, endRow: 0, endCol: 1),
PlayerRect(startRow: 1, startCol: 0, endRow: 1, endCol: 1)
]
let validation = ShikakuValidation.verify(size: 2, playerRects: playerRects, clues: clues)
XCTAssertTrue(validation.isSolved)
}
}