Angular4 扫雷小游戏

扫雷小游戏,可以升级过关,难度随关卡增加。但是有很明显的bug,以后有时间会继续优化!

 

 

HTML:

<div class="mainContent">
     <div class="bg-white text-center borderb paddingv10">
         <button class="flexWidth marginr10" (click)="gameStartFn()">Start</button>
         <button class="flexWidth marginr10" (click)="gameEndFn()">Stop Game</button>
         <span>Mine Left: {{this.mineArray.length}}</span>
     </div>
     <ul class="mineContainer clear" [ngStyle]="getWidth()">
         <li *ngFor="let column of columnArray" (mousedown)="onClickFn(column.index, $event)" oncontextmenu="return false" [ngClass]="{ 'bg-gray': column.clicked == true && column.number == 0}" >
            <span *ngIf="column.isMine && visibleItem.mine" class="fa fa-bomb fs-26 text-black"></span>
            <span *ngIf="!column.isOver && !column.isMine && column.number !=0">{{column.number}}</span>
            <span *ngIf="column.isFlag" class="fa fa-flag"></span>
            <!-- <span class="text-red">{{column.index}}</span> -->
         </li>
     </ul>
</div>

  

CSS:

.mineContainer {
    margin: 20px auto;
    box-sizing: border-box;
}
.mineContainer li {
    width: 50px;
    height: 50px;
    border: solid 1px #fff;
    float: left;
    background-color: orange;
    color: #fff;
    text-align: center;
    line-height: 50px;
    box-sizing: border-box;
    display: flex;
    justify-content: center;
    align-items: center;
}
.mineContainer li:hover {
    cursor: pointer;
}

  

TS:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

@Component ({
    templateUrl: './mineSweeping.component.html',
    styleUrls: ['./mineSweeping.component.css']
})

export class MineSweepingComponent implements OnInit {
    private hitSection: any = { sectionNum: 1, columnNum: '', minMineNum: '' }; // 关卡参数: 关卡数、列数、最小地雷数
    private visibleItem: any = { mine: false, location: false }; // 控制是否显示的参数:地雷、标记
    private columnArray: Array<any> = []; // 地雷画布数组(好多参数,下面会有赋值)
    private mineArray: Array<any> = []; // 地雷数组
    private rules: any; // 判断点击位置是否为最上下左右列--
    private isOver: boolean = false ; // 是否结束
    private isSuccess: boolean = false; // 是否成功

    constructor(private router: Router){}

    ngOnInit(){
        this.hitSectionInitFn();
        this.columnInitFn();
        this.mineInitFn();
    }

    hitSectionInitFn(){ // 根据关卡数调整列数,最小地雷总数
        this.hitSection.columnNum = this.hitSection.sectionNum * 5;
        this.hitSection.minMineNum = this.hitSection.sectionNum * 5;
    }
    columnInitFn(){ // 地雷画布初始化: 坐标(id)、水平坐标、垂直坐标、是否为雷、周围雷数、是否被点击、是否被标记
        this.columnArray = [];
        for(let i = 0; i < this.hitSection.columnNum ; i++){
            for(let j = 0; j < this.hitSection.columnNum; j++) {
                this.columnArray.push({ index: this.columnArray.length, horizontal: i, vertical: j,  isMine: false, number: 0, clicked: false, isFlag: false });
            }
        }
    }
    mineInitFn(){ // 地雷初始化
        let tempArray = [], tempMineNum;
        this.mineArray = [];
        // 根据最小地雷数,随机生成一个 [最小地雷数 - (最小地雷数 + 最小地雷数)]之间的数值,为本关的地雷总数(比如10 - 20之间的数值)
        tempMineNum = Math.round( Math.random() * this.hitSection.minMineNum +  this.hitSection.minMineNum);
        // 根据地雷总数,随机生成数字数组
        for(let i = 0; i < tempMineNum; i++){
            tempArray.push( Math.round ( Math.random() * (this.hitSection.columnNum * this.hitSection.columnNum) ) );
        }
        // 数组去重
        for(let i = 0; i < tempArray.length; i++){
            if(this.mineArray.indexOf(tempArray[i]) == -1){
                this.mineArray.push(tempArray[i]);
            }
        }
        // 根据去重数组,赋值给地雷画布数组中的 isMine 参数
        for(let i = 0; i < this.columnArray.length; i++) {
            for(let j = 0; j < this.mineArray.length; j++) {
                if(this.mineArray[j] == i){
                    this.columnArray[i].isMine = true;
                }
            }
        }
        console.log(this.mineArray);
    }
    onClickFn(index, event){
        if(event.button == 2){ // 点击右键,做雷区标记
            this.columnArray[index].isFlag = !this.columnArray[index].isFlag;
            if(this.columnArray[index].isFlag){
                this.mineArray.length--;
            } else {
                this.mineArray.length++;
            }
        } else { // 点击左键,计算周围雷数
            this.checkMineArroundFn(index);
        }
        // 每次点击后,查看是否过关
        setTimeout(() => {
            this.ifSuccessFn();
        }, 100);
    }
    getPositionRules(index: number){ // 判断点击位置是否为最上下左右列
        this.rules = {
            top: this.columnArray[index].horizontal == 0,
            bottom: this.columnArray[index].horizontal == (this.hitSection.columnNum - 1),
            left: this.columnArray[index].vertical == 0,
            right: this.columnArray[index].vertical == (this.hitSection.columnNum - 1)
        }
    }
    checkMineArroundFn(index: number){ // 计算周围雷数
        if(this.columnArray[index].clicked ){
            return;
        }
        this.getPositionRules(index);
        if(this.columnArray[index].isMine) {
            this.gameEndFn();
            return;
        }  else if (!this.columnArray[index].isMine) {
            // 这里逻辑比较复杂, 根据点击坐标,计算其上、下、左、右、左上、右上、左下、右下八块位置的雷数,如果是第一列,则不计算上、左上、右上(以此类推)
            if(!this.rules.top) { 
                if( this.columnArray[(index - this.hitSection.columnNum)].isMine ) { this.columnArray[index].number++; } // top
                if (!this.rules.left) { 
                    if( this.columnArray[(index - this.hitSection.columnNum - 1)].isMine ) { this.columnArray[index].number++; } // top left
                }
                if (!this.rules.right) { 
                    if( this.columnArray[(index - this.hitSection.columnNum + 1)].isMine ) { this.columnArray[index].number++; } // top right
                }
            }
            if(!this.rules.bottom) { 
                if( this.columnArray[(index + this.hitSection.columnNum)].isMine ) { this.columnArray[index].number++; } // bottom
                if (!this.rules.left) { 
                    if( this.columnArray[(index + this.hitSection.columnNum - 1)].isMine ) { this.columnArray[index].number++; }  // bottom left
                }
                if (!this.rules.right) { 
                    if( this.columnArray[(index + this.hitSection.columnNum + 1)].isMine ) { this.columnArray[index].number++; } // bottom right
                }
            }
            if(!this.rules.left) { 
                if( this.columnArray[(index - 1)].isMine ) { this.columnArray[index].number++; } // left
            }
            if(!this.rules.right) { 
                if( this.columnArray[(index + 1)].isMine ) { this.columnArray[index].number++; } //right
            }           
            this.columnArray[index].clicked = true;
        }
        
        // 如果周围没有雷,则执行下面函数(扩大计算面积,查找周围坐标的附近雷数)
        if( this.columnArray[index].number == 0 ){
            this.checkAroundFn(index);
        }
    }
    checkAroundFn(index: number){ // 扩大计算面积,查找周围坐标的附近雷数(还是如果是第一行,不查找左上、上、右上位置)
        if(!this.rules.top){
            this.checkMineArroundFn(index - this.hitSection.columnNum);
            if(!this.rules.left) {
                this.checkMineArroundFn(index - this.hitSection.columnNum - 1);
            }
            if(!this.rules.right){
                this.checkMineArroundFn(index - this.hitSection.columnNum + 1);
            }
        }
        if(!this.rules.bottom){
            this.checkMineArroundFn(index + this.hitSection.columnNum);
            if(!this.rules.left) {
                this.checkMineArroundFn(index + this.hitSection.columnNum - 1);
            }
            if(!this.rules.right){
                this.checkMineArroundFn(index + this.hitSection.columnNum + 1);
            }
        }
        if(!this.rules.left){
            this.checkMineArroundFn(index - 1);
        }
        if(!this.rules.right){
            this.checkMineArroundFn(index + 1);
        }
    }


    gameStartFn(){ // 游戏开始
        this.hitSectionInitFn();
        this.columnInitFn();
        this.mineInitFn();
        this.visibleItem = { mine: false, location: false,};
    }
    gameEndFn(){ // 游戏结束
        debugger
        this.visibleItem = { mine: true, location: false };
        this.isOver = true;
        for(let i = 0; i < this.columnArray.length; i++){
            this.columnArray[i].clicked = true;
            this.columnArray[i].isFlag = false;
        }
    }
    ifSuccessFn(){ //判断是否过关
        let temCheckSuccess = false;
        // 查看地雷画布中,所有 isMine 对应的 isFlag 是否同为 true(也就是说,左右雷都被标记)
        for(let i = 0; i < this.columnArray.length; i++){
            if( this.columnArray[i].isFlag != this.columnArray[i].isMine ) {
                temCheckSuccess = false;
                return;
            } else {
                temCheckSuccess = true;
            }
        }
        // 询问是否进入下一关
        if(temCheckSuccess){
            this.isSuccess = true;
            if(this.isSuccess){
                let confirmNext = confirm('Congaratulations! You have pass the section ' + this.hitSection.sectionNum + '. \n Would you like go on?')
                if(confirmNext){
                    this.hitSection.sectionNum++;
                    this.gameStartFn();
                } else {
                    this.router.navigate(['/home']);
                }
            }
        }
    }

    getWidth(){ // 根据列数,获取外层盒子宽度
        return { width: this.hitSection.columnNum * 50 + 'px' } 
    }

}

  

posted @ 2019-02-21 12:31  小娘子_yuan  阅读(330)  评论(0编辑  收藏  举报