之前编写过一个单机版的游戏
letters,晚上睡不着,稍加改动,变成联机版的了。
静态页面 letters.htm

 <SCRIPT>
<SCRIPT>
 var isIE=!!document.all;
var isIE=!!document.all;

 function checkMouseMove(event)
function checkMouseMove(event) {
{

 if (window.activeElement)
if (window.activeElement) {
{
 var elm = window.activeElement;
var elm = window.activeElement;
 elm.style.left = event.clientX-elm.innerX;
elm.style.left = event.clientX-elm.innerX;
 elm.style.top = event.clientY-elm.innerY;
elm.style.top = event.clientY-elm.innerY;
 if(xmlhttp)xmlhttp.abort();
if(xmlhttp)xmlhttp.abort();
 if(timer)clearTimeout(timer);
if(timer)clearTimeout(timer);
 }
}
 }
}

 function releaseMouse(event)
function releaseMouse(event) {
{

 if (window.activeElement)
if (window.activeElement) {
{
 var x = activeElement.offsetLeft;
    var x = activeElement.offsetLeft;
 var y = activeElement.offsetTop;
    var y = activeElement.offsetTop;
 var pos = activeElement.id;
    var pos = activeElement.id;
 var data =y.toString(16);
    var data =y.toString(16);
 data = x.toString(16)+"0000".substr(data.length)+data;
    data = x.toString(16)+"0000".substr(data.length)+data;
 var url = "http://localhost:8080/letters/letters.jsp?pos="+pos+"&data="+data;
    var url = "http://localhost:8080/letters/letters.jsp?pos="+pos+"&data="+data;
 if(xmlhttp)xmlhttp.abort();
    if(xmlhttp)xmlhttp.abort();
 xmlhttp = window.XMLHttpRequest?(new XMLHttpRequest()):(new ActiveXObject("Microsoft.XMLHTTP"));
    xmlhttp = window.XMLHttpRequest?(new XMLHttpRequest()):(new ActiveXObject("Microsoft.XMLHTTP"));
 xmlhttp.onreadystatechange= handleXML;
    xmlhttp.onreadystatechange= handleXML;
 xmlhttp.open("GET",url,true);
    xmlhttp.open("GET",url,true);
 xmlhttp.send(null);
    xmlhttp.send(null);
 window.activeElement = null;
    window.activeElement = null;
 }
}
 }
}

 function drag(event)
function drag(event) {
{
 if (event.button>1) return;
if (event.button>1) return;
 var elm = isIE?event.srcElement:event.target;
var elm = isIE?event.srcElement:event.target;
 window.activeElement = elm;
window.activeElement = elm;
 elm.oldX = elm.offsetLeft;
elm.oldX = elm.offsetLeft;
 elm.oldY = elm.offsetTop;
elm.oldY = elm.offsetTop;
 elm.innerX = event.clientX - elm.oldX;
elm.innerX = event.clientX - elm.oldX;
 elm.innerY = event.clientY - elm.oldY;
elm.innerY = event.clientY - elm.oldY;
 }
}


 function slideTo(id,x,y)
function slideTo(id,x,y) {
{
 var d=3;
var d=3;    
 var e = document.getElementById(id);
var e = document.getElementById(id);
 var l = e.style.left?parseInt(e.style.left):0;
var l = e.style.left?parseInt(e.style.left):0;
 var t = e.style.top?parseInt(e.style.top):0;
var t = e.style.top?parseInt(e.style.top):0;
 if(Math.abs(l-x)<=d && Math.abs(t-y)<=d) return;
if(Math.abs(l-x)<=d && Math.abs(t-y)<=d) return;
 if(l!=x) e.style.left=l+(l<x?d:-d);
if(l!=x) e.style.left=l+(l<x?d:-d);
 if(t!=y) e.style.top=t+(t<y?d:-d);
if(t!=y) e.style.top=t+(t<y?d:-d);
 if(e.timer) clearTimeout(e.timer);
if(e.timer) clearTimeout(e.timer);
 e.timer=setTimeout("slideTo("+id+","+x+","+y+")",3)
e.timer=setTimeout("slideTo("+id+","+x+","+y+")",3)
 }
}


 function jumpTo(id,x,y)
function jumpTo(id,x,y) {
{
 var e = document.getElementById(id);
var e = document.getElementById(id);
 if(e.timer) clearTimeout(e.timer);
if(e.timer) clearTimeout(e.timer);
 e.style.left=x;
e.style.left=x;
 e.style.top=y;
e.style.top=y;
 }
}

 var xmlhttp;
var xmlhttp;

 function refreshPos()
function refreshPos() {
{
 if(xmlhttp) return;
    if(xmlhttp) return;
 xmlhttp = window.XMLHttpRequest?(new XMLHttpRequest()):(new ActiveXObject("Microsoft.XMLHTTP"));
    xmlhttp = window.XMLHttpRequest?(new XMLHttpRequest()):(new ActiveXObject("Microsoft.XMLHTTP"));
 xmlhttp.onreadystatechange= handleXML;
    xmlhttp.onreadystatechange= handleXML;
 xmlhttp.open("GET","http://localhost:8080/letters/letters.jsp",true);
    xmlhttp.open("GET","http://localhost:8080/letters/letters.jsp",true);
 xmlhttp.setRequestHeader("If-Modified-Since","0");
    xmlhttp.setRequestHeader("If-Modified-Since","0");
 xmlhttp.send(null);
    xmlhttp.send(null);
 }
}

 function handleXML()
function handleXML() {
{

 if(xmlhttp.readyState==4&&xmlhttp.status==200)
    if(xmlhttp.readyState==4&&xmlhttp.status==200) {
{
 var posList = xmlhttp.responseText.split(",");
        var posList = xmlhttp.responseText.split(",");
 if(posList.length>=n)
        if(posList.length>=n)

 for(var i=0;i<n;i++)
        for(var i=0;i<n;i++) {
{
 var p = posList[i];
            var p = posList[i];
 var x = parseInt(p.substring(0,p.length-4),16);
            var x = parseInt(p.substring(0,p.length-4),16);
 var y = parseInt(p.substr(p.length-4),16);
            var y = parseInt(p.substr(p.length-4),16);
 if(!timer) jumpTo(i,x,y);
            if(!timer) jumpTo(i,x,y);
 else slideTo(i,x,y);
            else slideTo(i,x,y);
 }
        }
 xmlhttp=null;
        xmlhttp=null;
 timer = setTimeout("refreshPos()",500);
        timer = setTimeout("refreshPos()",500);
 }
    }
 }
}
 var n=104;
var n=104;
 var timer;
var timer;
 window.onload=refreshPos;
window.onload=refreshPos;
 </SCRIPT>
</SCRIPT>
 </HEAD>
</HEAD>

 <style>
<style> b{
b{ }{position:absolute;cursor:pointer;font-size:20}</style>
}{position:absolute;cursor:pointer;font-size:20}</style>
 <BODY onmousemove="checkMouseMove(event)" onmouseup="releaseMouse(event)" oncontextmenu="return false" onselectstart="return false" ondblclick="return false">
<BODY onmousemove="checkMouseMove(event)" onmouseup="releaseMouse(event)" oncontextmenu="return false" onselectstart="return false" ondblclick="return false">
 <div style="background-color:yellow;width:600;height:500;overflow:hidden">
<div style="background-color:yellow;width:600;height:500;overflow:hidden">

 <SCRIPT>
<SCRIPT>
 for(var i=0;i<n;i++)
for(var i=0;i<n;i++)
 document.write("<b onmousedown=\"drag(event)\" id=\""+i+"\" style=\"color:#"+(Math.floor(Math.random()*(1<<24))|(1<<23)).toString(16)+"\" onbeforselect=\"return false\">"+String.fromCharCode(i%26+65)+"</b>");
document.write("<b onmousedown=\"drag(event)\" id=\""+i+"\" style=\"color:#"+(Math.floor(Math.random()*(1<<24))|(1<<23)).toString(16)+"\" onbeforselect=\"return false\">"+String.fromCharCode(i%26+65)+"</b>");
 </SCRIPT>
</SCRIPT>
 </div>
</div>服务程序letters.jsp:

 <%
<% @ page contentType="text/html; charset=GBK" %>
@ page contentType="text/html; charset=GBK" %>

 <%
<% ! int[] letters;
! int[] letters;
 int maxLetters = 104;
int maxLetters = 104;

 %><%
%><%
 letters = (int[])application.getAttribute("letters");
letters = (int[])application.getAttribute("letters");
 if(null == letters){
if(null == letters){
 letters = new int[maxLetters];
  letters = new int[maxLetters];
 for(int i=0;i<maxLetters;i++) letters[i]=(Math.round(i/26)*15+1)+(((i%26+1)*15)<<16);
  for(int i=0;i<maxLetters;i++) letters[i]=(Math.round(i/26)*15+1)+(((i%26+1)*15)<<16);
 application.setAttribute("letters",letters);
  application.setAttribute("letters",letters);
 }
}
 String stPos = request.getParameter("pos");
String stPos = request.getParameter("pos");
 String stData = request.getParameter("data");
String stData = request.getParameter("data");
 if(stPos!=null && stData !=null){
if(stPos!=null && stData !=null){
 try{
  try{
 int pos = Integer.parseInt(stPos);
    int pos = Integer.parseInt(stPos);
 int data = Integer.parseInt(stData,16);
    int data = Integer.parseInt(stData,16);
 letters[pos]=data;
    letters[pos]=data;
 }catch(Exception e){
  }catch(Exception e){
 e.printStackTrace();
    e.printStackTrace();
 }
  }
 }
}
 for(int i=0;i<maxLetters;i++) out.print(Integer.toHexString(letters[i])+",");
for(int i=0;i<maxLetters;i++) out.print(Integer.toHexString(letters[i])+",");
 %>
%>

当然服务程序如果直接写servlet可以更优化,不过我写servlet很依赖IDE或者手册,用jsp写就比较容易贯彻裸奔精神了。直接用tomcat发布出去即可运行(注意静态页面中两处hardcode的“
http://localhost:8080/letters/letters.jsp”有可能需要根据发布环境做相应的修改)。服务程序代码做的相当简单,改asp版应该也不为难。详细的说明春节后补充,简单的介绍一下数据结构:
1 每个字母的位置由一个32位十六进制数字表示,前16位为横坐标,后16位为纵坐标,坐标空间65536*65536
2 application中维持一个所有字母的位置列表,通过“letters”这个key引用。
3 参数格式为pos:被移动的字母的序号,data:为该字母的新位置。
点击这里下载源码