Пример #1
0
 public bool ColumnCheck(StartingValue sv)//проверка по столбцу
 {
     for (int i = 0; i < 9; i++)
     {
         if (fieldGen[sv.x, i] == sv.val)
         {
             return(false);
         }
     }
     return(true);
 }
Пример #2
0
 /*public bool GridCheck(int d)//проверка одного Grid, указывать порядковый номер в field
  * {
  *  bool[] check = new bool[9];
  *  object v;
  *
  *  for (int i = 0; i < 9; i++)
  *  {
  *      v = field[d].Rows[i / 3].Cells[i % 3].Value;
  *      if (v != null)
  *      {// value ВСЕГДА должен быть в промежутке 1..9
  *          if (!check[(int)v - 1])//массив check 0..8, а значение value 1..9
  *              check[(int)v - 1] = true;
  *          else
  *              return false;
  *      }
  *  }
  *  return true;
  * }*/
 public bool RowCheck(StartingValue sv)//проверка по строке
 {
     for (int j = 0; j < 9; j++)
     {
         if (fieldGen[j, sv.y] == sv.val)
         {
             return(false);
         }
     }
     return(true);
 }
Пример #3
0
 /*public bool NoDeadLockCheck(int x, int y)//проверка по строке, столбцу и квадрату, что в ячейку по коорд. x,y можно
  * {
  *  bool[] vals = new bool[10];
  *  vals[0] = true;
  *  for (int i = 0; i < x; i++)
  *  {
  *      if (fieldGen[i, y] != 0)
  *          vals[fieldGen[i, y]] = true;
  *  }
  *  for (int i = x; i < 9; i++)
  *  {
  *      if (fieldGen[i, y] != 0)
  *          vals[fieldGen[i, y]] = true;
  *  }
  *  for (int i = 0; i < y; i++)
  *  {
  *      if (fieldGen[x, i] != 0)
  *          vals[fieldGen[i, y]] = true;
  *  }
  *  for (int i = y; i < 9; i++)
  *  {
  *      if (fieldGen[x, i] != 0)
  *          vals[fieldGen[i, y]] = true;
  *  }
  *
  *  return true;
  * }*/
 public bool AreaCheck(StartingValue sv)//проверка одного района
 {
     for (int i = sv.y / 3 * 3; i < sv.y / 3 * 3 + 3; i++)
     {
         for (int j = sv.x / 3 * 3; j < sv.x / 3 * 3 + 3; j++)
         {
             if (fieldGen[j, i] == sv.val)
             {
                 return(false);
             }
         }
     }
     return(true);
 }
Пример #4
0
        public Queue <StartingValue> Generate() //генерирует поле по правилам судоку (NewField()), выбираем из него стартовые значения для игрока и
        //передаем их в виде очереди стуктур StartingValue
        {
            StartingValue[]       svs;
            Queue <StartingValue> qsv = new Queue <StartingValue>();
            int rx = 0, ry = 0;

            NewField();

            for (int i = 0; i < 9; i++)               //идем по всем районам
            {
                int numbs = rnd.Next(rndMin, rndMax); //количество стартовых значения для каждого района
                svs = new StartingValue[numbs];
                for (int j = 0; j < numbs; j++)       //весь этот цикл нужен, чтобы после генерации координат rx И ry проверить на повтор
                {
                    bool check = false;
                    while (!check)//генерируем координаты стартовых значений в количестве numbs для каждого i-района
                    {
                        bool check2 = true;
                        rx = rnd.Next(i * 3 % 9, i * 3 % 9 + 3);  //координаты стартовых значений
                        ry = rnd.Next(i / 3 * 3, i / 3 * 3 + 3);  //от номера района зависят допустимые координаты x и y (0-2, 3-5 или 6-8)

                        for (int k = 0; k < j; k++)               //проверка с уже сгенерированными координатами х,y на пару совпадающих, при рандоме такое может быть
                        {
                            if (rx == svs[k].x && ry == svs[k].y) //если есть 2 совпадающих пары x,y...
                            {
                                check2 = false;                   //...то циклом while генерируем заного
                            }
                        }
                        if (check2)
                        {
                            check = true;//иначе заканчиваем цикл
                        }
                    }
                    svs[j] = new StartingValue(fieldGen[rx, ry], rx, ry);//после генерации координат формируем стартовое число...
                }

                for (int j = 0; j < numbs; j++)//... и вносим все, что сгенерировали в очередь
                {
                    qsv.Enqueue(svs[j]);
                }
            }


            return(qsv);//возвращаем все сгенерированные стартовые значения в виде очереди
        }
Пример #5
0
        private void NewField()
        {//суть - генерируется поле судоку, откуда мы будем выбирать стартовые значения.
            //сначала генерируется поле 9х7, а последние 2 строке генерируются отдельно, потому что
            //чем больше мы генерирует строк, тем больше вероятность попасть в ситуацию, когда мы для
            //ячейке не можем присвоить число 1-9, потому что все доступные цифры уже использованы по вертикали, горизонтали или в районе,
            //что говорит нам о непраильно сгенерированном поле.
            //первые 7 строк мы вполне можем сгенерировать через while, но в 8 строке есть только 1 правильный вариант из 512,
            //поэтому там генерировать перебором слишком затратно
            //Пример:
            //123 456 789
            //459 713 26Х <-- сюда 8 вставить нельзя из-за района, но нужно для этой строки, ошибка
            //
            //
            //
            //
            //
            //
            //
            int[,] last   = new int[9, 2];  //8 и 9 строки, сюда для каждых 9 столбцов выбираются возможные значения, которые не были использованы в 1-7 строках
            bool[,] check = new bool[9, 9]; //отмечаем, какие цифры в столбце мы уже использовали (требуется для генерации 8 и 9 строк)
            StartingValue sv;               //сюда генерирует цифру и проверяем ее на правильность для определенного квадрата.
            //если нет повтора, то записываем в fieldGen, если есть, то генерируем цифру заного
            bool b0 = true;

            while (b0)//генерируем поле 9х7 до тех пор, пока оно не сгенерируется правильно
            {
                bool b1 = true,
                     b2 = true;
                for (int i = 0; i < 7; i++)                            //7 строк
                {
                    for (int j = 0; j < 9; j++)                        //9 столбцов
                    {
                        sv = new StartingValue(rnd.Next(1, 10), j, i); //генерируем цифру (sv.val) для квадрата по координатам i строка (sv.y), j столбец (sv.x)
                        int d = 0;                                     //20 раз пытаемся генерерировать число
                        while (!FullCheck(sv))                         //проверка сгенерированной цифры для ij-квадрата на повтор в строке, столбце и районе
                        {
                            sv.val = rnd.Next(1, 10);                  //если число не прошло проверку, оно генерируется заного
                            if (d++ > 20)                              //если прошло более 20 попыток, значит, поле сгенерировалось с ошибкой, и начинаем сначало
                            {
                                b2 = false;
                                for (int i2 = 0; i2 <= i; i2++)
                                {
                                    for (int j2 = 0; j2 < 9; j2++)
                                    {
                                        fieldGen[j2, i2] = 0;//очищаем все заполненные значения в поле...
                                    }
                                }
                                check = new bool[9, 9];
                                break;//... и начинаем сначала
                            }
                        }
                        if (!b2)
                        {
                            b1 = false;
                            break;//начинаем сначала
                        }
                        fieldGen[sv.x, sv.y] = sv.val;
                        check[j, sv.val - 1] = true;// отмечаем, что значение sv.val уже использовано для j-столбца  (sv.x)
                    }
                    if (!b1)
                    {
                        break;//начинаем сначала
                    }
                }
                if (b1 && b2)   //если мы не прервали генерацию поля из-за ошибки и таким образом сгенерировли поле 9х7...
                {
                    b0 = false; //.. то заканчиваем цикл while
                }
            }

            for (int i = 0; i < 9; i++)//выбираем в массив last цифры (две на столбец) для каждого столбца, которые не были использованы в массиве check
            {
                int l = 0;
                for (int j = 0; j < 9; j++)
                {
                    if (!check[i, j])
                    {
                        last[i, l++] = j + 1;
                    }
                }
            }
            //итого мы знаем, какие 2 цифры в каждом столбце не были использованы, осталось только правильно их скомбинировать ДЛЯ 8 СТРОКИ,
            //чтобы не было повторов в строке и районе. 9 строка будет сгенерирована значениями, невошедшими в 8
            for (int i = 0; i < 511; i++) //2^9 всего возможных вариатов комбинаций
            {
                int[] a = ToBinary(i);    //переводим номер нашей попытки в двоичное число, где будет 0 - выбираем верхнюю цифру в массиве last, а 1 - нижнюю
                bool  b = true;           // если комбинация для 8 строки была правильной
                for (int j = 0; j < 9; j++)
                {
                    sv = new StartingValue(last[j, a[j]], j, 7);
                    if (!FullCheck(sv))//если случился повтор (комбинация неверная)
                    {
                        for (int k = 0; k < j; k++)
                        {
                            fieldGen[k, 7] = 0; //стираем все вставленные в 8 строку значения и начинаем заного
                        }
                        b = false;              //комбинация была неверной и...
                        break;                  //проверяем следующую
                    }
                    fieldGen[j, 7] = last[j, a[j]];
                }
                if (b)                 //если 8 строка была успешно подобрана, если нет, то игнорируем
                {
                    a = Invert(ref a); //инвертируем
                    for (int j = 0; j < 9; j++)
                    {
                        fieldGen[j, 8] = last[j, a[j]];//заполняем 9 строку
                    }
                    break;
                }
            }
        }
Пример #6
0
 public bool FullCheck(StartingValue sv)//проверка по строке, столбцу и району
 {
     return((AreaCheck(sv) && RowCheck(sv) && ColumnCheck(sv)) ? true : false);
 }