public void SetFillReason(int slotIndex, int value, FillReason reason)
    {
        _targetSlotIndex = slotIndex;

        SudokuUtility.ConvertToIndex(slotIndex, out int rowIndex, out int columnIndex, out int _);
        _text.text = string.Format("Solution {0} found at Row {1}, Column {2} by {3} method",
                                   value, rowIndex, columnIndex, GetReasonString(reason), slotIndex);
    }
Exemple #2
0
    private async void OnSudokuDataInputChanged()
    {
        if (SudokuUtility.IsSudokuDataComplete(_sData))
        {
            _isResolving = false;

            UIWindowCongratulations window = await UIWindowManager.Instance.GetWindow(SystemDefine.UI_WINDOW_NAME_CONGRATULATIONS) as UIWindowCongratulations;

            await window.Show(true, true);

            window.PlayAnimation();
        }
    }
Exemple #3
0
    private bool TryToFindNextStep()
    {
        _sData.Update();
        SolutionInfo solution = SudokuUtility.FindSolution(_sData);

        if (solution != null)
        {
            FillSolutionIntoSlot(solution.SlotData.SlotIndex, solution.Value, solution.Reason);
            return(true);
        }

        return(false);
    }
    public bool FillAllSolution()
    {
        if (!IsSolvable())
        {
            return(false);
        }

        while (this.HasEmptySlot())
        {
            SolutionInfo solution = SudokuUtility.FindSolution(this);
            SetSlotValueAndReason(solution.SlotData.SlotIndex, solution.Value, FillReason.PlayerInput);
            Update();
        }

        return(true);
    }
Exemple #5
0
        /// <summary>
        /// per ogni cella, rimuove tra gli AllowableValues i valori già presenti nella colonna
        /// </summary>
        /// <param name="game"></param>
        /// <returns>'true' se ha operato almeno un'azione</returns>
        protected bool useColumnConstraint(SudokuGame game)
        {
            bool atLeastOneOperation = false;

            for (int colIndex = 0; colIndex < game.GameMatrix.Count; ++colIndex)
            {
                List <SudokuCell> column = SudokuUtility.getMatrixSubSpace(game, new MatrixCoords {
                    TopologyType = SpaceType.COLUMN, COLUMN = colIndex
                });
                bool atLeastOneOperationInColumn = false;
                atLeastOneOperationInColumn = useConstraintOnGenericSpace(column);

                atLeastOneOperation |= atLeastOneOperationInColumn;
            }

            return(atLeastOneOperation);
        }
Exemple #6
0
        /// <summary>
        /// per ogni cella, rimuove tra gli AllowableValues i valori già presenti nella riga
        /// </summary>
        /// <param name="game"></param>
        /// <returns>'true' se ha operato almeno un'azione</returns>
        protected bool useRowConstraint(SudokuGame game)
        {
            bool atLeastOneOperation = false;

            for (int rowIndex = 0; rowIndex < game.GameMatrix.Count; ++rowIndex)
            {
                List <SudokuCell> row = SudokuUtility.getMatrixSubSpace(game, new MatrixCoords {
                    TopologyType = SpaceType.ROW, ROW = rowIndex
                });
                bool atLeastOneOperationInRow = false;
                atLeastOneOperationInRow = useConstraintOnGenericSpace(row);

                atLeastOneOperation |= atLeastOneOperationInRow;
            }

            return(atLeastOneOperation);
        }
    public bool IsSolvable()
    {
        SudokuData cloneData = GetClone();

        cloneData.Update();

        while (cloneData.HasEmptySlot())
        {
            SolutionInfo solution = SudokuUtility.FindSolution(cloneData);
            if (solution == null)
            {
                return(false);
            }

            cloneData.SetSlotValueAndReason(solution.SlotData.SlotIndex, solution.Value, FillReason.None);
            cloneData.Update();
        }

        return(true);
    }
Exemple #8
0
        /// <summary>
        /// per ogni cella, rimuove tra gli AllowableValues i valori già presenti nel rispettivo box
        /// </summary>
        /// <param name="game"></param>
        /// <returns>'true' se ha operato almeno un'azione</returns>
        protected bool useBoxConstraint(SudokuGame game)
        {
            bool atLeastOneOperation = false;

            for (int boxRowIndex = 0; boxRowIndex < SudokuUtility.DEFAULT_OUTERBOX_SIZE; ++boxRowIndex)
            {
                for (int boxColIndex = 0; boxColIndex < SudokuUtility.DEFAULT_OUTERBOX_SIZE; ++boxColIndex)
                {
                    List <SudokuCell> box = SudokuUtility.getMatrixSubSpace(game, new MatrixCoords
                    {
                        TopologyType = SpaceType.BOX,
                        ROW          = boxRowIndex * 3,
                        COLUMN       = boxColIndex * 3
                    });
                    bool atLeastOneOperationInBox = false;
                    atLeastOneOperationInBox = useConstraintOnGenericSpace(box);

                    atLeastOneOperation |= atLeastOneOperationInBox;
                }
            }

            return(atLeastOneOperation);
        }
 public void RefreshDisplay()
 {
     _textValue.color = SudokuUtility.GetFillReasonColor(_reason);
     _textValue.text  = _value == 0 ? string.Empty : string.Format("{0}", _value);
 }
    public void SetSlotValueAndReason(int rowIndex, int columnIndex, int value, FillReason reason)
    {
        int slotIndex = SudokuUtility.ConvertToSlotIndex(rowIndex, columnIndex);

        SetSlotValueAndReason(slotIndex, value, reason);
    }
    public SlotData GetSlotData(int rowIndex, int columnIndex)
    {
        int slotIndex = SudokuUtility.ConvertToSlotIndex(rowIndex, columnIndex);

        return(GetSlotData(slotIndex));
    }
    public static SolutionInfo FindByExclusion(SudokuData sData)
    {
        /////////////////////////////////////////////////////////
        // Method : 排除法, 已填了數字的欄位,                 //
        //          與該數字同行同列的位置不會再出現同樣的數字 //
        /////////////////////////////////////////////////////////

        // 需要建立該數字已出現在那行那列的資料
        // 檢查 1 ~ 9, 在每個九宮格中的 "可能出現位置" 是不是只剩下一個 ?
        for (int i = 0; i < PUZZLE_LENGTH; i++)
        {
            // For 1 ~ 9
            int checkNumber = i + 1;

            // NOTE: 若某一個數字在一個九宮格的可能出現欄位在同一行 or 列上
            //       則可以視為此行 or 列必定有一個該數字, 進而排除其他欄位
            bool       recheck    = true;
            List <int> tempRow    = new List <int>();
            List <int> tempColumn = new List <int>();

            while (recheck)
            {
                recheck = false;
                for (int squareIndex = 0; squareIndex < PUZZLE_LENGTH; squareIndex++)
                {
                    // For 每一個九宮格
                    if (SudokuUtility.IsNumberContainedInSquare(sData, checkNumber, squareIndex))
                    {
                        continue;
                    }

                    // For 九宮格裡的每一小格
                    List <SlotData> fillableSlot     = new List <SlotData>();
                    int             squareStartIndex = (squareIndex % SQUARE_LENGTH) * SQUARE_LENGTH + (squareIndex / SQUARE_LENGTH) * PUZZLE_LENGTH * SQUARE_LENGTH;         // 該九宮格的起始點(左上)的 Slot 的 Index, 用 0 ~ 80 表示
                    for (int j = 0; j < PUZZLE_LENGTH; j++)
                    {
                        int      slotIndex = squareStartIndex + (j % SQUARE_LENGTH) + ((j / SQUARE_LENGTH) * PUZZLE_LENGTH);                    // 該九宮格的目標點位置, 用 0 ~ 80 表示
                        SlotData slotData  = sData.SlotDataList[slotIndex];
                        if (slotData.Value != 0)
                        {
                            continue;
                        }

                        if (IsNumberContainedInRow(sData, checkNumber, slotData.RowIndex))
                        {
                            continue;
                        }

                        if (tempRow.Contains(slotData.RowIndex))
                        {
                            continue;
                        }

                        if (IsNumberContainedInColumn(sData, checkNumber, slotData.ColumnIndex))
                        {
                            continue;
                        }

                        if (tempColumn.Contains(slotData.ColumnIndex))
                        {
                            continue;
                        }

                        fillableSlot.Add(slotData);
                    }

                    if (fillableSlot.Count == 0)
                    {
                        // Do nothing
                    }
                    else if (fillableSlot.Count == 1)
                    {
                        return(new SolutionInfo {
                            SlotData = fillableSlot[0], Reason = FillReason.SlotExclude, Value = checkNumber
                        });
                    }
                    else
                    {
                        if (SudokuUtility.IsSlotSameRow(fillableSlot))
                        {
                            // 若這些候補 Slot 位置剛好在同一行上
                            tempRow.Add(fillableSlot[0].RowIndex);
                            recheck = true;
                        }
                        else if (SudokuUtility.IsSlotSameColumn(fillableSlot))
                        {
                            // 若這些候補 Slot 位置剛好在同一列上
                            tempColumn.Add(fillableSlot[0].ColumnIndex);
                            recheck = true;
                        }
                    }
                }
            }
        }

        return(null);
    }
Exemple #13
0
    private void FillSolutionIntoSlot(int slotIndex, int value, FillReason reason)
    {
        SudokuUtility.ConvertToIndex(slotIndex, out int rowIndex, out int columnIndex, out int _);

        FillSolutionIntoSlot(rowIndex, columnIndex, value, reason);
    }