Files
swiftGrammar/AIGrammar/Models/PuzzleGenerator.swift
2025-07-21 19:23:17 +08:00

113 lines
3.8 KiB
Swift

//
// PuzzleGenerator.swift
// AIGrammar
//
// Created by oscar on 2025/7/21.
//
import Foundation
import SwiftUI
class PuzzleGenerator {
private(set) var validationWords: Set<String> = []
private(set) var puzzleWords: [String] = []
init() {
//loadValidationWords()
//loadPuzzleWords()
validationWords = Set(loadWords(from: "wordlist"))
puzzleWords = loadWords(from: "puzzle")
}
///
private func loadWords(from fileName: String) -> [String] {
if let url = Bundle.main.url(forResource: fileName, withExtension: "txt") {
do {
let content = try String(contentsOf: url)
let words = content
.components(separatedBy: .newlines)
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() }
.filter { !$0.isEmpty }
logger.info("Loaded \(words.count) words from \(fileName).txt")
return words
} catch {
logger.warning("Failed to load \(fileName).txt: \(error)")
}
} else {
logger.warning("\(fileName).txt not found!")
}
return []
}
///
private func loadValidationWords() {
if let url = Bundle.main.url(forResource: "wordlist", withExtension: "txt") {
do {
let content = try String(contentsOf: url)
validationWords = Set(content
.components(separatedBy: .newlines)
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() }
.filter { !$0.isEmpty })
logger.info("Loaded validation words: \(validationWords.count)")
} catch {
logger.warning("Failed to load wordlist.txt: \(error)")
}
}
}
///
private func loadPuzzleWords() {
if let url = Bundle.main.url(forResource: "puzzle", withExtension: "txt") {
do {
let content = try String(contentsOf: url)
puzzleWords = content
.components(separatedBy: .newlines)
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() }
.filter { !$0.isEmpty }
logger.info("Loaded puzzle words: \(puzzleWords.count)")
} catch {
logger.warning("Failed to load puzzle.txt: \(error)")
}
}
}
///
func generatePuzzle() -> (Set<String>, [[String]]) {
var chosenWords: Set<String> = []
var uniqueLetters: Set<Character> = []
while (uniqueLetters.count < 16 && chosenWords.count < 6) || chosenWords.count < 4 {
if let word = puzzleWords.randomElement() {
chosenWords.insert(word)
uniqueLetters.formUnion(word)
}
}
// 16
var selectedLetters = Array(uniqueLetters)
let alphabet = Array("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
while selectedLetters.count < 16 {
let randomLetter = alphabet.randomElement()!
if !selectedLetters.contains(randomLetter) {
selectedLetters.append(randomLetter)
}
}
let shuffledLetters = selectedLetters.shuffled()
var letters: [[String]] = Array(repeating: Array(repeating: "", count: 4), count: 4)
for i in 0..<4 {
for j in 0..<4 {
letters[i][j] = String(shuffledLetters[i * 4 + j])
}
}
return (chosenWords, letters)
}
///
func validate(word: String) -> Bool {
validationWords.contains(word.uppercased())
}
}