////////////////////////////// // "Subgroup exclusion" // Jos isossa laatikossa olevat kaikki mahdolliset paikat ovat samassa vaaka- tai pystyrivissä, // estä ko. numeroiden asettaminen ko. riville muissa isoissa ruuduissa // JA // Jos samalla vaaka- tai pystyrivillä olevat mahdollisuudet ovat kaikki samassa isossa laatikossa, // estä ko. numeroiden asettaminen ko. ison laatikon muihin kohtiin. ////////////////////////////// bool Solver::SubgroupExclusion() { for (int number = 1; number <= MAX; number++) { for (int set = 0; set < MAX*3; set++) { // Hae setissä olevat mahdollisuudet numerolle Set mahdollisuudet = sets[set].GetPossibilitiesFor(number); if (mahdollisuudet.Filled() > 1 && mahdollisuudet.Filled() <= max) { // Käsiteltävänä iso ruutu if (set < MAX*2) { // Varmista että kaikki mahdollisuudet ovat ison ruudun sisällä if ( mahdollisuudet.LocationsOverlap( mahdollisuudet.GetSquare(0)->BigSquare() ) ) // Blockaa ruutuja update = mahdollisuudet.GetSquare(0)->BigSquare()->BlockAllExcluding(&mahdollisuudet,number) || update; } // Käsiteltävä vaaka- tai pystyrivi else if (set >= MAX*2) { if ( mahdollisuudet.LocationsOverlap( mahdollisuudet.GetSquare(0)->HLine() ) ) update = mahdollisuudet.GetSquare(0)->HLine()->BlockAllExcluding( mahdollisuudet.GetSquare(0)->BigSquare(), number ) || update; else if ( mahdollisuudet.LocationsOverlap( mahdollisuudet.GetSquare(0)->VLine() ) ) update = mahdollisuudet.GetSquare(0)->VLine()->BlockAllExcluding( mahdollisuudet.GetSquare(0)->BigSquare(), number ) || update; } } } } return update; }
///////////////////////////// // "Single possibility in set" // Jos numerolla vain yksi mahdollinen paikka setissä, laita numero siihen //////////////////////////// bool Solver::SinglePossibilityInSet() { if (easyMode) return false; for (int number = 1; number <= MAX; number++) { for (int set = 0; set < MAX*3; set++) { // Hae setissä olevat mahdollisuudet numerolle Set mahdollisuudet = sets[set].GetPossibilitiesFor(number); if (!easyMode) { if (mahdollisuudet.Filled() == 1) { mahdollisuudet.GetSquare(0)->PlaceNum(number); update = true; if (drawNumCallback != NULL) (*drawNumCallback)(mahdollisuudet.GetSquare(0)->GetID(), number); } } } } return update; }
bool Solver::XWingAndSwordfish() { for (int number = 1; number <= MAX; number++) { // Käydään läpi vain vaaka- ja pystyriveille (ei isoille neliöille) for (int i = 0; i <= 1; i++) { // Varataan tilaa ainoastaan riveille, // joilla on numerolle enemmän kuin 1 paikka ja vähemmän kuin 9 paikkaa (2-8) int NumberOfBondedSets[MAX-2]; Set BondedSets[MAX-2][MAX]; for (int y = 0; y < MAX-2; y++) NumberOfBondedSets[y] = 0; // Tehdään mahdollisten paikkojen mukaan taulukko, // josta voidaan etsiä onko mahdolliset ruudut samoilla vaaka- tai pystyriveillä for (int set = 0; set < MAX; set++) { Set tmpSet = sets[i*MAX + set].GetPossibilitiesFor(number); int section = tmpSet.Filled()-2; if (section >= 0 && section < MAX-2) { BondedSets[ section ][ NumberOfBondedSets [ section ] ] = tmpSet; NumberOfBondedSets [ section ]++; } } ////////////////////// // X-Wing /////////////////////// for (int y = 0; y < MAX-2; y++) { if (NumberOfBondedSets[y] == y+2) { // mahdollisuuksia rivillä yhtä monta kuin rivejä bool lineV; bool lineH; if (i == 0) { lineV = true; lineH = false; } else { lineV = false; lineH = true; } // Selvitetään kumman tyyppisen linjan ruudut muodostavat (jos muodostavat) for (int set = 1; set < NumberOfBondedSets[y]; set++) { if (i == 0 && !BondedSets[y][0].LocationsLine(&BondedSets[y][set],false)) { lineV = false; break; } else if (i == 1 && !BondedSets[y][0].LocationsLine(&BondedSets[y][set],true )) { lineH = false; break; } } if (lineV || lineH) { for (int square = 0; square < NumberOfBondedSets[y]; square++) { Set lineToBlock; if (lineV) lineToBlock = BondedSets[y][0].GetSquare(square)->VLine()->GetPossibilitiesFor(number); else lineToBlock = BondedSets[y][0].GetSquare(square)->HLine()->GetPossibilitiesFor(number); // Tarkistetaan onko rivillä blockattavaa if (lineToBlock.Filled() > NumberOfBondedSets[y]) { for (int bSquare = 0; bSquare < lineToBlock.Filled(); bSquare++) { // Älä blockkaa riviltä ruutuja, jotka muodostivat X-Wingin bool needsBlocking = true; for (int set = 0; set < NumberOfBondedSets[y]; set++) { if (lineToBlock.GetSquare(bSquare) == BondedSets[y][set].GetSquare(square)) { needsBlocking = false; break; } } if (needsBlocking) { update = lineToBlock.GetSquare(bSquare)->Block(number) || update; } } } } } } } /*if (update) { MessageBox("xwing",NULL,MB_OK); }*/ ///////////// // Swordfish (uses BondedSets initialized by X-Wing) ///////////// if (!update && NumberOfBondedSets[0] + NumberOfBondedSets[1] >= 3) { bool vertically; if (i == 0) vertically = true; else vertically = false; int sf_setsNum = NumberOfBondedSets[0] + NumberOfBondedSets[1]; Set** sf_sets = new Set*[sf_setsNum]; int k = 0; for (int j = 0; j < NumberOfBondedSets[0]; j++) { sf_sets[k] = &BondedSets[0][j]; k++; } for (int j = 0; j < NumberOfBondedSets[1]; j++) { sf_sets[k] = &BondedSets[1][j]; k++; } int set[3]; for (set[0] = 0; set[0] < sf_setsNum; set[0]++) { for (set[1] = 0; set[1] < sf_setsNum; set[1]++) { if (set[0] != set[1]) { Set used = Set(); // linkityksessä käytetyt ruudut if ( sf_sets[set[0]]->LinksWith( sf_sets[set[1]], vertically, &used ) ) { for (set[2] = 0; set[2] < sf_setsNum; set[2]++) { if (set[2] != set[0] && set[2] != set[1]) { Set used_tmp = used; if (sf_sets[set[2]]->LinksWith( sf_sets[set[0]], vertically, &used_tmp ) && sf_sets[set[2]]->LinksWith( sf_sets[set[1]], vertically, &used_tmp ) ) { // tarkista että settien kaikki ruudut ovat mukana linkissä if (used_tmp.Filled() == sf_sets[set[0]]->Filled() + sf_sets[set[1]]->Filled() + sf_sets[set[2]]->Filled()) { // swordfish found, start restricting... for (int j = 0; j < 3; j++) { for (int k = 0; k < sf_sets[set[j]]->Filled(); k++) { if (vertically) { update = sf_sets[set[j]]->GetSquare(k)->VLine()->BlockAllExcluding(&used_tmp,number) || update; } else { update = sf_sets[set[j]]->GetSquare(k)->HLine()->BlockAllExcluding(&used_tmp,number) || update; } } } } } } } } } } } delete [] sf_sets; /*if (update) MessageBox("swordfish",NULL,MB_OK); */ } ///////////////// } } return update; }