前端工程师新手一枚,之前一直做些小设计,以及静态页面的编写工作。刚刚接触 Angular 没有多久,四个月前对于 js 也只是会写 alert 之流,现在进步算是很大,下面是自制的华容道拼图(可以升级难度、关卡、更换图片,查看完整大图),希望大神临幸,千万别拍砖。

图片背景是用根据宽度,列数算好的公式用css写上去的,所以不同的列数,背景图片的比例不同,写着非常麻烦,但是又找不到简单方法,所以我只写到了第六关,希望有大神指点~~

第三关: 四列/15块儿

HTML:

<div class="gigContent">
<div class="paddingv10 borderb bg-white">
<span class="paddingr30">Section: {{colomnData.barrier}}</span>
<span class="paddingr30">Step: {{step}}</span>
<button (click)="resetFn()" class="flexWidth">Reset</button>
<button (click)="changePicFn()" class="flexWidth">Change Picture</button>
<button (click)="ifViewPic = true" class="flexWidth">View big picture</button>
</div>
<ul class="gigItem" [ngStyle]="getColumnWidth()">
<li *ngFor="let puzzle of puzzles; let i = index" (click)="moveBoxFn(i)" [ngClass]="{'empty': puzzle == '', 'full': puzzle != ''}" [ngStyle]="getPicPosition(puzzle)">
</li>
</ul>
</div> <div class="mask" *ngIf="ifViewPic">
<img src="../../assets/images/pic{{imgRandom}}.jpg" style="width: 500px;" />
<br/>
<button (click)="ifViewPic = false" class="flexWidth">Close</button>
</div>

  

CSS:

.mainContent {
width: 1000px;
box-sizing: border-box;
}
.gigContent {
width: 100%;
min-height: 500px;
text-align: center;
}
.gigContent .gigItem{
margin: 20px auto 0;
}
.gigContent .gigItem li {
list-style-type: none;
width: 100px;
height: 100px;
float: left;
line-height: 100px;
text-align: center;
color: #dedede;
font-size: 26px;
font-weight: bolder;
box-sizing: border-box;
border: solid 1px #dedede;
}
.gigContent .gigItem li.full {
background-repeat: no-repeat;
background-color: orange;
}
.gigContent .gigItem li.empty {
background-image: none!important;
border: none;
}
.gigContent .gigItem li.full:hover {
cursor: pointer;
box-shadow: 0px 0px 10px #fff;
}
.gigContent .gigItem:before, .gigContent .gigItem:after {
content: '';
display: block;
clear: both;
}
.mask {
font-size: 26px;
color: orange;
font-weight: bolder;
text-align: center;
padding-top: 100px;
}

TS:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router'; @Component ({
templateUrl: './gigsaw.component.html',
styleUrls: ['./gigsaw.component.css'] }) export class GigsawComponent implements OnInit {
private puzzles: Array<any>; // 随机生成的乱序数组
private positionArr: Array<any>; // 每点击一块儿,会生成其上下左右位置的数组
private emptyBox: any; // 空白小块儿
private boxMovable: boolean = false; // 图片是否可以移动
private isSuccessful: boolean = false; // 是否过关
private step: number = 0; // 移动步数
private colomnData: any = { barrier: 3, colomNum: 4, totalNum: 15 }; // 关卡数、列数、小块儿总数
private imgRandom: number; // 随机选择图片
private ifViewPic: boolean = false; // 是否查看大图 constructor(private router: Router){} ngOnInit(){
this.resetFn();
this.changePicFn();
} resetFn(){
let puzzlesRandom = [];
// 根据关卡数,生成相应的数组
for(let i = 1; i <= this.colomnData.totalNum; i++){
puzzlesRandom.push(i);
}
// 将数组打乱
this.puzzles = puzzlesRandom.sort(() => {
return Math.random() - 0.5;
});
// 将空白块儿加入
this.puzzles.push('');
this.step = 0;
} changePicFn(){
this.imgRandom = Math.round( Math.random() * 4 + 1);
} checkMovableFn(index: number){ // 查看所点击图片是否可以移动
// 获取所点击图片位置以及上下左右坐标
this.positionArr = [
{ name: 'curNum', value: this.puzzles[index], position: index },
{ name: 'topNum', value: this.puzzles[index - this.colomnData.colomNum], position: index - this.colomnData.colomNum },
{ name: 'btmNum', value: this.puzzles[index + this.colomnData.colomNum], position: index + this.colomnData.colomNum },
{ name: 'lftNum', value: this.puzzles[index - 1], position: index - 1 },
{ name: 'ritNum', value: this.puzzles[index + 1], position: index + 1 }
]
// 如果所点击的图片不是空白块儿,将value为空的一项赋值给emptyBox
if(this.puzzles[index] != ''){
this.emptyBox = this.positionArr.filter(function (k, v) { return k.value == '' })[0];
// 如果emptyBox有值,则表示周围有空白块,可以移动
if(this.emptyBox != undefined){
this.boxMovable = true;
}
}
} moveBoxFn(index: number){
// 移动小块儿,将被点击小块儿的值赋值给空白块儿,将被点击小块儿设置为空
this.boxMovable = false;
this.checkMovableFn(index);
if(this.boxMovable) {
this.puzzles[this.emptyBox.position] = this.puzzles[index];
this.puzzles[index] = '';
this.step++;
}
setTimeout(() => {
this.isSuccessfulFn();
}, 100);
} isSuccessfulFn(){
for(let i = 1; i <= this.colomnData.totalNum; i++) {
if(this.puzzles[i-1] != i) {
this.isSuccessful = false;
return;
}
}
this.isSuccessful = true;
if(this.isSuccessful){
let temConfirm = confirm('Conguratulations! You win! \n Would you like to go to next section?')
if(temConfirm){
this.getNextSectionFn();
} else {
this.router.navigate(['/home']);
}
}
} getNextSectionFn(){ // 进入下一关
this.colomnData.barrier = this.colomnData.barrier + 1;
this.colomnData.colomNum = (this.colomnData.barrier + 1) ;
this.colomnData.totalNum = this.colomnData.colomNum * this.colomnData.colomNum - 1;
if(this.colomnData.barrier >= 6) {
alert('Congaratulations! You pass all the sections!')
this.router.navigate(['/home']);
}
this.resetFn();
this.changePicFn();
} getColumnWidth(){ // 根据列数设置外层盒子的宽度
return { width: this.colomnData.colomNum * 100 + 'px' };
}
getPicPosition(index: number){ // 根据列数调整背景图片的位置!!! 好难
let posX, posY;
for(let n = 0; n < this.colomnData.colomNum; n++) {
if (index == this.colomnData.colomNum*n) {
posX = '100%';
} else if (index == this.colomnData.colomNum * n + 1){
posX = '0%';
}
else if (index == this.colomnData.colomNum * n + 2) {
posX = 100/(this.colomnData.colomNum - 1) + '%'; } else if (index == this.colomnData.colomNum * n + 3) {
posX = 100/(this.colomnData.colomNum - 1) * 2 + '%'; } else if (index == this.colomnData.colomNum * n + 4) {
posX = 100/(this.colomnData.colomNum - 1) * 3 + '%'; } else if (index == this.colomnData.colomNum * n + 5) {
posX = 100/(this.colomnData.colomNum - 1) * 4 + '%';
}
} if (index <= this.colomnData.colomNum) {
posY = '0%';
} else if (index > this.colomnData.colomNum && index <= this.colomnData.colomNum * 2){
posY = 100/(this.colomnData.colomNum - 1) + '%';
} else if (index > this.colomnData.colomNum * 2 && index <= this.colomnData.colomNum * 3) {
posY = 100/(this.colomnData.colomNum - 1) * 2 + '%';
} else if (index > this.colomnData.colomNum * 3 && index <= this.colomnData.colomNum * 4) {
posY = 100/(this.colomnData.colomNum - 1) * 3 + '%';
} else if (index > this.colomnData.colomNum * 4 && index <= this.colomnData.colomNum * 5) {
posY = 100/(this.colomnData.colomNum - 1) * 4 + '%';
} else if (index > this.colomnData.colomNum * (this.colomnData.colomNum - 1)
&& index < this.colomnData.colomNum * this.colomnData.colomNum ){
posY = '100%';
} return { backgroundPositionX: posX, backgroundPositionY: posY,
backgroundSize: this.colomnData.colomNum * 100 + 'px',
backgroundImage: 'url(\"../../assets/images/pic' + this.imgRandom + '.jpg\")' };
}
}

  

Angular4 自制华容道拼图(可以升级难度、关卡、更换图片)的更多相关文章

  1. 自制Unity小游戏TankHero-2D(4)关卡+小地图图标+碰撞条件分析

    自制Unity小游戏TankHero-2D(4)关卡+小地图图标+碰撞条件分析 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm ...

  2. Angular4 自制打地鼠游戏

    前端工程师新手一枚,之前一直做些小设计,以及静态页面的编写工作.刚刚接触 Angular 没有多久,四个月前对于 Javascript也只是会写 alert 之流,现在进步算是很大,下面是自制的打地鼠 ...

  3. [转]Angular4 自制分页控件

    本文转自:https://blog.csdn.net/Junyuan_123/article/details/79486276 过年后第一波,自制的分页控件,可能功能没有 PrimeNG 那么好,但是 ...

  4. Angular4 自制分页控件

    过年后第一波,自制的分页控件,可能功能没有 PrimeNG 那么好,但是基本可以实现自定义翻页功能,包括:首页/最后一页/上一页/下一页. 用户可以自定义: 1. 当前默认页码(如未提供,默认为第一页 ...

  5. mac系统xcode升级等软件更换appid账户

    删掉xcode 后发现 还是 会存在更新项,点击还是会提示输入之前app id 账号的密码 经过搜索和分析,发现是 Spotlight 在捣鬼,文件和目录删除了,但是索引文件没有被更新. 依次执行下面 ...

  6. 升级xcode时更换appid账户

    转自:http://blog.csdn.net/zhuzhihai1988/article/details/39803743 为了免下载安装Xcode,安装时使用了别人提供的Xcode.dmg安装,而 ...

  7. JavaScript写一个拼图游戏

    拼图游戏的代码400行, 有点多了, 在线DEMO的地址是:打开: 因为使用canvas,所以某些浏览器是不支持的: you know: 为什么要用canvas(⊙o⊙)?  因为图片是一整张jpg或 ...

  8. atitit.html5 拼图游戏的解决之道.

    atitit.html5 拼图游戏的解决之道. 1. 拼图游戏的操作(点击法and 拖动法) 1 1. 支持键盘上.下.左.右键移动: 1 2. 支持点击空白模块中的上下左右箭头移动: 1 3. 支持 ...

  9. 程序设计 之 C#实现《拼图游戏》 (下) 原理篇

    前言:在 http://www.cnblogs.com/labixiaohei/p/6698887.html 程序设计 之 C#实现<拼图游戏>(上),上传了各模块代码,而在本文中将详细剖 ...

随机推荐

  1. Visual Studio 2017RC 版本相关资料

    Visual Studio 2017 RC版本说明 1.社区版 Visual Studio Community 2017 RC Visual Studio Community 2017 RC 是针对个 ...

  2. Java学习---基础知识学习

    2016-07-23  周六 利用键盘输入的时候需要抛出异常 ,直接快捷键 ctrl + 1 ;定义数组 int score[] = new int[4]  ;  只有4个数字BufferedRead ...

  3. nginx+php+swoole安装记录

    领了台阿里服务器1vCPU 1G,做下测试研究. 系统 centos7,使用yum安装. Nginx yum install nginx ##开启nginx service nginx start 安 ...

  4. 3.5星|《刷屏:视频时代的风传法则》:YouTube热门视频回顾与分析

    刷屏:视频时代的疯传法则 作者2010年加入YouTube.本书是作者对YouTube上的热门视频的回顾与分析.第2-9章各讲一个类别的热门视频:恶搞.混音.网络歌曲.广告.现场目击.知识与科技.小众 ...

  5. Mof提权科普

    今天再拿一个站的时候遇到了很多问题,拿站的过程就不说了,其中要用到mof提权,不管能不能提下,我进行一个mof提权的科普 这里我综合各类mof提权进行了 综合 首先说一下,无shell情况下的mysq ...

  6. canvas学习笔记1

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  7. 3、Web Service-Jaxws(Eclipse版本)

    1.概述 开发手段: 使用jdk开发(1.6及以上的版本) 使用CXF框架开发 组成: -服务器端 -客户端 2.使用JDK开发 1).服务器端 -@WebService(SEI和SEI的实现类) - ...

  8. FreeMarker之根据模板生成Java代码

    FreeMarker根据模板生成Java代码,光这句话,大家想必也知道它的应用了,比如流行的DRY原则,该原则的意思,可简单概述为"不要写重复的代码". 比如Java中三层架构,数 ...

  9. Linux 启动进程结束进程通用代码

    linux启动springboot项目 start.sh #!/bin/sh rm -f tpid nohup java -jar restDate--SNAPSHOT.jar --spring.pr ...

  10. Redis(二)安全设置

    redis是一款流行的内存数据库,默认是无密码登录,若出于安全考虑,需要为其加上控制权限,则可以通过以下2种方法来设置. 1. 采用绑定IP的方式来进行控制(比较安全的方法) 在redis.conf( ...