源本科技 | 码上会

回文检测器

2026/01/12
13
0

学习目标

  • 理解回文的定义及其在编程中的判断逻辑

  • 掌握字符串预处理技巧:去除非字母数字字符、统一大小写

  • 学会使用正则表达式进行文本清洗

  • 实现完整的 Web 表单交互应用(HTML + CSS + JS)

  • 培养用户输入验证与友好反馈的设计意识


什么是回文

回文 是指正读和反读完全相同的单词、短语或数字序列。

经典示例:

  • 单词:"level""radar""madam"

  • 短语:"A man a plan a canal Panama"

  • 数字:123211221

注意:判断时需忽略空格、标点符号和大小写。例如 "Was it a car or a cat I saw?" 是回文


应用功能设计

我们将开发一个回文检测 Web 应用,具备以下特性:

  • 用户在文本框中输入任意内容(单词、句子、带标点的短语)

  • 点击【检查回文】按钮后,程序自动清洗并判断是否为回文

  • 动态显示结果,并使用颜色区分:

    • 绿色:是回文

    • 红色:不是回文

    • ⚠️ 橙色:输入为空


HTML 结构搭建

<div class="container">
  <h1>回文检测器</h1>
  <p>请输入一个单词或短语,检测它是否为回文。</p>
  <input type="text" id="input" placeholder="在此输入...">
  <button id="check">检查回文</button>
  <div id="result"></div>
</div>

元素说明:

  • <input type="text">:接受任意文本输入

  • id="input":用于 JavaScript 获取用户输入

  • id="check":按钮绑定点击事件

  • id="result":动态显示判断结果(使用 <div> 而非 <p> 更灵活)


CSS 样式美化

body {
  font-family: Arial, sans-serif;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: #f0f0f0;
  margin: 0;
}

.container {
  background-color: white;
  padding: 20px;
  border-radius: 10px;
  text-align: center;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
  width: 90%;
  max-width: 400px;
}

h1 {
  font-size: 1.5em;
  color: #333;
  margin-bottom: 10px;
}

p {
  font-size: 1em;
  color: #666;
  margin-bottom: 20px;
}

input {
  width: 100%;
  padding: 10px;
  font-size: 1em;
  border: 1px solid #ddd;
  border-radius: 5px;
  margin-bottom: 10px;
  box-sizing: border-box;
}

button {
  width: 100%;
  padding: 10px;
  font-size: 1em;
  background-color: #007BFF;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  transition: background-color 0.2s;
}

button:hover {
  background-color: #0056b3;
}

#result {
  margin-top: 20px;
  font-size: 1.1em;
  min-height: 1.5em; /* 防止布局跳动 */
}

设计亮点:

  • 响应式布局max-width: 400px 适配移动端

  • 视觉反馈:按钮悬停变色 + 平滑过渡

  • 布局稳定min-height 避免结果切换时页面“抖动”


JavaScript 核心逻辑

document.getElementById('check').addEventListener('click', function () {
  // 1. 获取并清理用户输入
  const userInput = document.getElementById('input').value.trim();
  const resultElement = document.getElementById('result');

  // 2. 输入验证
  if (!userInput) {
    resultElement.textContent = '请输入一些文本。';
    resultElement.style.color = 'orange';
    return;
  }

  // 3. 文本标准化:仅保留字母和数字,并转为小写
  const normalized = userInput.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();

  // 4. 反转字符串
  const reversed = normalized.split('').reverse().join('');

  // 5. 判断并显示结果
  if (normalized === reversed) {
    resultElement.innerHTML = `“${userInput}” 是一个回文!`;
    resultElement.style.color = 'green';
  } else {
    resultElement.innerHTML = `“${userInput}” 不是回文。`;
    resultElement.style.color = 'red';
  }
});

关键技术点

步骤

技术实现

说明

文本清洗

replace(/[^a-zA-Z0-9]/g, '')

使用正则表达式移除所有非字母数字字符

大小写统一

.toLowerCase()

确保 "A""a" 被视为相同

字符串反转

split('').reverse().join('')

将字符串转数组 → 反转 → 合并回字符串

结果展示

使用 innerHTML

支持显示引号包裹的原始输入

性能提示:对于超长文本,可考虑双指针法(从两端向中间比较),避免创建反转字符串,节省内存


完整代码整合

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>回文检测器</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      background-color: #f0f0f0;
      margin: 0;
    }
    .container {
      background-color: white;
      padding: 20px;
      border-radius: 10px;
      text-align: center;
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
      width: 90%;
      max-width: 400px;
    }
    h1 {
      font-size: 1.5em;
      color: #333;
      margin-bottom: 10px;
    }
    p {
      font-size: 1em;
      color: #666;
      margin-bottom: 20px;
    }
    input {
      width: 100%;
      padding: 10px;
      font-size: 1em;
      border: 1px solid #ddd;
      border-radius: 5px;
      margin-bottom: 10px;
      box-sizing: border-box;
    }
    button {
      width: 100%;
      padding: 10px;
      font-size: 1em;
      background-color: #007BFF;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      transition: background-color 0.2s;
    }
    button:hover {
      background-color: #0056b3;
    }
    #result {
      margin-top: 20px;
      font-size: 1.1em;
      min-height: 1.5em;
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>回文检测器</h1>
    <p>请输入一个单词或短语,检测它是否为回文。</p>
    <input type="text" id="input" placeholder="在此输入...">
    <button id="check">检查回文</button>
    <div id="result"></div>
  </div>

  <script>
    document.getElementById('check').addEventListener('click', function () {
      const userInput = document.getElementById('input').value.trim();
      const resultElement = document.getElementById('result');

      if (!userInput) {
        resultElement.textContent = '请输入一些文本。';
        resultElement.style.color = 'orange';
        return;
      }

      const normalized = userInput.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
      const reversed = normalized.split('').reverse().join('');

      if (normalized === reversed) {
        resultElement.innerHTML = `“${userInput}” 是一个回文!`;
        resultElement.style.color = 'green';
      } else {
        resultElement.innerHTML = `“${userInput}” 不是回文。`;
        resultElement.style.color = 'red';
      }
    });
  </script>
</body>
</html>

进阶练习

  1. 实时检测:监听 input 事件,用户输入时自动检测(需防抖)

  2. 支持中文回文:如 “上海海上”、“山西运煤车煤运西山”

  3. 高亮差异:若非回文,标出第一个不匹配的位置

  4. 历史记录:保存最近 5 次检测结果

  5. 算法优化:使用双指针法,空间复杂度 O(1)

// 双指针法示例(更高效)
function isPalindrome(str) {
  let left = 0, right = str.length - 1;
  while (left < right) {
    if (str[left] !== str[right]) return false;
    left++;
    right--;
  }
  return true;
}

重点总结

  • 回文本质:正反读一致,需忽略格式干扰

  • 文本清洗:正则 /[^a-zA-Z0-9]/g 是关键

  • 字符串反转split-reverse-join 是常用技巧

  • 用户体验:清晰提示 + 颜色反馈 + 输入验证

  • 工程实践:事件委托、DOM 操作、样式分离


思考题

  1. 当前代码无法正确处理中文回文(如 “人人为我,我为人人”)。如何修改正则表达式以支持 Unicode 字符?

  2. 如果用户输入 "race a car",标准化后为 "raceacar",这不是回文。但若我们只考虑字母(忽略空格和标点),它是否应被视为回文?为什么?

  3. 如何防止用户输入超长字符串(如 10 万字符)导致页面卡顿?请提出至少两种优化方案。