在Sudoku中解决裸体三重奏

时间:2010-06-10 22:11:58

标签: c# .net math sudoku

我希望我更加关注Uni的数学课程。 :)

如何为裸三元组实现此数学公式?

Naked Triples
取三个单元格C = {c1,c2,c3}共享一个单位U.取三个数字 N = {n1,n2,n3}。如果C中的每个单元格都有候选ci⊆N,那么我们可以删除所有单元格 ni∈N来自其他单元格。**

我有一个方法,它将一个单位(例如一个Box,一行或一列)作为参数。 该单元包含9个单元,因此我需要从框中一次比较3个单元的所有组合,或者将它们放入堆栈或集合中以进行进一步计算。

下一步将逐个采用这些3细胞组合,并将它们的候选物与3个数字进行比较。同样,这3个数字可以是1到9之间的任何可能组合。这就是我所需要的全部。

但我该怎么做?我会得到多少组合?我是否为单元格获得3 x 9 = 27种组合,然后对数字(N)进行相同的处理?

你如何在经典的C#循环中解决这个问题?没有Lambda表达,请我已经足够困惑了:))

代码: 为了在这里代表他们,我不得不缩短班级。

public class Cell : INotifyPropertyChanged
    {

public ObservableCollection<ObservableCollection<Candidate>> CandidateActual {...}

public int Id { ... }

//Position of the Cell inside a box if applicable
public int CellBoxPositionX { get; private set; }  
public int CellBoxPositionY { get; private set; }

//Position of the Cell inside the game board
public int CellBoardPositionX { get; private set; }
public int CellBoardPositionY { get; private set; }

//Position of the Box inside the game board
public int BoxPositionX { get; private set; }
public int BoxPositionY { get; private set; }

public int CountCandidates { ... }    
public int? Value { ...}

public Candidate this[int number]
        {
            get
            {
                if (number < 1 || number > PossibleValues.Count)
                {
                    throw new ArgumentOutOfRangeException("number", number, "Invalid Number Index");
                }

                switch (number)
                {
                    case 1:
                        return CandidateActual[0][0];
                    case 2:
                        return CandidateActual[0][1];
                    case 3:
                        return CandidateActual[0][2];
                    case 4:
                        return CandidateActual[1][0];
                    case 5:
                        return CandidateActual[1][1];
                    case 6:
                        return CandidateActual[1][2];
                    case 7:
                        return CandidateActual[2][0];
                    case 8:
                        return CandidateActual[2][1];
                    case 9:
                        return CandidateActual[2][2];
                    default:
                        return null;
                }
            }
        }
}

候选

public class Candidate : INotifyPropertyChanged
    {

        private int? _value;

        public int? Value { ... }

    }

箱:

public class Box : INotifyPropertyChanged
    {

public ObservableCollection<ObservableCollection<Cell>> BoxActual { ... }

public Cell this[int row, int column]
        {
            get
            {
                if(row < 0 || row >= BoxActual.Count)
                {
                    throw new ArgumentOutOfRangeException("row", row, "Invalid Row Index");
                }
                if(column < 0 || column >= BoxActual.Count)
                {
                    throw new ArgumentOutOfRangeException("column", column, "Invalid Column Index");
                }
                return BoxActual[row][column];
            }
        }
}

public class Board : INotifyPropertyChanged 
    {

 public ObservableCollection<ObservableCollection<Box>> GameBoard {...}

public Cell this[int boardRowPosition, int boardColumnPosition]
        {
            get
            {
                int totalSize = GameBoard.Count*GameBoard.Count();
                if (boardRowPosition < 0 || boardRowPosition >= totalSize) 
                    throw new ArgumentOutOfRangeException("boardRowPosition", boardRowPosition, "Invalid boardRowPosition index");
                if (boardColumnPosition < 0 || boardColumnPosition >= totalSize)
                    throw new ArgumentOutOfRangeException("boardColumnPosition", boardColumnPosition, "Invalid boardColumnPosition index");
                return
                    GameBoard[boardRowPosition/GameBoard.Count][boardColumnPosition/GameBoard.Count][
                        boardRowPosition%GameBoard.Count, boardColumnPosition%GameBoard.Count];
            }
        }



        public Box this[int boardRowPosition, int boardColumnPosition, bool b]
        {
            get
            {
                int totalSize = GameBoard.Count * GameBoard.Count();
                if (boardRowPosition < 0 || boardRowPosition >= totalSize)
                    throw new ArgumentOutOfRangeException("boardRowPosition", boardRowPosition, "Invalid boardRowPosition index");
                if (boardColumnPosition < 0 || boardColumnPosition >= totalSize)
                    throw new ArgumentOutOfRangeException("boardColumnPosition", boardColumnPosition, "Invalid boardColumnPosition index");
                return
                    GameBoard[boardRowPosition / GameBoard.Count][boardColumnPosition / GameBoard.Count];
            }
        }
}

非常感谢您的帮助,

1 个答案:

答案 0 :(得分:1)

Psuedo-Code算法;我的C有点生锈。

我建议您从候选值中找到所有可能的三位数组合。可以有6到504个这样的组合,取决于你有多少候选人(由n!/(3!*(n-3)!)给出。

对于每一个,循环浏览单元中的所有单元格,看看它们是否与没有任何数字的条件匹配。如果某个组合有三个或更多,那么你可以应用它。

combos = (array containing 3-long combination of candidates)
for each combo in combos                 # iterate through every combo
  matches = new array                    # initialize a blank array
  for each cell in unit
    if (cell does not contain candidates other than the ones in your current combo)
      matches.add(cell)                  # this is a match!
    end
  end

  if matches.size >= 3                   # naked triple found! (three matches for given combo)
    for each cell in unit
      if (cell is not in matches)
        (delete every candidate in current combo in this cell)
      end
    end
  end
  delete matches                         # clear up memory
end

希望这有帮助!如果你需要,我会给你这个代码;无论如何,我一直想要刷新我的C.

另外,如果您还不知道,使用不涉及任何逻辑手动编程的计算机解决数独游戏的方法要简单得多。但我认为你尝试这样做的方式非常高尚。


生成所有可能组合的数组

有很多方法可以做到这一点,可能有一个最好的方法;我自己没有做过任何认真的研究。我推荐谷歌:combination algorithm ...我实际上自己找到了one solution in C

请务必加入支票以确保您的候选人数量合适。对于n = 3,只有一种可能的候选组合,您的算法应该为您找到它。对于n = 1和n = 2,Naked Triples甚至不适用。