//checks for boxes with only 1 possible input public ErrorLogger checkBSP(ref bool madeChange) { ErrorLogger RV = new ErrorLogger(); bool noChange = false; List<short> curList = new List<short>(); while (!noChange) { noChange = true; for (int i = 0; i < 81; i++) { if (numBoxes[i].getValue() == 0) { curList.Clear(); curList.AddRange(numBoxes[i].getPV()); if (curList.Count == 1) { RV = RV + insertNum(numBoxes[i], curList[0]); Console.WriteLine("Single Box Insert: " + i.ToString() + " inserting value: " + curList[0].ToString()); noChange = false; madeChange = true; } else if (curList.Count == 0) { RV = RV + new ErrorLogger(-1, "Box " + i + " has no possible values"); } } if (RV.hasError()) break; } if (RV.hasError()) break; } return RV; }
private ErrorLogger insertNum(NumBox NB, short val) { //this value insertion verifies that it is not inserting a conflict value //colors boxes red if a conflict occurs //updates all validNumbers for pertinent boxes ErrorLogger RV = new ErrorLogger(); RV = RV + checkStruct(val, NBRows[NB.getRow()]); //if (RV!= 0) return RV; RV = RV + checkStruct(val, NBColumns[NB.getColumn()]); //if (RV!= 0) return RV; RV = RV + checkStruct(val, NBBOX[NB.getBox()]); //if (RV != 0) return RV; if(NB.getID() == 44) val = val; //if code makes it here, there are no conflicts, add value to box NB.setValue(val); valueArray[NB.getID()] = val; if (NB.getID() == 38) val = val; if (!RV.hasError()) { foreach (NumBox NBt in NBRows[NB.getRow()]) { NBt.removePotentialValue(val); if (NBt.getID() == 44) val = val; } foreach (NumBox NBt in NBColumns[NB.getColumn()]) { NBt.removePotentialValue(val); } foreach (NumBox NBt in NBBOX[NB.getBox()]) { NBt.removePotentialValue(val); } } else { Console.WriteLine("Skipped removing potential vals"); } return RV; }
private ErrorLogger checkStruct(short val, NumBox[] NBStruct) { ErrorLogger RV = new ErrorLogger(); //if a value exists, remove it from the rest of the row foreach (NumBox NBInner in NBStruct) { //checks if attempting to remove a po if (val == NBInner.getValue()) { RV = RV + new ErrorLogger(1, "checkStruct failed: BOXID: " + NBInner.getID()+ " value: " + val); NBInner.setTBcolor(Color.Red); } if (RV.hasError()) break; } return RV; }
private ErrorLogger checkBoardValidity() { ErrorLogger RV = new ErrorLogger(); string[] cuNums = new string[81]; for (int i = 0; i < 81; i++) { cuNums[i] = numBoxes[i].getTBText(); } RV = RV + resetBoxes(); if (RV.hasError()) return RV; for (int i = 0; i < 81; i++) { numBoxes[i].setTBText(cuNums[i]); } RV = RV + sanitizeInputs(); if (RV.hasError()) return RV; //indicates a bad input solution RV = RV + colorBoxes(); if (RV.hasError()) return RV; //unknown error during box coloring RV = RV + validateInstance(); if (RV.hasError()) return RV; //invalid instance detected return RV; }
public ErrorLogger solve(ref bool foundSolution) { /* * This call is recursive, or will create new boards * */ ErrorLogger RV = new ErrorLogger(); RV = checkBoardValidity(); if (RV.hasError()) return RV; //if program has made it this far, problem is valid Console.WriteLine("----BEGIN SOLVE-----"); bool madeChange = true; while (madeChange) { madeChange = false; RV = levelOneTests(ref madeChange); if (RV.hasError() ) break; if (madeChange) continue; //don't bother with level two unless level one made no changes RV = levelTwoTests(ref madeChange); if (RV.hasError()) break; if (madeChange) continue; //don't bother with level two unless level one made no changes } if (checkForSolution()) { if (!RV.hasError()) { foundSolution = true; RV = RV + new ErrorLogger(this); } } else { //if code enters here it could not find a solution, it should make a guess and call solve again if (!RV.hasError()) { RV = RV + makeGuesses(ref foundSolution); if (foundSolution) { if (RV.hasBoard()) { short[] tArray = RV.getBoard().getArray(); //fills in correct board for (int i = 0; i < 81; i++) { if (numBoxes[i].getValue() == 0) { insertNum(numBoxes[i], tArray[i]); } } } } } } return RV; }
//checks for rows where a val can only go to a single box public ErrorLogger checkRCB(NumBox[][] NBstruct,ref bool madeChange) { ErrorLogger RV = new ErrorLogger(); NumBox[] boxArray; bool noChange = false; while (!noChange) { noChange = true; List<short> PVs = new List<short>(); for (int i = 0; i < 9; i++) //does for each row { short[] occuranceCount = new short[9]; for (int j = 0; j < 9; j++) occuranceCount[j] = 0; boxArray = NBstruct[i]; foreach (NumBox NB in boxArray) //counts the occurances of each potential value in the struct { if (NB.getID() == 44) PVs = PVs; PVs.Clear(); PVs.AddRange(NB.getPV()); for (int j = 0; j < PVs.Count; j++) { int T = PVs[j]; occuranceCount[T - 1] = (short)(occuranceCount[T - 1] + 1); } } for (short j = 0; j < 9; j++) { if (occuranceCount[j] == 1) //if there are any instances of a value being possible in only one spot, it is placed { foreach (NumBox NB in boxArray) { if (NB.getID() == 44) PVs = PVs; PVs.Clear(); PVs.AddRange(NB.getPV()); if(PVs.Contains((short)(j+1))) { for (int k = 0; k < PVs.Count; k++) { occuranceCount[j] = (short)(occuranceCount[j] - 1); } RV = RV + insertNum(NB,(short)(j + 1)); Console.WriteLine("RCB Insert: " + NB.getID() + " inserting value: " + (j + 1).ToString()); madeChange = true; noChange = false; } if (RV.hasError()) break; } } if (RV.hasError()) break; } if (RV.hasError()) break; } if (RV.hasError()) break; } return RV; }