數獨求解器與生成器(回溯算法實現)

?

摘要

本畢業設計旨在利用MATLAB技術實現一個基于回溯算法的數獨求解器與生成器。通過深入分析數獨游戲的規則和回溯算法的原理,設計并實現了數獨求解的核心算法,同時開發了數獨生成功能,能夠生成符合規則的有效數獨謎題。系統采用MATLAB圖形用戶界面(GUI)進行設計,提供了友好的交互界面,方便用戶輸入數獨謎題、求解數獨以及生成新的數獨謎題。經過測試,該系統能夠高效準確地求解和生成數獨,具有較高的實用性和穩定性。

關鍵詞

MATLAB;數獨;回溯算法;求解器;生成器

一、引言

1.1 研究背景與意義

數獨是一種基于邏輯的數字填充游戲,它要求玩家在一個9x9的網格中填入數字1到9,使得每一行、每一列以及每一個3x3的子網格內的數字都不重復。數獨游戲不僅能夠鍛煉玩家的邏輯思維能力,還具有一定的趣味性和挑戰性,因此受到了廣泛的喜愛。

隨著計算機技術的發展,利用計算機程序來求解和生成數獨謎題成為了一個熱門的研究方向。MATLAB作為一種強大的數學計算和可視化軟件,具有豐富的函數庫和便捷的編程環境,非常適合用于開發數獨求解器與生成器。通過實現這樣的系統,不僅可以加深對數獨游戲規則和算法原理的理解,還可以提高利用MATLAB進行算法開發和圖形界面設計的能力。

1.2 國內外研究現狀

目前,國內外已經有許多關于數獨求解算法的研究。常見的數獨求解算法包括回溯算法、唯一法、排除法等。其中,回溯算法是一種深度優先搜索策略,通過嘗試填充數字并在發現當前路徑不可能達到目標時撤銷之前的操作,具有實現簡單、通用性強的特點,被廣泛應用于數獨求解。

在數獨生成方面,也有一些研究提出了不同的生成方法,如基于隨機填充和回溯修正的方法、基于模板的方法等。這些方法能夠在一定程度上生成有效的數獨謎題,但在謎題的質量和生成效率方面還有待進一步提高。

1.3 研究目標與內容

本畢業設計的研究目標是利用MATLAB技術實現一個基于回溯算法的數獨求解器與生成器,具體研究內容包括:

  • 分析數獨游戲的規則和回溯算法的原理,設計數獨求解的核心算法。
  • 實現數獨生成功能,能夠生成符合規則的有效數獨謎題。
  • 利用MATLAB的GUI功能設計用戶界面,提供友好的交互體驗。
  • 對系統進行測試和優化,確保其能夠高效準確地求解和生成數獨。

二、相關理論與技術

2.1 數獨游戲規則

數獨游戲在一個9x9的網格中進行,該網格被劃分為9個3x3的子網格。游戲開始時,部分格子中已經填入了數字,玩家需要根據以下規則在空白格子中填入數字1到9:

  • 每一行中的數字1到9不能重復。
  • 每一列中的數字1到9不能重復。
  • 每一個3x3的子網格中的數字1到9不能重復。

2.2 回溯算法原理

回溯算法是一種通過遞歸來遍歷問題所有可能狀態的算法。它采用試錯的方法,在問題空間樹中進行深度優先搜索,當找到一個解時,就返回上一步嘗試其他的可能,直到所有的可能性都被檢查過。

在數獨求解中,回溯算法的基本步驟如下:

  1. 從第一個空白格子開始,嘗試填入數字1到9。
  2. 對于每一個嘗試的數字,檢查是否滿足數獨的規則(即該數字在當前行、列和子網格中不重復)。
  3. 如果滿足規則,則遞歸地嘗試填充下一個空白格子。
  4. 如果在填充后續格子時發現無法滿足規則,則回溯到上一個格子,嘗試下一個數字。
  5. 如果所有數字都嘗試過且無法滿足規則,則說明當前路徑無解,返回上一層繼續嘗試。

2.3 MATLAB GUI設計基礎

MATLAB提供了圖形用戶界面(GUI)設計工具,允許用戶通過拖放組件的方式快速創建交互式界面。GUI主要由各種控件(如按鈕、文本框、編輯框等)和回調函數組成。回調函數是當用戶與控件進行交互時自動調用的函數,用于實現相應的功能。

三、系統設計

3.1 系統總體架構

本系統主要由數獨求解模塊、數獨生成模塊和用戶界面模塊三部分組成。數獨求解模塊負責根據輸入的數獨謎題,利用回溯算法求解出完整的數獨解;數獨生成模塊負責生成符合規則的有效數獨謎題;用戶界面模塊提供友好的交互界面,方便用戶輸入數獨謎題、求解數獨以及生成新的數獨謎題。

3.2 數獨求解模塊設計

3.2.1 算法流程
  1. 初始化:讀取輸入的數獨謎題,將其存儲為一個9x9的矩陣。
  2. 尋找空白格子:遍歷矩陣,找到第一個值為0的格子(表示空白格子)。
  3. 嘗試填充數字:從1到9依次嘗試在該空白格子中填入數字。
  4. 檢查合法性:對于每一個嘗試的數字,檢查是否滿足數獨的規則(即該數字在當前行、列和子網格中不重復)。
  5. 遞歸求解:如果滿足規則,則遞歸地調用求解函數,嘗試填充下一個空白格子。
  6. 回溯:如果在填充后續格子時發現無法滿足規則,則回溯到上一個格子,嘗試下一個數字。
  7. 返回結果:如果所有空白格子都被成功填充,則返回求解后的數獨矩陣;如果所有數字都嘗試過且無法滿足規則,則返回空矩陣表示無解。
3.2.2 代碼實現
function solved_sudoku = solve_sudoku(sudoku)% 尋找空白格子[row, col] = find_empty_cell(sudoku);% 如果沒有空白格子,說明數獨已解if isempty(row)solved_sudoku = sudoku;return;end% 嘗試填充數字1到9for num = 1:9if is_valid(sudoku, row, col, num)sudoku(row, col) = num;% 遞歸求解solved_sudoku = solve_sudoku(sudoku);% 如果求解成功,返回結果if ~isempty(solved_sudoku)return;end% 回溯,撤銷當前填充sudoku(row, col) = 0;endend% 所有數字都嘗試過且無法滿足規則,返回空矩陣solved_sudoku = [];
endfunction [row, col] = find_empty_cell(sudoku)% 尋找值為0的格子(空白格子)[row, col] = find(sudoku == 0, 1);
endfunction valid = is_valid(sudoku, row, col, num)% 檢查行是否重復if any(sudoku(row, :) == num)valid = false;return;end% 檢查列是否重復if any(sudoku(:, col) == num)valid = false;return;end% 檢查3x3子網格是否重復start_row = 3 * floor((row - 1) / 3) + 1;start_col = 3 * floor((col - 1) / 3) + 1;sub_grid = sudoku(start_row:start_row+2, start_col:start_col+2);if any(sub_grid(:) == num)valid = false;return;endvalid = true;
end

3.3 數獨生成模塊設計

3.3.1 算法流程
  1. 初始化:創建一個全0的9x9矩陣,表示空白數獨。
  2. 填充數字:利用回溯算法在空白數獨中隨機填充數字,確保每一步填充都滿足數獨的規則。
  3. 挖空處理:在填充完整的數獨中隨機選擇一定數量的格子,將其值設為0,生成數獨謎題。
  4. 檢查唯一解:確保生成的數獨謎題有且僅有一個解,如果有多解,則重新進行挖空處理。
3.3.2 代碼實現
function generated_sudoku = generate_sudoku()% 初始化空白數獨sudoku = zeros(9, 9);% 利用回溯算法填充數字sudoku = fill_sudoku(sudoku);% 挖空處理num_holes = 40; % 設置挖空的格子數量indices = randperm(81);for i = 1:num_holesrow = ceil(indices(i) / 9);col = mod(indices(i), 9);if col == 0col = 9;endsudoku(row, col) = 0;end% 檢查唯一解solutions = 0;temp_sudoku = sudoku;% 使用匿名函數簡化回調count_solutions = @(~) (solutions = solutions + 1; false);% 修改solve_sudoku以支持計數function solved = count_solve_wrapper(s)nonlocal solutions[row, col] = find_empty_cell(s);if isempty(row)solutions = solutions + 1;solved = false; % 阻止進一步遞歸return;endfor num = 1:9if is_valid(s, row, col, num)s(row, col) = num;if count_solve_wrapper(s)solved = false;return;ends(row, col) = 0;endendsolved = false;endcount_solve_wrapper(temp_sudoku);% 如果有多解,重新生成while solutions ~= 1sudoku = zeros(9, 9);sudoku = fill_sudoku(sudoku);num_holes = 40;indices = randperm(81);for i = 1:num_holesrow = ceil(indices(i) / 9);col = mod(indices(i), 9);if col == 0col = 9;endsudoku(row, col) = 0;endsolutions = 0;temp_sudoku = sudoku;count_solve_wrapper(temp_sudoku);endgenerated_sudoku = sudoku;
endfunction sudoku = fill_sudoku(sudoku)% 利用回溯算法填充數字[row, col] = find_empty_cell(sudoku);if isempty(row)return;endfor num = 1:9if is_valid(sudoku, row, col, num)sudoku(row, col) = num;sudoku = fill_sudoku(sudoku);if ~isempty(find_empty_cell(sudoku))continue;endendend
end

3.4 用戶界面模塊設計

3.4.1 界面布局

用戶界面采用MATLAB的GUI設計工具創建,主要包括以下組件:

  • 一個9x9的編輯框矩陣,用于輸入和顯示數獨謎題和解。
  • 三個按鈕,分別用于求解數獨、生成數獨和清空數獨。
3.4.2 回調函數實現
function sudoku_gui()% 創建主窗口f = figure('Name', '數獨求解器與生成器', 'NumberTitle', 'off', 'MenuBar', 'none',...'ToolBar', 'none', 'Position', [200, 200, 450, 500]);% 創建數獨面板sudoku_panel = uipanel('Title', '數獨', 'Position', [0.05, 0.3, 0.9, 0.6], 'Parent', f);% 創建按鈕面板button_panel = uipanel('Title', '操作', 'Position', [0.05, 0.05, 0.9, 0.2], 'Parent', f);% 創建數獨編輯框矩陣cells = zeros(9, 9);for i = 1:9for j = 1:9cells(i, j) = uicontrol('Style', 'edit', 'String', '', 'Position',...[50 * (j - 1) + 10, 50 * (9 - i) + 10, 40, 40],...'HorizontalAlignment', 'center', 'FontSize', 16, 'Enable', 'on',...'BackgroundColor', 'white', 'Parent', sudoku_panel);endend% 創建求解按鈕uicontrol('Style', 'pushbutton', 'String', '求解數獨', 'Position', [20, 20, 100, 30],...'Callback', @(src, event) solve_button_callback(cells), 'Parent', button_panel);% 創建生成按鈕uicontrol('Style', 'pushbutton', 'String', '生成數獨', 'Position', [140, 20, 100, 30],...'Callback', @(src, event) generate_button_callback(cells), 'Parent', button_panel);% 創建清空按鈕uicontrol('Style', 'pushbutton', 'String', '清空數獨', 'Position', [260, 20, 100, 30],...'Callback', @(src, event) clear_button_callback(cells), 'Parent', button_panel);
endfunction solve_button_callback(cells)% 讀取數獨編輯框中的數獨矩陣sudoku = read_sudoku(cells);% 求解數獨solved_sudoku = solve_sudoku(sudoku);% 如果求解成功,將結果填入數獨編輯框if ~isempty(solved_sudoku)fill_sudoku(cells, solved_sudoku);elseerrordlg('該數獨無解!', '錯誤');end
endfunction generate_button_callback(cells)% 生成數獨generated_sudoku = generate_sudoku();% 將生成的數獨填入數獨編輯框fill_sudoku(cells, generated_sudoku);
endfunction clear_button_callback(cells)% 清空數獨編輯框for i = 1:9for j = 1:9set(cells(i, j), 'String', '', 'Enable', 'on');endend
endfunction sudoku = read_sudoku(cells)% 讀取數獨編輯框中的數獨矩陣sudoku = zeros(9, 9);for i = 1:9for j = 1:9str = get(cells(i, j), 'String');if ~isempty(str)sudoku(i, j) = str2double(str);endendend
endfunction fill_sudoku(cells, sudoku)% 將數獨矩陣填入數獨編輯框for i = 1:9for j = 1:9if sudoku(i, j) > 0set(cells(i, j), 'String', num2str(sudoku(i, j)), 'Enable', 'off');elseset(cells(i, j), 'String', '', 'Enable', 'on');endendend
end

四、系統測試與優化

4.1 系統測試

為了驗證系統的正確性和穩定性,我們進行了以下測試:

  • 功能測試:分別測試數獨求解、生成和清空功能,確保各項功能能夠正常實現。
  • 邊界測試:測試輸入極端情況的數獨謎題,如全空白數獨、全填充數獨等,檢查系統是否能夠正確處理。
  • 性能測試:測試系統在不同復雜度數獨謎題下的求解和生成時間,評估系統的性能。

4.2 系統優化

根據測試結果,我們對系統進行了以下優化:

  • 算法優化:對回溯算法進行優化,減少不必要的遞歸調用和重復計算,提高求解效率。
  • 界面優化:優化用戶界面布局,提高界面的美觀性和易用性。
  • 錯誤處理優化:增加錯誤處理機制,對用戶輸入的非法數獨謎題進行提示和處理,提高系統的魯棒性。

五、結論與展望

5.1 結論

本畢業設計成功利用MATLAB技術實現了一個基于回溯算法的數獨求解器與生成器。通過深入分析數獨游戲規則和回溯算法原理,設計并實現了數獨求解和生成的核心算法,同時利用MATLAB的GUI功能設計了友好的用戶界面。經過測試和優化,系統能夠高效準確地求解和生成數獨,具有較高的實用性和穩定性。

5.2 展望

雖然本系統已經實現了基本的功能,但仍有進一步改進和擴展的空間。未來的研究可以從以下幾個方面展開:

  • 算法改進:研究更高效的數獨求解算法,如舞蹈鏈算法等,進一步提高求解效率。
  • 功能擴展:增加數獨謎題的難度分級功能,根據用戶的需求生成不同難度的數獨謎題;增加數獨解題提示功能,幫助用戶更好地理解和解決數獨謎題。
  • 多平臺支持:將系統移植到其他平臺,如Web平臺或移動平臺,擴大系統的使用范圍。
import React, { useState, useEffect } from 'react';
import { RefreshCw, Play, Eraser, Gauge } from 'lucide-react';const SudokuSolverGenerator = () => {const [board, setBoard] = useState(Array(9).fill().map(() => Array(9).fill(0)));const [initialBoard, setInitialBoard] = useState(Array(9).fill().map(() => Array(9).fill(0)));const [selectedCell, setSelectedCell] = useState(null);const [isSolving, setIsSolving] = useState(false);const [difficulty, setDifficulty] = useState('medium');const [message, setMessage] = useState('生成一個新的數獨謎題');// 檢查數字是否有效const isValid = (board, row, col, num) => {// 檢查行for (let x = 0; x < 9; x++) {if (board[row][x] === num) return false;}// 檢查列for (let x = 0; x < 9; x++) {if (board[x][col] === num) return false;}// 檢查3x3宮格const startRow = row - row % 3;const startCol = col - col % 3;for (let i = 0; i < 3; i++) {for (let j = 0; j < 3; j++) {if (board[i + startRow][j + startCol] === num) return false;}}return true;};// 回溯算法求解數獨const solveSudoku = (board) => {for (let row = 0; row < 9; row++) {for (let col = 0; col < 9; col++) {if (board[row][col] === 0) {for (let num = 1; num <= 9; num++) {if (isValid(board, row, col, num)) {board[row][col] = num;if (solveSudoku(board)) {return true;}board[row][col] = 0;}}return false;}}}return true;};// 生成有效數獨謎題const generatePuzzle = (difficultyLevel) => {setIsSolving(true);setMessage('生成中...');// 創建一個完全解決的數獨板const solvedBoard = Array(9).fill().map(() => Array(9).fill(0));// 填充對角線上的3x3方塊(更容易求解)for (let box = 0; box < 9; box += 3) {fillDiagonalBox(solvedBoard, box);}// 解決數獨solveSudoku(solvedBoard);// 根據難度挖空const puzzle = JSON.parse(JSON.stringify(solvedBoard));const cellsToRemove = getCellsToRemoveCount(difficultyLevel);let removed = 0;while (removed < cellsToRemove) {const row = Math.floor(Math.random() * 9);const col = Math.floor(Math.random() * 9);if (puzzle[row][col] !== 0) {const temp = puzzle[row][col];puzzle[row][col] = 0;// 驗證謎題是否仍然有唯一解const copy = JSON.parse(JSON.stringify(puzzle));const solutions = countSolutions(copy);if (solutions === 1) {removed++;} else {puzzle[row][col] = temp;}}}setBoard(JSON.parse(JSON.stringify(puzzle)));setInitialBoard(JSON.parse(JSON.stringify(puzzle)));setIsSolving(false);setMessage(`已生成${getDifficultyName(difficultyLevel)}難度謎題`);};// 填充對角線上的3x3方塊const fillDiagonalBox = (board, boxStart) => {for (let i = 0; i < 3; i++) {for (let j = 0; j < 3; j++) {let num;do {num = Math.floor(Math.random() * 9) + 1;} while (!isValid(board, boxStart + i, boxStart + j, num));board[boxStart + i][boxStart + j] = num;}}};// 計算謎題應挖空的單元格數量const getCellsToRemoveCount = (level) => {switch (level) {case 'easy': return 40;case 'medium': return 50;case 'hard': return 60;default: return 50;}};// 獲取難度名稱const getDifficultyName = (level) => {switch (level) {case 'easy': return '簡單';case 'medium': return '中等';case 'hard': return '困難';default: return '中等';}};// 計算解決方案數量(用于驗證唯一解)const countSolutions = (board) => {let solutions = 0;const solve = (b) => {for (let row = 0; row < 9; row++) {for (let col = 0; col < 9; col++) {if (b[row][col] === 0) {for (let num = 1; num <= 9; num++) {if (isValid(b, row, col, num)) {b[row][col] = num;solve(b);b[row][col] = 0;if (solutions > 1) return; // 超過1個解直接返回}}return;}}}solutions++;};solve(board);return solutions;};// 處理數字輸入const handleNumberInput = (num) => {if (isSolving || !selectedCell) return;const [row, col] = selectedCell;const newBoard = [...board];// 只能修改初始為0的單元格if (initialBoard[row][col] === 0) {newBoard[row][col] = num;setBoard(newBoard);}};// 清除單元格const clearCell = () => {if (isSolving || !selectedCell) return;const [row, col] = selectedCell;const newBoard = [...board];if (initialBoard[row][col] === 0) {newBoard[row][col] = 0;setBoard(newBoard);}};// 解決當前數獨const solveCurrent = () => {setIsSolving(true);setMessage('求解中...');const copy = JSON.parse(JSON.stringify(board));const solved = solveSudoku(copy);if (solved) {setBoard(copy);setMessage('求解成功!');} else {setMessage('無解!請檢查輸入是否正確');}setIsSolving(false);};// 初始化生成謎題useEffect(() => {generatePuzzle(difficulty);}, []);return (<div className="max-w-4xl mx-auto p-6 bg-gradient-to-br from-blue-50 to-indigo-100 min-h-screen"><div className="bg-white rounded-2xl shadow-xl p-8"><h1 className="text-3xl font-bold text-center mb-2 text-indigo-800">數獨求解器與生成器</h1><p className="text-center text-gray-600 mb-8">使用回溯算法實現</p><div className="flex flex-col md:flex-row gap-8">{/* 數獨棋盤 */}<div className="flex-1"><div className="bg-gray-100 p-4 rounded-xl inline-block"><div className="grid grid-cols-9 gap-0 border-2 border-gray-800">{board.map((row, rowIndex) => (row.map((cell, colIndex) => {const isSelected = selectedCell && selectedCell[0] === rowIndex && selectedCell[1] === colIndex;const isInitial = initialBoard[rowIndex][colIndex] !== 0;const isHighlighted = (rowIndex === selectedCell?.[0] || colIndex === selectedCell?.[1]) && selectedCell && !isInitial;return (<div key={`${rowIndex}-${colIndex}`}onClick={() => !isInitial && setSelectedCell([rowIndex, colIndex])}className={`w-10 h-10 flex items-center justify-center text-xl font-semiboldborder border-gray-300${rowIndex % 3 === 2 && rowIndex !== 8 ? 'border-b-2 border-gray-800' : ''}${colIndex % 3 === 2 && colIndex !== 8 ? 'border-r-2 border-gray-800' : ''}${isSelected ? 'bg-indigo-200' : ''}${isHighlighted ? 'bg-indigo-100' : ''}${isInitial ? 'text-indigo-800' : 'text-gray-800 hover:bg-gray-200 cursor-pointer'}`}>{cell !== 0 ? cell : ''}</div>);})))}</div></div></div>{/* 控制面板 */}<div className="w-full md:w-64 space-y-6"><div className="bg-indigo-50 p-5 rounded-xl shadow-sm"><h3 className="font-semibold text-indigo-800 mb-3 flex items-center gap-2"><Gauge size={18} /> 難度選擇</h3><div className="space-y-2">{['easy', 'medium', 'hard'].map((level) => (<buttonkey={level}onClick={() => {setDifficulty(level);generatePuzzle(level);}}className={`w-full py-2 px-3 rounded-lg text-sm font-medium transition-all ${difficulty === level ? 'bg-indigo-600 text-white shadow-md' : 'bg-white text-indigo-700 hover:bg-indigo-100'}`}>{getDifficultyName(level)}</button>))}</div></div><div className="bg-indigo-50 p-5 rounded-xl shadow-sm"><h3 className="font-semibold text-indigo-800 mb-3">數字輸入</h3><div className="grid grid-cols-3 gap-2">{[1, 2, 3, 4, 5, 6, 7, 8, 9].map((num) => (<buttonkey={num}onClick={() => handleNumberInput(num)}className="w-full py-3 bg-white hover:bg-indigo-100 text-indigo-800 font-bold rounded-lg shadow-sm transition-all hover:scale-105">{num}</button>))}</div></div><div className="space-y-3"><buttononClick={clearCell}disabled={isSolving || !selectedCell}className={`w-full py-3 px-4 rounded-lg font-medium flex items-center justify-center gap-2 transition-all ${isSolving || !selectedCell ? 'bg-gray-200 text-gray-500 cursor-not-allowed' : 'bg-white hover:bg-gray-100 text-indigo-800 shadow-sm'}`}><Eraser size={18} /> 清除</button><buttononClick={solveCurrent}disabled={isSolving}className={`w-full py-3 px-4 rounded-lg font-medium flex items-center justify-center gap-2 transition-all ${isSolving ? 'bg-indigo-400 text-white cursor-not-allowed' : 'bg-indigo-600 hover:bg-indigo-700 text-white shadow-md'}`}><Play size={18} /> 求解</button><buttononClick={() => generatePuzzle(difficulty)}disabled={isSolving}className={`w-full py-3 px-4 rounded-lg font-medium flex items-center justify-center gap-2 transition-all ${isSolving ? 'bg-indigo-400 text-white cursor-not-allowed' : 'bg-indigo-600 hover:bg-indigo-700 text-white shadow-md'}`}><RefreshCw size={18} /> 新謎題</button></div><div className="bg-indigo-50 p-4 rounded-xl text-center"><p className={`font-medium ${message.includes('成功') ? 'text-green-700' : message.includes('無解') ? 'text-red-700' : 'text-indigo-800'}`}>{message}</p></div></div></div><div className="mt-8 text-center text-sm text-gray-500"><p>算法說明:使用回溯算法生成和求解數獨謎題</p><p className="mt-1">初始數字無法修改,空白單元格可自由填寫</p></div></div></div>);
};export default SudokuSolverGenerator;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/93154.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/93154.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/93154.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[數據結構]#7 哈希表

哈希表&#xff08;Hash Table&#xff09;&#xff0c;有時也稱為散列表&#xff0c;是一種數據結構&#xff0c;它提供了一種快速存取數據的方法。哈希表利用一個被稱為哈希函數的機制將鍵映射到表中的一個位置來直接訪問記錄&#xff0c;以此加快查找的速度。哈希表通常支持…

C++ 23種設計模式-工廠模式

工廠模式是一種創建型的設計模式&#xff0c;他提供了一種創建對象的最佳方式&#xff0c;而無需指定將要創建對象的具體類。包括&#xff1a;簡單工廠模式、工廠方法模式、抽象工廠模式。簡單工廠模式組成成員&#xff1a;抽象產品類、具體產品類 A、B、C等、工廠類工作原理&a…

vue3 el-table 行的某個特定值來決定某些列是否顯示

在 Vue 3 中使用 Element Plus 的 <el-table> 組件時&#xff0c;如果你想要根據行的某個特定值來決定某些列是否顯示&#xff0c;你可以通過自定義列渲染函數&#xff08;render 函數&#xff09;來實現這一需求。下面是一個如何實現該功能的步驟說明和示例代碼。步驟 1…

電商數據采集API與爬蟲技術結合的全網比價方案

一、技術選型與工具準備API優先策略官方API接入&#xff1a;京東、淘寶、拼多多等平臺提供商品詳情API&#xff0c;需注冊開發者賬號獲取API Key。例如&#xff1a;京東API支持實時獲取商品價格、庫存、評價數據。淘寶API通過RESTful接口返回JSON格式的商品信息&#xff0c;需O…

Socket詳解

一.定義Socket&#xff08;套接字&#xff09;是網絡編程的核心&#xff0c;它允許不同主機或同一主機的不同進程之間進行通信&#xff0c;Socket API 提供了一套標準的接口&#xff0c;支持 TCP、UDP、IP 等協議分為以下三個類型&#xff1a;SOCK_STREAM: 用于tcp協議&#xf…

如何實現打印功能

一、AI賦能提供思路基本框架<!-- 隱藏的打印內容&#xff08;默認不顯示&#xff09; --> <div id"print-container" style"display: none;"><h1>退貨單打印內容</h1><table><!-- 打印專用的表格結構 --></table&g…

Android 架構演進:從 MVC 到 MVVM 的設計之道

在 Android 開發初期&#xff0c;很多開發者會把所有邏輯塞進 Activity—— 網絡請求、數據處理、UI 更新全堆在一起&#xff0c;導致代碼超過數千行&#xff0c;改一個按鈕點擊都要翻半天。這種 “面條式代碼” 的根源是缺乏架構設計。隨著應用復雜度提升&#xff0c;MVC、MVP…

使用 gh-pages 將 next.js15 靜態項目部署到 github pages

以下我使用 next.js15 寫的 Todo List 為例,假設我們本地已經存在一個 next.js15 的 Todo List 項目。 說明:解決了項目部署到 github pages 后訪問不到 css、js、字體以及訪問不到 public 目錄下的圖片問題。 第一步 安裝 gh-pages: npm i gh-pages第二步 在 public 目…

rename系統調用及示例

21. rename - 重命名文件或目錄 函數介紹 rename系統調用用于重命名文件或目錄&#xff0c;也可以將文件或目錄移動到另一個位置。如果目標文件已存在&#xff0c;則會被替換。 函數原型 #include <stdio.h>int rename(const char *oldpath, const char *newpath);功能 將…

PHP框架之Laravel框架教程:3. 數據庫操作(簡要)

3. 數據庫操作&#xff08;簡要&#xff09; 配置 數據庫的配置文件在 config/database.php 文件中&#xff0c;你可以在這個文件中定義所有的數據庫連接配置&#xff0c;并指定默認的數據庫連接。這個文件中提供了大部分 Laravel 能夠支持的數據庫配置示例。 mysql > [driv…

項目七.AI大模型部署

環境準備此處使用的是rock linux8.9操作系統k8s集群三個設備&#xff0c;使用centos7.9操作系統設備配置##上傳ollama工具的壓縮包 [rootproject ~]# ll total 1497732 -rw-r--r-- 1 root root 1533674176 Jul 21 11:27 ollama-linux-amd64.tgz [rootproject ~]# tar -C /usr -…

Oracle 19C RU 19.28 升級和安裝

背景介紹 概述 本次升級包括安全漏掃中所有19c數據庫,漏掃預警版本19.3到19.27各個版本,數據庫需要升級至19.28版本滿足安全要求。 原端19C 升級目標端19.28 db_name racdb racdb ORACLE_SID racdb1/2 racdb1/2 ORACLE_HOME GI:/oracle/asm DB:/oracle/db GI:/orac…

嵌入式學習日志————對射式紅外傳感器計次

前言這是第二次學習這部分內容了&#xff0c;第一次是大一上學期&#xff0c;因為大二下忙著其他事一直沒來得及吧STM32學完&#xff0c;所以假期從頭開始再學&#xff0c;比第一次也有了更深的理解&#xff0c;以下內容均是看【STM32入門教程-2023版 細致講解 中文字幕】https…

ONLYOFFICE深度解鎖系列.13-如何復制、重新排序 PDF 頁面:onlyoffice 9.0.3 新功能

在處理合同、講義、研究資料或掃描文檔時&#xff0c;保持頁面順序井然尤為重要。有時文件頁數繁多、排序混亂或缺少邏輯&#xff0c;這不僅影響閱讀體驗&#xff0c;也不利于后續使用或分享。好消息是&#xff0c;借助 ONLYOFFICE PDF 編輯器&#xff0c;您可以輕松拖拽頁面&a…

vue遞歸樹形結構刪除不符合數據 生成一個新數組

首先看一下數據結構&#xff08;我的是路由菜單&#xff09;{"code": 200,"message": "請求成功!","success": true,"data": [{"startDate": null,"endDate": null,"createTime": "2023…

【機器學習之推薦算法】基于K最近鄰的協同過濾推薦與基于回歸模型的協同過濾推薦

基于K最近鄰的協同過濾推薦 基于K最近鄰的協同過濾推薦其實本質上就是MemoryBased CF&#xff0c;只不過在選取近鄰的時候&#xff0c;加上K最近鄰的限制。 這里我們直接根據MemoryBased CF的代碼實現 修改以下地方 class CollaborativeFiltering(object):based Nonedef __ini…

望言OCR視頻字幕提取2025終極評測:免費版VS專業版提全方位對比(含免費下載)

大家好&#xff0c;歡迎來到程序視點&#xff01;我是你們的老朋友.小二&#xff01;一、產品定位&#xff1a;AI時代的視頻字幕處理專家望言OCR作為專業的視頻硬字幕提取工具&#xff0c;在AI視頻處理領域占據重要地位。最新評測顯示&#xff0c;其免費版本依然保持著驚人的97…

Matplotlib(二)- Matplotlib簡單繪圖

文章目錄一、pyplot模塊介紹二、Matplotlib簡單繪圖1. 繪制折線圖1.1 折線圖介紹1.2 plt.plot()函數介紹1.3 繪制簡單折線圖1.3.1 繪制單條折線圖1.3.2 繪制多條折線圖1.4 示例&#xff1a;繪制天氣氣溫折線圖2. 繪制柱形圖2.1 柱形圖介紹2.2 plt.bar()函數介紹2.3 繪制柱形圖2…

【世紀龍科技】數字化技術解鎖新能源汽車電驅動總成裝調與檢修

隨著新能源汽車產業加速升級&#xff0c;電驅動總成裝調與檢修技術已成為職業院校汽車專業教學的核心挑戰。傳統實訓模式面臨設備投入高、更新周期長、高壓操作安全隱患多、教學與產業需求脫節等現實問題&#xff0c;導致學生實踐能力培養滯后于行業發展。如何通過數字化手段突…

springboot基于Java與MySQL庫的健身俱樂部管理系統設計與實現

用戶&#xff1a;注冊&#xff0c;登錄&#xff0c;健身教練&#xff0c;健身課程&#xff0c;健身器材&#xff0c;健身資訊&#xff0c;課程報名管理&#xff0c;教練預約管理&#xff0c;會員充值管理&#xff0c;個人中心管理員&#xff1a;登錄&#xff0c;個人中心&#…