English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Esempio di metodo di Sudoku sviluppato con Vue

1. Introduzione

Recentemente ho incontrato un problema nel lavoro, poiché la pagina della gestione del backend non ha nuove esigenze, mi sono chiesto cosa mettere nella homepage, recentemente ho pensato di mettere un sudoku, perché è un sudoku? Le regole sono diverse dal sudoku standard, è sufficiente che ogni riga e ogni colonna abbia numeri diversi! Questo esempio è basato su vue, il codice viene condiviso con tutti. Non sto condividendo il codice per farvi copiare direttamente il codice, ma per farvi vedere il codice come un progetto di pratica o per imparare qualcosa. Se pensate che qualcosa sia scritto male o sbagliato, siete i benvenuti a farlo sapere, così possiamo scambiare opinioni e migliorare insieme.

Il codice è stato caricato su github: chi è interessato può starlo!vue-demos

2. Effetto di esecuzione


3. Passi di implementazione

Passi di implementazione, sembra un po' complicato, consiglio di leggere l'articolo man mano che si scrive, in modo che non si diventi confusi. O vedere direttamente il codice sorgente (sudoku) e capirlo! Questo progetto non è complesso!

3-1. Preparazione dei dati e del layout

Non ripeterò molto il codice HTML + CSS di layout, il layout è semplice, questo non dovrebbe essere difficile per nessuno. Più complesso è l'interazione dei dati!
Iniziamo con il primo passo, prepariamo i dati del sudoku, cosa sono i dati, tutti lo sanno, sono dati come quelli di seguito!

L'effetto di layout è il seguente.

Il codice HTML è il seguente

<div class="num-table" @mouseleave="hoverCol=''" :class="{'shake':isShake}">
 <!--遍历每一行-->
 <div v-for="riga,index in tuttiI Numeri" class="riga-numero chlearfix">
 <!--遍历行里面的每一列-->
 <div v-for="num1,indexSub in row" class="num-col">
  {{allNumText[index][indexSub]}}
 </div>
 </div>
</div>

Il codice è anche semplice, come segue

mounted(){
 let arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
 let row = [], rowCol = 0;
 for (let i = 0, len = arr1.length; i < len; i++) {
 row = Object.assign([], arr1);
 this.allNum.push(row);
 //Eliminare il primo numero e registrarne
 rowCol = arr1.splice(0, 1)[0];
 //Inserire il numero alla fine
 arr1.push(rowCol);
 }
}

Potete anche notare che questa dati, ogni riga e ogni colonna del numero sono diversi!

3-2. Disordinare le righe

Poi è necessario disordinare l'ordine casualmente, per garantire un presupposto, è necessario garantire che ogni numero in ogni riga e ogni colonna sia diverso. In questo modo, ho usato un metodo semplice e crudo - disordinare per righe o colonne. Ad esempio, la prima riga e la terza riga scambiano posizioni, la prima colonna e la quinta colonna scambiano posizioni. Ora parliamo del disordine dell'ordine delle righe!

Il disordine delle righe è molto semplice, è sufficiente disordinare l'array casualmente! Un'unica riga di codice lo risolve!

this.allNum.sort((n1, n2) => Math.random() - 0.5);


3-3. Disordinare le colonne

Le righe sono state disordinate, ora procediamo a disordinare le colonne, che è un po' più complesso.

Pensate, ad esempio, se il secondo colonna è scambiato con il quinto, allora il valore della seconda cella di ogni riga viene scambiato con il valore della quinta cella di ogni riga, quindi è necessario percorrere ogni riga! per lo scambio, riguardo ai numeri di colonna secondo e quinto menzionati prima, può essere implementato con una funzione!

Vediamo il codice sottostante!

//Randomly obtain the indices of two columns
function randomText() {
 let rondomIndex = 0, rondomIndexAfter = 0;
 //ottenere l'indice della prima colonna
 rondomIndex = Math.floor(Math.random() * 9);
 function randomDo() {
 rondomIndexAfter = Math.floor(Math.random() * 9);
 //Se l'indice della prima colonna e della seconda colonna sono uguali, ottenere di nuovo casualmente l'indice della seconda colonna
 if (rondomIndexAfter === rondomIndex) {
  randomDo();
 }
 }
 randomDo();
 //ritorna l'indice di due colonne
 return [rondomIndex, rondomIndexAfter];
}
//mescolare le colonne
let randomArr = [], nowValue = 0;
//medesimo percorso 9 volte
for (let i = 0; i < 9; i++) {
 randomArr = Object.assign([], randomText());
 //percorso di ogni riga, scambio casuale di valori tra due colonne per ogni riga
 for (let j = 0, len = this.allNum.length; j < len; j++) {
 //scambio casuale di valori tra due colonne
 nowValue = this.allNum[j][randomArr[0]];
 this.allNum[j][randomArr[0]] = this.allNum[j][randomArr[1]];
 this.allNum[j][randomArr[1]] = nowValue;
 }
}


3-3. Rimozione casuale delle celle vuote

La rimozione casuale delle celle vuote implica la selezione casuale di alcune caselle e la richiesta a chi gioca il sudoku di riempirle!

La mia implementazione attuale è che ogni riga ha due caselle vuote, il mio metodo è registrare le coordinate di ogni casella prima, quindi ottenere casualmente le coordinate dal registro delle coordinate e utilizzare le coordinate ottenute per creare caselle vuote!

Prima di tutto, ottenere tutte le coordinate dei punti

//registrazione di tutte le coordinate
let rowText = '', arrText = [];
for (let i = 0; i < 9; i++) {
 rowText = ''
 for (let j = 0; j < 9; j++) {
  rowText += i + '-' + j + ',';
 }
 arrText.push(rowText.substr(0, rowText.length - 1))
}
console.log(arrText);


Vedendo questa coordinate, è facile capire che un elemento dell'array è la prima riga, '0-0' è la prima casella della prima riga. L'ultimo elemento dell'array è l'ultima riga, '8-8' è l'ultima casella dell'ultima riga, altrimenti, così via!

Procediamo con la rimozione casuale, il codice è molto semplice!

//randommente scavare
let nowItme = [], _option, nowOption = [];
for (let i = 0; i < 9; i++) {
 //estratto di tutte le coordinate della riga corrente
 nowItme = arrText[i].split(',');
 nowOption = [];
 //Rimozione di due coordinate casuali della riga corrente
 for (let j = 0; j < 2; j++) {
  //Estrazione di una coordinate casuale della riga corrente
  _option = Math.floor(Math.random() * nowItme.length);
  //Suddivisione delle coordinate x, y
  nowOption = nowItme.splice(_option,1)[0].split("-");
  this.allNum[nowOption[0]][nowOption[1]] = '';
 }
}

Così, forse alcuni di voi lo trovano strano, procediamo a modificare lo stile, modificando lo stile delle caselle vuote! La classe .no ha lo stile definito nel file css, fate attenzione a questo.

<!--遍历每一行-->
<div v-for="riga,index in tuttiI Numeri" class="riga-numero chlearfix">
 <!--遍历行里面的每一列-->
 <!--
  no:被掏空数组的样式
 -->
 <div v-for="numero1,indexSotto in riga" :class="{'no':numero1===''}" class="colonna-numero">
  {{allNumText[index][indexSub]}}
 </div>
</div>


3-4. Mostra la tastiera numerica

Prima di tutto, uso un diagramma di flusso per spiegare la logica, come segue

Poi, riguardo alla posizione della tastiera numerica, vedi l'immagine sottostante (non entrerò nei dettagli dello stile della tastiera numerica, è solo una configurazione di posizionamento relativo e assoluto).

Come mostrato nell'immagine, ho cliccato sulla terza casella della prima riga, prima di tutto, mi aspetto che lo stile della casella cliccata cambi per facilitare la distinzione, non è difficile, è sufficiente utilizzare una classe per cambiare lo stile. Questo può essere visto nel codice sottostante, utilizzo una classe .cur per controllare lo stile. C'è anche l'aspettativa che la tastiera numerica appaia nella quarta casella della seconda riga. In questo modo, tutti sapranno come posizionare la tastiera numerica! La posizione verticale della tastiera numerica è l'indice della riga cliccata + 160 (60 è la larghezza e altezza della casella), la posizione orizzontale è l'indice della colonna cliccata + 160 (60 è la larghezza e altezza della casella). Ad esempio, nella terza casella della prima riga, top=(0+1)*60+'px', left=(2+1)*60+'px'.

Ecco il codice

<!--遍历每一行-->
 <div v-for="riga,index in tuttiI Numeri" class="riga-numero chlearfix">
  <!--遍历行里面的每一列-->
  <!--
   no:被掏空数组的样式
   cur:格子被点击时触发,被点击的格子样式
  -->
  <div v-for="num1,indexSub in row"
    :class="{'no':num1==='',
    "cur":curRiga===indice&&indiceSotto===curColonna"
    @click="mostraCheck(indice,indiceSotto)" class="colonna-numero">
   {{allNumText[index][indexSub]}}
  </div>
 </div>
<!--数字键盘-->
<div class="num-check chearfix" :style="{'top':(curRow+1)*60+'px','left':(curCol+1)*60+'px'}"}}
  v-show="checkShow"
 <ul>
  <li @click="inputText(1)">1</li>
  <li @click="inputText(2)">2</li>
  <li @click="inputText(3)">3</li>
  <li @click="inputText(4)">4</li>
  <li @click="inputText(5)">5</li>
  <li @click="inputText(6)">6</li>
  <li @click="inputText(7)">7</li>
  <li @click="inputText(8)">8</li>
  <li @click="inputText(9)">9</li>
 </ul>
</div>

Codice JavaScript

/**
 * @description Visualizza la tastiera numerica
 * @param i1
 * @param i2
 */
showCheck(i1, i2){
 //Il quadrato cliccato è stato svuotato?
 if (this.allNum[i1][i2] !== '') {
  return
 }
 // Se la cella cliccata è la cella cliccata l'ultima volta (cella corrente)
 if (i1 === this.curRow && i2 === this.curCol) {
  // Nascondere la tastiera numerica, impostare curRow e curCol a vuoto
  this.checkShow = false;
  this.curRow = '';
  this.curCol = '';
 }
 else {
  // Nascondere la tastiera numerica, impostare curRow e curCol sul punto corrente
  this.checkShow = true;
  this.curRow = i1;
  this.curCol = i2;
 }
,

Effetto di esecuzione

3-5. Evidenziare la riga e la colonna identiche

Questo passaggio è molto semplice, prima di tutto, evidenziare la riga, tutti sanno come fare, è sufficiente impostare lo stile del div corrispondente a :hover e impostare lo stile della cella corrispondente, non c'è molto da dire!

Poi, evidenziare la colonna, è più complesso ma anche semplice, la logica penso che tutti la conoscano, è quando il mouse entra nel quadrato, nel data, si utilizza una variabile per memorizzare l'indice della colonna del quadrato entrante, poi si fa una verifica, se l'indice della colonna del quadrato è uguale all'indice della colonna del quadrato entrante, si aggiunge una classe, qui uso .cur-col.

Ecco il codice

<!--遍历每一行-->
<div v-for="row,index in allNum" class="num-row clear">
 <!--遍历行里面的每一列-->
 <!--
  no:被掏空数组的样式
  cur:格子被点击时触发,被点击的格子样式
  cur-col:鼠标进入时触发,与被点击格子同一列的格子的样式
 -->
 <div v-for="num1,indexSub in row"
   :class="{'no':num1==='',
   'cur':curRow===index&&indexSub===curCol,
   'cur-col': hoverCol===indexSub"
   @click="showCheck(index,indexSub)" @mouseenter="hoverCol=indexSub;" class="num-col">
  {{allNumText[index][indexSub]}}
 </div>
</div>

Effetto di esecuzione

3-6. Operazioni di inserimento e messaggi di errore

Questa operazione della funzione, la esprimerò direttamente in codice, perché vedere il codice è più chiaro di quello che dico, dopo tutto, dico qualcosa di tortuoso

<!--遍历每一行-->
<div v-for="row,index in allNum" class="num-row clear">
 <!--遍历行里面的每一列-->
 <!--
  no:被掏空数组的样式
  cur:格子被点击时触发,被点击的格子样式
  cur-col:鼠标进入时触发,与被点击格子同一列的格子的样式
  err:填写错误时触发的样式
 -->
 <div v-for="num1,indexSub in row"
   :class="{'no':num1==='',
   'cur':curRow===index&&indexSub===curCol,
   'cur-col':hoverCol===indexSub,
   'err':(optionNow.x===index&&optionNow.y===indexSub)||(optionNowInRow.x===index&&optionNowInRow.y===indexSub)||(optionNowInCol.x===index&&optionNowInCol.y===indexSub)}"
   @click="showCheck(index,indexSub)" @mouseenter="hoverCol=indexSub;" class="num-col">
  {{allNumText[index][indexSub]}}
 </div>
</div>

Codice JavaScript

inputText(_text){
 //*****************************Inizializzazione prima del controllo
 let _row = this.curRow, _col = this.curCol;
 this.curRow = '';
 this.curCol = '';
 this.isErr = false;
 this.optionNow = {
  x: '',
  y: '',
 }
 this.optionNowInRow = {
  x: '',
  y: '',
 }
 this.optionNowInCol = {
  x: '',
  y: '',
 }
 //*****************************Controllo delle righe
 //Assegnazione in base al quadrato corrente
 this.allNumText[_row][_col] = _text;
 let rowCheck = Object.assign(this.allNumText[_row], []);
 this.checkShow = false;
 for (let i = 0, len = rowCheck.length; i < len; i++) {
  //Se i valori sono uguali ma le coordinate diverse, è un errore di inserimento
  if (_text === rowCheck[i] && _col !== i) {
   this.isErr = true;
   this.isShake = true;
   //Registrazione delle informazioni della cella corrente
   this.optionNow = {
    x: _row,
    y: _col,
   }
   //Registrazione delle coordinate delle celle della stessa riga e dello stesso valore della cella corrente
   this.optionNowInRow = {
    x: _row,
    y: i,
   }
  }
 }
 //*****************************Controllo delle colonne
 let colCheck = [];
 //Prima di tutto salvare i valori di quella colonna di ogni riga
 for (let i = 0, len = this.allNumText.length; i < len; i++) {
  colCheck.push(this.allNumText[i][_col]);
 }
 //Eseguire la scansione di controllo
 for (let i = 0, len = colCheck.length; i < len; i++) {
  //Se i valori sono uguali ma le coordinate diverse, è un errore di inserimento
  if (_text === colCheck[i] && _row !== i) {
   this.isErr = true;
   this.isShake = true;
   //Record the coordinates of the cells in the same column and with the same value as the current cell
   this.optionNowInCol = {
    x: i,
    y: _col,
   }
  }
 }
 //If the same is found
 if (this.isErr) {
  setTimeout(() => {
   this.isShake = false;
  }, 1000)
  return;
 }
 //If the length of the array after deduplication is less than 9, it means the row is not completed
 rowCheck = rowCheck.filter(item => item !== '');
 if (rowCheck.length !== 9) {
  //console.log('Riga non completata')
  return;
 }
 let coloCheck = [];
 //If the length of the array after deduplication is less than 9, it means the column is not completed
 for (let i = 0, len = this.allNumText.length; i < len; i++) {
  coloCheck = [...new Set(this.allNumText[i])];
  coloCheck = coloCheck.filter(item => item !== '');
  if (coloCheck.length !== 9) {
   //console.log('Non completato')
   return;
  }
 }
 alert('Challenge successful, but no prize');
 this.numShow = false;
}

L'ologramma del codice sopra, in breve

1.. La classe err viene utilizzata per impostare il testo in rosso. Per quanto riguarda il giudizio, all'interno della funzione inputText ci sono optionNow, optionNowInRow e optionNowInCol. Se la coordinata del quadrato è uguale a uno di questi tre, viene aggiunta la classe e il testo diventa rosso.

2.. La classe isShake controlla l'animazione di tremolo. Dopo aver aggiunto questa classe, dopo un secondo, deve essere rimossa, altrimenti la prossima aggiunta non avrà l'effetto dell'animazione.

3. All'interno della funzione inputText, la lista Sudoku che opero non è quella menzionata prima, allNum, ma quella generata tramite una copia profonda di allNum, ossia allNumText (this.allNumText = JSON.parse(JSON.stringify(this.allNum));). Il motivo principale è evitare la situazione illustrata nella figura sottostante!

Così facendo, quando si inseriscono numeri nei quadrati vuoti, il quadrato non può più essere modificato, nemmeno se si inserisce un numero sbagliato, non può essere modificato. Il controllo dello stile non è corretto! Il formato corretto dovrebbe essere così, anche se si inserisce qualcosa, lo stile del quadrato rimane grigio, il che facilita il riconoscimento di quale quadrato è stato vuoto in quel momento, e anche se si inserisce qualcosa di sbagliato, è possibile modificarlo.

4. Complete code

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>vue-所谓的数独</title>
 <link rel="stylesheet" href="../../reset.css" rel="external nofollow" >
 <style>
  li{
   list-style-type: none;
  }
  .shake {
   animation: shake-opacity 500ms 1 ease-in-out;
  }
  @keyframes shake-opacity {
   0% {
    transform: translate(0px, 0px) rotate(0deg);
    opacity: 0.6;
   }
   10% {
    transform: translate(-2px, -1px) rotate(-0.5deg);
    opacity: 0.5;
   }
   20% {
    transform: translate(-4px, 4px) rotate(1.5deg);
    opacity: 0.4;
   }
   30% {
    transform: translate(-4px, -1px) rotate(-1.5deg);
    opacità: 0.8;
   }
   40% {
    transform: translate(-2px, -1px) rotate(-2.5deg);
    opacity: 0.3;
   }
   50% {
    transform: translate(-4px, 1px) rotate(-2.5deg);
    opacity: 0.5;
   }
   60% {
    transform: translate(-2px, 4px) rotate(0.5deg);
    opacity: 0.1;
   }
   70% {
    transform: translate(-3px, 1px) rotate(-0.5deg);
    opacity: 0.4;
   }
   80% {
    transform: translate(0px, 0px) rotate(-0.5deg);
    opacity: 0.5;
   }
   90% {
    transform: translate(2px, -1px) rotate(-2.5deg);
    opacità: 0.8;
   }
  }
  .num-box {
   margin: 0 auto;
   width: 540px;
   position: relative;
  }
  .num-box .num-check {
   position: absolute;
   width: 180px;
   box-shadow: 0 0 10px 0 #000;
   left: 0;
   top: 0;
  }
  .num-box .num-check li {
   box-sizing: border-box;
   float: left;
   background: #fff;
   color: #58B7FF;
   width: 60px;
   height: 60px;
   text-align: center;
   line-height: 60px;
   font-size: 24px;
   border: 1px solid #58B7FF;
   cursor: pointer;
   transition: all .5s;
  }
  .num-box .num-check li:hover {
   color: #fff;
   background: #58B7FF;
   border: 1px solid #fff;
  }
  .num-tips{
   color: #333;
   line-height: 32px;
   font-size: 16px;
  }
  .num-table{
   position: relative;
  }
  .num-row {
   font-size: 0;
  }
  .num-row:hover .num-col, .num-row:hover .num-col.no, .num-row:hover .num-col.cur-col {
   background: #0068b7;
  }
  .num-row .num-col {
   width: 60px;
   height: 60px;
   line-height: 60px;
   float: left;
   box-sizing: border-box;
   text-align: center;
   background: #58B7FF;
   color: #fff;
   font-size: 24px;
   font-weight: bold;
   border: 1px solid #ccc;
  }
  .num-row .num-col.no {
   background: #ccc;
   border: 1px solid #fff;
  }
  .num-row .num-col.err {
   color: #ff4949;
  }
  .num-row .num-col.cur-col {
   background: #0068b7;
  }
  .num-row .num-col.cur {
   background: #fff !important;
  }
 </style>
</head>
<body>
<div class="num-box" v-show="numShow" id="num">
 <div class="num-tips">
  <p>所谓的数独:规则</p>
  <p>1.每一行数字不重复</p>
  <p>2.每一列数字不重复</p>
 </div>
 <div class="num-table" @mouseleave="hoverCol=''" :class="{'shake':isShake}">
  <!--遍历每一行-->
  <div v-for="row,index in allNum" class="num-row clear">
   <!--遍历行里面的每一列-->
   <!--
    no:被掏空数组的样式
    cur:格子被点击时触发,被点击的格子样式
    cur-col:鼠标进入时触发,与被点击格子同一列的格子的样式
    err:填写错误时触发的样式
   -->
   <div v-for="num1,indexSub in row"
     :class="{'no':num1==='',
     'cur':curRow===index&&indexSub===curCol,
     'cur-col':hoverCol===indexSub,
     'err':(optionNow.x===index&&optionNow.y===indexSub)||(optionNowInRow.x===index&&optionNowInRow.y===indexSub)||(optionNowInCol.x===index&&optionNowInCol.y===indexSub)}"
     @click="showCheck(index,indexSub)" @mouseenter="hoverCol=indexSub;" class="num-col">
    {{allNumText[index][indexSub]}}
   </div>
  </div>
  <!--数字键盘-->
  <div class="num-check clear" :style="{'top':(curRow+1)*60+'px','left':(curCol+1)*60+'px'}"
    v-show="checkShow"
   <ul>
    <li @click="inputText(1)">1</li>
    <li @click="inputText(2)">2</li>
    <li @click="inputText(3)">3</li>
    <li @click="inputText(4)">4</li>
    <li @click="inputText(5)">5</li>
    <li @click="inputText(6)">6</li>
    <li @click="inputText(7)">7</li>
    <li @click="inputText(8)">8</li>
    <li @click="inputText(9)">9</li>
   </ul>
  </div>
 </div>
</div>
</body>
<script src="../vue.min.js"></script>
<script>
 new Vue({
  el:'#num',
  data:{
    name: 'welcome',
    testText: 'Benvenuti a',
    nowIndex: 0,
    allNum: [],//Disposizione dei numeri
    answer: [],//Punti di coordinate di tutte le risposte
    allNumText: [],//Numeri, inclusi i numeri di input
    curRow: '',//Indice della riga del quadrato corrente
    curCol: '',//Indice della colonna del quadrato corrente
    checkShow: false,//Visualizzazione della tastiera numerica
    hoverCol: '',//Colonna corrente al passaggio del mouse
    hoverRow: 0,//Riga corrente al passaggio del mouse
    numShow: true,//Visualizzazione del Sudoku
    optionNow: {},//Coordinate del quadrato di input
    optionNowInRow: {},//Coordinate del quadrato nella stessa riga dell'input e dello stesso valore
    optionNowInCol: {},//Coordinate del quadrato nella stessa colonna dell'input e dello stesso valore
    isErr: false,//Dopo l'errore di input
    isShake: false//Visualizza lo stile di vibrazione
  ,
  methods: {
   /**
    * @description Visualizza la tastiera numerica
    * @param i1
    * @param i2
    */
   showCheck(i1, i2){
    //Il quadrato cliccato è stato svuotato?
    if (this.allNum[i1][i2] !== '') {
     return
    }
    // Se la cella cliccata è la cella cliccata l'ultima volta (cella corrente)
    if (i1 === this.curRow && i2 === this.curCol) {
     // Nascondere la tastiera numerica, impostare curRow e curCol a vuoto
     this.checkShow = false;
     this.curRow = '';
     this.curCol = '';
    }
    else {
     // Nascondere la tastiera numerica, impostare curRow e curCol sul punto corrente
     this.checkShow = true;
     this.curRow = i1;
     this.curCol = i2;
    }
   ,
   inputText(_text){
    //*****************************Inizializzazione prima del controllo
    let _row = this.curRow, _col = this.curCol;
    this.curRow = '';
    this.curCol = '';
    this.isErr = false;
    this.optionNow = {
     x: '',
     y: '',
    }
    this.optionNowInRow = {
     x: '',
     y: '',
    }
    this.optionNowInCol = {
     x: '',
     y: '',
    }
    //*****************************Controllo delle righe
    //Salvare il valore della cella corrente
    this.allNumText[_row][_col] = _text;
    let rowCheck = Object.assign(this.allNumText[_row], []);
    this.checkShow = false;
    for (let i = 0, len = rowCheck.length; i < len; i++) {
     //Se i valori sono uguali ma le coordinate diverse, è un errore di inserimento
     if (_text === rowCheck[i] && _col !== i) {
      this.isErr = true;
      this.isShake = true;
      //Registrazione delle informazioni della cella corrente
      this.optionNow = {
       x: _row,
       y: _col
      }
      //Registrazione delle coordinate delle celle della stessa riga e dello stesso valore della cella corrente
      this.optionNowInRow = {
       x: _row,
       y: i
      }
     }
    }
    //*****************************Controllo delle colonne
    let colCheck = [];
    //Prima di tutto salvare i valori di quella colonna di ogni riga
    for (let i = 0, len = this.allNumText.length; i < len; i++) {
     colCheck.push(this.allNumText[i][_col]);
    }
    //Eseguire la scansione di controllo
    for (let i = 0, len = colCheck.length; i < len; i++) {
     //Se i valori sono uguali ma le coordinate diverse, è un errore di inserimento
     if (_text === colCheck[i] && _row !== i) {
      this.isErr = true;
      this.isShake = true;
      //Record the coordinates of the cells in the same column and with the same value as the current cell
      this.optionNowInCol = {
       x: i,
       y: _col
      }
     }
    }
    //If the same is found
    if (this.isErr) {
     setTimeout(() => {
      this.isShake = false;
     }, 1000)
     return;
    }
    //If the length of the array after deduplication is less than 9, it means the row is not completed
    rowCheck = rowCheck.filter(item => item !== '');
    if (rowCheck.length !== 9) {
     console.log('Row not completed');
     return;
    }
    let coloCheck = [];
    //If the length of the array after deduplication is less than 9, it means the column is not completed
    for (let i = 0, len = this.allNumText.length; i < len; i++) {
     coloCheck = [...new Set(this.allNumText[i])];
     coloCheck = coloCheck.filter(item => item !== '');
     if (coloCheck.length !== 9) {
      console.log('Not completed');
      return;
     }
    }
    alert('Challenge successful, but no prize');
    this.numShow = false;
   }
  ,
  mounted(){
   let arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
   let row = [], rowCol = 0;
   for (let i = 0, len = arr1.length; i < len; i++) {
    row = Object.assign([], arr1);
    this.allNum.push(row);
    rowCol = arr1.splice(0, 1)[0];
    arr1.push(rowCol);
   }
   //Shuffle the rows
   this.allNum.sort((n1, n2) => Math.random() - 0.5);
   //Randomly obtain the indices of two columns
   function randomText() {
    let rondomIndex = 0, rondomIndexAfter = 0;
    //ottenere l'indice della prima colonna
    rondomIndex = Math.floor(Math.random() * 9);
    function randomDo() {
     rondomIndexAfter = Math.floor(Math.random() * 9);
     //se l'indice della prima colonna e dell'indice della seconda colonna sono uguali, l'indice della seconda colonna viene nuovamente recuperato
     if (rondomIndexAfter === rondomIndex) {
      randomDo();
     }
    }
    randomDo();
    //ritorna l'indice di due colonne
    return [rondomIndex, rondomIndexAfter];
   }
   //mescolare le colonne
   let randomArr = [], nowValue = 0;
   //medesimo percorso 9 volte
   for (let i = 0; i < 9; i++) {
    randomArr = Object.assign([], randomText());
    //percorso di ogni riga, scambio casuale di valori tra due colonne per ogni riga
    for (let j = 0, len = this.allNum.length; j < len; j++) {
     //scambio casuale di valori tra due colonne
     nowValue = this.allNum[j][randomArr[0]];
     this.allNum[j][randomArr[0]] = this.allNum[j][randomArr[1]];
     this.allNum[j][randomArr[1]] = nowValue;
    }
   }
   //registrazione di tutte le coordinate
   let rowText = '', arrText = [];
   for (let i = 0; i < 9; i++) {
    rowText = ''
    for (let j = 0; j < 9; j++) {
     rowText += i + '-' + j + ',';
    }
    arrText.push(rowText.substr(0, rowText.length - 1))
   }
   console.log(arrText);
   //randommente scavare
   let nowItme = [], _option, nowOption = [];
   for (let i = 0; i < 9; i++) {
    //estratto di tutte le coordinate della riga corrente
    nowItme = arrText[i].split(',');
    nowOption = [];
    //Rimozione di due coordinate casuali della riga corrente
    for (let j = 0; j < 2; j++) {
     //Estrazione di una coordinate casuale della riga corrente
     _option = Math.floor(Math.random() * nowItme.length);
     //Suddivisione delle coordinate x, y
     nowOption = nowItme.splice(_option,1)[0].split("-");
     this.allNum[nowOption[0]][nowOption[1]] = '';
    }
   }
   //Copia profonda dei numeri del Sudoku
   this.allNumText = JSON.parse(JSON.stringify(this.allNum));
  }
 })
</script>
</html>

reset.css e vue.min.js possono essere scaricati autonomamente da github!

5. Conclusione

Bene, questo è tutto per il Sudoku fatto con Vue, la logica è un po' ingarbugliata, ma credo che altri problemi non siano difficili per voi. Questo esempio è più complicato dei tre piccoli esempi di入门 veloce, ma è anche facile da capire! Spero che chiunque guardi con un po' di attenzione possa capire! Infine, se pensate che l'articolo sia scritto male, dove è stato scritto male, siete i benvenuti a dare consigli o indicazioni. Aspetto di scambiare opinioni con voi, e di progredire insieme!

Questo è tutto il contenuto dell'articolo, spero che il contenuto di questo articolo abbia un valore di riferimento per lo studio o il lavoro di tutti. Se avete domande, potete lasciare un messaggio di commento per scambiare opinioni, grazie per il supporto di Guida a URL!

Dichiarazione: il contenuto di questo articolo è stato preso da Internet, appartiene al proprietario del copyright, il contenuto è stato contribuito e caricato autonomamente dagli utenti di Internet, questo sito non detiene i diritti di proprietà, non è stato editato manualmente e non assume responsabilità legali correlate. Se trovi contenuti sospetti di violazione del copyright, ti preghiamo di inviare una email a: notice#oldtoolbag.com (al momento dell'invio dell'email, sostituisci # con @) per segnalare, fornendo prove pertinenti. Una volta verificata, questo sito eliminerà immediatamente il contenuto sospetto di violazione del copyright.

Ti potrebbe interessare