继"一题比较刁的面试题" - 其实也不过如此。 sliverlight 实现
继 上次的随笔 一题比较***的面试题
大致内容------------------------------------------------------------------------------------------------------------
昨天晚上看到群里在聊面试题,回想最近几个月的面试经历,很是感慨。
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设置为可见。
------------------------------------------------------------------------------------------------------------------------------
上回采用JavaScript实现 ,今天用sliverlight实习了该功能,发现也就如此,没啥难度。最近公司没事 开始学习sliverlight了(为了混饭吃)。
实现思路和上次基本上是一样的
主要还是一个链表,记录每一步操作的Button
其中 button的操作有两种 1.点击 2.新增加
回放时用一个定时器遍历链表 判断需要的操作 被隐藏则显示 否则执行button的click 方法 click 方法时回进行一系列的操作 如 值累加、与上一个按钮连接等操作。
全部代码----------------------------------------------------------------------------
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Threading; namespace ConnectionButton { public partial class MainPage : UserControl { /// <summary> /// 按钮容器框的宽度 /// </summary> private readonly double canvas4btnsWidth; /// <summary> /// 按钮容器框的高度 /// </summary> private readonly double canvas4btnsHeight; /// <summary> /// 最大按钮值 /// </summary> private readonly int maxBtnValue = 100; /// <summary> /// 最后被点击的按钮 /// </summary> private XButton LastClickButton = null; /// <summary> /// 初始化时的按钮 /// </summary> private IList<XButton> InitButtonsList = new List<XButton>(); /// <summary> /// 增加的按钮 /// </summary> private IList<XButton> AddedButtonsList = new List<XButton>(); private List<object> MyList = new List<object>(); bool IsPlaying = false; DispatcherTimer playTimer = new DispatcherTimer() { Interval = new TimeSpan(4000000) }; int LIndex = 0; public MainPage() { InitializeComponent(); canvas4btnsWidth = canvas4btns.ActualWidth; canvas4btnsHeight = canvas4btns.ActualHeight; //初始化按钮 InitButtons(); //定时器的Tick事件 playTimer.Tick += (s, e) => { if (MyList.Count == 0 || LIndex + 1 > MyList.Count) { playTimer.Stop(); LIndex = 0; IsPlaying = false; } else { object item = MyList[LIndex]; if (item is XButton) { XButton btn = item as XButton; if (btn.IsHide()) { btn.Show(); } else { //点击 ButtonClick(item); } } LIndex++; } }; } /// <summary> /// 产生随机数 /// </summary> /// <param name="min"></param> /// <param name="max"></param> /// <returns></returns> private int GetRandomNumber(int min, int max) { long tick = DateTime.Now.Ticks; Random r = new Random(Guid.NewGuid().GetHashCode()); if (min == -1 && max == -1) { return r.Next(); } if (min == -1 && max != -1) { return r.Next(max); } return r.Next(min, max); } /// <summary> /// 初始化面板 /// </summary> private void InitButtons() { int max = GetRandomNumber(5, 10); for (int i = 0; i < max; i++) { XButton btn = CreateButton(); InitButtonsList.Add(btn); canvas4btns.Children.Add(btn); } } /// <summary> /// 产生随机位置的按钮 /// </summary> /// <returns></returns> private XButton CreateButton() { double canvasLeft = GetRandomNumber(50, Convert.ToInt32(canvas4btnsWidth - 50)); double canvasTop = GetRandomNumber(50, Convert.ToInt32(canvas4btnsHeight - 50)); XButton btn = new XButton() { Height = 40, Width = 40, Content = GetRandomNumber(1, maxBtnValue).ToString(), Background = new SolidColorBrush() { Color = Colors.Blue } }; btn.SetValue(Canvas.LeftProperty, canvasLeft); btn.SetValue(Canvas.TopProperty, canvasTop); btn.Click += (button, e) => { if (!IsPlaying) { ButtonClick(button); } }; return btn; } /// <summary> /// 按钮点击 /// </summary> /// <param name="button"></param> public void ButtonClick(object button) { XButton nowBtn = button as XButton; nowBtn.IsEnabled = false; nowBtn.Background = new SolidColorBrush() { Color = Colors.Red }; txtCount.Text = (int.Parse(nowBtn.Content.ToString()) + int.Parse(txtCount.Text)).ToString(); if (LastClickButton != null) { DrawLine(LastClickButton.Position(), nowBtn.Position()); } //设置最后被点击的按钮 LastClickButton = nowBtn; if (!LastClickButton.Clicked) { MyList.Add(LastClickButton); LastClickButton.Clicked = true; } } /// <summary> /// 增加节点 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnAdd_Click(object sender, RoutedEventArgs e) { if (!IsPlaying) { XButton btn = CreateButton(); AddedButtonsList.Add(btn); MyList.Add(btn); canvas4btns.Children.Add(btn); } } /// <summary> /// 画线 /// </summary> /// <param name="startPoint"></param> /// <param name="endPoint"></param> private void DrawLine(Point startPoint, Point endPoint) { Line l = new Line() { X1 = startPoint.X, X2 = endPoint.X, Y1 = startPoint.Y, Y2 = endPoint.Y, StrokeThickness = 2 }; l.Stroke = new SolidColorBrush() { Color = Color.FromArgb(255, 41, 57, 85) }; canvas4btns.Children.Add(l); } /// <summary> /// 回放 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnRePlay_Click(object sender, RoutedEventArgs e) { if (!IsPlaying) { ///回到最初 BackToTheBeginning(); Paly(); } } /// <summary> /// 播放 /// </summary> private void Paly() { IsPlaying = true; playTimer.Start(); } /// <summary> /// 回到最初 /// </summary> private void BackToTheBeginning() { txtCount.Text = "0"; LastClickButton = null; //将后来添加的按钮移除 foreach (XButton btn in AddedButtonsList) { btn.Init(); btn.Hide(); } foreach (XButton btn in InitButtonsList) { btn.Init(); } //移除所有连线 var lineElements = canvas4btns.Children.Where(c => c is Line); foreach (Line line in lineElements) { line.Hide(); } //while (canvas4btns.Children.Where(c => c is Line).Count() != 0) //{ // for (int i = 0; i < canvas4btns.Children.Count; i++) // { // if (canvas4btns.Children[i] is Line) // { // canvas4btns.Children.RemoveAt(i); // break; // } // } //} } } /// <summary> /// 扩展类 /// </summary> public static class Extension { /// <summary> /// 获取按钮的位置 仅相对于Canvas布局 /// </summary> /// <param name="btn"></param> /// <returns></returns> public static Point Position(this XButton btn) { return new Point() { X = Convert.ToDouble(btn.GetValue(Canvas.LeftProperty)) + btn.ActualWidth / 2, Y = Convert.ToDouble(btn.GetValue(Canvas.TopProperty)) + btn.ActualHeight / 2, }; } public static void Init(this XButton btn) { btn.BeBlue(); btn.Visibility = Visibility.Visible; btn.IsEnabled = true; } public static int Value(this XButton btn) { return int.Parse(btn.Content.ToString()); } public static void BeRed(this XButton btn) { btn.Background = new SolidColorBrush() { Color = Colors.Red }; } public static void BeBlue(this XButton btn) { btn.Background = new SolidColorBrush() { Color = Colors.Blue }; } public static bool IsHide(this XButton btn) { return btn.Visibility == Visibility.Collapsed; } public static void Show(this XButton btn) { btn.Visibility = Visibility.Visible; } public static void Hide(this XButton btn) { btn.Visibility = Visibility.Collapsed; } public static void Hide(this Line line) { line.Visibility = Visibility.Collapsed; } public static void Click(this XButton btn) { btn.Visibility = Visibility.Collapsed; } } public class XButton : Button { public bool Clicked { get; set; } } }
效果图----------------------------------------------------------------------------------------------------------------
够简单吧。。。。
去年10月到现在时间也不短了,还把这道面试题找出来,看来我还是对那次面试耿耿于怀啊。。。此处不留爷,自有留爷处。
那家公司从家道那边要1个多小时,幸亏没去,不然就亏大了。
全部代码下载 /tandly/ConnectionButton.rar
苏州 很恶心的雨
汤晓华 QQ 1881597 MSN tension1990@hotmail.com
2010 04 14