Example #1
0
//////////////////////////////
// "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;
}
Example #2
0
/////////////////////////////
// "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;
}
Example #3
0
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;
}