
一、应用概述与游戏背景
成语接龙是一款经典的中文文字游戏,历史悠久,深受大众喜爱。游戏规则简单明了:参与者需要根据上一个成语的最后一个字,接出下一个以该字开头的成语。这个游戏不仅能锻炼语言表达能力,还能增长成语知识,培养思维敏捷性。
成语接龙小应用将这个传统游戏数字化,让用户可以在闲暇时光进行单人练习。应用内置了20个常用成语,用户需要从成语库中选择合适的成语进行接龙。每次成功接龙都会获得积分,同时记录接龙历史,让用户可以回顾自己的游戏过程。
这款应用基于HarmonyOS ArkUI框架开发,采用了声明式UI开发范式。界面简洁直观,操作便捷,适合各年龄段用户使用。从技术角度来看,这个应用涵盖了HarmonyOS开发中的多个核心知识点:字符串操作、数组管理、条件验证、TextInput组件应用、游戏逻辑实现等。通过学习这个应用的开发过程,开发者可以深入理解ArkTS语言的字符串处理能力和游戏逻辑设计思路。
二、功能特性详解
2.1 核心功能列表
成语接龙小应用提供了以下核心功能:
| 功能模块 | 功能描述 | 技术实现 |
|---|---|---|
| 成语显示 | 显示当前成语和提示信息 | Text组件 |
| 用户输入 | TextInput接收成语输入 | TextInput + onChange |
| 成语验证 | 验证成语的有效性和接龙规则 | checkIdiom方法 |
| 得分统计 | 记录成功接龙的次数 | 状态变量score |
| 历史记录 | 展示接龙历史链 | 数组history |
| 重新开始 | 重置游戏状态 | Button + onClick |
| 参考成语 | 显示可用成语列表 | Text + join |
2.2 游戏规则说明
成语接龙游戏的规则如下:
#mermaid-svg-jGJbKD7C0nBCkson{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jGJbKD7C0nBCkson .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jGJbKD7C0nBCkson .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jGJbKD7C0nBCkson .error-icon{fill:#552222;}#mermaid-svg-jGJbKD7C0nBCkson .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jGJbKD7C0nBCkson .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jGJbKD7C0nBCkson .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jGJbKD7C0nBCkson .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jGJbKD7C0nBCkson .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jGJbKD7C0nBCkson .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jGJbKD7C0nBCkson .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jGJbKD7C0nBCkson .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jGJbKD7C0nBCkson .marker.cross{stroke:#333333;}#mermaid-svg-jGJbKD7C0nBCkson svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jGJbKD7C0nBCkson p{margin:0;}#mermaid-svg-jGJbKD7C0nBCkson .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jGJbKD7C0nBCkson .cluster-label text{fill:#333;}#mermaid-svg-jGJbKD7C0nBCkson .cluster-label span{color:#333;}#mermaid-svg-jGJbKD7C0nBCkson .cluster-label span p{background-color:transparent;}#mermaid-svg-jGJbKD7C0nBCkson .label text,#mermaid-svg-jGJbKD7C0nBCkson span{fill:#333;color:#333;}#mermaid-svg-jGJbKD7C0nBCkson .node rect,#mermaid-svg-jGJbKD7C0nBCkson .node circle,#mermaid-svg-jGJbKD7C0nBCkson .node ellipse,#mermaid-svg-jGJbKD7C0nBCkson .node polygon,#mermaid-svg-jGJbKD7C0nBCkson .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jGJbKD7C0nBCkson .rough-node .label text,#mermaid-svg-jGJbKD7C0nBCkson .node .label text,#mermaid-svg-jGJbKD7C0nBCkson .image-shape .label,#mermaid-svg-jGJbKD7C0nBCkson .icon-shape .label{text-anchor:middle;}#mermaid-svg-jGJbKD7C0nBCkson .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jGJbKD7C0nBCkson .rough-node .label,#mermaid-svg-jGJbKD7C0nBCkson .node .label,#mermaid-svg-jGJbKD7C0nBCkson .image-shape .label,#mermaid-svg-jGJbKD7C0nBCkson .icon-shape .label{text-align:center;}#mermaid-svg-jGJbKD7C0nBCkson .node.clickable{cursor:pointer;}#mermaid-svg-jGJbKD7C0nBCkson .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jGJbKD7C0nBCkson .arrowheadPath{fill:#333333;}#mermaid-svg-jGJbKD7C0nBCkson .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jGJbKD7C0nBCkson .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jGJbKD7C0nBCkson .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jGJbKD7C0nBCkson .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jGJbKD7C0nBCkson .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jGJbKD7C0nBCkson .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jGJbKD7C0nBCkson .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jGJbKD7C0nBCkson .cluster text{fill:#333;}#mermaid-svg-jGJbKD7C0nBCkson .cluster span{color:#333;}#mermaid-svg-jGJbKD7C0nBCkson div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jGJbKD7C0nBCkson .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jGJbKD7C0nBCkson rect.text{fill:none;stroke-width:0;}#mermaid-svg-jGJbKD7C0nBCkson .icon-shape,#mermaid-svg-jGJbKD7C0nBCkson .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jGJbKD7C0nBCkson .icon-shape p,#mermaid-svg-jGJbKD7C0nBCkson .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jGJbKD7C0nBCkson .icon-shape .label rect,#mermaid-svg-jGJbKD7C0nBCkson .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jGJbKD7C0nBCkson .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jGJbKD7C0nBCkson .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jGJbKD7C0nBCkson :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 字数不对
首字不对
已使用
不在库中
验证通过
游戏开始
显示初始成语
用户输入成语
验证成语
提示:请输入四字成语
提示:首字不对
提示:成语已用过
提示:不是有效成语
添加到历史
得分+1
更新当前成语
清空输入框
显示成功提示
2.3 界面设计说明
应用的界面设计遵循简洁直观的原则,主要分为以下几个区域:
- 得分显示区:顶部显示当前得分,蓝色字体醒目
- 当前成语区:显示当前成语和接龙提示,大号字体突出
- 输入区域:TextInput组件接收用户输入,支持回车提交
- 提交按钮:蓝色按钮,点击验证成语
- 提示信息区:显示验证结果,绿色或红色区分成功失败
- 历史记录区:用箭头连接展示接龙历史
- 重新开始按钮:灰色按钮,重置游戏状态
- 参考成语区:显示成语库中的所有成语
三、成语库设计
3.1 成语数据结构
应用使用数组存储成语库:
typescript
idioms_1: string[] = [
'一心一意', '意气风发', '发扬光大', '大海捞针', '针锋相对',
'对牛弹琴', '琴棋书画', '画蛇添足', '足智多谋', '谋事在人',
'人山人海', '海阔天空', '空穴来风', '风花雪月', '月明星稀',
'稀奇古怪', '怪力乱神', '神采飞扬', '扬眉吐气', '气吞山河'
];
3.2 成语库特点分析
这个成语库的设计有以下特点:
| 特点 | 说明 | 优势 |
|---|---|---|
| 链式设计 | 成语首尾相连 | 确保可以连续接龙 |
| 数量适中 | 20个成语 | 适合单人练习 |
| 常用成语 | 都是常见成语 | 降低游戏难度 |
| 循环可能 | 可形成闭环 | 增加游戏趣味 |
3.3 成语接龙链分析
成语库中的成语形成了完整的接龙链:
#mermaid-svg-qYT4dxX55xATFejD{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qYT4dxX55xATFejD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qYT4dxX55xATFejD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qYT4dxX55xATFejD .error-icon{fill:#552222;}#mermaid-svg-qYT4dxX55xATFejD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qYT4dxX55xATFejD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qYT4dxX55xATFejD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qYT4dxX55xATFejD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qYT4dxX55xATFejD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qYT4dxX55xATFejD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qYT4dxX55xATFejD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qYT4dxX55xATFejD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qYT4dxX55xATFejD .marker.cross{stroke:#333333;}#mermaid-svg-qYT4dxX55xATFejD svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qYT4dxX55xATFejD p{margin:0;}#mermaid-svg-qYT4dxX55xATFejD .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qYT4dxX55xATFejD .cluster-label text{fill:#333;}#mermaid-svg-qYT4dxX55xATFejD .cluster-label span{color:#333;}#mermaid-svg-qYT4dxX55xATFejD .cluster-label span p{background-color:transparent;}#mermaid-svg-qYT4dxX55xATFejD .label text,#mermaid-svg-qYT4dxX55xATFejD span{fill:#333;color:#333;}#mermaid-svg-qYT4dxX55xATFejD .node rect,#mermaid-svg-qYT4dxX55xATFejD .node circle,#mermaid-svg-qYT4dxX55xATFejD .node ellipse,#mermaid-svg-qYT4dxX55xATFejD .node polygon,#mermaid-svg-qYT4dxX55xATFejD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qYT4dxX55xATFejD .rough-node .label text,#mermaid-svg-qYT4dxX55xATFejD .node .label text,#mermaid-svg-qYT4dxX55xATFejD .image-shape .label,#mermaid-svg-qYT4dxX55xATFejD .icon-shape .label{text-anchor:middle;}#mermaid-svg-qYT4dxX55xATFejD .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qYT4dxX55xATFejD .rough-node .label,#mermaid-svg-qYT4dxX55xATFejD .node .label,#mermaid-svg-qYT4dxX55xATFejD .image-shape .label,#mermaid-svg-qYT4dxX55xATFejD .icon-shape .label{text-align:center;}#mermaid-svg-qYT4dxX55xATFejD .node.clickable{cursor:pointer;}#mermaid-svg-qYT4dxX55xATFejD .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qYT4dxX55xATFejD .arrowheadPath{fill:#333333;}#mermaid-svg-qYT4dxX55xATFejD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qYT4dxX55xATFejD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qYT4dxX55xATFejD .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qYT4dxX55xATFejD .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qYT4dxX55xATFejD .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qYT4dxX55xATFejD .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qYT4dxX55xATFejD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qYT4dxX55xATFejD .cluster text{fill:#333;}#mermaid-svg-qYT4dxX55xATFejD .cluster span{color:#333;}#mermaid-svg-qYT4dxX55xATFejD div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qYT4dxX55xATFejD .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qYT4dxX55xATFejD rect.text{fill:none;stroke-width:0;}#mermaid-svg-qYT4dxX55xATFejD .icon-shape,#mermaid-svg-qYT4dxX55xATFejD .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qYT4dxX55xATFejD .icon-shape p,#mermaid-svg-qYT4dxX55xATFejD .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qYT4dxX55xATFejD .icon-shape .label rect,#mermaid-svg-qYT4dxX55xATFejD .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qYT4dxX55xATFejD .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qYT4dxX55xATFejD .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qYT4dxX55xATFejD :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 一心一意
意气风发
发扬光大
大海捞针
针锋相对
对牛弹琴
琴棋书画
画蛇添足
足智多谋
谋事在人
人山人海
海阔天空
空穴来风
风花雪月
月明星稀
稀奇古怪
怪力乱神
神采飞扬
扬眉吐气
气吞山河
3.4 成语库扩展方向
如果需要扩展成语库,可以添加更多成语:
typescript
extendedIdioms: string[] = [
// 基础成语库
'一心一意', '意气风发', '发扬光大', ...
// 扩展成语
'河清海晏', '晏开警道', '道听途说', '说三道四',
'四面楚歌', '歌舞升平', '平步青云', '云开雾散'
];
四、状态管理实现
4.1 状态变量声明
应用使用了多个状态变量来管理游戏数据:
typescript
@State currentIdiom_1: string = '一心一意';
@State inputText_1: string = '';
@State history_1: string[] = ['一心一意'];
@State score_1: number = 0;
@State message_1: string = '';
状态变量说明表:
| 状态变量 | 类型 | 初始值 | 作用 |
|---|---|---|---|
| currentIdiom_1 | string | '一心一意' | 当前成语 |
| inputText_1 | string | '' | 用户输入内容 |
| history_1 | string\[\] | '一心一意' | 接龙历史记录 |
| score_1 | number | 0 | 游戏得分 |
| message_1 | string | '' | 提示信息 |
4.2 状态变量响应机制
当状态变量变化时,UI会自动更新:
界面组件 验证逻辑 状态变量 TextInput 用户 界面组件 验证逻辑 状态变量 TextInput 用户 #mermaid-svg-U1uuMPA7ibCX2E6D{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-U1uuMPA7ibCX2E6D .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-U1uuMPA7ibCX2E6D .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-U1uuMPA7ibCX2E6D .error-icon{fill:#552222;}#mermaid-svg-U1uuMPA7ibCX2E6D .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-U1uuMPA7ibCX2E6D .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-U1uuMPA7ibCX2E6D .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-U1uuMPA7ibCX2E6D .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-U1uuMPA7ibCX2E6D .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-U1uuMPA7ibCX2E6D .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-U1uuMPA7ibCX2E6D .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-U1uuMPA7ibCX2E6D .marker{fill:#333333;stroke:#333333;}#mermaid-svg-U1uuMPA7ibCX2E6D .marker.cross{stroke:#333333;}#mermaid-svg-U1uuMPA7ibCX2E6D svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-U1uuMPA7ibCX2E6D p{margin:0;}#mermaid-svg-U1uuMPA7ibCX2E6D .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-U1uuMPA7ibCX2E6D text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-U1uuMPA7ibCX2E6D .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-U1uuMPA7ibCX2E6D .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-U1uuMPA7ibCX2E6D .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-U1uuMPA7ibCX2E6D .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-U1uuMPA7ibCX2E6D #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-U1uuMPA7ibCX2E6D .sequenceNumber{fill:white;}#mermaid-svg-U1uuMPA7ibCX2E6D #sequencenumber{fill:#333;}#mermaid-svg-U1uuMPA7ibCX2E6D #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-U1uuMPA7ibCX2E6D .messageText{fill:#333;stroke:none;}#mermaid-svg-U1uuMPA7ibCX2E6D .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-U1uuMPA7ibCX2E6D .labelText,#mermaid-svg-U1uuMPA7ibCX2E6D .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-U1uuMPA7ibCX2E6D .loopText,#mermaid-svg-U1uuMPA7ibCX2E6D .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-U1uuMPA7ibCX2E6D .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-U1uuMPA7ibCX2E6D .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-U1uuMPA7ibCX2E6D .noteText,#mermaid-svg-U1uuMPA7ibCX2E6D .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-U1uuMPA7ibCX2E6D .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-U1uuMPA7ibCX2E6D .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-U1uuMPA7ibCX2E6D .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-U1uuMPA7ibCX2E6D .actorPopupMenu{position:absolute;}#mermaid-svg-U1uuMPA7ibCX2E6D .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-U1uuMPA7ibCX2E6D .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-U1uuMPA7ibCX2E6D .actor-man circle,#mermaid-svg-U1uuMPA7ibCX2E6D line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-U1uuMPA7ibCX2E6D :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输入成语更新inputText_1点击提交调用checkIdiom验证成语更新状态变量触发重新渲染显示验证结果
4.3 数据流向分析
游戏中的数据流向:
- 用户输入 → TextInput接收成语
- 状态更新 → 更新inputText_1
- 验证触发 → 点击提交按钮
- 验证逻辑 → checkIdiom方法执行
- 状态变化 → 更新相关状态变量
- UI更新 → 显示验证结果和历史
五、成语验证逻辑
5.1 验证方法实现
成语验证是游戏的核心逻辑,以下是完整的验证方法:
typescript
checkIdiom_1() {
if (this.inputText_1.length !== 4) {
this.message_1 = '请输入四字成语';
return;
}
let lastChar_1: string = this.currentIdiom_1.slice(-1);
let firstChar_1: string = this.inputText_1.slice(0, 1);
if (lastChar_1 !== firstChar_1) {
this.message_1 = '首字不对,应该是 "' + lastChar_1 + '" 开头';
return;
}
if (this.history_1.includes(this.inputText_1)) {
this.message_1 = '这个成语已经用过了';
return;
}
if (!this.idioms_1.includes(this.inputText_1)) {
this.message_1 = '不是有效的成语';
return;
}
this.history_1 = this.history_1.concat([this.inputText_1]);
this.currentIdiom_1 = this.inputText_1;
this.score_1++;
this.inputText_1 = '';
this.message_1 = '回答正确!+1分';
}
5.2 验证流程详解
#mermaid-svg-jAKtfqI24ZSIbWJL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jAKtfqI24ZSIbWJL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jAKtfqI24ZSIbWJL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jAKtfqI24ZSIbWJL .error-icon{fill:#552222;}#mermaid-svg-jAKtfqI24ZSIbWJL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jAKtfqI24ZSIbWJL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jAKtfqI24ZSIbWJL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jAKtfqI24ZSIbWJL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jAKtfqI24ZSIbWJL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jAKtfqI24ZSIbWJL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jAKtfqI24ZSIbWJL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jAKtfqI24ZSIbWJL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jAKtfqI24ZSIbWJL .marker.cross{stroke:#333333;}#mermaid-svg-jAKtfqI24ZSIbWJL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jAKtfqI24ZSIbWJL p{margin:0;}#mermaid-svg-jAKtfqI24ZSIbWJL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jAKtfqI24ZSIbWJL .cluster-label text{fill:#333;}#mermaid-svg-jAKtfqI24ZSIbWJL .cluster-label span{color:#333;}#mermaid-svg-jAKtfqI24ZSIbWJL .cluster-label span p{background-color:transparent;}#mermaid-svg-jAKtfqI24ZSIbWJL .label text,#mermaid-svg-jAKtfqI24ZSIbWJL span{fill:#333;color:#333;}#mermaid-svg-jAKtfqI24ZSIbWJL .node rect,#mermaid-svg-jAKtfqI24ZSIbWJL .node circle,#mermaid-svg-jAKtfqI24ZSIbWJL .node ellipse,#mermaid-svg-jAKtfqI24ZSIbWJL .node polygon,#mermaid-svg-jAKtfqI24ZSIbWJL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jAKtfqI24ZSIbWJL .rough-node .label text,#mermaid-svg-jAKtfqI24ZSIbWJL .node .label text,#mermaid-svg-jAKtfqI24ZSIbWJL .image-shape .label,#mermaid-svg-jAKtfqI24ZSIbWJL .icon-shape .label{text-anchor:middle;}#mermaid-svg-jAKtfqI24ZSIbWJL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jAKtfqI24ZSIbWJL .rough-node .label,#mermaid-svg-jAKtfqI24ZSIbWJL .node .label,#mermaid-svg-jAKtfqI24ZSIbWJL .image-shape .label,#mermaid-svg-jAKtfqI24ZSIbWJL .icon-shape .label{text-align:center;}#mermaid-svg-jAKtfqI24ZSIbWJL .node.clickable{cursor:pointer;}#mermaid-svg-jAKtfqI24ZSIbWJL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jAKtfqI24ZSIbWJL .arrowheadPath{fill:#333333;}#mermaid-svg-jAKtfqI24ZSIbWJL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jAKtfqI24ZSIbWJL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jAKtfqI24ZSIbWJL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jAKtfqI24ZSIbWJL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jAKtfqI24ZSIbWJL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jAKtfqI24ZSIbWJL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jAKtfqI24ZSIbWJL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jAKtfqI24ZSIbWJL .cluster text{fill:#333;}#mermaid-svg-jAKtfqI24ZSIbWJL .cluster span{color:#333;}#mermaid-svg-jAKtfqI24ZSIbWJL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jAKtfqI24ZSIbWJL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jAKtfqI24ZSIbWJL rect.text{fill:none;stroke-width:0;}#mermaid-svg-jAKtfqI24ZSIbWJL .icon-shape,#mermaid-svg-jAKtfqI24ZSIbWJL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jAKtfqI24ZSIbWJL .icon-shape p,#mermaid-svg-jAKtfqI24ZSIbWJL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jAKtfqI24ZSIbWJL .icon-shape .label rect,#mermaid-svg-jAKtfqI24ZSIbWJL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jAKtfqI24ZSIbWJL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jAKtfqI24ZSIbWJL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jAKtfqI24ZSIbWJL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 不是4字
是4字
不匹配
匹配
已使用
未使用
不在库中
在库中
开始验证
检查字数
返回:请输入四字成语
获取首尾字
首字匹配
返回:首字不对
检查是否已用
返回:成语已用过
检查成语库
返回:不是有效成语
验证通过
添加到历史
更新当前成语
得分+1
清空输入
返回:回答正确
5.3 验证条件分析
| 验证条件 | 检查内容 | 错误提示 | 优先级 |
|---|---|---|---|
| 字数验证 | inputText.length === 4 | 请输入四字成语 | 1 |
| 首字验证 | 首字 === 当前成语尾字 | 首字不对 | 2 |
| 重复验证 | history.includes(inputText) | 成语已用过 | 3 |
| 库验证 | idioms.includes(inputText) | 不是有效成语 | 4 |
5.4 字符串操作详解
验证过程中使用了多个字符串操作方法:
typescript
// 获取最后一个字符
let lastChar_1: string = this.currentIdiom_1.slice(-1);
// 获取第一个字符
let firstChar_1: string = this.inputText_1.slice(0, 1);
// 检查是否包含
this.history_1.includes(this.inputText_1)
this.idioms_1.includes(this.inputText_1)
字符串方法说明:
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
| slice(-1) | -1 | 最后一个字符 | 获取字符串末尾 |
| slice(0, 1) | 0, 1 | 第一个字符 | 获取字符串开头 |
| includes() | 字符串 | boolean | 检查是否包含 |
| length | 无 | 数字 | 字符串长度 |
六、用户输入处理
6.1 TextInput组件实现
用户输入使用TextInput组件:
typescript
TextInput({ placeholder: '输入四字成语' })
.width('80%')
.height(48)
.margin({ top: 20 })
.onChange((value_1: string) => {
this.inputText_1 = value_1;
})
.onSubmit(() => {
this.checkIdiom_1();
})
6.2 TextInput属性说明
| 属性 | 值 | 说明 |
|---|---|---|
| placeholder | '输入四字成语' | 占位提示文本 |
| width | '80%' | 宽度为父容器80% |
| height | 48 | 高度48px |
| onChange | 回调函数 | 输入变化时更新状态 |
| onSubmit | 回调函数 | 回车键提交 |
6.3 onChange回调详解
onChange回调实时更新输入内容:
typescript
.onChange((value_1: string) => {
this.inputText_1 = value_1;
})
回调机制说明:
- 参数value_1:当前输入的文本
- 每次输入变化都会触发
- 实时更新状态变量
- 为验证提供输入数据
6.4 onSubmit回调详解
onSubmit回调支持回车键提交:
typescript
.onSubmit(() => {
this.checkIdiom_1();
})
回调特点:
- 用户按下回车键时触发
- 直接调用验证方法
- 提供快捷提交方式
- 提升用户体验
七、提交按钮实现
7.1 提交按钮代码
提交按钮用于触发成语验证:
typescript
Button('提交')
.width('60%')
.height(40)
.margin({ top: 12 })
.backgroundColor('#0A59F7')
.onClick(() => {
this.checkIdiom_1();
})
7.2 按钮属性说明
| 属性 | 值 | 说明 |
|---|---|---|
| text | '提交' | 按钮文本 |
| width | '60%' | 宽度60% |
| height | 40 | 高度40px |
| backgroundColor | '#0A59F7' | 蓝色背景 |
| onClick | 回调函数 | 点击验证成语 |
7.3 提交流程分析
#mermaid-svg-pGS9pVBKioVnw5HA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pGS9pVBKioVnw5HA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pGS9pVBKioVnw5HA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pGS9pVBKioVnw5HA .error-icon{fill:#552222;}#mermaid-svg-pGS9pVBKioVnw5HA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pGS9pVBKioVnw5HA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pGS9pVBKioVnw5HA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pGS9pVBKioVnw5HA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pGS9pVBKioVnw5HA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pGS9pVBKioVnw5HA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pGS9pVBKioVnw5HA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pGS9pVBKioVnw5HA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pGS9pVBKioVnw5HA .marker.cross{stroke:#333333;}#mermaid-svg-pGS9pVBKioVnw5HA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pGS9pVBKioVnw5HA p{margin:0;}#mermaid-svg-pGS9pVBKioVnw5HA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pGS9pVBKioVnw5HA .cluster-label text{fill:#333;}#mermaid-svg-pGS9pVBKioVnw5HA .cluster-label span{color:#333;}#mermaid-svg-pGS9pVBKioVnw5HA .cluster-label span p{background-color:transparent;}#mermaid-svg-pGS9pVBKioVnw5HA .label text,#mermaid-svg-pGS9pVBKioVnw5HA span{fill:#333;color:#333;}#mermaid-svg-pGS9pVBKioVnw5HA .node rect,#mermaid-svg-pGS9pVBKioVnw5HA .node circle,#mermaid-svg-pGS9pVBKioVnw5HA .node ellipse,#mermaid-svg-pGS9pVBKioVnw5HA .node polygon,#mermaid-svg-pGS9pVBKioVnw5HA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pGS9pVBKioVnw5HA .rough-node .label text,#mermaid-svg-pGS9pVBKioVnw5HA .node .label text,#mermaid-svg-pGS9pVBKioVnw5HA .image-shape .label,#mermaid-svg-pGS9pVBKioVnw5HA .icon-shape .label{text-anchor:middle;}#mermaid-svg-pGS9pVBKioVnw5HA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pGS9pVBKioVnw5HA .rough-node .label,#mermaid-svg-pGS9pVBKioVnw5HA .node .label,#mermaid-svg-pGS9pVBKioVnw5HA .image-shape .label,#mermaid-svg-pGS9pVBKioVnw5HA .icon-shape .label{text-align:center;}#mermaid-svg-pGS9pVBKioVnw5HA .node.clickable{cursor:pointer;}#mermaid-svg-pGS9pVBKioVnw5HA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pGS9pVBKioVnw5HA .arrowheadPath{fill:#333333;}#mermaid-svg-pGS9pVBKioVnw5HA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pGS9pVBKioVnw5HA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pGS9pVBKioVnw5HA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pGS9pVBKioVnw5HA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pGS9pVBKioVnw5HA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pGS9pVBKioVnw5HA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pGS9pVBKioVnw5HA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pGS9pVBKioVnw5HA .cluster text{fill:#333;}#mermaid-svg-pGS9pVBKioVnw5HA .cluster span{color:#333;}#mermaid-svg-pGS9pVBKioVnw5HA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-pGS9pVBKioVnw5HA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pGS9pVBKioVnw5HA rect.text{fill:none;stroke-width:0;}#mermaid-svg-pGS9pVBKioVnw5HA .icon-shape,#mermaid-svg-pGS9pVBKioVnw5HA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pGS9pVBKioVnw5HA .icon-shape p,#mermaid-svg-pGS9pVBKioVnw5HA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pGS9pVBKioVnw5HA .icon-shape .label rect,#mermaid-svg-pGS9pVBKioVnw5HA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pGS9pVBKioVnw5HA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pGS9pVBKioVnw5HA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pGS9pVBKioVnw5HA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 验证失败
验证成功
点击提交按钮
调用checkIdiom方法
执行验证
显示错误提示
更新游戏状态
保持输入内容
清空输入框
更新得分和历史
显示成功提示
八、提示信息显示
8.1 提示信息实现
提示信息根据验证结果显示不同颜色:
typescript
Text(this.message_1)
.fontSize(14)
.fontColor(this.message_1.includes('正确') ? '#34C759' : '#FF3B30')
.margin({ top: 12 })
8.2 提示信息类型
| 提示类型 | 提示内容 | 颜色 | 含义 |
|---|---|---|---|
| 成功提示 | 回答正确!+1分 | #34C759(绿色) | 验证通过 |
| 字数错误 | 请输入四字成语 | #FF3B30(红色) | 输入格式错误 |
| 首字错误 | 首字不对,应该是... | #FF3B30(红色) | 接龙规则错误 |
| 重复错误 | 这个成语已经用过了 | #FF3B30(红色) | 重复使用 |
| 库错误 | 不是有效的成语 | #FF3B30(红色) | 成语不存在 |
8.3 动态颜色设置
提示信息的颜色根据内容动态设置:
typescript
.fontColor(this.message_1.includes('正确') ? '#34C759' : '#FF3B30')
颜色逻辑:
- 检查message是否包含'正确'
- 包含则使用绿色(成功)
- 不包含则使用红色(失败)
- 提供直观的视觉反馈
九、历史记录展示
9.1 历史记录实现
历史记录用箭头连接展示接龙链:
typescript
Text(this.history_1.join(' → '))
.fontSize(14)
.fontColor('#666666')
.margin({ top: 8, left: 20 })
.width('90%')
.maxLines(3)
.textOverflow({ overflow: TextOverflow.Ellipsis })
9.2 join方法详解
join方法将数组转换为字符串:
typescript
this.history_1.join(' → ')
join方法说明:
| 参数 | 说明 | 示例 |
|---|---|---|
| separator | 分隔符 | ' → ' |
| 返回值 | 连接后的字符串 | '一心一意 → 意气风发' |
9.3 历史记录示例
假设用户成功接龙了3次,历史记录显示如下:
一心一意 → 意气风发 → 发扬光大 → 大海捞针
9.4 文本溢出处理
历史记录可能很长,需要处理溢出:
typescript
.maxLines(3)
.textOverflow({ overflow: TextOverflow.Ellipsis })
溢出处理说明:
| 属性 | 值 | 说明 |
|---|---|---|
| maxLines | 3 | 最大显示3行 |
| textOverflow | Ellipsis | 超出部分显示省略号 |
十、重新开始功能
10.1 重新开始按钮实现
重新开始按钮重置游戏状态:
typescript
Button('重新开始')
.width('60%')
.height(40)
.margin({ top: 20 })
.backgroundColor('#8E8E93')
.onClick(() => {
this.currentIdiom_1 = '一心一意';
this.inputText_1 = '';
this.history_1 = ['一心一意'];
this.score_1 = 0;
this.message_1 = '';
})
10.2 状态重置说明
| 状态变量 | 重置值 | 说明 |
|---|---|---|
| currentIdiom_1 | '一心一意' | 重置为初始成语 |
| inputText_1 | '' | 清空输入框 |
| history_1 | '一心一意' | 重置历史记录 |
| score_1 | 0 | 清零得分 |
| message_1 | '' | 清空提示信息 |
10.3 重置流程分析
#mermaid-svg-6K9o2nt5HMKvyvSh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-6K9o2nt5HMKvyvSh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6K9o2nt5HMKvyvSh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6K9o2nt5HMKvyvSh .error-icon{fill:#552222;}#mermaid-svg-6K9o2nt5HMKvyvSh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6K9o2nt5HMKvyvSh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6K9o2nt5HMKvyvSh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6K9o2nt5HMKvyvSh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6K9o2nt5HMKvyvSh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6K9o2nt5HMKvyvSh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6K9o2nt5HMKvyvSh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6K9o2nt5HMKvyvSh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6K9o2nt5HMKvyvSh .marker.cross{stroke:#333333;}#mermaid-svg-6K9o2nt5HMKvyvSh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6K9o2nt5HMKvyvSh p{margin:0;}#mermaid-svg-6K9o2nt5HMKvyvSh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6K9o2nt5HMKvyvSh .cluster-label text{fill:#333;}#mermaid-svg-6K9o2nt5HMKvyvSh .cluster-label span{color:#333;}#mermaid-svg-6K9o2nt5HMKvyvSh .cluster-label span p{background-color:transparent;}#mermaid-svg-6K9o2nt5HMKvyvSh .label text,#mermaid-svg-6K9o2nt5HMKvyvSh span{fill:#333;color:#333;}#mermaid-svg-6K9o2nt5HMKvyvSh .node rect,#mermaid-svg-6K9o2nt5HMKvyvSh .node circle,#mermaid-svg-6K9o2nt5HMKvyvSh .node ellipse,#mermaid-svg-6K9o2nt5HMKvyvSh .node polygon,#mermaid-svg-6K9o2nt5HMKvyvSh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6K9o2nt5HMKvyvSh .rough-node .label text,#mermaid-svg-6K9o2nt5HMKvyvSh .node .label text,#mermaid-svg-6K9o2nt5HMKvyvSh .image-shape .label,#mermaid-svg-6K9o2nt5HMKvyvSh .icon-shape .label{text-anchor:middle;}#mermaid-svg-6K9o2nt5HMKvyvSh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-6K9o2nt5HMKvyvSh .rough-node .label,#mermaid-svg-6K9o2nt5HMKvyvSh .node .label,#mermaid-svg-6K9o2nt5HMKvyvSh .image-shape .label,#mermaid-svg-6K9o2nt5HMKvyvSh .icon-shape .label{text-align:center;}#mermaid-svg-6K9o2nt5HMKvyvSh .node.clickable{cursor:pointer;}#mermaid-svg-6K9o2nt5HMKvyvSh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-6K9o2nt5HMKvyvSh .arrowheadPath{fill:#333333;}#mermaid-svg-6K9o2nt5HMKvyvSh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6K9o2nt5HMKvyvSh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6K9o2nt5HMKvyvSh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6K9o2nt5HMKvyvSh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6K9o2nt5HMKvyvSh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6K9o2nt5HMKvyvSh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-6K9o2nt5HMKvyvSh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6K9o2nt5HMKvyvSh .cluster text{fill:#333;}#mermaid-svg-6K9o2nt5HMKvyvSh .cluster span{color:#333;}#mermaid-svg-6K9o2nt5HMKvyvSh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-6K9o2nt5HMKvyvSh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6K9o2nt5HMKvyvSh rect.text{fill:none;stroke-width:0;}#mermaid-svg-6K9o2nt5HMKvyvSh .icon-shape,#mermaid-svg-6K9o2nt5HMKvyvSh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6K9o2nt5HMKvyvSh .icon-shape p,#mermaid-svg-6K9o2nt5HMKvyvSh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-6K9o2nt5HMKvyvSh .icon-shape .label rect,#mermaid-svg-6K9o2nt5HMKvyvSh .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6K9o2nt5HMKvyvSh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6K9o2nt5HMKvyvSh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6K9o2nt5HMKvyvSh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 点击重新开始
重置当前成语
清空输入内容
重置历史记录
清零得分
清空提示信息
触发UI更新
游戏回到初始状态
十一、参考成语展示
11.1 参考成语实现
参考成语显示成语库中的所有成语:
typescript
Text(this.idioms_1.join(' 、'))
.fontSize(12)
.fontColor('#999999')
.margin({ top: 8, left: 20 })
.width('90%')
.maxLines(4)
.textOverflow({ overflow: TextOverflow.Ellipsis })
11.2 参考成语示例
成语库中的成语用顿号连接显示:
一心一意 、意气风发 、发扬光大 、大海捞针 、针锋相对 、对牛弹琴...
11.3 参考成语的作用
| 作用 | 说明 | 价值 |
|---|---|---|
| 提供参考 | 用户可以查看可用成语 | 降低游戏难度 |
| 学习成语 | 展示成语库内容 | 增长成语知识 |
| 辅助接龙 | 提示可接龙的成语 | 提高成功率 |
十二、UI布局结构
12.1 整体布局结构
应用采用Column垂直布局作为根容器:
#mermaid-svg-2fV0P7yZtZU0wV0L{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2fV0P7yZtZU0wV0L .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2fV0P7yZtZU0wV0L .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2fV0P7yZtZU0wV0L .error-icon{fill:#552222;}#mermaid-svg-2fV0P7yZtZU0wV0L .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2fV0P7yZtZU0wV0L .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2fV0P7yZtZU0wV0L .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2fV0P7yZtZU0wV0L .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2fV0P7yZtZU0wV0L .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2fV0P7yZtZU0wV0L .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2fV0P7yZtZU0wV0L .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2fV0P7yZtZU0wV0L .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2fV0P7yZtZU0wV0L .marker.cross{stroke:#333333;}#mermaid-svg-2fV0P7yZtZU0wV0L svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2fV0P7yZtZU0wV0L p{margin:0;}#mermaid-svg-2fV0P7yZtZU0wV0L .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2fV0P7yZtZU0wV0L .cluster-label text{fill:#333;}#mermaid-svg-2fV0P7yZtZU0wV0L .cluster-label span{color:#333;}#mermaid-svg-2fV0P7yZtZU0wV0L .cluster-label span p{background-color:transparent;}#mermaid-svg-2fV0P7yZtZU0wV0L .label text,#mermaid-svg-2fV0P7yZtZU0wV0L span{fill:#333;color:#333;}#mermaid-svg-2fV0P7yZtZU0wV0L .node rect,#mermaid-svg-2fV0P7yZtZU0wV0L .node circle,#mermaid-svg-2fV0P7yZtZU0wV0L .node ellipse,#mermaid-svg-2fV0P7yZtZU0wV0L .node polygon,#mermaid-svg-2fV0P7yZtZU0wV0L .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2fV0P7yZtZU0wV0L .rough-node .label text,#mermaid-svg-2fV0P7yZtZU0wV0L .node .label text,#mermaid-svg-2fV0P7yZtZU0wV0L .image-shape .label,#mermaid-svg-2fV0P7yZtZU0wV0L .icon-shape .label{text-anchor:middle;}#mermaid-svg-2fV0P7yZtZU0wV0L .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2fV0P7yZtZU0wV0L .rough-node .label,#mermaid-svg-2fV0P7yZtZU0wV0L .node .label,#mermaid-svg-2fV0P7yZtZU0wV0L .image-shape .label,#mermaid-svg-2fV0P7yZtZU0wV0L .icon-shape .label{text-align:center;}#mermaid-svg-2fV0P7yZtZU0wV0L .node.clickable{cursor:pointer;}#mermaid-svg-2fV0P7yZtZU0wV0L .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2fV0P7yZtZU0wV0L .arrowheadPath{fill:#333333;}#mermaid-svg-2fV0P7yZtZU0wV0L .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2fV0P7yZtZU0wV0L .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2fV0P7yZtZU0wV0L .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2fV0P7yZtZU0wV0L .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2fV0P7yZtZU0wV0L .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2fV0P7yZtZU0wV0L .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2fV0P7yZtZU0wV0L .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2fV0P7yZtZU0wV0L .cluster text{fill:#333;}#mermaid-svg-2fV0P7yZtZU0wV0L .cluster span{color:#333;}#mermaid-svg-2fV0P7yZtZU0wV0L div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2fV0P7yZtZU0wV0L .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2fV0P7yZtZU0wV0L rect.text{fill:none;stroke-width:0;}#mermaid-svg-2fV0P7yZtZU0wV0L .icon-shape,#mermaid-svg-2fV0P7yZtZU0wV0L .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2fV0P7yZtZU0wV0L .icon-shape p,#mermaid-svg-2fV0P7yZtZU0wV0L .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2fV0P7yZtZU0wV0L .icon-shape .label rect,#mermaid-svg-2fV0P7yZtZU0wV0L .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2fV0P7yZtZU0wV0L .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2fV0P7yZtZU0wV0L .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2fV0P7yZtZU0wV0L :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Column 根容器
Row 标题栏
Column 内容区
Button 返回
Text 标题
Text 得分
Text 当前成语提示
Text 当前成语
Text 接龙提示
TextInput 输入框
Button 提交
Text 提示信息
Text 历史记录标题
Text 历史记录内容
Button 重新开始
Text 参考成语标题
Text 参考成语内容
12.2 标题栏实现
标题栏采用Row横向布局:
typescript
Row() {
Button('返回')
.onClick(() => router.back())
Text('成语接龙小应用')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
.textAlign(TextAlign.Center)
}
.width('100%')
.padding(12)
.backgroundColor('#F1F3F5')
12.3 当前成语展示
当前成语使用大号字体突出显示:
typescript
Text('当前成语')
.fontSize(14)
.fontColor('#666666')
.margin({ top: 20 })
Text(this.currentIdiom_1)
.fontSize(32)
.fontWeight(FontWeight.Bold)
.margin({ top: 8 })
.fontColor('#333333')
Text('请接: ' + this.currentIdiom_1.slice(-1) + ' 开头')
.fontSize(14)
.fontColor('#FF9500')
.margin({ top: 4 })
12.4 得分显示实现
得分使用蓝色字体醒目显示:
typescript
Text('得分: ' + String(this.score_1))
.fontSize(16)
.fontWeight(FontWeight.Medium)
.margin({ top: 20 })
.fontColor('#0A59F7')
十三、字符串操作详解
13.1 常用字符串方法
本应用使用了多种字符串操作方法:
| 方法 | 用途 | 示例 |
|---|---|---|
| slice | 截取字符串 | str.slice(-1) |
| includes | 检查包含 | str.includes('正确') |
| length | 获取长度 | str.length |
| join | 数组连接 | arr.join(' → ') |
13.2 slice方法详解
slice方法用于截取字符串的一部分:
typescript
// 获取最后一个字符
let lastChar_1: string = this.currentIdiom_1.slice(-1);
// 获取第一个字符
let firstChar_1: string = this.inputText_1.slice(0, 1);
// 获取中间字符
let middle_1: string = this.inputText_1.slice(1, 3);
slice参数说明:
| 参数 | 说明 | 示例 |
|---|---|---|
| start | 开始位置 | 0(从开头) |
| end | 结束位置 | 1(到第1个字符) |
| 负数 | 从末尾计算 | -1(最后一个) |
13.3 includes方法详解
includes方法检查字符串或数组是否包含指定内容:
typescript
// 字符串包含检查
this.message_1.includes('正确')
// 数组包含检查
this.history_1.includes(this.inputText_1)
this.idioms_1.includes(this.inputText_1)
includes返回值:
- true:包含指定内容
- false:不包含指定内容
13.4 字符串长度检查
验证成语字数使用length属性:
typescript
if (this.inputText_1.length !== 4) {
this.message_1 = '请输入四字成语';
return;
}
length说明:
- 返回字符串的字符数
- 中文汉字每个算1个字符
- 用于验证输入格式
十四、数组操作详解
14.1 数组常用方法
本应用使用了多种数组操作方法:
| 方法 | 用途 | 示例 |
|---|---|---|
| concat | 添加元素 | history.concat(idiom) |
| includes | 检查包含 | history.includes(idiom) |
| join | 连接字符串 | history.join(' → ') |
14.2 concat方法详解
concat方法用于添加元素到数组:
typescript
this.history_1 = this.history_1.concat([this.inputText_1]);
concat特点:
- 不修改原数组
- 返回新数组
- 可以添加多个元素
- 适合状态变量更新
14.3 includes方法详解
includes方法检查数组是否包含元素:
typescript
// 检查历史记录
this.history_1.includes(this.inputText_1)
// 检查成语库
this.idioms_1.includes(this.inputText_1)
includes应用场景:
- 检查成语是否已使用
- 检查成语是否在库中
- 防止重复使用成语
14.4 join方法详解
join方法将数组转换为字符串:
typescript
// 历史记录连接
this.history_1.join(' → ')
// 参考成语连接
this.idioms_1.join(' 、')
join分隔符选择:
| 分隔符 | 应用场景 | 视觉效果 |
|---|---|---|
| ' → ' | 历史记录 | 显示接龙链 |
| ' 、' | 参考成语 | 中文顿号分隔 |
十五、应用扩展方向
15.1 多人对战模式
可以扩展为双人对战模式:
typescript
@State currentPlayer_1: number = 1;
@State player1Score_1: number = 0;
@State player2Score_1: number = 0;
// 切换玩家
switchPlayer() {
this.currentPlayer_1 = this.currentPlayer_1 === 1 ? 2 : 1;
}
// 显示当前玩家
Text('当前玩家: ' + (this.currentPlayer_1 === 1 ? '玩家一' : '玩家二'))
15.2 难度选择功能
添加难度选择,调整成语库:
typescript
difficultyLevels: Record<string, string[]> = {
'easy': ['一心一意', '意气风发', ...],
'medium': ['河清海晏', '晏开警道', ...],
'hard': ['魑魅魍魉', '魉魑魅魍', ...]
};
@State currentDifficulty_1: string = 'easy';
// 切换难度
Select(['简单', '中等', '困难'])
.onSelect((index: number) => {
this.currentDifficulty_1 = ['easy', 'medium', 'hard'][index];
this.idioms_1 = this.difficultyLevels[this.currentDifficulty_1];
})
15.3 提示功能
添加提示功能,帮助用户接龙:
typescript
@State hintsRemaining_1: number = 3;
// 获取提示成语
getHintIdiom(): string {
let lastChar_1: string = this.currentIdiom_1.slice(-1);
let availableIdioms_1: string[] = this.idioms_1.filter(idiom =>
idiom.slice(0, 1) === lastChar_1 && !this.history_1.includes(idiom)
);
return availableIdioms_1.length > 0 ? availableIdioms_1[0] : '';
}
// 提示按钮
Button('提示 (' + String(this.hintsRemaining_1) + ')')
.onClick(() => {
if (this.hintsRemaining_1 > 0) {
let hint_1: string = this.getHintIdiom();
this.message_1 = '提示: 可以接 "' + hint_1 + '"';
this.hintsRemaining_1--;
}
})
15.4 成语释义功能
添加成语释义,帮助用户学习:
typescript
idiomDefinitions: Record<string, string> = {
'一心一意': '心思、意念专一',
'意气风发': '形容精神振奋,气概昂扬',
'发扬光大': '使好的作风、传统等得到发展和提高'
};
// 显示释义
Text(this.idiomDefinitions[this.currentIdiom_1] || '')
.fontSize(12)
.fontColor('#666666')
.margin({ top: 4 })
15.5 数据持久化
使用Preferences存储游戏数据:
typescript
import preferences from '@ohos.data.preferences';
// 保存最高得分
async saveHighScore(score: number) {
let prefs = await preferences.getPreferences(context, 'idiom_game');
let highScore: number = await prefs.get('highScore', 0) as number;
if (score > highScore) {
await prefs.put('highScore', score);
await prefs.flush();
}
}
// 加载最高得分
async loadHighScore(): Promise<number> {
let prefs = await preferences.getPreferences(context, 'idiom_game');
return await prefs.get('highScore', 0) as number;
}
十六、性能优化建议
16.1 渲染优化
- 减少不必要的渲染:只在验证时更新状态
typescript
// 验证失败时不更新历史和得分
if (!valid) {
this.message_1 = '验证失败';
return; // 不触发其他状态更新
}
- 优化历史记录显示:限制显示长度
typescript
// 只显示最近10个成语
getDisplayHistory(): string[] {
return this.history_1.slice(-10);
}
16.2 数据优化
- 成语库优化:使用Set提高查找效率
typescript
idiomSet_1: Set<string> = new Set([
'一心一意', '意气风发', ...
]);
// 使用Set查找
if (!this.idiomSet_1.has(this.inputText_1)) {
this.message_1 = '不是有效的成语';
}
- 历史记录优化:限制历史长度
typescript
if (this.history_1.length > 50) {
this.history_1 = this.history_1.slice(-50);
}
16.3 用户体验优化
- 输入优化:自动清空输入框
typescript
// 验证成功后清空
this.inputText_1 = '';
- 提示优化:提供友好的错误提示
typescript
// 具体的错误提示
this.message_1 = '首字不对,应该是 "' + lastChar_1 + '" 开头';
十七、完整代码清单
17.1 主组件完整代码
typescript
import { router } from '@kit.ArkUI';
@Entry
@Component
struct IdiomGameApp {
@State currentIdiom_1: string = '一心一意';
@State inputText_1: string = '';
@State history_1: string[] = ['一心一意'];
@State score_1: number = 0;
@State message_1: string = '';
idioms_1: string[] = [
'一心一意', '意气风发', '发扬光大', '大海捞针', '针锋相对',
'对牛弹琴', '琴棋书画', '画蛇添足', '足智多谋', '谋事在人',
'人山人海', '海阔天空', '空穴来风', '风花雪月', '月明星稀',
'稀奇古怪', '怪力乱神', '神采飞扬', '扬眉吐气', '气吞山河'
];
checkIdiom_1() {
if (this.inputText_1.length !== 4) {
this.message_1 = '请输入四字成语';
return;
}
let lastChar_1: string = this.currentIdiom_1.slice(-1);
let firstChar_1: string = this.inputText_1.slice(0, 1);
if (lastChar_1 !== firstChar_1) {
this.message_1 = '首字不对,应该是 "' + lastChar_1 + '" 开头';
return;
}
if (this.history_1.includes(this.inputText_1)) {
this.message_1 = '这个成语已经用过了';
return;
}
if (!this.idioms_1.includes(this.inputText_1)) {
this.message_1 = '不是有效的成语';
return;
}
this.history_1 = this.history_1.concat([this.inputText_1]);
this.currentIdiom_1 = this.inputText_1;
this.score_1++;
this.inputText_1 = '';
this.message_1 = '回答正确!+1分';
}
build() {
Column() {
Row() {
Button('返回')
.onClick(() => router.back())
Text('成语接龙小应用')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
.textAlign(TextAlign.Center)
}
.width('100%')
.padding(12)
.backgroundColor('#F1F3F5')
Column() {
Text('得分: ' + String(this.score_1))
.fontSize(16)
.fontWeight(FontWeight.Medium)
.margin({ top: 20 })
.fontColor('#0A59F7')
Text('当前成语')
.fontSize(14)
.fontColor('#666666')
.margin({ top: 20 })
Text(this.currentIdiom_1)
.fontSize(32)
.fontWeight(FontWeight.Bold)
.margin({ top: 8 })
.fontColor('#333333')
Text('请接: ' + this.currentIdiom_1.slice(-1) + ' 开头')
.fontSize(14)
.fontColor('#FF9500')
.margin({ top: 4 })
TextInput({ placeholder: '输入四字成语' })
.width('80%')
.height(48)
.margin({ top: 20 })
.onChange((value_1: string) => {
this.inputText_1 = value_1;
})
.onSubmit(() => {
this.checkIdiom_1();
})
Button('提交')
.width('60%')
.height(40)
.margin({ top: 12 })
.backgroundColor('#0A59F7')
.onClick(() => {
this.checkIdiom_1();
})
Text(this.message_1)
.fontSize(14)
.fontColor(this.message_1.includes('正确') ? '#34C759' : '#FF3B30')
.margin({ top: 12 })
Text('历史记录')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.margin({ top: 24, left: 20 })
.width('90%')
Text(this.history_1.join(' → '))
.fontSize(14)
.fontColor('#666666')
.margin({ top: 8, left: 20 })
.width('90%')
.maxLines(3)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Button('重新开始')
.width('60%')
.height(40)
.margin({ top: 20 })
.backgroundColor('#8E8E93')
.onClick(() => {
this.currentIdiom_1 = '一心一意';
this.inputText_1 = '';
this.history_1 = ['一心一意'];
this.score_1 = 0;
this.message_1 = '';
})
Text('参考成语')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.margin({ top: 24, left: 20 })
.width('90%')
Text(this.idioms_1.join(' 、'))
.fontSize(12)
.fontColor('#999999')
.margin({ top: 8, left: 20 })
.width('90%')
.maxLines(4)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.width('100%')
.layoutWeight(1)
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
}
17.2 代码结构说明
| 代码区域 | 行数 | 功能说明 |
|---|---|---|
| 导入声明 | 1 | 导入router模块 |
| 状态声明 | 6-10 | 声明状态变量 |
| 成语库 | 12-17 | 定义成语数组 |
| 验证方法 | 19-48 | 成语验证逻辑 |
| build方法 | 50-160 | UI构建方法 |
十八、开发经验总结
18.1 技术要点回顾
通过开发这个成语接龙应用,我们掌握了以下技术要点:
- 字符串操作:slice、includes、length等方法的使用
- 数组管理:concat、includes、join等数组方法
- 条件验证:多层验证逻辑的实现
- 状态管理:使用@State装饰器管理游戏状态
- TextInput应用:onChange、onSubmit回调的使用
- 游戏逻辑设计:验证流程和状态更新
18.2 常见问题解决
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 验证逻辑错误 | 条件顺序不当 | 按优先级排列验证条件 |
| 首字匹配失败 | slice参数错误 | 使用slice(-1)获取尾字 |
| 历史记录不更新 | 直接修改数组 | 使用concat创建新数组 |
| 提示颜色不变化 | 条件判断错误 | 使用includes检查内容 |
18.3 最佳实践建议
- 验证逻辑:按优先级排列验证条件,提高效率
- 字符串操作:熟练掌握slice、includes等方法
- 状态管理:使用数组方法创建新数组,确保UI更新
- 用户体验:提供详细的错误提示,帮助用户理解规则
十九、总结
成语接龙小应用是一款趣味益智游戏,展示了HarmonyOS ArkUI框架在游戏逻辑实现方面的能力。应用采用了经典的成语接龙规则,界面简洁直观,操作便捷高效。
从技术实现角度来看,应用涵盖了字符串操作、数组管理、条件验证、TextInput组件应用、游戏逻辑设计等核心技术点。通过学习这个应用的开发过程,开发者可以深入理解ArkTS语言的字符串处理能力和游戏逻辑设计思路。
应用的核心价值在于提供趣味性的成语接龙游戏,用户可以单人练习,增长成语知识。验证逻辑确保了游戏规则的严格执行,历史记录让用户可以回顾游戏过程,参考成语降低了游戏难度。未来可以进一步扩展应用的功能,如添加多人对战模式、难度选择、提示功能、成语释义、数据持久化等特性,使其成为一个更加完善的成语接龙游戏。
这个应用也可以作为学习HarmonyOS开发的入门项目,帮助开发者快速掌握ArkTS和ArkUI的基础知识,理解字符串操作和游戏逻辑设计。