// ==UserScript== // @name 每日杀手数独自动高亮 // @version 0.3.0 // @description Daily killer Sudoku AutoHighlight.(含指定高亮及冲突高亮) // @author DreamNya // @match https://www.dailykillersudoku.com/puzzle/* // @grant none // @license MIT // @run-at document-end // @namespace https://greasyfork.org/users/809466 // ==/UserScript== // localStorage const getKey = function (key, defaultValue) { const value = JSON.parse(localStorage.getItem('AutoHighlight-' + key)); return value ?? defaultValue; }; const setKey = function (key, value) { localStorage.setItem('AutoHighlight-' + key, JSON.stringify(value)); return value; }; // 等待元素加载 await new Promise((resolve) => { $(puzzleBoard).ready(function () { resolve(); }); }); // 关联格与宫 const blocks = Array(3) .fill() .map((i) => Array(3) .fill() .map((n) => []) ); const boardCells = DKS.puzzle.board._cells.flat(); boardCells.forEach((cell) => { const row = Math.floor(cell.row / 3); const column = Math.floor(cell.column / 3); blocks[row][column].push(cell); }); blocks.flat().forEach((block) => { block.forEach((cell) => { cell.block = block; }); }); // 自动高亮(指定) const AutoHighlight = {}; window.AutoHighlight = AutoHighlight; const config = {}; AutoHighlight.config = config; config.num = getKey('num', true); config.subnum = getKey('subnum', true); config.errorLint = getKey('errorLint', true); AutoHighlight.num = 0; // 切换设置 AutoHighlight.toggleConfig = function (item, element) { config[item] = setKey(item, !config[item]); $(element).attr('data-icon', config[item] ? 'toggle-on' : 'toggle-off'); if (item == 'errorLint') { !config.errorLint && AutoErrorLint.clearErrorLint(); config.errorLint && AutoErrorLint.errorLint(); } }; // 清除指定高亮 AutoHighlight.reset = function () { AutoHighlight.highlight(0); }; // 指定高亮 AutoHighlight.highlight = function (num) { DKS.puzzle.board.clearHighlightedCells(); if (AutoHighlight.num == num) { num = 0; } AutoHighlight.num = num; if (num == 0) { return; } const cells = boardCells.reduce((arr, cell) => { let flag = false; if (config.num) { if (cell.value == num) { flag = true; } } if (!flag && config.subnum) { if (cell.pencilMarks.includes(num)) { flag = true; } } if (flag) { arr.push(cell); } return arr; }, []); DKS.puzzle.board.highlightedCells.push(...cells); DKS.puzzle.board._drawHighlightedCells(); }; // 自动高亮(冲突) const AutoErrorLint = {}; window.AutoErrorLint = AutoErrorLint; AutoErrorLint.errorCells = new Set(); AutoErrorLint.clearErrorLint = function () { AutoErrorLint.errorCells.forEach((cell) => cell.removeErrorTint()); AutoErrorLint.errorCells.clear(); }; // 检查实数冲突 AutoErrorLint.checkValue = function ({ row, column, value }, cells) { if (value == 0) { return false; } let flag = false; cells.forEach((cell) => { if (cell.row == row && cell.column == column) { return; } const conflict = cell.value == value || cell.pencilMarks.includes(value); if (conflict) { cell.addErrorTint(); AutoErrorLint.errorCells.add(cell); flag = true; } }); return flag; }; // 检查候选数冲突 AutoErrorLint.checkMarks = function ({ row, column, pencilMarks }, cells) { if (pencilMarks.length == 0) { return false; } let flag = false; cells.forEach((cell) => { if (cell.row == row && cell.column == column) { return; } const conflict = pencilMarks.includes(cell.value); // || pencilMarks.some((mark) => cell.pencilMarks.includes(mark)); if (conflict) { cell.addErrorTint(); AutoErrorLint.errorCells.add(cell); flag = true; } }); return flag; }; // 检查格 AutoErrorLint.checkCells = function (cell, cells) { return AutoErrorLint.checkValue(cell, cells) || AutoErrorLint.checkMarks(cell, cells); }; // 检查宫 AutoErrorLint.checkBlock = function (cell) { const { block } = cell; return AutoErrorLint.checkCells(cell, block); }; // 检查笼 AutoErrorLint.checkCage = function (cell) { const cells = cell.cage.cells; return AutoErrorLint.checkCells(cell, cells); }; // 检查行 AutoErrorLint.checkRow = function (cell) { const { row } = cell; const cells = DKS.puzzle.board._cells[row]; return AutoErrorLint.checkCells(cell, cells); }; // 检查列 AutoErrorLint.checkColumn = function (cell) { const { column } = cell; const cells = DKS.puzzle.board._cells.map((_cells) => _cells[column]); return AutoErrorLint.checkCells(cell, cells); }; // 冲突高亮 AutoErrorLint.errorLint = function () { AutoErrorLint.clearErrorLint(); //DKS.puzzle.board.highlightedCells boardCells.forEach((cell) => { const cage = AutoErrorLint.checkCage(cell); const block = AutoErrorLint.checkBlock(cell); const column = AutoErrorLint.checkColumn(cell); const row = AutoErrorLint.checkRow(cell); if (cage || block || column || row) { cell.addErrorTint(); AutoErrorLint.errorCells.add(cell); } }); }; config.errorLint && AutoErrorLint.errorLint(); document.addEventListener('keyup', function () { config.errorLint && AutoErrorLint.errorLint(); }); const off = 'M384 64H192C85.961 64 0 149.961 0 256s85.961 192 192 192h192c106.039 0 192-85.961 192-192S490.039 64 384 64zM64 256c0-70.741 57.249-128 128-128 70.741 0 128 57.249 128 128 0 70.741-57.249 128-128 128-70.741 0-128-57.249-128-128zm320 128h-48.905c65.217-72.858 65.236-183.12 0-256H384c70.741 0 128 57.249 128 128 0 70.74-57.249 128-128 128z'; const on = 'M384 64H192C86 64 0 150 0 256s86 192 192 192h192c106 0 192-86 192-192S490 64 384 64zm0 320c-70.8 0-128-57.3-128-128 0-70.8 57.3-128 128-128 70.8 0 128 57.3 128 128 0 70.8-57.3 128-128 128z'; $(document.body).append( `
Reset
Color

AutoHighlight

冲突高亮
实数
候选数
${Array(9) .fill() .reduce((str, _, index) => { str += `
${index + 1}
`; return str; }, '')}
` ); $('#AutoHighlight').on('click mousedown', (e) => { e.stopPropagation(); }); $(document).on('mousedown', (e) => { if (DKS.puzzle.board.highlightedCells.length == 0) { AutoHighlight.num = 0; } }); const colorPicker = {}; AutoHighlight.colorPicker = colorPicker; config.numColor = getKey('numColor', DKS.isDarkMode ? '#ddf' : '#363686'); colorPicker.lastTime = 0; colorPicker.colorStyle = $(``).appendTo( document.body ); colorPicker.colorPicker = document.querySelector('#colorPicker'); colorPicker.colorPicker.value = config.numColor; $(colorPicker.colorPicker).on('input', function (e) { const now = Date.now(); if (now - colorPicker.lastTime < 100) { return; } colorPicker.lastTime = now; config.numColor = setKey('numColor', this.value); colorPicker.colorStyle.html(`.pencil-marks,.cell-value{color:${config.numColor}!important}`); }); colorPicker.pick = function (e) { colorPicker.colorPicker.showPicker(); };