前段时间微软给技术部送来了几个魔方,办公室就开始流行玩这个东西。有个同事是玩魔方专家,我让他给捎了一个国丙的三阶魔方,花了40人民币,质量很不错,非一般地摊货可比。然后照着教程鼓捣鼓捣,基本也算可以弄全六面,当然都是照着教程一边看一边转的。
魔方的初级玩法一般按六步走:
1.拼好底面和底面的四个棱、四个角。这一步转转就弄会了,非常简单。
2.调整第二层的棱;
3.顶面划十字;
4.对好顶面;
5.调整顶面四角顺序;
6.排列好最后的棱色块。
每一步都有两种算法,但是其实所有的算法都是另一种算法的对角线镜像,转两遍的效果和另外一种是相同的,负负得正嘛:),所以不追求速度的话每一步记住一种算法就可以了。
教程地址:魔方的入门玩法
PDF下载:http://panweizeng.com/download/rubik-tutorial.pdf
为大家都能学好初级玩法,在这里特别免费放出秘笈图纸一张,打印出来每天演练一遍,十日可成。
更新(20080621):
我已经可以脱离教程和图纸完成六面。
有这么一种场景,有一个Category的实体类对应着一个名为Category的数据库表。Category类中有Name和Path属性,在新建或更新Category对象时要保证这两个属性在数据库中的值唯一。当然你可以在数据库中的Name和Path字段都建一个唯一索引,那如果不采用这种做法应该怎么做呢?最简单的方法就是写两个名为CheckNameValid和CheckPathValid的函数。很明显这种做法不易于维护,比如说当Category类增加其他需要保证唯一的属性或者属性名字需要改变的时候。我的写法如下:
- /// <summary>
- /// 检查数据库字段中的值是否唯一
- /// </summary>
- /// <param name="t">Cateroy的集合</param>
- /// <param name="func">表达式</param>
- /// <param name="isNew">是否是新建Category</param>
- /// <returns></returns>
- protected bool CheckValid(
- IEnumerable<Category> t,
- Func<Category, Boolean> func,
- bool isNew)
- {
- Category c = t.SingleOrDefault(func);
- if (isNew)
- return c == null;
- else
- return c == null || (c != null && c.ID == Convert.ToInt32(ID.Text));
- }
-
- //调用方法一
- protected Func<Category, Boolean> func = null;
- protected void Page_Load(object sender, EventArgs e)
- {
- func = selectCategory;
- }
- protected bool selectCategory(Category c)
- {
- return c.Name == this.Name.Text;
- }
- CheckValid(kr.Categories, selectCategory, true);
- //调用方法二
- CheckValid(kr.Categories, delegate(Category c){
- return c.Name == Name.Text;
- }
- , true);
- CheckValid(kr.Categories, delegate(Category c){
- return c.Path == Path.Text;
- }
- , false);
- //调用方法三
- CheckValid(kr.Categories, c => c.Name == Name.Text, true);
- CheckValid(kr.Categories, c => c.Path == Path.Text, false);
三种调用方法,当然是使用了lambda表达式的方法三最简洁明了。还可以扩展一下,可以把它写成某个Utility类泛型静态方法,专门检查实体类在数据库字段中的值是否唯一,这时Convert.ToInt32(ID.Text)就要抽出来做成一个参数,这里不就写了。
另外在瘦子师兄的点拨下,发现C# 3.0里面有个类似Javascript中prototype的概念,称为扩展方法(Extension Methods),在System.Linq中运用了大量的扩展方法(例如前面例子中的SingleOrDefault)。扩展方法貌似没prototype灵活,比较的例子如下:
- public static class Program
- {
- public static void Main(string [] args)
- {
- string s = "Hello World";
- s.Print();
- s.ToString();
- Console.WriteLine(s.ToString());
- Console.Read();
- }
- }
- public static class Tools
- {
- public static void Print(this string s)
- {
- Console.WriteLine(s.ToUpper());
- }
- public static void ToString(this string s)
- {
- Console.WriteLine(s.ToUpper());
- }
- }
- function A(){this.name = "AA";}
- A.prototype = {
- show:function(){ alert(this.name);}
- }
- var a1 = new A();
- a1.show();
- //直接覆写A的prototype中的show
- A.prototype.show = function(){ alert("modified:"+this.name);}
- var a2 = new A();
- a2.name = "a2";
- a2.show();
对于一个你不能修改源代码的类,可以通过这种方式为它添加方法。但这个只是编译期的(s.Print()翻译成tools.Print(s)),也就是说编译之后是不能通过反射来取得它的,它并不是要扩展类(例子中的String类)中的真正方法,而是某个静态类(例子中的Tools)的静态方法。
具体介绍参见这篇文章Deep Dive on Extension Methods。
相比于动态网站的列表页分页,静态列表页的分页是件麻烦的事情。因为旧的列表页发布出去以后就无法知道之后发布的总页数,而且也不可能每次更新列表页时去更新所有以前发布过的列表页(频道树节点多时,这个量非常大),所以一般的CMS处理得都比较简单。比如说新浪很多频道的列表页都是按日期归档的,一天发表的文章生成一个列表页,而有些专题的子频道列表页直接就没有处理分页。凤凰网的列表页分页就只有上一页和下一页的链接,系统在处理的时候就更新两个列表页-当前最新的列表页和最后更新过的列表页,规则是当上次处理分页后更新的文章数大于等于三分之五Pagesize时进行分页操作。搜狐的列表页就要复杂一些,有列表页首页链接,有输入页码跳转等,在页尾的Javascript脚本中里面有一个变量maxPage,猜测应该是后期include包含进去的。
在最近的一个项目中,对列表页的分页处理比上面说的几种要复杂一些。不看代码,先看效果。
这里的静态列表页是这样的,最早发布出去的第一页是列表页名字_1.html, 第二页是列表页名字_2.html,以此类推,到最后一页就是最新的一页是列表页名字.html或者列表页名字_列表页总页数.html。
下面是代码
- var Paging = {
- holder:'paging',
- currentNo:1,
- currentFileName:'',//当前文件名,不包括后缀名和页码
- listSize:10,//列表项链接的显示数目
- totalNo:35,//列表页总页数
- //初始化currentFileName和currentNo
- preRender:function(){
- var _lastIndex = location.href.lastIndexOf('/');
- var _fileName = location.href.substr(_lastIndex+1);
- var matchItem = _fileName.match(/(.*)_(\d+).html/i);
- if(matchItem != null){
- this.currentFileName = matchItem[1];
- this.currentNo = parseInt(matchItem[2]);
- } else {
- this.currentFileName = _fileName.split('.')[0];
- this.currentNo = this.totalNo;
- }
- },
- render:function(){
- //在页面上显示的页码
- var realNo = this.totalNo - this.currentNo;
- //页码对listSize的倍数
- var tens = Math.floor(realNo / this.listSize);
- //页码对listSize的余数
- var units = realNo % this.listSize;
- var html = '';
- html += '<span><a href="'+this.currentFileName+'.html">首页</a></span>';
- //如果不是在第一个listSize,例如第一个十页,就显示上一页
- if(tens != 0) {
- html += '<span>'
- +'<a href="'+this.currentFileName+'_'+(this.currentNo+1)
- +'.html">上一页</a></span>';
- }
-
- var _no=0,_linkNo=0,_isCurrent=false;
- for(var i = 1 ; i < this.listSize+1 ; i++){
- _no = tens*this.listSize+i;
- //链接为倒序
- _linkNo = this.totalNo - _no + 1;
- _isCurrent = i == units+1 ? true : false;
-
- //到达最后一页就退出
- if(_linkNo < 1) break;
- //是否当前页
- if(_isCurrent)
- html += '<span class="current">';
- else
- html += '<span>';
- //是否是列表页第一页
- if(_no != 1 && !_isCurrent)
- html += '<a href="'+this.currentFileName+'_'+_linkNo.toString()+'.html">';
- else if (!_isCurrent)
- html += '<a href="'+this.currentFileName+'.html">';
- html += _no.toString();
- html += '</a>';
- html += '</span>';
- }
-
- //如果没到最后一个listSize,显示下一页
- if(tens != Math.floor(this.totalNo / this.listSize)) {
- html += '<span><a href="'+this.currentFileName+'_'
- +(this.currentNo-1)+'.html">下一页</a></span>';
- }
- html += '<span><a href="'+this.currentFileName+'_1.html">末页</a></span>';
- $(this.holder).innerHTML = html;
- },
- init:function(){
- this.preRender();
- this.render();
- }
- }
- Paging.init();
其中代码中的Paging.totalNo是列表页的总数,这个是后期加入的。目前可以想到两种方法给脚本传递这个值,一个就是像搜狐一样在页面中include进去一个后期更新的文件,另外还有比较别扭的方法,就是最后更新的列表页传入一个值,形如doclist.html?535,后续打开的页面都会带着这个值,如果万一不是从第一页进入的比如从搜索引擎过来的话,在页面中会记录一个该列表当时发布的总页数作为补充。最后还是决定使用搜狐的方法,在更新最新的列表页时同时新发一个记录列表页总数的文件。另外为了SEO,可以专门做一个汇总归档页,当然也可以由CMS生成上一页和下一页的链接,这些方法都是容易做到的。
脚本浏览地址:http://panweizeng.com/others/itv_playlist_paging/paging.js
if(你.经常锻炼 == true || 你.意志力强 == true) return;
1.万米跑这种耐力运动最大的敌人是你的身体。
2.运动前的几个小时应该保证摄入充足的食物,饿着肚子跑是不现实的。这些食物应该含有足够的碳水化合物,米饭和馒头都是不错的选择。
3.穿着舒适的运动裤和上衣,要保证一双合脚的布鞋或者跑鞋,不好的鞋容易引起膝关节的损伤。
4.准备一个随身听(Mp3或磁带机均可),播放一些快节奏的曲目,分散自己的注意力。
5.运动前需要进行热身,快走和慢跑都可以,这个非常关键。热身使运动神经开始兴奋,身体开始进入运动状态,能有效防止运动的损伤和过度的疲劳感。
6.根据自己的身体调整运动的节奏。我一般是:10-20分钟快走(6km/h)热身,10分钟慢速跑(8km/h),10分钟快速跑(12km/h),10分钟快走,10分钟慢速跑,10分钟中速跑(10km/h),10分钟快走,10分钟慢速跑,最后10分钟快走结束。这样70-90分钟就能完成万米跑。
7.运动中及时补充身体的水分。纯净水和运动饮料都可以,但是注意不要暴饮,否则会加重胃部的负担。
8.如果很久都没有参加运动了,前面几次应该量力而为,不要勉强自己。因为长期不运动,心肺功能跟不上,大脑会容易缺氧,万一晕倒在跑步机上面就要受伤了。
9.如果跑步的目的和我一样,减脂不减肌肉,那么就要好好把握一下运动的时间。我之前的《减肥参考数据》文章中提到,我认为最佳运动时间应该在[1,1.5](单位:小时)之间。另外,即使你身上有很多的肥肉,但是运动也应该适量,毛主席教导我们:贵有恒,何必三更眠五更起;最无益,只怕一日暴十日寒。运动要持之以恒,偶尔突击一下肯定是不行的。
原作品是06世界杯临近期间英文雅虎页面上的阿迪达斯倒计时牌冠名广告。设计富有金属质感,属于我比较喜欢的风格。反编译以后发现代码比较乱,然后手就有点痒,再然后就有了下面的代码。
首先是CountDown的类,其中handler是Function类型的公有变量,该函数将用于处理怎么显示倒计时代码。
- class CountDown {
- private var finalTime:Date;
- private var currentTime:Date;
- private var timeDiff:Number;
- public var handler:Function = null;
-
- public function CountDown(date:Date) {
- this.finalTime = date != null ? date : new Date(1900, 0, 0, 0, 0, 0);
- }
-
- private function init():Void {
- this.currentTime = new Date();
- this.timeDiff = finalTime.getTime() - currentTime.getTime();
- if (this.timeDiff < 0)
- this.timeDiff = 0;
- }
-
- public function run():Void {
- init();
- var _day:Number = Math.floor(timeDiff/(1000*60*60*24));
- var _hour:Number = Math.floor((timeDiff/(1000*60*60))%24);
- var _minute:Number = Math.floor((timeDiff/(1000*60))%60);
- var _second:Number = Math.floor((timeDiff/1000)%60);
- show(_day,_hour,_minute,_second);
- }
-
- private function show(day:Number, hour:Number, minute:Number, second:Number):Void {
- if(handler != null)
- handler(day,hour,minute,second);
- }
- }
在倒计时影片剪辑中加入以下代码,其中1和2两个位置的判断很重要。
- var cd = new CountDown(new Date(2012, 8, 22, 0, 0, 0));
- var oldDigitString = "000000000";
- function doStart(day,hour,minute,second){
- doShow(digitFix(day,4)+digitFix(hour,2)+digitFix(minute,2)+digitFix(second,2));
- }
-
- function doShow(digitString){
- if(oldDigitString == digitString) return;//1.
- for(var i = 0; i < digitString.length; i++){
- if(oldDigitString.charAt(i) != digitString.charAt(i))//2.
- doDisplay(eval('d_'+i),oldDigitString.charAt(i),digitString.charAt(i));
- }
- oldDigitString = digitString;
- }
-
- function doDisplay(o,oldNum,newNum){
- o._prev = oldNum;
- o._next = newNum;
- o.gotoAndPlay(2);
- }
-
- function digitFix(num,len):String{
- while(num.toString().length < len)
- num = '0'+num;
- return num.toString();
- }
-
- cd.handler = doStart;
-
- this.onEnterFrame = function()
- {
- cd.run();
- }
剽窃后的成果-_-!
对不起,您的浏览器禁用脚本或者您的Flash播放器版本较低!请点击
这里获取最新版本。
其中这里的终点时间是我30岁的生日,到倒计时牌都是0000000000的时候,不知道我会不会哭泣……