一题比较刁的面试题
昨天晚上看到群里在聊面试题,回想最近几个月的面试经历,很是感慨。
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
/** * @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
<!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>
效果图