它山之石
最近非常非常忙,手上悬着好几个计划,以至于似乎都没有时间上来码字了。分享近日看到的几个好东西吧。
首先,在刘未鹏那里看到了一篇关于为什么要写博客的文章,刘未鹏是《代码之美》一书的译者,这本书值得一看,这个译者的博客更值得一看。那里有很多有意思的东西。最近看了太多的人写自己为什么要写博客,大概这是独立博客作者在一定的时期都会思考的事情,而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);
}





