一题比较刁的面试题
昨天晚上看到群里在聊面试题,回想最近几个月的面试经历,很是感慨。
10月底从昆山回到苏州。直到11月底才找到工作,跑到哪都是有没有工作经验,没有。。。好吧,回去等通知吧。
2009年11月19日来到苏州热线面试(苏州比较大的门户网站)
面试结束后带回去了一个题、
要求:
1.任何语言 任何形式(web,winform,flash,flex,silverlight)等等。。
2.实现内容
a.初始化一个面板,面板内随机分布着一些按钮 按钮上有一些随机的数字。
b.有一个按钮 名字叫“新增节点” 点击 该按钮后 可以向面板内随机添加新的 按钮。
c.任意顺序点击面板内的按钮。按顺序将所点按钮用线条连接。并且将按钮的 数值进行累加 显示到 文本框。
d.回放 功能。 有一个名叫 “回放的按钮” 点击该按钮后 将所有操作慢动作回放。
包括增加节点 和 连接 的一切操作。完整再现。
这题拿回家做了3个班小时。水平不行啊。。花了很长时间在想用什么技术好。结果用了 JavaScript (jQuery)
在中间遇到了一些难点。
1.画线问题。一开始想到的是 vml 但是由于浏览器兼容问题。最后在网上找啊找。
使用了别人写的一个函数 用JavaScript 画线 主要思路是 利用三角函数 画出该线的每一个像素点(非常占资源)
2.记录和回放问题。如何记录下每一个操作并回放,这个问题也想了很久
记录:最后是这样的。在全局存放一个对象,该对象是一个 button 的 dom 。用来保存上一次点击的按钮对象。
当点击一个按钮时。首先将该按钮存放到一个array(存放Button对象)中,再将判断上一次是否存在点击。如果存在,则将这两个按钮连接。
当添加按钮时 首先将随机产生的按钮添加至 array 中 。
回放:当点击回放时 首先是要初始化板面中的按钮和线条等。 策略是:线条全部删除。中途添加的按钮 全部隐藏。
回放的过程实际是 一个 array 的遍历过程。
判断 array 中 Button的 状态。当Button 为显示时。调用 Button的 click 方法。否则 将Button设置为可见。
这就是基本思路。
贴出我的实现代码。
Test.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | /** * @author 汤晓华 * * @copyright 2009 汤晓华 * * */ /*** * 用于绘制线条 * @param {Object} x1 第一点的X坐标 * @param {Object} y1 第一点的Y坐标 * @param {Object} x2 第二点的X坐标 * @param {Object} y2 第二点的Y坐标 * @param {Object} color 颜色 */ function line(x1, y1, x2, y2, color){ var html = "" ; var tmp if (x1 >= x2) { tmp = x1; x1 = x2; x2 = tmp; tmp = y1; y1 = y2; y2 = tmp; } for ( var i = x1; i <= x2; i++) { x = i; y = (y2 - y1) / (x2 - x1) * (x - x1) + y1; html += " <img border='1' class='line' style='border-color: " +color+ ";position:absolute;left:" + (x + 20) + "px;top:" + (y + 20) + "px;background-color:" + color + "' width=1 height=1>" ; } return html; } /** * 全局变量 */ //容器对象 var container = null ; //被点击过的按钮 var clickedBtn = null ; //初始化按钮数量 var InitBtnNum = 5; //按钮最大的ID var maxId = InitBtnNum; //存放依次点击的按钮的Id的Array对象 var BtnArray = new Array(); //是否在回放 var IsPlayBack = false ; /** * 产生随机数函数 * @param {Object} min * @param {Object} max */ var random = function (min, max){ max = max == null ? 50 : max; min = min == null ? 1 : min; return Math.floor(Math.random() * max + min); } /** * 初始化容器中的按钮 */ function InitButton(){ for ( var i = 0; i < InitBtnNum; i++) { CreateBtn(i); } } /** * 创建按钮 * @param {Object} id */ function CreateBtn(id){ var value = random(); var top = random(60, 400); var left = random(60, 700); var button = "<button id=\"btn" + id + "\" isClick=\"false\" class=\"btn\" onclick=\"BtnClick(this)\" style=\"top: " + top + "px;left: " + left + "px;\">" + value + "</button>" ; container.append(button); } /** * 容器中按钮的点击事件 * @param {Object} obj */ function BtnClick(obj){ var nowBtn = $(obj); if (nowBtn.attr( "isClick" ) != "false" ) { return ; } if (!IsPlayBack) { //将当前的按钮对象推入BtnArray中 BtnArray.push(nowBtn); } //设置按钮的颜色 nowBtn.css( "background" , "blue" ); if (clickedBtn != null ) { var _x1 = nowBtn.css( "left" ); var x1 = _x1.substring(0, _x1.indexOf( "px" )); x1 = parseInt(x1) - 5; var _y1 = nowBtn.css( "top" ); var y1 = _y1.substring(0, _y1.indexOf( "px" )); y1 = parseInt(y1) - 8; var _x2 = clickedBtn.css( "left" ); var x2 = _x2.substring(0, _x2.indexOf( "px" )); x2 = parseInt(x2) - 5; var _y2 = clickedBtn.css( "top" ); var y2 = _y2.substring(0, _y2.indexOf( "px" )); y2 = parseInt(y2) - 8; var _line = line(x1, y1, x2, y2, "red" ); //将联系追加到容器中 container.append(_line); } //计算文本框的值 CountValue(nowBtn); //将按钮的属性设置为已点击 nowBtn.attr( "isClick" , "true" ); //将当前按钮设置为最后一个点击过的按钮 clickedBtn = nowBtn; } /** * 累加结果 * @param {Object} obj 按钮对象 */ function CountValue(obj){ var txtBox = $( "#countResult" ); txtBox.val(parseInt(txtBox.val()) + parseInt(obj.html())) } /** * 回放 */ function Playback(){ if (IsPlayBack) { return ; } IsPlayBack = true ; //将结果归0 $( "#countResult" ).val(0); //移除连接 $( ".line" ).remove(); //将按钮的isClick属性设置成 false $( ".btn" ).attr( "isClick" , "false" ); //先全部隐藏按钮 $( ".btn" ).css( "display" , "none" ); //现实初始化时就存在的按钮 for ( var i = 0; i < InitBtnNum; i++) { $( "#btn" + i).css( "display" , "block" ); } //颜色全部设置成初始色 $( ".btn" ).css( "background" , "#ff8901" ); //最后点击的按钮设置为Null clickedBtn = null ; //1秒后开始回放连接过程 setTimeout( "DoPlayBack(0)" , "1000" ); } /** * 执行回放动作 */ function DoPlayBack(index){ if (index < BtnArray.length) { var display = BtnArray[index].css( "display" ); if (display == "none" ) { BtnArray[index].css( "display" , "block" ) } else { BtnArray[index].click(); } index += 1; } else { IsPlayBack = false ; alert( "回放结束" ); return ; } setTimeout( "DoPlayBack(" + index + ")" , "300" ); } /** * 页面DOM载入完毕后执行函数 */ jQuery( function (){ InitBtnNum = random(3, 4); $( "#countResult" ).val(0); ///为增加按钮增加点击事件 $( "#AddButton" ).click( function (){ maxId += 1; CreateBtn(maxId); if (!IsPlayBack) { //将当前的按钮对象推入BtnArray中 var id = "#btn" + maxId; BtnArray.push($(id)); } }); ///为回放按钮增加点击事件 $( "#Playback" ).click( function (){ Playback(); }); //获取container对象 container = $( "#container" ); //初始化容器中的按钮 InitButton(); }); |
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | <! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> < html xmlns="http://www.w3.org/1999/xhtml"> < head > < meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> < title >面试题</ title > < script type="text/javascript" src="lib/jquery/jquery-1.3.2.min.js"> </ script > < script type="text/javascript" src="lib/Test.js"> </ script > < style type="text/css"> div#container { width: 800px; height: 500px; border: 1px red solid } button.btn { position: absolute; BACKGROUND: #ff8901; PADDING-BOTTOM: 0px; CURSOR: pointer; COLOR: #fff; BORDER-TOP-STYLE: none; LINE-HEIGHT: 20px; PADDING-TOP: 0px; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; LETTER-SPACING: 1px; BORDER-BOTTOM-STYLE: none; width: 30px; height: 20px; } button.btn1 { position: relative; BACKGROUND: #ff8901; PADDING-BOTTOM: 0px; CURSOR: pointer; COLOR: #fff; BORDER-TOP-STYLE: none; LINE-HEIGHT: 20px; PADDING-TOP: 0px; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; LETTER-SPACING: 1px; BORDER-BOTTOM-STYLE: none; width: 80px; height: 24px; } </ style > </ head > < body > < div > 累加结果:< input type="text" readonly="true" id="countResult" style="width:70px" value="0" /> < button id="AddButton" class="btn1"> 增加节点 </ button > < button id="Playback" class="btn1"> 回 放 </ button > </ div > < div id="container"> </ div > </ body > </ html > |
效果图
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述