首先看一下html的布局方式在index.html文件中:
[html]
<!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>连连看</title>
<link rel="stylesheet" type="text/css" href="http://www.php1.cn/">
</head>
<body>
<center>
<div id="whole">
<div id="gamepanel" tabindex="0">
<div id="pieces">
</div>
</div>
<div id="gamelogo">
</div>
<div id="scorepanel">
<span>分 数</span>
</div>
<div id="score">
<span>0</span>
</div>
<div id="timepanel">
<span>时 间</span>
</div>
<div id="time">
<span>0</span>
</div>
<div id="button">
<input id="start" type="button" onclick="start();" value="开始"></input>
<input id="reset" type="button" onclick="reset();"value="重置"></input>
</div>
</div>
</center>
<script type="text/javascript" src="js/map.js"></script>
<script type="text/javascript" src="js/piece.js"></script>
<script type="text/javascript" src="js/game.js"></script>
</body>
</html>
css文件夹下的index.css文件如下:
[css]
body {
font-size : 16px;
font-weight : bold;
color : grey;
}
#whole {
border : 1px double #999999;
border-width : 5px;
width : 800px;
height : 505px;
position : relative;
}
#gamepanel {
margin: 1px 1px 1px 1px;
width : 602px;
height : 502px;
background : url(../img/background.gif) repeat;
position : absolute;
}
#pieces {
margin-top : 35px;
border : 1px solid #999999;
width : 546px;
height : 434px;
position: relative;
}
#pieces .piece {
width : 32px;
height : 36px;
position : relative;
cursor : pointer;
float : left;
}
#pieces .track {
width : 32px;
height : 36px;
position : relative;
float : left;
}
#pieces .track2 {
width : 32px;
height : 36px;
position : relative;
float : left;
background : red;
}
#gamelogo {
margin-top : 60px;
border : 1px solid #999999;
left : 607px;
width : 187px;
height : 73px;
background : url(../img/logo.gif);
position: absolute;
}
#scorepanel {
border : 1px solid #999999;
left : 607px;
top : 200px;
width : 187px;
height : 30px;
position : absolute;
}
#score {
border : 1px solid #999999;
left : 607px;
top : 240px;
width : 187px;
height : 30px;
position : absolute;
}
#timepanel {
border : 1px solid #999999;
left : 607px;
top : 300px;
width : 187px;
height : 30px;
position : absolute;
}
#time {
border : 1px solid #999999;
left : 607px;
top : 340px;
width : 187px;
height : 30px;
position : absolute;
}
#button {
border : 1px solid #999999;
left : 607px;
top : 400px;
width : 187px;
height : 30px;
position : absolute;
}
下面让我们来看一下最核心的js部分实现代码,js部分分为三个源文件即game.js、map.js、piece.js每一个源文件对应一个类,其中本游戏通
过game类来操纵map和图片piece对象:
game.js代码如下:
[javascript]
// 游戏控制类
var game = {
// 游戏背景
gamepanel : null,
// 分数
score : 0,
// 时间
time : 0,
// 图片映射表
piecemap : null,
// 图片列表
piecelist : [],
// 图片列表不包含图片
pieceimglist : [],
// 图片随机数列表
randomlist : [],
// 轨迹列表
tracklist : [],
// 游戏是否开始
isgamebigin : false,
// 游戏是否结束
isgameover : false,
// 游戏是否重置
isgamereset : false,
// 图片元素是否第一次点击
isfirstclick : true,
// 开始游戏
start : function() {
document.getelementbyid(start).disabled = true;
document.getelementbyid(reset).disabled = false;
if (this.isgamereset) {
this.isgameover = false;
this.starttime();
return;
} else if (this.isgamebegin) {
return;
} else {
this.init();
return;
}
},
reset : function() {
document.getelementbyid(start).disabled = false;
document.getelementbyid(reset).disabled = true;
this.clear();
this.initpieces();
this.initimgpieces();
this.time = 0;
document.getelementbyid(time).innerhtml = 0;
this.score = 0;
document.getelementbyid(score).innerhtml = 0;
this.isgamereset = true;
this.isgamebegin = true;
},
// 初始化
init : function() {
if (this.isgamebegin) {
return;
}
this.piecemap = new map();
var _this = this;
this.time = 0;
this.starttime();
this.gamepanel = document.getelementbyid(pieces);
this.initpieces();
this.initimgpieces();
this.isgamebegin = true;
},
// 将随机生成的150张图片添加进画布
initpieces : function() {
var _this = this;
this.initrandomlist();
// 打乱随机列表排序
this.messrandomlist();
for (var i = 0; i < 204; i ++) {
var piece = new piece(this);
this.piecelist.push(piece);
var x = (i%17);
var y = math.floor(i/17);
this.piecemap.put(x+","+y, piece);
piece.setposition(x, y);
this.gamepanel.appendchild(piece.dom);
if (x == 0 || x == 16 || y == 0 || y == 11) {
piece.track = document.createelement("div");
piece.track.classname = "track";
piece.dom.appendchild(piece.track);
piece.istracked = true;
continue;
} else {
if (x == 1 || x == 15 || y == 1 || y == 10) {
piece.setatedge(true);
}
this.pieceimglist.push(piece);
}
}
},
// 初始化图片
initimgpieces : function() {
for (var i = 0; i < this.pieceimglist.length; i ++) {
this.pieceimglist[i].initimg();
this.pieceimglist[i].img.src = "img/pieces/"+this.randomlist[i]+".gif"
this.pieceimglist[i].setimgsrc(this.pieceimglist[i].img.src);
// 执行图片点击事件
this.pieceimglist[i].onclick();
}
},
// 初始化随机表
initrandomlist : function() {
// 获取随机数列,成双出现
for (var i = 0; i < 75; i ++) {
var random = parseint(math.random()*22*10000, 10);
var number = random%23;
this.randomlist.push(number);
this.randomlist.push(number);
}
},
// 打乱随机表
messrandomlist : function() {
for (var i = 0; i < this.randomlist.length; i ++) {
var random = parseint(math.random()*15*10000, 10);
var number = random%150;
var temp;
temp = this.randomlist[i];
this.randomlist[i] = this.randomlist[number];
this.randomlist[number] = temp;
}
},
// 开始计时
starttime : function() {
var _this = this;
if (this.isgameover) {
return;
} else {
this.time ++;
document.getelementbyid("time").innerhtml = this.time;
this.isgamebegin = true;
settimeout(function() {_this.starttime();}, 1000);
}
},
// 清除
clear : function() {
for (var i = 0; i < this.piecelist.length; i ++) {
this.gamepanel.removechild(this.piecelist[i].dom);
}
this.piecelist = [];
this.randomlist = [];
this.pieceimglist = [];
this.isgameover = true;
this.isgamebegin = false;
}
}
window.onload = function() {
document.getelementbyid("start").disabled = false;
document.getelementbyid("reset").disabled = true;
}
// 游戏开始入口
function start() {
game.start();
}
// 游戏重置入口
function reset() {
game.reset();
}
自定义的js版映射结构map.js源文件如下:
[javascript]
var map = function(){
this.data = [];
}
map.prototype = {
put : function(key, value) {
this.data[key] = value;
},
get : function(key) {
return this.data[key];
},
remove : function(key) {
this.data[key] = null;
},
isempty : function() {
return this.data.length == 0;
},
size : function() {
return this.data.length;
}
}
图片类piece.js源文件如下:
[javascript]
var piece = function(game) {
// 游戏对象
this.game = game;
// 是否为边缘元素
this.isedge = false;
// 是否挨着边缘元素
this.atedge = false;
// 图片dom元素
this.dom = null;
// 图片元素
this.img = null;
// 图片元素来源
this.src = null;
// 轨迹元素
this.track = null;
// 是否可以作为轨迹
this.istracked = false;
// 选中标记元素
this.selected = null;
// 图片横向排列
this.x = 0;
// 图片纵向排列
this.y = 0;
// 图片闪烁id
this.flashid = null;
// 图片是否点击
this.onclicked = false;
// 闪烁次数
this.flashcount = 0;
this.init();
}
piece.prototype = {
// 初始化
init : function() {
this.dom = document.createelement("div");
this.dom.classname = "piece";
this.selected = document.createelement("img");
},
// 初始化图片
initimg : function() {
this.img = document.createelement("img");
this.dom.appendchild(this.img);
},
// 满足算法后初始化track元素
inittrack : function() {
if (this.flashid != null) {
// 停止闪烁
this.stopflash();
}
//alert("inittrack middle");
if (this.track != null) {
return;
}
this.onclicked = false;
this.dom.removechild(this.img);
this.track = document.createelement("div");
this.track.classname = "track";
this.dom.appendchild(this.track);
},
// 位图片设置来源
setimgsrc : function(src) {
this.src = src;
},
// 为图片设置二维排列位置
setposition : function(x, y) {
this.x = x;
this.y = y;
},
// 为图片设置选中元素
setselected : function() {
if (this.flashcount ++ % 2 == 0) {
//this.dom.removechild(this.img);
//this.selected.src = "img/selected.gif";
//this.dom.appendchild(this.selected);
this.img.src = "img/pieces/flash.gif";
} else {
//if (this.selected != null) {
// this.dom.removechild(this.selected);
//}
this.img.src = this.src;
//this.dom.appendchild(this.img);
}
},
// 设置是否为边缘元素
setedge : function(isedge) {
this.isedge = isedge;
},
// 设置是否挨着边缘元素
setatedge : function(atedge) {
this.atedge = atedge;
},
// 开始闪烁
flash : function() {
var _this = this;
this.flashid = setinterval(function() {_this.setselected();}, 500);
},
// 停止闪烁
stopflash : function() {
clearinterval(this.flashid);
if (this.flashcount % 2 == 1) {
//if (this.selected != null) {
// this.dom.removechild(this.selected);
//}
this.img.src = this.src;
//this.dom.appendchild(this.img);
}
},
// 对象被选择的内部函数
onclick : function() {
if (this.onclicked) {
return;
}
var _this = this;
this.img.onclick = function() {
if (!document.getelementbyid("start").disabled) {
return;
}
if (_this.onclicked) {
return;
}
if (_this.checkpiece()) {
return;
}
_this.flash();
_this.onclicked = true;
};
},
// 检查是否有被点击的图片
checkpiece : function() {
for (var i = 0; i < this.game.piecelist.length; i ++) {
if (this.game.piecelist[i].onclicked && !this.game.piecelist[i].equal(this)) {
if (this.game.piecelist[i].equalimage(this)) {
//alert("the same image");
this.searchtrack(this.game.piecelist[i]);
} else {
this.game.piecelist[i].stopflash();
this.game.piecelist[i].onclicked = false;
this.onclicked = false;
return false;
}
return true;
} else {
continue;
}
}
return false;
},
// 是否为同一个对象
equal : function(piece) {
return (this.x == piece.x && this.y == piece.y);
},
// 是否为同一个图片
equalimage : function(piece) {
return this.src == piece.src;
},
// 搜寻路径
searchtrack : function(piece) {
if (this.isnear(piece)) {
this.linktrack(piece);
return;
}
if (this.isreach(piece) || this.isreach2(piece)) {
this.linktrack(piece);
return;
}
},
// 是否相邻
isnear : function(piece) {
var a = (math.abs(piece.x - this.x) == 1) && (piece.y == this.y)
|| (math.abs(piece.y - this.y) == 1) && (piece.x == this.x);
return a;
},
// 直线
isstraightreach : function(piece) {
//alert("isstraightreach");
if (this.isnear(piece)) {
return true;
}
var a = false;
var b = false;
// 沿y轴方向搜索
if (this.x == piece.x) {
//alert("!!!!!!!!!!!");
for (var i = this.min(this.y, piece.y) + 1; i < this.max(this.y, piece.y); i ++) {
//alert("this.x == piece.x: " + piece.x + "," + i);
if (this.game.piecemap.get(piece.x + "," + i).ispass()) {
a = true;
this.game.tracklist.push(this.game.piecemap.get(piece.x + "," + i));
continue;
} else {
a = false;
this.game.tracklist = [];
return a;
}
}
}
// 沿x轴方向搜索
if (this.y == piece.y) {
//alert("!!!!!!!!!!!");
for (var i = this.min(this.x, piece.x) + 1; i < this.max(this.x, piece.x); i ++) {
//alert("this.y == piece.y: " + i + "," + piece.y);
if (this.game.piecemap.get(i + "," + piece.y).ispass()) {
b = true;
this.game.tracklist.push(this.game.piecemap.get(i + "," + piece.y));
continue;
} else {
b = false
this.game.tracklist = [];
return b;
}
}
}
return a || b;
},
// 拐一次弯搜索
isreach1 : function(piece) {
//alert("isreach1");
var corner_1 = this.game.piecemap.get(this.x + "," + piece.y);
var corner_2 = this.game.piecemap.get(piece.x + "," + this.y);
var _this = this;
if ((_this.isstraightreach(corner_1))
&& (corner_1.isstraightreach(piece))
&& corner_1.ispass()) {
//alert("corner_1: " + this.x + "," + piece.y);
this.game.tracklist.push(corner_1);
return true;
}
if ((_this.isstraightreach(corner_2))
&& (corner_2.isstraightreach(piece))
&& corner_2.ispass()) {
//alert("corner_2: " + piece.x + "," + this.y);
this.game.tracklist.push(corner_2);
return true;
}
return false;
},
// 直接或拐一次弯搜索
isreach : function(piece) {
var a = this.isstraightreach(piece);
var b = this.isreach1(piece);
return a || b;
},
// 拐两次弯搜索
isreach2 : function(piece) {
// 沿x轴正向搜索
for (var i = this.x + 1; i < 17; i ++) {
if (!this.game.piecemap.get(i + "," + this.y).ispass()) {
this.game.tracklist = [];
break;
} else if (this.game.piecemap.get(i + "," + this.y).isreach(piece)
&& this.game.piecemap.get(i + "," + this.y).ispass()) {
this.game.tracklist.push(this.game.piecemap.get(i + "," + this.y));
return true;
}
}
// 沿x轴搜索
for (var i = this.x - 1; i >= 0; i --) {
if (!this.game.piecemap.get(i + , + this.y).ispass()) {
this.game.tracklist = [];
break;
} else if (this.game.piecemap.get(i + , + this.y).isreach(piece)
&& this.game.piecemap.get(i + , + this.y).ispass()) {
this.game.tracklist.push(this.game.piecemap.get(i + , + this.y));
return true;
}
}
// 沿y轴搜索
for (var i = this.y - 1; i >= 0; i --) {
if (!this.game.piecemap.get(this.x + , + i).ispass()) {
this.game.tracklist = [];
break;
} else if (this.game.piecemap.get(this.x + , + i).isreach(piece)
&& this.game.piecemap.get(this.x + , + i).ispass()) {
this.game.tracklist.push(this.game.piecemap.get(this.x + , + i));
return true;
}
}
// 沿y轴正向搜索
for (var i = this.y + 1; i < 12; i ++) {
if (!this.game.piecemap.get(this.x + , + i).ispass()) {
this.game.tracklist = [];
break;
} else if (this.game.piecemap.get(this.x + , + i).isreach(piece)
&& this.game.piecemap.get(this.x + , + i).ispass()) {
this.game.tracklist.push(this.game.piecemap.get(this.x + , + i));
return true;
}
}
return false;
},
// 路径连接
linktrack : function(piece) {
this.inittrack();
piece.inittrack();
this.changescore();
this.showtrack(piece);
},
// 显示足迹
showtrack : function(piece) {
this.game.tracklist.push(piece);
this.track.classname = track2;
for (var i = 0; i < this.game.tracklist.length; i ++) {
//alert(i);
this.game.tracklist[i].track.classname = track2;
}
var _this = this;
settimeout(function() {_this.hidetrack()}, 500);
},
// 隐匿足迹
hidetrack : function() {
for (var i = 0; i < this.game.tracklist.length; i ++) {
this.game.tracklist[i].track.classname = track;
}
this.game.tracklist = [];
this.track.classname = track;
this.istracked = true;
},
// 分数增加
changescore : function() {
this.game.score += 100;
document.getelementbyid(score).innerhtml = this.game.score;
},
min : function(a, b) {
if (a < b) {
return a;
} else {
return b;