继扫地机器人之后的又一道mac题,不过这次只有63关,号称"最简单的mac题",手快有手慢无啊....
先介绍下这个游戏的玩法:
每关会提供一个n行m列的二维地图,这里(n=3,m=3) 初始值
010
011
010
然后每关会提供a块piece。(这里等于3)
piece1 由3块组成,格式为:X.,XX,该格式代表的形状如下:
X
XX
piece2 由2块组成,格式为XX,该格式代表的形状如下:
XX
piece3 由3块组成,格式为X,X,X,该格式代表的形状如下:
X
X
X
再提供一个modu值,这里的modu=2。
然后你可以把这3块piece放在地图上任意一个位置,不能超出地图的边界。piece不可旋转,每个piece只能用1次也必须用1次。
当你放置一个piece之后,地图上被这个piece覆盖的格子的值会相应的加1。 如果格子中的值等于modu,又会被重置为0..
地图最初的状态
010
011
010
如果把piece1放在地图的1,1位置(第2行第2列) piece放置的位置:
000
0X0
0XX
地图变成了:
010
001
001
接着把piece2放在地图的0,1位置(第1行第2列) piece放置的位置:
0XX
000
000
map变成了
001
001
001
接着再把piece3放在地图的0,2位置(第一行第三列) piece放置的位置:
00x
00x
00x
map变成了
000
000
000
当map中的每个元素都是0,该题通过。
然后是demo部分,这里选取了49关,每一关信息都会通过一个json串得到,like:
var mod={"level":49,"modu":"3","map":["0222210","0201210","2210112","1022020","1200120","2120120","0211000"],"pieces":["X..,XX.,.XX,.X.","...X,..XX,.XX.,XX..",".X,XX,.X,.X","XXX,..X,.XX",".X.,.XX,XX.,.XX","...X,XXXX,.X..","XXX.,.XX.,..XX","XX.,XXX,.X.","XXX,X..,X..,X..,X..","XX,XX,.X,.X",".X..,XXXX","XX,XX,XX",".X.,XXX,X..","..X.,X.X.,XXXX","XXX,XXX,..X","XX..,.X.X,.XXX","XX.,.XX,..X","X..X,XXXX,.X..","XX,X.","X..,X..,X..,XX.,.XX"]};
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>千里码</title>
<link href="http://www.qlcoder.com//css/bootstrap.min.css" rel="stylesheet">
<link href="http://www.qlcoder.com//css/bootstrap-theme.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="http://www.qlcoder.com//css/bootstrap-markdown.min.css">
<link href="http://www.qlcoder.com//css/reset4.css" rel="stylesheet">
<style>
#piece .piece-item{
padding:10px;
border:1px solid #ddd;
width:32%;
float:left;
margin:10px 0 50px 1%;
}
#piece .piece-item span{
float: left;
font-size: 20px;
margin-right: 10px;
}
</style>
</head>
<body>
<div class="container">
<div>
你好,gaga,现在的level:0
<br>
<input type="button" value="重玩本关" onclick="NextLevel(0)" style="margin:10px 0;">
<br>
<input id="level" type="hidden" value="0">
<!--<input type="button" value="游戏说明" onclick="DoHelp()">-->
<input type="button" value="上一关" onclick="NextLevel(-1)">
<input type="button" value="下一关" onclick="NextLevel(1)">
</div>
<div class="">
<div style="float:left;margin-top:10px;max-width: 450px;overflow: auto;">
<canvas id="canvas" width="700" height="500">提示:你的浏览器不支持canvas标签 </canvas>
</div>
<div id="piece" style="float: right;border:1px solid #ddd;margin:10px 0 0 20px;width:750px;">
<!--<div class="piece-item"><input type="radio" name="piece" /><span></span></div>-->
</div>
</div>
<img src="images/iconfont-0.png" id="num0" style="display: none;" />
<img src="images/iconfont-1.png" id="num1" style="display: none;" />
<img src="images/iconfont-2.png" id="num2" style="display: none;" />
<img src="images/iconfont-3.png" id="num3" style="display: none;" />
<img src="images/iconfont-4.png" id="num4" style="display: none;" />
</div>
<!-- Footer -->
<footer>
<p>Copyright © 2015 qlcoder.com. All Rights Reserved. 浙ICP备15038807号-1. | 联系我们:oreo@qlcoder.com <a target="_blank" href="http://shang.qq.com/wpa/qunwpa?idkey=08dcd44232943b517c2ed04dceb097155575f604791c57bbd2f9759e90e22d58">qq群480394714</a></p>
</footer>
<script> var mod={"level":49,"modu":"3","map":["0222210","0201210","2210112","1022020","1200120","2120120","0211000"],"pieces":["X..,XX.,.XX,.X.","...X,..XX,.XX.,XX..",".X,XX,.X,.X","XXX,..X,.XX",".X.,.XX,XX.,.XX","...X,XXXX,.X..","XXX.,.XX.,..XX","XX.,XXX,.X.","XXX,X..,X..,X..,X..","XX,XX,.X,.X",".X..,XXXX","XX,XX,XX",".X.,XXX,X..","..X.,X.X.,XXXX","XXX,XXX,..X","XX..,.X.X,.XXX","XX.,.XX,..X","X..X,XXXX,.X..","XX,X.","X..,X..,X..,XX.,.XX"]};</script>
<script src="js/jquery.min.js"></script>
<script src="http://www.qlcoder.com//js/bootstrap.min.js"></script>
<script src="js/module.js"></script>
<script>
// console.log(pieces[1][0][1]);
if(document.getElementsByClassName("container")[0]!=null)
document.getElementsByClassName("container")[0].style.minHeight=window.innerHeight-133+"px";
</script>
</body>
</html>
js:
/**
* Created by Diego on 16/1/11. v1.3
* v1.2修改了单选piece在点击地图的方式,改为默认当前碎片的第一个,点击地图成功后原来第一个碎片移除,新增piece有无判断.修改地图长宽错误.修改几处样式(虽然还是很丑)
* 取消map.js和piece.js,通过转换json(html中的mod)来得到map和piece,新增toArrMap函数
* js加jq这样的写法还有谁吗?! 16/1/17
* v1.3 新增提示框,经过map的时候就显示piece大小的透明度为0.2的框
*/
var w=h=32;
var num0=document.getElementById("num0");
var num1=document.getElementById("num1");
var num2=document.getElementById("num2");
var num3=document.getElementById("num3");
var num4=document.getElementById("num4");
var canvas=document.getElementById("canvas");
var piece=document.getElementById("piece");
//var level=parseInt(document.getElementById("level").getAttribute("value"));
var context = canvas.getContext('2d');
var curMap;//当前地图数据数组,初始与curLevel相同,游戏中改变
var curPiece;
var curLevel;//当前级地图数据,游戏中不变,用来判断游戏是否结束
var modu;
var pos={};
var flag=true;
var clickCount=0;//点击次数
var level=mod.level;
function init(){
initLevel();
}
//关卡初始化
function initLevel()
{
modu=mod.modu;
//console.log(modu);
curMap=toArrMap(mod.map);
//console.log(curMap);
curLevel=toArrMap(mod.map);
canvas.setAttribute("width",(curLevel[0].length)*(w));//这里的宽高原来是反的原来是w:curLevel.length
canvas.setAttribute("height",(curLevel.length)*(h));
DrawMap(curMap,context);
curPiece= toArr(mod.pieces);
//console.log(curPiece);
DrawPieceMap(curPiece);
$(".piece-item").first().css("border-color","red");
}
//初始化piece,防止进入前后关只增
function initPiece(){
//var remove=document.getElementsByClassName("piece-item");
//for(;remove.length>0;){
// piece.removeChild(piece.lastChild);
// //打代码快点么??没感觉出来的咯
//}
$(".piece-item").remove();
}
//初始化地图
function DrawMap(level,con){
var pic;
for(var i=0;i<level.length;i++)//y轴
{
for(var j=0;j<level[i].length;j++)//x轴
{
var num=level[i][j];
switch (num){
case 0:
pic=num0;
break;
case 1:
pic=num1;
break;
case 2:
pic=num2;
break;
case 3:
pic=num3;
break;
case 4:
pic=num4;
break;
}
con.fillStyle="#fff";
con.fillRect(w*j,h*i+1,pic.width,pic.height);//重新画个矩形把原来的覆盖了,不然新的会在原有的上面叠加
con.drawImage(pic,w*j,h*(i)+1,pic.width,pic.height);//(图片,x,y,width,height)
}
}
}
//piece字符串转成数字表示的数组
function toArr(level){
//console.log(level);
var arr=new Array();
//创建多维数组
for(var i=0;i<level.length;i++){
arr[i]=new Array();
var _arr=level[i].split(",").length;
//console.log(_arr);
for(var j=0;j<_arr;j++){
arr[i][j]=new Array();
}
}
//把piece转化为数组
for(var i=0;i<level.length;i++)
{
var x=0;
var y=0;
for(var j=0;j<level[i].length;j++){
//console.log("x1:"+x);
//console.log(arr[i][x]);
//console.log("y1:"+y);
//有逗号的时候,数组成员要多一个
if(level[i][j]=="X"){arr[i][x][y]=1;y++;}
else if(level[i][j]=="."){arr[i][x][y]=0;y++;}
else if(level[i][j]==","){
x++;
y=0;
}
//console.log(arr[i][x][y-1]);
//console.log("y2:"+y);
}
}
return arr;
}
//var map=mod.map;
//var x=toArrMap(map);
//console.log(x);
//把mod.map转化成数组
function toArrMap(map){
var mapArr=new Array(); //一维数组mod.map
for(var i=0;i<map.length;i++){ //二维数组mod.map[i]
mapArr[i]=new Array();
for(var j=0;j<map[i].length;j++){
mapArr[i][j]=new Array();//三维数组mod.map[i][j]
mapArr[i][j]=parseInt(map[i][j]);
}
}
//for(var i=0;i<map.length;i++){
// for(var j=0;j<map[i].length;j++){
// mapArr[i][j]=parseInt(map[i][j]);
// }
//}
return mapArr;
}
//把piece转化成图片
function DrawPieceMap(level){
for(var i=0;i<level.length;i++){
//console.log(level[i]);
//动态创建piece图片
for(var j=0;j<level[i].length;j++){
var pcanvas=document.createElement("canvas");
var pcontext=pcanvas.getContext('2d');
pcanvas.setAttribute("width",(level[i][j].length)*(w+1));//这里的宽高原来写反了.已改正
pcanvas.setAttribute("height",(level[i].length)*(h+1));
}
//绘制piece
DrawMap(level[i],pcontext);
//动态生成piece前面的单选按钮和它的父元素,最后统一放到id=piece的容器中(好多piece真乱...)
var div=document.createElement("div");
div.setAttribute("class","piece-item");
var span=document.createElement("span");//原先的单选改成默认第一个,后面取消单选判断
span.innerHTML=i+" :";
span.setAttribute("data",i);
span.setAttribute("datay",level[i].length);
span.setAttribute("datax",level[i][0].length);
div.appendChild(span);
div.appendChild(pcanvas);
piece.appendChild(div);
}
}
//添加事件响应
canvas.addEventListener('click', function(e){
if(flag){
p = getEventPosition(e);
showPos(p);
clickCount++;
tip(p);
}
}, false);
canvas.addEventListener("mousemove",function(e){
var t=getEventPosition(e);
DrawMap(curMap,context);
tip(t);
});
//得到点击的坐标
function getEventPosition(ev){
var x, y;
if (ev.layerX || ev.layerX == 0) {
x = ev.layerX;
y = ev.layerY;
}else if (ev.offsetX || ev.offsetX == 0) { // Opera
x = ev.offsetX;
y = ev.offsetY;
}
return {x: x, y: y};
}
//选中的piece覆盖到地图上
function showPos(p){
for(var j =0;j<curLevel.length;j++)
{
for(var i=0;i<curLevel[0].length;i++)
{
if(w*i<p.x && w*(i+1)>p.x && h*j<p.y &&h*(j+1)>p.y)//获得地图点击位置的坐标
{
//console.log(i+" "+j);
var x=curLevel[0].length-i;//距边界的距离
var y=curLevel.length-j;
var _i=i;
var _j=j;//嗯..这是piece上个部分的坐标..
//console.log(x+" "+y);
change(x,y,_i,_j);//zhenshi caodan de hanshu...
}
}
}
}
//caodan hanshu start..
function change(x,y,ci,cj){
var piecex=$(".piece-item").first().children("span").attr("datax");
var piecey=$(".piece-item").first().children("span").attr("datay");
var index=$(".piece-item").first().children("span").attr("data");
//console.log(piecex+" piecex");
//console.log(piecey+" piecey");
//先判断是否有碎片
if($(".piece-item").length<1)
{
alert("诶诶,碎片没了!");
return;
}
else{
//判断是否超出边界
if(x>=piecex && y>=piecey)
{
//console.log(curPiece[index].length);
//curMap[ci][cj]=1;
for(var i=0;i<curPiece[index].length;i++){
for(var j=0;j<curPiece[index][i].length;j++){
var val=curPiece[index][i][j];
//console.log(i+" i");
//console.log(j+" j");
//console.log(val+" val");
var _ci=ci;
var _cj=cj;
//console.log(_ci+" _ci");
//console.log(_cj+" _cj");
changeMap(i,j,_ci,_cj,val);
}
}
DrawMap(curMap,context);
$(".piece-item").first().remove();
$(".piece-item").first().css("border-color","red");
if(CheckFinish()){
alert("过关了!恭喜!")
NextLevel(1);
}
}
else{
alert("碎片在这个位置的话会超出边界了呢亲~");
}
}
}
//点击地图之后,遍历piece转化成数组之后里面的值,传到这里去修改地图的值,这函数越改越多了= =!
function changeMap(ti,tj,tti,ttj,value){//参数分别对应,piece对应的数组下标,当前地图点击的坐标和当前piece对应的值
curMap[ttj+ti][tti+tj]=(curMap[ttj+ti][tti+tj]+value)%modu;
//console.log(CheckFinish());
}
//点击地图后出现提示piece在地图中的位置
function tip(t){
if(clickCount>19)
{return;}
context.strokeStyle="rgb(255,0,0)";
context.lineWidth=4;
context.strokeRect(t.x, t.y,(curPiece[clickCount][0].length-0.5)*(w),(curPiece[clickCount].length-1)*(h));
context.fillStyle="rgba(255,255,255,0.5)";
context.fillRect(t.x, t.y,(curPiece[clickCount][0].length-0.5)*(w),(curPiece[clickCount].length-1)*(h));
}
//判断是否完成本关
function CheckFinish()
{
for(var i=0;i<curMap.length;i++)//y轴
{
for(var j=0;j<curMap[i].length;j++)//x轴
{
if(curMap[i][j]!=0)
{
//console.log("asd");
return false;
}
}
}
return true;
}
function NextLevel(i)
{
flag=true;
level=level+i;
if(level<0)
{
iCurLevel=0;
return;
}
var len=level.length;
if(level>len-1)
{
iCurLevel=len-1;
return;
}
document.getElementById("level").setAttribute("value",level);
initPiece();
initLevel();
}
//克隆二维数组
function copyArray(arr)
{
var b=[];
for(var i=0;i<arr.length;i++)
{
b[i]=arr[i].concat();
}
return b;
}
window.onload=init;