Hot For Coding
JavaScript版拼图游戏

前两天,用JavaScript写了一款贪吃蛇,接着趁热也写一款JavaScript版的拼图游戏,耗时四个小时,代码两百多行,滑动效果借助于jQuery animate函数,欢迎大家试玩。

拼图相比贪吃蛇,简单多了,但如果逻辑不清晰会容易迷糊,甚至卡死不知道如何继续下去。本文介绍的是九宫拼图,类似其它4乘4格的拼图跟我这里讨论的实现原理一致。

Demo点这里

拆图

首先,要把图片拆成9格,这里以150px宽高一格为例子,为了让每一格都能显示不同的区域最终组成一张图片,这里使用创建150宽高div,然后背景图可以这么设置

...

READ ALL

两天用JavaScript写了一个变色贪吃蛇,欢迎试玩!

最早接触贪吃蛇是在诺基亚老式单色手机上,曾经有很长一段时间都迷恋这款游戏,尽管当时丰富的3D网游已经遍地都是。贪吃蛇算不上智力游戏,规则简单,于是我就想写一个JavaScript版本的贪吃蛇。

源码直接看Demo就有: 点这里试玩

分析游戏规则与需求

  • 在一个范围内计算出n*n列格子(根据屏幕宽高)
  • 画出蛇在中间位置 (计算)
  • 蛇能移动 (定时处理)
  • 蛇能控制方向 (键盘事件)
  • 撞边或者尾巴就Game over (有一个Game over规则)
  • 吃蛋(预计下一步坐标与蛋坐标是否相等)
  • 每吃一个蛋蛇身加长一个单位(节点操作)
  • 随机位置出蛋(不要在蛇身上)
  • 每吃一个速度越快(定时函数处理)

...

READ ALL

雅虎spider你在干嘛

这几天访问量突增,流量/IO一下上去了,于是检查Nginx日志,发现有好多都是Spider爬行记录。谷歌Spider与百度Spider居多,剩余的什么有道、微软Bing、Yahoo等七八个都在爬。而雅虎Spider貌似比其他更顽固。

我有一个go页面是做留言者网站跳转用的,所以Spider爬到该页面的时候多半是302,最后Spider都会绕行。唯独雅虎Spider不放弃,每天坚持N次才罢休

110.75.171.110 - - [20/Mar/2013:17:07:17 +0800] "GET /20120554.html HTTP/1.1" 200 7965 "-" "Yahoo! Slurp China" -
110.75.172.109 - - [20/Mar/2013:17:10:20 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.107 - - [20/Mar/2013:17:10:26 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.108 - - [20/Mar/2013:17:10:35 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.112 - - [20/Mar/2013:17:10:48 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.111 - - [20/Mar/2013:17:10:54 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.109 - - [20/Mar/2013:17:10:56 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.109 - - [20/Mar/2013:17:10:58 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.107 - - [20/Mar/2013:17:11:00 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.108 - - [20/Mar/2013:17:11:02 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.112 - - [20/Mar/2013:17:11:07 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.111 - - [20/Mar/2013:17:11:17 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.110 - - [20/Mar/2013:17:11:26 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.109 - - [20/Mar/2013:17:11:32 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.107 - - [20/Mar/2013:17:11:36 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.108 - - [20/Mar/2013:17:11:38 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.112 - - [20/Mar/2013:17:11:39 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.111 - - [20/Mar/2013:17:11:41 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.110 - - [20/Mar/2013:17:11:44 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.109 - - [20/Mar/2013:17:11:48 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.172.107 - - [20/Mar/2013:17:11:55 +0800] "GET /go/BeT0h1 HTTP/1.1" 302 5 "-" "Yahoo! Slurp China" -
110.75.173.195 - - [20/Mar/2013:17:59:07 +0800] "GET /201302280.html HTTP/1.1" 200 6544 "-" "Yahoo! Slurp China" -

...

READ ALL

HTML5不刷新修改URL

HTML5新添加了两个API分别是pushState和replaceState,DOM中的window对象通过window.history方法提供了对浏览器历史记录的读取,可以在用户的访问记录中前进和后退,我们可以开始操作这个历史记录堆栈。

实例一、通过pushState修改URL

通过这句代码可以无刷新改变URL

window.history.pushState({}, 0, url);

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>HTML5无刷修改URL</title>
    <script type="text/javascript">
      function changeURL(){
        var url = document.getElementById('url').value;
        window.history.pushState({},0,'http://'+window.location.host+'/'+url);
      }
    </script>
  </head>
  <body>
    <h1>html5无刷新改变url</h1>
    <div id="info" style="margin:30px 0;">
      页面真实地址:
      <span style="color:red;"><script type="text/javascript">document.write(window.location.href);</script></span>
    </div>
    <div>
    请输入要改变地URL字符串:<input id='url' type="text" />
    <button onclick="changeURL();">点击无刷改变url</button>
    </div>
    <div style="color:red;margin-top:30px;">请使用支持html5的浏览器访问</div>
  </body>
</html>

...

READ ALL

PHP中IP与整型互相转换

IP转换成整型存储是数据库优化一大趋势,不少人目前存储IP时还在使用字符串类型存储,字符串索引比整型索引消耗资源很多,特别是表中数据量大的时候,以及求查询某一个IP段的数据,今天说的IP是指IPv4,IPv6不在本文范围内。

系统函数ip2long与long2ip

PHP中有内置函数ip2long可以将ip地址转换整型。

$ip = '210.110.11.49';
echo ip2long($ip);

// Output: -764540111

输出的整型有负号是因为我们得到的结果是有符号整型,有符号整型最大值2147483647,要把结果转换为无符号型可以这么写

...

READ ALL

基于jQuery写的一个Dialog插件

基于jQuery写的一个弹窗插件,功能简陋,效果单一,主要是是用jQuery的animate函数做同时滑动淡出淡入效果

JavaScript Code

(function($) {
  $.fn.dialog = function (param) {
    if (typeof param.dialog === 'undefined') {
      return;
    }

    var dialog = param.dialog;
    var close = param.close || '.close';
    var speed = 400;
    var margin_left = '-'+parseInt($(dialog).width()/2)+'px';
    var margin_top = '-'+parseInt($(dialog).height()/2)+'px';
    var _this = null; 
    var bg = '<div class="dialog_bg" style="width:100%;height:'+$(document).height()+'px;background:#000;opacity:0.7;filter:alpha(opacity=70);  position:absolute;left:0;top:0;z-index:2147483600;display:none;"></div>';

    $(dialog).css({
      position: 'fixed',
      'margin-left': margin_left,
      'margin-top': margin_top,
      left: '50%',
      top:'50%',
      display: 'none',
      'z-index': 2147483601
    });

    $('body').append(bg);

    $(this).each(function(){
      _this = $(this);
      _this.click(function(){
        if (!$(dialog).is(':visible')) {
          $('.dialog_bg').fadeIn(parseInt(speed/2));
          $(dialog).css({'top':'35%','display':'block','opacity':0.0});
          $(dialog).animate({top:'50%',opacity:1},speed);
        }
      });

      $(dialog+' '+close).click(function(){
        $(dialog)
          .animate({
            top: '65%',
            opacity:0
          },speed,false,function() {
            $(this)
              .hide()
              .css('top','50%');
            $('.dialog_bg').fadeOut(parseInt(speed/2));
          });
      });
    });
  }
   
})(jQuery);

...

READ ALL

Python石头剪子布简单程序

我之前写过一篇基于JS的石头剪子布程序 《JavaScript写的一个石头剪子布游戏,大家进来玩玩吧!》,今天又基于Python写了一个实例,这里边的算法有点特殊但一时也想不到一个好的算法规律。

Python Code

# encoding=UTF-8
# 石头剪子布 程序
import random
 
# 定义石头剪子布字典
dict = {1:'剪子',2:'石头',3:'布'}
 
for row in dict:
  print '编号:',row,' = ',dict[row]
 
print '您出什么?'
 
loop = True
while loop:
  you = raw_input('请输入编号回车: ')
  try:
    you = int(you)
    if you>=1 and you<=3:
      loop = False
    else:
      print '请输入 1-3 范围内的编号'
  except Exception,e:
    print '请输入正确的数字编号'
 
dn = random.randint(1,3)
print '你出:',dict[you]
print '电脑出:',dict[dn]
print '结果:',
 
if dn==you:
  print '平局'
elif (you>dn and you-dn==1) or you+2==dn:
  print '你胜'
else:
  print '电脑胜'

...

READ ALL

shell执行PHP传入参数的三种方式

有些时候需要在shell命令下执行PHP脚本,比如定时任务。这就涉及到在shell命令下如何给PHP传参的问题,通常有三种方式传参

使用$argv $argc参数接收

<?php
/**
 * 使用 $argc $argv 接受参数
 */
 
echo "接收到{$argc}个参数";
print_r($argv);

Example

[root@DELL113 lee]# /usr/local/php/bin/php test.php
接收到1个参数Array
(
  [0] => test.php
)
[root@DELL113 lee]# /usr/local/php/bin/php test.php a b c d
接收到5个参数Array
(
  [0] => test.php
  [1] => a
  [2] => b
  [3] => c
  [4] => d
)
[root@DELL113 lee]#

...

READ ALL

基于jQuery开发的焦点图插件

同事找帮忙需要写一个普通的焦点图,切换效果是渐变,默认不自动切换,图片有小点,点击小点可以切换图片。花了三个多小时写好,贴出来的目的是让那些开发jQuery插件的童鞋做个参考。

源码

focus.js

/**
 * 焦点图
 * 2013-03-11
 */
(function($) {
  $.fn.focus = function(param){   
    // 默认高度
    var height = param.height || 200;   
    // 默认宽度
    var width = param.width || 100; 
    var _this = null;

    // jQuery的对象选择器是多个,所以这里使用each遍历每一个节点对象
    $(this).each(function(){

      // 把每一个节点对象赋给一个变量,这有助于程序效率
      _this = $(this);

      $('body').css({margin: 0, padding: 0});

      // 改变盒子大小 
      _this.css({
        width: width + 'px',
        height: height+'px',
        position: 'relative',
        padding: 0
      });
    

      var fock_png_width = 16;            // png宽度(px)
      var fock_png_margin_sx = 8;         // png 小图标上下间距(px)
      var ul_height = fock_png_width + fock_png_margin_sx * 2; // 底部黑条的高度(px)
      var box_height = _this.height();            
      var box_width = _this.width();
      var fock_png_margin_zy = 10;            // png 小图标左右间距
      var js = document.scripts;
      var speed = 500;
      var sper_url = '';              // js路径
      var sper_file_name = 'sper.png';        // png 文件名
      var last_index = 0;
      var lock = false;

      var objImg = _this.find('>img');     // 查找所有图片

      if (objImg.length === 0) {
        return false;   
      }else{
        var img_length = objImg.length; 
      }

      // 获取js文件路径 目的是为了使用png图片
      for (var i = js.length; i>0; i--) {
        if (js[i-1].src.indexOf('lee_plug')>-1) {
          sper_url = js[i-1].src.substring(0, js[i-1].src.lastIndexOf("/") + 1) + sper_file_name;
        }
      }

      // 底部黑条     
      _this.append('<div style="position:absolute;top:'+(height-ul_height)+'px;background:#000;opacity:0.7;height:'+ul_height+'px;margin:0 auto;padding:0;width:100%;"></div>');

      // 创建小图标
      var html = '<ul style="position:absolute;top:'+(height-ul_height)+'px;height:'+ul_height+'px;margin:0 auto;padding:0;width:100%;opacity:0.7;">';
      for (var i=0; i < img_length; i++) {
        $(objImg[i]).css({
          width: '100%',
          height: '100%',
          position: 'absolute',
          margin: 0,
          padding: 0
        });

        if (i >= 1) {
          $(objImg[i]).hide();        
          var sper_weizhi = 0;
        }else{
          var sper_weizhi = '-' + fock_png_width + 'px';
        }

        var left = parseInt((box_width - img_length*(fock_png_width+fock_png_margin_zy*2)) /2) + i*(fock_png_width+fock_png_margin_zy);

        html += '<li style="display:block;position:absolute;width:'+fock_png_width+'px;height:'+fock_png_width+'px;background:url('+sper_url+') 0 '+sper_weizhi+' no-repeat;margin:0; padding:0;cursor:pointer; top:'+parseInt((ul_height-fock_png_width)/2)+'px;left:'+left+'px;"></li>';
      }
      html += '</ul>';

      _this.append(html);

      // 绑定单击事件
      _this.find('>ul>li').each(function(i){
        // 这里使用的js原生事件绑定,因为jQuery 的 click怎么闭包传入i没有弄明白,所以使用原生函数处理
        $(this).get(0).onclick = function (num, obj) {
          return function(){
            if (num === last_index || lock) {
              return false;
            }
            lock = true;
            obj.find('>ul>li').each(function (i) {
              $(this).css('background', 'url(' + sper_url + ') 0 0 no-repeat');
            });
            obj.find('>ul>li:eq(' + num + ')').css('background','url(' + sper_url + ') 0 -' + fock_png_width + 'px no-repeat');
            obj.find('>img:visible').fadeOut(speed);
            obj.find('>img:eq(' + num + ')').fadeIn(speed, function () {
              lock = false;
              last_index = num;   
            });
          }
        }(i, _this); 
      });
    }); 
  };      
  
})(jQuery);

...

READ ALL

SQLServer CONVERT()用法疑问

SQLServer CONVERT()函数是格式化时间,在做时间对比时很有用。但CONVERT()函数的第二个参数虽然是日期类型,但不接受字符串拼接的格式

什么是CONVERT()

CONVERT()函数是把日期转换为新数据类型的通用函数。此函数可以用不同的格式显示日期/时间数据。

语法

CONVERT(data_type(length),data_to_be_converted,style)

  • data_type(length) 规定目标数据类型(带有可选的长度)
  • data_to_be_converted 含有需要转换的值
  • style规定日期/时间的输出格式。

...

READ ALL