喔唷,我也有PR了,外加牲口几头

听说PR更新了,我就跑去查了一下,突然就发现我也有PR了,而且是3,不过北街说了:4级PR才算达标。呃,好吧,它不是零,我就觉得挺爽的。

老6还说了:PR算个屁啊,所以我也就没把这玩意有多少当回事过。博客,该咋写还是咋写,日子该咋过还是咋过,我又没打算在这上面放广告,它排多少名关我P事啊!

好了,清明节拍了些牲口,下面上片

黄牛

水牛

果然是黄牛老实一点,水牛好动一点。下面再来个毛茸茸的微距

毛虫

小路错误页面

小路是个什么玩意?是路人假的吉祥物,或者叫做形象代言人,嗯,本人不好意思露面,就派个家伙出来撑场面。

想看么?他喜欢躲猫猫,一般是看不着的,只有你访问我的blog出错的时候才会出现,比如400错误401错误403错误404错误,还有500错误

顺便普及一下这些错误页的含义:

  • 400 - 请求无效
  • 401 - 访问未授权
  • 403 - 禁止访问
  • 404 - 页面不存在
  • 500 - 服务器内部错误

它山之石

最近非常非常忙,手上悬着好几个计划,以至于似乎都没有时间上来码字了。分享近日看到的几个好东西吧。

首先,在刘未鹏那里看到了一篇关于为什么要写博客的文章,刘未鹏是《代码之美》一书的译者,这本书值得一看,这个译者的博客更值得一看。那里有很多有意思的东西。最近看了太多的人写自己为什么要写博客,大概这是独立博客作者在一定的时期都会思考的事情,而lurenfake.com在诞生的那一天,我就很清楚它是为什么存在的。我根本不在乎我有多少流量,多少人气,实际上大部分来到这里的人是通过搜索引擎,他们在这里找到他们想要的东西,解决了自己的问题,我就满足了。我不喜欢看到回复里面出现跟文章无关的乱七八糟的话,那样的留言我通常无视,而且一定不会回访,想通过这种方式拉流量的可以直接绕道了。

其二,偶然看到一篇高效JavaScript,优秀程序员和普通程序员的区别之一就是,前者能用比后者更精练的代码写出更高效的程序。仅仅用代码实现功能是北大青鸟这种地方一个月就能培训出来的,从IT民工走向IT精英,大概缺的就是修炼。若干年前,当我看完《Effective C++》和《More Effective C++》之后,我意识到会写代码和写好代码之间的差距,而这也会导致日后收入的差距甚至人生的差距。永远把效率问题排在日程表上,不光对于代码,对于工作生活同样应该如此。

其三,看到一个BT工作原理演示动画,很有意思,非常生动地演示了BT的原理,不过貌似用IE是看不了的。。。盯着这个动画发呆了好久,据说是JavaScript写成的,之前还见过一个JavaScript写的windows 3.1,这些人似乎都是天才,可惜我不是。

用二级域名输出原始feed

feedsky的抽风问题不是一天两天了,不是一片空白就是干脆不更新,实在忍不下去了,决定换回原始feed。

幸好当初比较有远见,订阅地址都是使用的二级域名feed.lurenfake.com,当然这也是当初我选择feedsky而不是feedburner的原因之一。

我的原始feed地址是http://www.lurenfake.com/rss/,如果能让阅读器访问feed.lurenfake.com的时候自动转向到新的地址,那么所有的订阅用户都不用更换订阅源,对了,这就是301转向。

操作方法:

1. 到feedsky后台撤销二级域名绑定。

2. 到域名服务商处添加一个A记录到主机ip。

3. 到主机后台添加一个子域名feed,根目录下会出现一个feed文件夹。

4. 在feed文件夹下新建一个index.php文件,里面写如下内容

<? 
    header("HTTP/1.1 301 Moved Permanently"); 
    header("Location:http://www.lurenfake.com/rss/"); 
    exit(); 
?>

注意第3行里面的网址要改成自己的feed源地址。

5. 坐等全球DNS服务器刷新

这个方法还有一个好处,以后如果想使用feedburner了,直接把这个网址换成新的源地址就可以实现无缝迁移了。

Javascript贪吃蛇

这个就是昨天那传说中的Konami Code里提到的彩蛋啦,好多人告诉我看不到,汗。。。

敲了Konami Code以后发现木有反应的一定都是老访客啦,您的浏览器已经缓存了我blog的css和js文件,所以你看到的其实不是最新的博客代码,只是最新的文章。。。sablog的缓存时间是多久我还真不知道,貌似非常久。。。所以呢,您可能需要清空浏览器临时文件,不知道怎么做的看这里

再试试,还看不到,那你用的是ie6吧?ie6下是有问题的,我有空再去研究,还是呼吁大家尽快抛弃ie6吧。。。

↑↑↓↓←→←→BA,这下总能发现什么了吧。。。嗯,一个贪吃蛇游戏,代码参考了CNWander的版本

snake.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>贪吃蛇小游戏 - lurenfake.com</title>
        <link rel="stylesheet" href="./style.css" media="all" />
        <script type="text/javascript" src="./script.js">
        </script>
    </head>
    <body>
        <div id="stage">
        </div>
        <div id="info">
            <div class="fl">
                <span id="start">S</span>
                <span> - 开始 | </span>
                <span id="reset">R</span>
                <span> - 复位 | </span>
                <span id="pause">P</span>
                <span> - 暂停/继续</span>
            </div>
            <div class="fr">
                <span>Level: </span>
                <span id="level">1</span>
                <span>| Score: </span>
                <span id="score">0</span>
            </div>
            <div class="cb">
                <a href="http://www.lurenfake.com">@路人假</a>
            </div>
        </div>
    </body>
</html>

style.css

* {
    margin: 0;
    padding: 0
}

body {
    text-align: center;
    background: #333;
    font-size: 12px;
}

table {
    margin: 0 auto;
    overflow: hidden;
    border-collapse: collapse;
}

td {
    width: 12px;
    height: 12px;
    border: 1px solid #eee;
    background: #f4f4f4;
}

.snake_body {
    background: #39c;
}

.snake_head {
    background: #37a;
}

.food {
    background: #093
}

#info {
    width: 390px;
    margin: 0 auto;
    line-height: 17px;
    color: white;
}

#info span {
    float: left;
}

#level, #score {
    min-width: 25px;
    max-width: 25px;
    overflow: visible;
    display: block;
    text-align: right;
}

#start, #reset, #pause {
    max-width: 6px;
    overflow: visible;
}

.fl {
    float: left;
}

.fr {
    float: right;
}

.cb {
    clear: both;
}

a {
    color: #ff6055;
}

script.js

function $(id){
 return document.getElementById(id);
}

var STAGE_SIZE = 30,
 speed = 10,
 level = 1,
 score = 0,
 direction = 1, //方向: 0-上, 1-右, 2-下, 3-左
 snake = new Array(),
 timer = null,
 keyLocked = false,
 stage;
 window.onload = function(){
  stage = initStage();
  snake = new Array();
  initSnake();
  generateFood();
  document.onkeydown = attachEvents;
 }
 
function initStage(){
 var table = document.createElement("table"),
  tbody = document.createElement("tbody");
 for(var row = 0; row < STAGE_SIZE; row++){   
        var tr = tbody.insertRow(-1);   
        for(var col = 0; col < STAGE_SIZE; col++) {   
            var td = tr.insertCell(-1);   
        }
    }
 table.appendChild(tbody);
 $("stage").appendChild(table);
 return table;
}

function initSnake(){
 var x = Math.floor(Math.random() * (STAGE_SIZE/2 - 2) + 2),
  y = Math.floor(Math.random() * STAGE_SIZE);
 stage.rows[y].cells[x].className = 'snake_head';
 snake.push([x,y]);
 stage.rows[y].cells[x-1].className = 'snake_body';
 snake.push([x-1,y]);
 stage.rows[y].cells[x-2].className = 'snake_body';
 snake.push([x-2,y]);
}

function generateFood(){
 var x = Math.floor(Math.random() * STAGE_SIZE),
  y = Math.floor(Math.random() * STAGE_SIZE);
 if(stage.rows[y].cells[x].className != ""){
  generateFood();
  return;
 }
 stage.rows[y].cells[x].className = 'food';
}

function clearStage(){
 for(var i = 0; i < STAGE_SIZE; i++){
  for(var j = 0; j < STAGE_SIZE; j++){
   stage.rows[j].cells[i].className = '';
  }
 }
 snake = new Array();
 initSnake();
 generateFood();
}

function attachEvents(e){
 e = e || event;
 switch(e.keyCode) {
  case 80: //P
   fontEffect($('pause'));
   pause();
   break;
  case 82: //R
   fontEffect($('reset'));
   reset();
   break;
  case 83: //S
   fontEffect($('start'));
   move();
   break;
  case 37: //左
   if(!keyLocked) direction = (direction == 1) ? 1 : 3;
   break;
  case 38: //上
   if(!keyLocked) direction = (direction == 2) ? 2 : 0;
   break;
  case 39: //右
   if(!keyLocked) direction = (direction == 3) ? 3 : 1;
   break;
  case 40: //下
   if(!keyLocked) direction = (direction == 0) ? 0 : 2;
   break;
 }
 keyLocked = true;
 return false;
}

function pause(){
 if(timer) {
  window.clearInterval(timer);
  timer = null;
 } else {
  timer = window.setInterval(moveOneStep, Math.floor(3000/speed));
 }
}

function reset(){
 if(timer) window.clearInterval(timer);
 speed = 10;
 level = 1;
 $('level').innerHTML = 1;
 score = 0;
 $('score').innerHTML = 0;
 direction = 1;
 clearStage();
}

function move(){
 if(timer) window.clearInterval(timer);
 timer = window.setInterval(moveOneStep, Math.floor(3000/speed));
}

function moveOneStep(){
 var headX = snake[0][0],
  headY = snake[0][1],
   tailX = snake[snake.length-1][0],
  tailY = snake[snake.length-1][1];
 //移动一格
 switch(direction){
  case 0: headY -= 1; break; //y-1
  case 1: headX += 1; break; //x+1
  case 2: headY += 1; break; //y+1
  case 3: headX -= 1; break; //x-1
 }
 
 //游戏结束
 if(headX >= STAGE_SIZE || headX < 0 
  || headY >= STAGE_SIZE || headY < 0 
  || stage.rows[headY].cells[headX].className == 'snake_body') {
  alert("游戏结束 :( \n您的得分: " + score);
  window.clearInterval(timer);
  return;
 }

 //吃到食物
 if(stage.rows[headY].cells[headX].className == 'food'){
  generateFood();
  score += 1;
  //setText('score', score);
  fontEffect($('score'), 12, 24, 1);
  //每吃5个升一级,最多10级
  if(score % 5 == 0 && level < 10) {
   speed += 5;
   level += 1;
   //setText('level', level);
   fontEffect($('level'), 12, 24, 1);
   move(); 
  }
 } else {
  stage.rows[tailY].cells[tailX].className = '';
  snake.pop();
 }
 stage.rows[headY].cells[headX].className = 'snake_head';
 snake.unshift([headX, headY]);
 stage.rows[snake[1][1]].cells[snake[1][0]].className = 'snake_body';
 keyLocked = false; //释放键盘
}

function fontEffect(target,minFont,maxFont,addNum){
 minFont = minFont || 12;
 maxFont = maxFont || 24;
 addNum = addNum || 0;
 
 if(addNum != 0){
  var num = parseInt(target.innerHTML,10) + addNum;
  target.innerHTML = num;
 }
 var fontSize = minFont;
 var zoomIn = setInterval(function(){
  fontSize += 2;
  target.style.fontSize = fontSize + "px";
  if(fontSize > maxFont){
   clearInterval(zoomIn);
   var zoomOut = setInterval(function(){
    fontSize -= 2;
    target.style.fontSize = fontSize + "px";
    if (fontSize <= minFont) {
     clearInterval(zoomOut);
    }
   },20);
  }
 },20);
}