继 上次的随笔 一题比较刁的面试题
大致内容------------------------------------------------------------------------------------------------------------
昨天晚上看到群里在聊面试题,回想最近几个月的面试经历,很是感慨。
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