Masalah sudoku skrip taip menunjukkan papan yang terisi separa
P粉135799949
P粉135799949 2023-09-08 00:14:34
0
1
499

Saya telah berjaya menukar penjana Sudoku js kepada penjana ts untuk latihan Satu-satunya masalah ialah bagaimana untuk menjadikannya hanya mengeluarkan papan Sudoku yang lengkap. Kini, ia mengeluarkan tanpa mengira sama ada cakera itu lengkap atau tidak, dan saya perlu menyegarkan semula sehingga cakera yang betul muncul.

Saya tidak pasti cara menulis fungsi berikut supaya ia hanya mengeluarkan cakera lengkap:

function fillBoard(puzzleArray: number[][]): number[][] {
    if (nextEmptyCell(puzzleArray).colIndex === -1) return puzzleArray;

    let emptyCell = nextEmptyCell(puzzleArray);

    for (var num in shuffle(numArray)) {
      if (safeToPlace(puzzleArray, emptyCell, numArray[num])) {
        puzzleArray[emptyCell.rowIndex][emptyCell.colIndex] = numArray[num];
        fillBoard(puzzleArray);
      } 
    }

    return puzzleArray;
  }

Ini semua kod saya:

import { Box } from "./Box";

export function Board() {
  let BLANK_BOARD = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
  ];

  let NEW_BOARD = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0],
  ];

  let counter: number = 0;
  let check: number[];
  const numArray: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9];

  function rowSafe(
    puzzleArray: number[][],
    emptyCell: { rowIndex: number; colIndex: number },
    num: number
  ): boolean {
    return puzzleArray[emptyCell.rowIndex].indexOf(num) == -1;
  }

  function colSafe(
    puzzleArray: number[][],
    emptyCell: { rowIndex: number; colIndex: number },
    num: number
  ): boolean {
    let test = puzzleArray.flat();
    for (let i = emptyCell.colIndex; i < test.length; i += 9) {
      if (test[i] === num) {
        return false;
      }
    }
    return true;
  }

  function regionSafe(
    puzzleArray: number[][],
    emptyCell: { rowIndex: number; colIndex: number },
    num: number
  ): boolean {
    const rowStart: number = emptyCell.rowIndex - (emptyCell.rowIndex % 3);
    const colStart: number = emptyCell.colIndex - (emptyCell.colIndex % 3);

    for (let i = 0; i < 3; i++) {
      for (let j = 0; j < 3; j++) {
        if (puzzleArray[rowStart + i][colStart + j] === num) {
          return false;
        }
      }
    }
    return true;
  }

  console.log(rowSafe(BLANK_BOARD, { rowIndex: 4, colIndex: 6 }, 5));
  console.log(colSafe(BLANK_BOARD, { rowIndex: 2, colIndex: 3 }, 4));
  console.log(regionSafe(BLANK_BOARD, { rowIndex: 5, colIndex: 6 }, 5));

  function safeToPlace(
    puzzleArray: number[][],
    emptyCell: { rowIndex: number; colIndex: number },
    num: number
  ): boolean {
    return (
      regionSafe(puzzleArray, emptyCell, num) &&
      rowSafe(puzzleArray, emptyCell, num) &&
      colSafe(puzzleArray, emptyCell, num)
    );
  }

  console.log(safeToPlace(BLANK_BOARD, { rowIndex: 5, colIndex: 6 }, 5));

  function nextEmptyCell(puzzleArray: number[][]): {
    colIndex: number;
    rowIndex: number;
  } {
    let emptyCell = { rowIndex: -1, colIndex: -1 };
    for (let i = 0; i < 9; i++) {
      for (let j = 0; j < 9; j++) {
        if (puzzleArray[i][j] === 0) {
          return { rowIndex: i, colIndex: j };
        }
      }
    }
    return emptyCell;
  }

  function shuffle(array: number[]): number[] {
    // using Array sort and Math.random

    let shuffledArr = array.sort(() => 0.5 - Math.random());
    return shuffledArr;
  }

  function fillBoard(puzzleArray: number[][]): number[][] {
    if (nextEmptyCell(puzzleArray).colIndex === -1) return puzzleArray;

    let emptyCell = nextEmptyCell(puzzleArray);

    for (var num in shuffle(numArray)) {
      if (safeToPlace(puzzleArray, emptyCell, numArray[num])) {
        puzzleArray[emptyCell.rowIndex][emptyCell.colIndex] = numArray[num];
        fillBoard(puzzleArray);
      } else {
        puzzleArray[emptyCell.rowIndex][emptyCell.colIndex] = 0;
      }
    }

    return puzzleArray;
  }

  console.log(nextEmptyCell(BLANK_BOARD));

  NEW_BOARD = fillBoard(BLANK_BOARD);

  function fullBoard(puzzleArray: number[][]): boolean {
    return puzzleArray.every((row) => row.every((col) => col !== 0));
  }

  return (
    <div
      style={{
        height: "450px",
        width: "450px",
        display: "inline-grid",
        gap: "10px",
        gridTemplateColumns: "repeat(9,50px)",
        gridTemplateRows: "repeat(9,50px)",
        position: "absolute",
        top: "30px",
        left: "0px",
        right: "0px",
        marginLeft: "auto",
        marginRight: "auto",
      }}
    >
      {NEW_BOARD.flat().map((item) => (
        <Box i={item} />
      ))}
    </div>
  );
}

P粉135799949
P粉135799949

membalas semua(1)
P粉638343995

Apabila didapati nombor yang sah tidak boleh ditambah dalam sel kosong, fungsi ini akan mengembalikan papan Sudoku yang tidak lengkap.

Untuk menyelesaikan masalah ini, fungsi anda hendaklah:

  • Mencapai pengunduran yang betul, iaitu membatalkan langkah yang tidak berjaya
  • Menyebabkan fungsi mengembalikan nilai Boolean (menunjukkan kejayaan/kegagalan) - tidak perlu kembali puzzleArray kerana tatasusunan diubah suai di tempatnya, jadi pemanggil boleh mengakses perubahan ini.
    • Ini juga bermakna NEW_BOARD = fillBoard(BLANK_BOARD);的副作用是NEW_BOARDBLANK_BOARDmerujuk papan Sudoku yang sama, dan ia tidak lagi kosong (jadi nama itu mengelirukan).
  • Pecah/kembali ke gelung pada kejayaan.

Berikut ialah pelaksanaan yang diubah suai:

function fillBoard(puzzleArray: number[][]): boolean {
    if (nextEmptyCell(puzzleArray).colIndex === -1) return true; // 布尔值

    let emptyCell = nextEmptyCell(puzzleArray);

    for (var num in shuffle(numArray)) {
      if (safeToPlace(puzzleArray, emptyCell, numArray[num])) {
        puzzleArray[emptyCell.rowIndex][emptyCell.colIndex] = numArray[num];
        if fillBoard(puzzleArray) return true; // 成功时退出
      } 
    }
    puzzleArray[emptyCell.rowIndex][emptyCell.colIndex] = 0; // 撤销
    return false; // 布尔值 - 没有成功
}

Pemanggil harus menyemak nilai pulangan, tetapi jika anda bermula dengan batu tulis kosong, anda dijamin mendapat true sebagai nilai pulangan. Jadi anda boleh melakukan ini:

const puzzleArray = BLANK_BOARD.map(row => [...row]); // 深拷贝
const success = fillBoard(puzzleArray); // 返回一个布尔值
// ... 对puzzleArray做一些操作 ...
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan