<!DOCTYPE html>
<html>

<head>
        <meta charset="utf-8" />
        <title>地雷游戏</title>

<style>
            .guoshengcontentdiv{
                width:1255px;
                height:600px;
                margin:auto;
            }
            .guoshengonediv {
                position: relative;
                width: 1000px;
                height: 600px;
                float: left;
            }
            
            .canvasguosheng {
                width: 1000px;
                height: 600px;
                position: absolute;
                left: 0px;
                top: 0px;
                border: 1px #aaa solid;
            }
            
            .guoshengtwodiv {
                float: left;
                width: 250px;
                height: 600px;
                border: 1px #aaa solid;
            }
        </style>

</head>

<body>

<div class="guoshengcontentdiv">
            
            <div class="guoshengonediv">
                <canvas id="guoshengcanvas" width="1000" height="600" style="position:absolute;left:0px;top:0px;border:1px #aaa solid"></canvas>
            </div>

<div class="guoshengtwodiv">
                <h2 align="center">扫雷-郭胜</h2>
                <hr />
                <table width="100%">
                    <tr align="center">
                        <td>10*10&nbsp;&nbsp;(bombers*20)</td>    
                        <td>
                            <input type="button" id="mod1" value="选择" οnclick="init(10,10,20);" />
                        </td>
                    </tr>
                    <tr align="center">
                        <td>20*10&nbsp;&nbsp;(bombers*60)</td>    
                        <td>
                            <input type="button" id="mod2" value="选择" οnclick="init(15,20,60);" />
                        </td>
                    </tr>
                    <tr align="center">
                        <td>30*20&nbsp;&nbsp;(bombers*100)</td>    
                        <td>
                            <input type="button" id="mod3" value="选择" οnclick="init(20,30,100);" />
                        </td>
                    </tr>
                </table>
                <hr />
                
                <!--
                    作者:offline
                    时间:2018-01-11
                    描述:自定义模块  郭胜
                -->
                <fieldset>
                    <legend>自定义</legend>
                    列数:<input type="text" id="cols" value="20"><br />
                    行数:<input type="text" id="rows" value="10"/><br />
                    炸弹数:<input type="text" id="bomber" value="50" /><br />
                    <input type="button" value="确定" id="custom" />
                </fieldset>
                <hr />
                
                <table>
                    <tr>
                        <td>时间:</td>
                        <td><input type="text" id="time" value="0" readonly="true" style="border:none"/></td>
                    </tr>
                    <tr>
                        <td>雷数:</td>
                        <td><input type="text" id="bombernum" value="0" readonly="true" style="border:none"/></td>
                    </tr>
                </table>
                <hr />
                <div >
                    <p>有问题的人欢迎联系我</p>
                    <p>艾尚编程工作室(郭经理):18795465900</p>
                </div>
            </div>
            
        </div>
    </body>

</html>
<script type="text/javascript">
    /*
     * 加载完页面后执行
     * 郭胜
     */
    window.onload = function(){
        init(15,20,40);
    }
    
    var $id = function(idname){return document.getElementById(idname);}
    var s;
    var yougess;
    var bombnum;
    
    /*
     * 显示时间
     * 郭胜
     */
    function showtime(){
        $id("time").value = Number($id("time").value)+1;
    }
    
    /*
     * 数据验证
     * 郭胜
     */
    $id("cols").onblur = function(){
        if(!isNaN($id("cols").value)){//是否是数字
            if(Number($id("cols").value)>30 || Number($id("cols").value)<0){
                alert("数字必须在0~30之间!记住!记住!记住!");
                $id("cols").value = 20;
            }
        }else{
            alert("是不是瞎?是不是瞎?是不是瞎?输入数字!是数字!TMD是数字啊!!!");
            $id("cols").value = 20;
        }
    }
    
    /*
     * 数据验证
     * 郭胜
     */
    $id("rows").onblur = function(){
        if(!isNaN($id("rows").value)){//是否是数字
            if(Number($id("rows").value)>20 || Number($id("rows").value)<0){
                alert("数字必须在0~30之间!记住!记住!记住!");
                $id("rows").value = 10;
            }
        }else{
            alert("是不是瞎?是不是瞎?是不是瞎?输入数字!是数字!TMD是数字啊!!!");
            $id("rows").value = 10;
        }
    }
    
    /*
     * 数据验证
     * 郭胜
     */
    $id("bomber").onblur = function(){
        if(!isNaN($id("bomber").value)){//是否是数字
            if(Number($id("bomber").value)> Number($id("rows").value)*Number($id("cols").value)*0.85 || Number($id("bomber").value)<0){
                alert("数字必须在0~"+Number($id("rows").value)*Number($id("cols").value)*0.85+"之间!记住!记住!记住!");
                $id("bomber").value = 50;
            }
        }else{
            alert("是不是瞎?是不是瞎?是不是瞎?输入数字!是数字!TMD是数字啊!!!");
            $id("bomber").value = 50;
        }
    }
    
    /*
     * 自定义初值
     */
    $id("custom").onclick = function(){
        init(Number($id("cols").value),Number($id("rows").value),Number($id("bomber").value));
    }
    
    var nowI = -1, nowJ = -1, preI = -1, preJ = -1;
    
    /*
     * 初始化
     */
    function init(cols,rows,bomb){
        bombnum = bomb;
        clearInterval(s);//清除上次的时间
        $id("time").value = 0;//时间更新为0
        s = setInterval(showtime(),1000);
        $id("bombernum").value = bombnum;
        var gamedata = new doubleArray(rows,cols);
        var i = bombnum;
        while(i>0){//初始化炸弹信息,炸弹值为-1
            //Math.ceil向上取整,Math.floor,舍弃取整,向下取整
            var randnum = Math.ceil(Math.random()*rows*cols);
            if(Math.floor(randnum/cols)==randnum/cols){//列的整数倍
                var tmpx = Math.floor(randnum/cols) -1;//不能超过行数
            }else{
                var tmpx = Math.floor(randnum/cols);
            }
            var tempy = randnum - tmpx * cols -1;
            if(gamedata[tmpx][tempy] != -1){
                gamedata[tmpx][tempy] = -1;
                i--;
            }
        }
        //初始化除了炸弹之外的数据
        for(var i = 0;i<rows;i++){
            for(var j = 0;j<cols;j++){
                if(gamedata[i][j] != -1){
                    /*
                     * 值为0:上下左右都没有炸弹
                     * 值为1:左下、正左、左上、正下、正上、右上、正右、右下则肯定有且只有一个炸弹
                     * 值为2:左下、正左、左上、正下、正上、右上、正右、右下则肯定有且只有两个炸弹
                     * 值为3:左下、正左、左上、正下、正上、右上、正右、右下则肯定有且只有三个炸弹
                     * 值为4:左下、正左、左上、正下、正上、右上、正右、右下则肯定有且只有四个炸弹
                     * 值为5:左下、正左、左上、正下、正上、右上、正右、右下则肯定有且只有五个炸弹
                     * 值为6:左下、正左、左上、正下、正上、右上、正右、右下则肯定有且只有六个炸弹
                     * 值为7:左下、正左、左上、正下、正上、右上、正右、右下则肯定有且只有七个炸弹
                     * 值为8:左下、正左、左上、正下、正上、右上、正右、右下则肯定有且只有八个炸弹
                     * 郭胜
                     */
                    gamedata[i][j] = (exist(gamedata,i-1,j-1) == 1?1:0) //左下
                                    + (exist(gamedata,i-1,j) == 1?1:0)  //正左
                                    + (exist(gamedata,i-1,j+1) == 1?1:0) //左上
                                    +(exist(gamedata,i,j-1) == 1?1:0) //正下
                                    + (exist(gamedata,i,j+1) == 1?1:0) //正上
                                    +(exist(gamedata,i+1,j-1) == 1?1:0) //右上
                                    +(exist(gamedata,i+1,j) == 1?1:0)//正右
                                    +(exist(gamedata,i+1,j+1) == 1?1:0);//右下
                }
            }
        }
        var ctx = $id("guoshengcanvas").getContext("2d");
        //返回之前保存过的路径状态和属性
        ctx.restore();
        //在给定的矩形内清除指定的像素
        ctx.clearRect(0,0,1000,600);
        //保存当前环境的状态
        ctx.save();
        
        //重新映射画布上的 (0,0) 位置
        ctx.translate(500 - 15*cols,300-15*rows);
        //起始一条路径,或重置当前路径
        ctx.beginPath();
        //绘制“被填充”的矩形
        ctx.fillRect(0,0,30*cols,30*rows);
        gamestart(ctx,gamedata);//开始游戏
    }
    
    /*
     * 开始游戏
     * 郭胜
     */
    function gamestart(ctx,gamedata){
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        var placestate = new doubleArray(rows,cols);//各个点的状态,翻转与否
        for(var i=0;i<rows;i++){//初始化
            for(var j = 0;j<cols;j++){
                placestate[i][j] = "0";
            }
        }
        
        //完全初始化
        for(var i=0;i<rows;i++){
            for(var j=0;j<cols;j++){
                startprint(ctx,gamedata,i,j);
            }
        }
        
        //移动模拟
        $id("guoshengcanvas").onmousemove = function(e){
            havor(ctx,gamedata,placestate,e.offsetX,e.offsetY);
        }
        
        //按键模拟
        $id("guoshengcanvas").onmousedown = function(e){
            if(e.button == 0){
                show(ctx,gamedata,placestate,e.offsetX,e.offsetY);
            }else{//标记炸弹
                addmark(ctx,gamedata,placestate,e.offsetX,e.offsetY);
            }
        }
    }
    
    /*
     * 点击之后显示的结果
     * 将坐标值转化为确定的值
     * 郭胜
     */
    function show(ctx,gamedata,placestate,x,y){
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        if(x>500-15*cols && y>300-15*rows && x<500+15*cols && y<300+15*rows){
            findspace(ctx,gamedata,placestate, Math.floor((y-(300 -15*rows))/30), Math.floor((x-(500-15*cols))/30) );
        }
    }
    
    /*
     * 寻找可以一起翻开的空格
     * 郭胜
     */
    function findspace(ctx ,gamedata,placestate,x,y){
        //x,y是指整数位置
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        var X = y*30;
        var Y = x*30;
        //XY是标准的坐标偏移量
        ctx.fillStyle = "rgb(189,199,224)";
        ctx.fillRect(X,Y,29,29);
        placestate[x][y] = "1";//先翻开再说
        var tmp = gamedata[x][y];
        switch(tmp){
            case 1: ctx.fillStyle = "rgb(60,80,182)"; break;
            case 2: ctx.fillStyle = "rgb(35,100,6)"; break;
            case 3: ctx.fillStyle = "rgb(174,4,9)"; break;
            case 4: ctx.fillStyle = "rgb(8,8,130)"; break;
            case 5: ctx.fillStyle = "rgb(95,12,18)"; break;
            case 6: ctx.fillStyle = "rgb(255,128,0)"; break;
            case 7: ctx.fillStyle = "rgb(152,33,254)"; break;
            case 8: ctx.fillStyle = "rgb(51,84,62)"; break;
        }
        if(tmp == -1){//是炸弹
            for(var i = 0;i<rows;i++){
                for(var j = 0;j<cols;j++){
                    addbomber(ctx,gamedata,i,j);
                }
            }
            clearInterval(s);
            if(confirm("没有一点熊用,这么简单的游戏还输了!!!") == true){
                init(15,20,40);
                return false;
            }else{
                return false;
            }
        }else{//不是炸弹,则画出数字
            ctx.font = "28px Adobe Gothic Std B";
            ctx.fillText(tmp,X+7,Y+23);
        }
        //双重循环,循环本次位置的左上,左下,右上,右下
        for(var i = -1;i<= 1;i++){
            for(var j= -1;j<=1;j++){
                if(i != 0 || j != 0){
                    if(exist(gamedata,x+i,y+j) != "notexist"){//位置存在
                        if(exist(gamedata,x,y) != 0){//位置存在,且值不是12345678,保证不把炸弹翻出来,当前位置
                            if(placestate[x+i][y+j] == "0"){//未翻开,递归继续
                                findspace(ctx,gamedata,placestate,x+i,y+j)
                            }
                        }else{//下一个位置未翻看并且下一个位置的值为0,代表着该位置的周围八个位置都没有炸弹,下个位置
                            if(placestate[x+i][y+j] == "0" && exist(gamedata,x+i,y+j) == "none"){
                                findspace(ctx,gamedata,placestate,x+i,y+j)
                            }
                        }
                    }
                }
            }
        }
        return false;
    }
    
    /*
     * 绘制炸弹
     * 郭胜
     */
    function addbomber(ctx,gamedata,i,j){
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        ctx.fillStyle = "red";
        ctx.save();
        ctx.translate(j*30,i*30);//重新定位坐标
        if(gamedata[i][j] == -1){
            ctx.save();
            ctx.shadowOffsetX = 2;
            ctx.shadowOffsetY = 2;
            ctx.shadowBlur = 2;
            ctx.shadowColor = "rgba(0,0,0,0.5)";
            ctx.translate(15,15);//重新定位圆点坐标
            ctx.beginPath();
            ctx.arc(0,0,10,0,Math.PI*2,false);
            ctx.fill();
            ctx.restore();
        }
        ctx.restore();
    }
    
    /*
     * 添加标记
     * 郭胜
     */
    function addmark(ctx,gamedata,placestate,x,y){
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        var i = Math.floor((y-(300-15*rows))/30);//画布中方块的位置
        var j = Math.floor((x-(500-15*cols))/30);//画布中方块的位置
        ctx.fillStyle = "green";
        ctx.save();
        ctx.shadowOffsetX = 2;
        ctx.shadowOffsetY = 2;
        ctx.shadowBlur = 2;
        ctx.shadowColor = "rgba(0,0,0,0.5)";
        ctx.translate(j*30,i*30);
        if(placestate[i][j] == "0"){//未翻转
            ctx.translate(15,15);
            ctx.beginPath();
            ctx.arc(0,0,10,0,Math.PI*2,false);
            ctx.fill();
        }
        ctx.restore();
        placestate[i][j] = "1";
        if(gamedata[i][j] == -1){
            bombnum --;
        }
        if(bombnum == 0){
            clearInterval(s);
            if(confirm("臭小子,你用了"+$id("time").value+"秒赢了游戏,不要骄傲!要不要再来一次,巩固一下基础?") == true){
                init(15,20,40);
            }
        }
    }
    
    
    /*
     * 悬浮之后样式的变化
     * 郭胜
     * x,y是相对浏览器中的坐标
     * 要计算出画布中的坐标
     * 画布相对于浏览器的起始坐标是(500-15*cols),300 - 15*rows,但是对于画布则是(0,0)
     *
     */
    function havor(ctx,gamedata,placestate,x,y){
        var rows  = gamedata.length;
        var cols = gamedata[0].length;
        if(x>500 - 15*cols && y>300-15*rows &&x<500+15*cols && y<300+15*rows){//判断鼠标点击所在的左边是否在游戏主界面内
            ctx.fillStyle = "rgb(255,128,0)";
            //计算出鼠标所在的画布中的方块的起始坐标
            nowJ = Math.floor((y-(300-15*rows))/30)*30;//新位置的绝对坐标
            nowI = Math.floor((x-(500 - 15*cols))/30)*30;//新位置的绝对坐标
            if(nowI != preI || nowJ != preJ){
                if(placestate[Math.round(nowJ/30)][Math.round(nowI/30)] == "0"){//判断该位置是否已翻开,0为未翻开
                    ctx.fillRect(nowI,nowJ,29,29);
                }
                //将原来的没翻开的方块还原
                if(preI != -1 && placestate[Math.round(preJ/30)][Math.round(preI/30)] == "0"){
                    //设置颜色渐变
                    var radgrad = ctx.createRadialGradient(30,30,1,45,45,(rows>cols?rows:cols)*30);
                    radgrad.addColorStop(0,'#C4E1FF');
                    radgrad.addColorStop(0.9,'rgb(36,66,147)');
                    ctx.fillStyle = radgrad;
                    ctx.fillRect(preI,preJ,29,29);
                }
                preI = nowI;//老位置的绝对坐标
                preJ = nowJ;//老位置的绝对坐标
            }
        }
    }
    
    /*
     * 图形上特定位置初始化
     * 郭胜
     */
    function startprint(ctx,gamedata,x,y){
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        //创建放射状/环形的渐变(用在画布内容上)createRadialGradient()
        var radgrad = ctx.createRadialGradient(30,30,1,45,45,(rows>cols?rows:cols)*30);
        radgrad.addColorStop(0,'#C4E1FF');
        radgrad.addColorStop(0.9,'rgb(36,66,147)');
        //设置或返回用于填充绘画的颜色、渐变或模式
        ctx.fillStyle = radgrad;
        ctx.fillRect(30*y,30*x,29,29);
    }
    
    /*
     * 检测位置是否存在,并判断有没有雷
     * 郭胜
     */
    function exist(gamedata,x,y){
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        if(x>= 0 && y>=0 && x<rows && y<cols){
            if(gamedata[x][y] == -1){//存在,并且是炸弹,返回1
                return Number(1);
            }else if(gamedata[x][y] == 0){//存在,值为0,安全值,留给递归查询出来
                return "none";
            }else{//存在,其它情况即:12345678
                return Number(0);
            }
        }else{
            return "notexist";
        }
    }
    
    /*
     * 创建二维数组
     * 郭胜
     */
    function doubleArray(m,n){
        var arr = new Array(m);//先创建一个一维数组arr
        for(var i= 0;i<m;i++){
            var arrtmp = new Array(n);
            arr[i] = arrtmp;//为arr每个元素再创建一个数组arrtmp
        }
        return arr;//返回二维数组
    }
</script>

扫雷游戏javascript html相关推荐

  1. Javascript实现扫雷游戏

    文章目录 前言 一.扫雷是什么? 二.游戏流程 1.初始界面 2.游戏过程 (1)绘制背景色 (2)绘制底部方块 (3)绘制数字 (4)绘制遮挡方块 (5)绘制标记 (6)绘制计时以及地雷数 3.游戏 ...

  2. JavaScript网页特效-“扫雷”游戏随机布雷功能

    "扫雷"游戏是一款经典益智小游戏.游戏目标是在最短的时间内找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输.本节介绍"扫雷"游戏随机布雷功能的设计与实现. ...

  3. JavaScript扫雷游戏,仿Windows扫雷

    javascript版仿windows扫雷游戏,单个HTML文件. CSDN下载(v2.2):http://download.csdn.net/user/cuixiping CSDN下载(v2.1): ...

  4. javaScript开发扫雷游戏

    前言 扫雷是windows自带的游戏,通过翻开小方块,来推理雷的位置 本文讲解如何通过javaScript制作扫雷游戏,并运用canvas画布绘制windows扫雷效果 一.技术拆分 canvas画图 ...

  5. 用纯JavaScript制作扫雷游戏-2

    网页扫雷游戏 - part 2

  6. 完全使用 HTML/CSS 实现的经典扫雷游戏

    大家好,我是你们的章鱼猫. 扫雷大家都玩过吧,Windows 里面的经典游戏.我记得上初中那会,上计算机课,都是偷偷玩这个游戏,怀念呀.但是不得不说,扫雷相比纸牌难度还是大一点的,毕竟还要费一点脑子的 ...

  7. 用js制作一个扫雷游戏(vue版)

    使用js来制作一个扫雷游戏,可以分为以下几个步骤 1.根据不同难度构建扫雷游戏区域: 2.在游戏区域中放置地雷: 3.处理点击事件: 4.处理游戏结束事件 1.根据不同难度构建扫雷游戏区域 创建一个二 ...

  8. 帮我写一个网页扫雷游戏基本的版本

    好的,我来帮你写一个基本版本的网页扫雷游戏. 首先,你需要熟悉 HTML.CSS 和 JavaScript 等前端技术,并了解二维数组.循环.判断语句等编程基础知识. 以下是简单的代码实现: HTML ...

  9. python扫雷 广度优先_Leetcode之广度优先搜索(BFS)专题-529. 扫雷游戏(Minesweeper)...

    Leetcode之广度优先搜索(BFS)专题-529. 扫雷游戏(Minesweeper) BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ary Tre ...

最新文章

  1. 在杭州,我们逛了一家“数据博物馆”
  2. linux常用基础命令操作收集
  3. java结丹期(14)----javaweb(cookiesession)
  4. [css]你有使用过preload、preconnect、prefetch这些属性吗?说说它们都有什么作用?
  5. linux下php支持mysql_linux下php扩展mysqli的支持 .
  6. 高性能HTTP加速器Varnish(性能调优篇)
  7. cygwin汉化简单操作【ZT】
  8. bash git 如何切换目录_【git】命令行与本地仓库/远程仓库
  9. Centos7 下Jenkins 安装
  10. [zt]扫盲,什么叫MAD(a11s)
  11. AC日记——找最大数序列 openjudge 1.9 10
  12. Unity之VideoPlayer组件——循环播放视频
  13. 汽车服务架构(SOA)开发设计
  14. OC中浮点数转整数的进一法和去尾法
  15. 详解从p12证书提取RSA公私钥和序列号(小白向)
  16. 台式计算机配置作业,大学计算机上机课作业.doc
  17. 微信支付V3版本的 签名生成,验签,解密,统一下单的简单封装
  18. alfred 常用搜索_如何使用Alfred完善macOS的Spotlight搜索
  19. 《C语言程序设计》课程总结报告
  20. SRAM FPGA控制,实际产品拷机测试过

热门文章

  1. 台式计算机亮度调整,事实:如何在台式计算机上设置显示亮度调整
  2. kali_study
  3. 京东云分布式链路追踪在金融场景的最佳实践
  4. Linux那些事儿 之 戏说USB(25)设备的生命线(四)
  5. Google Voice
  6. SpringBoot相比传统Spring,有哪些优势?
  7. Win 10 C 盘突然爆满,怎么清理?
  8. C#理论 —— 窗体应用WinForm
  9. 模仿爱奇艺账号登录限制人数,SpringBoot 并发登录人数控制,踢人功能
  10. 办公计算机配置单,普通办公电脑怎么配?office三件套办公电脑主机配置推荐