diff --git a/text-to-cards.html b/text-to-cards.html index a54febd..739de8d 100644 --- a/text-to-cards.html +++ b/text-to-cards.html @@ -92,9 +92,9 @@

編碼:文字 → 撲克牌

- - -
0 / 13 字符
+ + +
0 / 14 字符
等待輸入文字...
@@ -259,42 +259,38 @@ /** * 將文字轉換為撲克牌排列 - * 這是整個編碼系統的核心函數 - * 步驟:文字 → 數字編碼 → 排列 → 撲克牌順序 + * 新版本:直接編碼14個字符,不足的用null字符填充 + * 步驟:文字 → 填充到14字符 → 數字編碼 → 排列 → 撲克牌順序 * * @param {string} text - 要編碼的文字 * @returns {Array} 對應的撲克牌索引排列 */ function textToCards(text) { - // 計算最大可編碼的字符數(每個字符16位,總共224位) - const maxChars = Math.floor(224 / 16); - - // 檢查文字長度是否超出限制(需要保留1個字符位置存儲長度信息) - if (text.length > maxChars - 1) { - throw new Error(`文字長度不能超過 ${maxChars - 1} 個字符`); + // 檢查文字長度是否超出限制 + if (text.length > 14) { + throw new Error('文字長度不能超過 14 個字符'); } - // 先將文字長度編碼到數字中 - let bigNumber = BigInt(text.length); + // 將文字填充到14個字符,不足的用null字符(\u0000)填充 + let paddedText = text.padEnd(14, '\u0000'); + + // 將填充後的文字轉換為一個大數字 + let bigNumber = 0n; // 將每個字符的Unicode編碼拼接到數字中(每個字符佔16位) - for (let i = 0; i < text.length; i++) { - let charCode = text.charCodeAt(i); + for (let i = 0; i < 14; i++) { + let charCode = paddedText.charCodeAt(i); bigNumber = bigNumber * (2n ** 16n) + BigInt(charCode); } - // 在末尾補零,確保總長度固定 - let remainingBits = (maxChars - 1 - text.length) * 16; - bigNumber = bigNumber * (2n ** BigInt(remainingBits)); - // 將數字轉換為52張牌的排列 return convertToPermutation(bigNumber, 52); } /** * 將撲克牌排列轉換回文字 - * 這是textToCards函數的逆運算 - * 步驟:撲克牌順序 → 排列 → 數字解碼 → 文字 + * 新版本:解碼14個字符,遇到第一個null字符就停止 + * 步驟:撲克牌順序 → 排列 → 數字解碼 → 14字符字串 → 去除null填充 * * @param {Array} cardOrder - 撲克牌索引排列 * @returns {string} 解碼出的文字 @@ -314,31 +310,24 @@ // 將排列轉換回數字 let bigNumber = convertFromPermutation(cardOrder); - // 計算參數 - let maxChars = Math.floor(224 / 16) - 1; - let lengthBits = maxChars * 16; - - // 從高位提取文字長度信息 - let textLength = Number(bigNumber >> BigInt(lengthBits)); - - // 提取內容部分(去掉長度信息) - let contentMask = (2n ** BigInt(lengthBits)) - 1n; - bigNumber = bigNumber & contentMask; - - let result = ""; - - // 移除末尾的填充零 - let paddingBits = (maxChars - textLength) * 16; - bigNumber = bigNumber >> BigInt(paddingBits); - - // 逐個字符解碼(從低位開始) - for (let i = 0; i < textLength; i++) { + // 逐個字符解碼(從低位開始,總共14個字符) + let chars = []; + for (let i = 0; i < 14; i++) { let charCode = Number(bigNumber % (2n ** 16n)); // 取低16位 - result = String.fromCharCode(charCode) + result; // 插入到字串開頭 + chars.unshift(String.fromCharCode(charCode)); // 插入到數組開頭 bigNumber = bigNumber >> 16n; // 右移16位,處理下一個字符 } - return result; + // 將字符數組合併成字串 + let fullText = chars.join(''); + + // 找到第一個null字符的位置,如果沒有則返回完整字串 + let nullIndex = fullText.indexOf('\u0000'); + if (nullIndex === -1) { + return fullText; // 沒有null字符,返回完整的14字符 + } else { + return fullText.substring(0, nullIndex); // 在第一個null字符處截斷 + } } /** @@ -502,7 +491,7 @@ const cardsOutputEl = document.getElementById('cardsOutput'); // 更新字符計數顯示 - charCountEl.textContent = `${text.length} / 13 字符`; + charCountEl.textContent = `${text.length} / 14 字符`; // 如果沒有輸入文字,顯示等待訊息 if (text.length === 0) {