js数独解析,以及数独九宫格生成

题目.png

解数独

let board = [
["5","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]
]
const startTime = Date.now()
const lastPoint = getLastPointIndex()

// 校验
function verify (row, col, val) {
  // 校验横竖轴
  for (let i = 0; i < 9; i++) {
    if (board[i][col] === val || board[row][i] === val) {
      return false
    }
  }
  // 校验3*3
  const rect9RowIndex = row / 3 | 0
  const rect9ColIndex = col / 3 | 0
  for (let i= 0; i < 3; i++) {
    for (let r= 0; r < 3; r++) {
      const currntVal = board[rect9RowIndex * 3 + i][rect9ColIndex * 3 + r]
      if (currntVal === val) return false
    }
  }
  return true
}
// 主运行函数
function solveSudoku (current) {
  // console.log('curr:', current)
  let i = current / 9 | 0
  let r = current % 9
  if (current === lastPoint + 1) {
    console.log('time:', Date.now() - startTime)
    // console.log('board:', board)
    return true
  }
  if (board[i][r] !== '.') return solveSudoku(current + 1)
  for (let item = 1; item < 10; item++) {
    if (verify(i, r, item + '')) {
      board[i][r] = item + ''
      if (solveSudoku(current + 1)) return true
      board[i][r] = '.'
    }
  }
}

// 获取最后一个点的下标
function getLastPointIndex () {
  const boardArr = board.flat()
  const last = boardArr.lastIndexOf('.')
  console.log('last:', last)
  return last
}
solveSudoku(0)

生成九宫格的思路

九宫格.png
  1. 先在上面的1、5、9(3*3)框内填写1-9的随机数
  2. 再使用回溯法填写其他的空格
// 生成9*9宫格题目
const totalArr = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
let board = []

for (let i = 0; i < 9; i ++) {
  board.push([])
  for (let r = 0; r < 9; r++) {
    board[i].push('.')
  }
}

// 校验
function verify (row, col, val) {
  // 校验横竖轴
  for (let i = 0; i < 9; i++) {
    if (board[i][col] === val || board[row][i] === val) {
      return false
    }
  }
  // 校验3*3宫格
  const rect9RowIndex = row / 3 | 0
  const rect9ColIndex = col / 3 | 0
  for (let i= 0; i < 3; i++) {
    for (let r= 0; r < 3; r++) {
      const currntVal = board[rect9RowIndex * 3 + i][rect9ColIndex * 3 + r]
      if (currntVal === val) return false
    }
  }
  return true
}

// 先设置三个3*3数独值
function firstSetValue (rowIndex, colIndex) {
  const rect9RowIndex = rowIndex / 3 | 0
  const rect9ColIndex = colIndex / 3 | 0
  const totalArr = shuffle(['1', '2', '3', '4', '5', '6', '7', '8', '9'])
  for (let i= 0; i < 3; i++) {
    for (let r= 0; r < 3; r++) {
      board[rect9RowIndex * 3 + i][rect9ColIndex * 3 + r] = totalArr.pop()
    }
  }
}

// 洗牌法打乱一个数组
function shuffle (array) {
  var m = array.length,
    t, i;
  while (m) {
      i = Math.floor(Math.random() * m--);
      t = array[m];
      array[m] = array[i];
      array[i] = t;
  }
  return array;
}

// 主程序
function main (current) {
  let i = current / 9 | 0
  let r = current % 9
  if (current === 81) {
    console.log('time:', Date.now() - startTime)
    console.log('board:', board)
    return true
  }
  if (board[i][r] !== '.') return main(current + 1)
  for (let item = 1; item < 10; item++) {
    if (verify(i, r, item + '')) {
      board[i][r] = item + ''
      if (main(current + 1)) return true
      board[i][r] = '.'
    }
  }
}

// 先在上面的1、5、9(3*3)框内填写1-9的随机数
[0, 3, 6].forEach(item => {
  firstSetValue(item, item)
})
const startTime = Date.now()

main(0)

你可能感兴趣的:(js数独解析,以及数独九宫格生成)