来看看实现的效果图
游戏规则:双击颜色一样的星星,双击相同的部分就消失了
实例代码
<!doctype html>
<html>
<head>
<meta charset="utf-8" content="target-densitydpi=320,width=640,user-scalable=no" />
<noscript><meta http-equiv="refresh" content="0"></noscript>
<title></title>
<meta name="description" id="seo_description" content="消灭星星">
<meta name="viewport" content="initial-scale=1, width=device-width, maximum-scale=1, user-scalable=no">
<meta name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1" media="(device-height: 568px)">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name='apple-touch-fullscreen' content='yes'>
<meta name="full-screen" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<meta name="format-detection" content="address=no">
<link rel="icon" href="" type="image/x-icon">
<script id="jquery_183" type="text/javascript" class="library" src="http://runjs.cn/js/sandbox/jquery/jquery-1.8.3.min.js"></script>
<style>
* {margin:0; padding:0;}
body {background:#000; width:100%; height:100%;}
#box {position:absolute; margin-top:50px;}
#star_box {position:relative; }
#star_box .star {width:40px; height:40px; position:absolute; cursor:pointer; }
#star_box .star img {border-radius:5px;}
#star_box .link img {border:2px solid #fff; border-radius:5px;}
</style>
<script>
$(function(){
app.run();
});
// 2015-1-30 16:26
// 基本都已经实现
// 积分系统还没开始
var app = {};
app.linkstars = [];
app.searchstars = [];
app.stars = [];
app.newstars = [];
app.colsnonenum = 0;
app.star = {
width:30, // 星星的宽度
height:30, // 高度
margin:5, // 每个星星的边距
rownum:10, // 行数
colsnum:10, // 列数
colornum:5, // 星星颜色数量 最大值为5 因为我tmd就做了5张星星图片
};
app.timer = null;
app.run = function() {
this.box = $('#box');
this.starbox = this.box.find('#star_box');
this.initcanvas();
this.initstars();
this.draw();
this.initbox();
// this.write();
}
app.initcanvas = function() {
var height = $(window).height();
$('body').css('height', height+'px');
}
// 初始化box样式
app.initbox = function() {
var boxwidth = this.star.width*this.star.colsnum+this.star.margin*this.star.colsnum;
var boxheight = this.star.height*this.star.rownum+this.star.margin*this.star.rownum;
var left = ($(window).width() - boxwidth) / 2;
this.box.css('left', left+'px');
this.box.css('width', boxwidth+'px');
this.box.css('height', boxheight+'px');
}
// 初始化星星数组
app.initstars = function() {
for(var i = 0; i < this.star.rownum; i++) {
this.stars[i] = [];
for(var k = 0; k < this.star.colsnum; k++) {
var color_index = math.floor((math.random()*this.star.colornum));
this.stars[i][k] = color_index;
}
}
// this.stars = [[0,1,0,1,1],[0,0,0,1,0]]; // bug测试
this.newstars = left2array(this.stars);
this.noleftchangestars = left2array(this.stars);
}
app.initcolslink = function() {
// 当前查找状态,一个数组对象,每个对象代表一列
this.colslink = [];
for(var i = 0; i < this.star.colsnum; i++) {
this.colslink[i] = {x:[], num:0, max:number(-1), count:this.initrowarray(1)};
}
}
app.click = function(x, y) {
x = parseint(x);
y = parseint(y);
var searchstars = [];
searchstars[0] = {x:x, y:y};
this.count = 0;
this.linkstars = [];
this.searchstars = [];
this.bigsearch(searchstars); // 搜索 连接的星星
this.clickanimate();
}
app.mouseup = function() {
cleartimeout(app.timer);
app.timer = settimeout(function() {
app.starbox.find('.star').removeclass('link');
}, 500);
}
// 触摸某个星星
// x坐标 和 y坐标
app.touch = function(x, y) {
x = parseint(x);
y = parseint(y);
var searchstars = [];
searchstars[0] = {x:x, y:y};
this.count = 0;
this.linkstars = [];
this.searchstars = [];
this.bigsearch(searchstars); // 搜索 连接的星星
this.initcolslink();
this.colsnonelenth = this.initcolsarray(0);
this.leftdata = {min:number(this.star.colsnum), y:[], num:0, count:this.initcolsarray(1)};
this.makestars(); // 重新生成星星数组
this.animate();
// this.draw(); // 重新绘制星星
// this.write(); // debug
}
// 星星动画
app.animate = function() {
if(this.linkstars.length < 2) return;
for(var i in this.linkstars) {
var x = parseint(this.linkstars[i].x);
var y = parseint(this.linkstars[i].y);
app.delanimate(x, y);
}
for(var i in this.colslink) {
var x = parseint(this.colslink[i].max);
var y = parseint(i);
if(this.colslink[i].x.length > 1) {
var moffset = 0;
for(var j = this.colslink[i].x.length-1; j >= 0; j--) {
moffset += this.colslink[i].count[j];
var r = this.colslink[i].x[j-1];
if(j - 1 < 0) r=-1;
for(var t_x = this.colslink[i].x[j]-1; t_x > r; t_x--) {
this.downanimate(t_x, y, moffset);
}
}
}
else {
for(var t_x = x-1; t_x >= 0; t_x--) {
this.downanimate(t_x, y, this.colslink[y].num);
}
}
}
if(this.leftdata.min > -1) {
if(this.leftdata.y.length > 1) {
var moffset = 0;
for(var j = 0; j <= this.leftdata.y.length-1; j++) {
moffset += this.leftdata.count[j];
var r = this.leftdata.y[j+1];
if(j + 1 > this.leftdata.y.length-1) r=this.star.colsnum;
for(var n_x = 0; n_x <= this.star.rownum-1; n_x++) {
for(var n_y = this.leftdata.y[j]+1; n_y < r; n_y++) {
this.leftanimate(n_x, n_y, moffset);
}
}
}
}
else {
var y = parseint(this.leftdata.min);
for(var n_x = 0; n_x <= this.star.rownum-1; n_x++) {
for(var n_y = y+1; n_y < this.star.colsnum; n_y++) {
this.leftanimate(n_x, n_y, this.leftdata.num);
}
}
}
}
// this.leftanimate();
}
/* 消除星星的动画效果 */
app.delanimate = function(x,y) {
var index = x*this.star.colsnum + y; // 根据x、y计算对应dom中星星的 id
var stardiv = this.starbox.find('.id_'+index);
var left = parseint(stardiv.css('left')) + this.star.width/2
var top = parseint(stardiv.css('top')) + this.star.height/2
stardiv.find('img').animate({width:'0',height:'0'}, 500);
stardiv.animate({ left:left+'px', top:top+'px', opacity:0}, 500, function(){$(this).hide();});
stardiv.removeclass('id_'+index);
}
/* 星星向下移动的动画效果 */
app.downanimate = function(x, y, move_num) {
if(this.checkrepeat(x, y)) {
return ;
}
var index = x*this.star.colsnum + y;
var stardiv = this.starbox.find('.id_'+index);
var dtop = parseint(stardiv.css('top'));
var top = dtop + (this.star.height + this.star.margin) * move_num;
stardiv.animate({top:top+'px'}, 300);
var n_x_ = x + move_num;
stardiv.attr('ondblclick', 'app.touch('+n_x_+','+y+')');
stardiv.attr('onmousedown', 'app.click('+n_x_+','+y+')');
stardiv.removeclass('id_'+index);
var id = parseint(n_x_*this.star.colsnum) + parseint(y);
stardiv.addclass('id_'+id);
}
/* 星星向左移动的动画效果 */
app.leftanimate = function(x, y, move_num) {
var index = x*this.star.colsnum + y;
var stardiv = this.starbox.find('.id_'+index);
var dleft = parseint(stardiv.css('left'));
var left = dleft - (this.star.width + this.star.margin) * move_num;
stardiv.animate({left:left+'px'}, 300);
var n_y_ = y - move_num;
stardiv.attr('ondblclick', 'app.touch('+x+','+n_y_+')');
stardiv.attr('onmousedown', 'app.click('+x+','+n_y_+')');
stardiv.removeclass('id_'+index);
var id = parseint(x*this.star.colsnum) + parseint(n_y_);
stardiv.addclass('id_'+id);
}
// 点击提示连接星星动画
app.clickanimate = function() {
if(this.linkstars.length < 2) return;
this.starbox.find('.star').removeclass('link');
for(var i in this.linkstars) {
var x = parseint(this.linkstars[i].x);
var y = parseint(this.linkstars[i].y);
var index = x*this.star.colsnum + y;
var stardiv = this.starbox.find('.id_'+index);
stardiv.addclass('link');
}
}
/* 递归遍历查找 */
app.bigsearch = function(searchstars) {
if(searchstars.length == 0) return ;
this.newsearchstars = [];
this.s_count = 0;
for(var i in searchstars) {
var star = searchstars[i];
var x = parseint(star.x);
var y = parseint(star.y);
if(!this.checkrepeat(x, y)) {
this.linkstars[this.count] = {x:x, y:y};
}
this.count++;
this.search(x, y, 'top');
this.search(x, y, 'right');
this.search(x, y, 'down');
this.search(x, y, 'left');
}
this.bigsearch(this.newsearchstars);
}
/* 上下左右 查找 */
app.search = function(x, y, position) {
if(position == 'top') {
var top = x-1;
if(top < 0) return;
if(this.stars[x][y] == this.stars[top][y] && !this.checkrepeat(top, y)) {
this.newsearchstars[this.s_count] = {x:top, y:y};
}
}
else if(position == 'right') {
var right = y+1;
if(right > this.star.colsnum-1) return;
if(this.stars[x][y] == this.stars[x][right] && !this.checkrepeat(x, right)) {
this.newsearchstars[this.s_count] = {x:x, y:right};
}
}
else if(position == 'down') {
var down = x+1;
if(down > this.star.rownum-1) return;
if(this.stars[x][y] == this.stars[down][y] && !this.checkrepeat(down, y)) {
this.newsearchstars[this.s_count] = {x:down, y:y};
}
}
else if(position == 'left') {
var left = y-1;
if(left < 0) return;
if(this.stars[x][y] == this.stars[x][left] && !this.checkrepeat(x, left)) {
this.newsearchstars[this.s_count] = {x:x, y:left};
}
}
this.s_count++;
}
// 根据传递的x, y来检测是否存在在linkstars中 如果存在则返回 true
app.checkrepeat = function(x, y) {
if(this.linkstars.length == 0) return false;
for(var i in this.linkstars) {
var star = this.linkstars[i];
if(parseint(star.x) == parseint(x) && parseint(star.y) == parseint(y)) return true;
}
return false;
}
// 从新构造“星星”数组
// stars、newstars必须初始化完成
// linkstars必须>=2个星星
app.makestars = function() {
if(this.stars.length==0 || this.newstars.length==0 || this.linkstars.length==0 || this.linkstars.length<2) return false;
// -== setp-1 ==-
/*
在相连数组中查找当前星星是否是相连的
如果是相连的星星 则在newstars中把该星星以上的星星的值都赋值给x+1的星星
然后在newstars中把最上面的一个元素 即[0][y]的元素值设为-1;
*/
var clx_count = this.initcolsarray(0);
for(var x in this.stars) {
x = parseint(x);
for(var y in this.stars[x]) {
y = parseint(y);
if(this.stars[x][y] != -1 && this.checkrepeat(x,y)) {
for(var n_x = x-1; n_x >= 0; n_x--) {
this.newstars[n_x+1][y] = this.newstars[n_x][y];
}
this.newstars[0][y] = -1;
this.colslink[y].num += 1;
if(this.colslink[y].max < x) {
this.colslink[y].max = x;
if((x+1 <= this.stars.length-1 && !this.checkrepeat(x+1,y)) || (x == this.stars.length-1 && this.checkrepeat(x,y))) {
this.colslink[y].x[clx_count[y]] = x;
clx_count[y]++;
}
else if(x+1 <= this.stars.length-1 && this.checkrepeat(x+1,y)) {
this.colslink[y].count[clx_count[y]] += 1;
}
}
this.colsnonelenth[y] += 1;
}
}
}
// -== setp-2 ==-
// 主要是为生成左移动画统计数据
this.noleftchangestars = left2array(this.newstars);
var ld_count = 0;
for(var y = 0; y <= this.star.colsnum-1; y++) {
y = parseint(y);
// if(this.star.colsnum - (y+1) < this.colsnonenum) continue;
// 判断当前列是否全部被设置为-1
if(this.checkcolsnone(y)) {
if(this.leftdata.min > y) {
this.leftdata.min = y;
}
if((y+1 <= this.star.colsnum-1 && !this.checkcolsnone(y+1)) || (y == this.star.colsnum-1)) {
this.leftdata.y[ld_count] = y;
ld_count++;
}
else if(y+1 <= this.star.colsnum-1 && this.checkcolsnone(y+1)) {
this.leftdata.count[ld_count] += 1;
}
this.leftdata.num += 1;
// this.colsnonenum += 1;
}
}
// -== setp-3 ==-
// 左移数据 并从新构造新数组
if(this.leftdata.min > -1) {
var check = this.leftdata.min;
for(var y = 0; y < this.star.colsnum; y++) {
if(this.checknewcolsnone(check)) {
for(var n_x = 0; n_x <= this.star.rownum-1; n_x++) {
for(var n_y = check+1; n_y < this.star.colsnum; n_y++) {
this.newstars[n_x][n_y-1] = this.newstars[n_x][n_y];
}
this.newstars[n_x][this.star.colsnum-1] = -1;
}
}
else {
check += 1;
}
}
}
// 把新构造的数组 再赋值给星星数组
this.stars = left2array(this.newstars);
}
// 检测当前列是否全部消空 如果消空返回true
// 数组未被左移破坏,只被下移修改过
app.checkcolsnone = function(y) {
var count = 0;
for(var x = 0; x < this.star.rownum; x++) {
if(this.noleftchangestars[x][y] == number(-1)) count++;
}
if(count == this.star.rownum) return true;
return false;
}
// 检测当前列是否全部消空 如果消空返回true
// 数组为每次下移和左移之后新生成的数组
app.checknewcolsnone = function(y) {
var count = 0;
for(var x = 0; x < this.star.rownum; x++) {
if(this.newstars[x][y] == number(-1)) count++;
}
if(count == this.star.rownum) return true;
return false;
}
app.draw = function() {
var starsdiv = '';
for(var x in this.stars) {
x = parseint(x);
for(var y in this.stars[x]) {
y = parseint(y);
var star = this.stars[x][y];
if(star == -1) {
continue;
}
var left = y*this.star.width+y*5;
var top = x*this.star.height+x*5;
var index = x*this.star.colsnum + y;
starsdiv += '<div class="star id_'+index+'" style="left:'+left+'px; top:'+top+'px; width:'+this.star.width+'px;height:'+this.star.height+'px;" ondblclick="app.touch('+x+','+y+');" onmousedown="app.click('+x+','+y+');" onmouseup="app.mouseup();"><img src="http://sandbox.runjs.cn/uploads/rs/437/doeiphrq/star_'+star+'.png" width="'+this.star.width+'" height="'+this.star.height+'"/></div>';
}
}
$('#star_box').html(starsdiv);
}
app.initcolsarray = function(val) {
var array = [];
if(val == 'undefined') val = 0;
for(var i = 0; i < this.star.colsnum; i++) {
array[i] = val;
}
return array;
}
app.initrowarray = function(val) {
var array = [];
if(val == 'undefined') val = 0;
for(var i = 0; i < this.star.rownum; i++) {
array[i] = val;
}
return array;
}
app.write = function() {
var html = '';
for(var i in this.stars) {
var line = this.stars[i];
for(var j in line) {
var star = line[j];
var color = 'red';
if(star == -1) {
color = 'blue';
}
html += '<font color="'+color+'">'+star+'</font><font color="#999">('+i+','+j+')</font> ';
}
html += '<br/><br/>';
}
html += '<p>--===================================================--<p>';
$('#show').append(html);
}
function left2array(array) {
if(array.length < 0) return array;
var newarray = [];
for(var i in array) {
newarray[i] = [];
for(var j in array[i]) {
newarray[i][j] = array[i][j];
}
}
return newarray;
}
</script>
</head>
<body>
<div id="box">
<div id="star_box">
</div>
</div>
<div id="show" style="padding-top:600px;"></div>
<!-- x:<input type="text" id="x" value=""/>
y:<input type="text" id="y" value=""/>
<input type="button" value="点击" onclick="app.touch($('#x').val(), $('#y').val());"/>
<br/>
<br/> -->
</body>
</html>