Checkered game

After resuming work years later, I wrote a grid game to practice hand skills.

The name of the game I first thought of was Snowman Going Home. I couldn't find a suitable snowman head, so I simply called it a grid game, haha.

 

Project address (open to play)

http://mumuqiuer.gitee.io/snowman/

There is currently no mobile version and can only be played on PC.

 

game instructions:

Use the four arrow buttons up, down, left, and right on the keyboard to move the little girl, and reach the position of the little house before the countdown ends, that is, the game challenge is successful.

Each time you are restricted to move one square, the red and green squares represent the positive and negative points, and the squares you pass by will no longer receive points.

Countdown, the system sets the time to 30 seconds, you can modify the time by yourself to adjust the difficulty of the game.

The game is more than the score within a limited time. Of course, if the game time is over and you have not returned home, it is 0 points. Haha.

The game replay function, the board remains unchanged, you can repeat it. Record the score of each replay, come and compete with your friends!

If you don’t want to play this game anymore, you can play another game, and the board will be regenerated with random scores for each grid.

 

Game realization ideas

h5+vue+js implementation

The principle of movement is the position offset of css translate(x,y)

 

difficulty

1. Get the score of the target grid reached by the current move.

Initialize a grid dictionary array. When the board is created, the corresponding square score recorded in the dictionary is updated synchronously. Each time the accumulated offset is moved, the dictionary array is traversed, and the target square is determined by comparing the offset, thereby obtaining the score of the target square.

 

2. Game review.

Make sure that the score displayed in the square remains unchanged, and the square that you walked past and set to 0 needs to be restored. In the checkerboard array, record two scores, one is the score of the random grid, and the other is the modified score usedScore. The score is always the same in a game, the value of usedScore changes dynamically, and the score is 0 after the record fails. In the display of the chessboard, usedScore is displayed if usedScore is 0, otherwise score is displayed.

 

Game source code sharing

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <title>方格游戏</title>
    <link rel="shortcut icon" href="favicon.ico">
    <meta name="keywords" content="方格游戏">
    <meta name="description" content="方格游戏">
    <script src="vue.js"></script>
    <style>
        body{
            width: 100%;
            height:100%;
            margin:0;
            background: #fff;
            overflow: hidden;
            box-sizing: border-box;
        }
        div.container{
            width: 100%;
            display: flex;
            justify-content: center;
            margin-top:80px;
            text-align: center;
        }
        div.container div.chess{
            width:700px;
            height:700px;
            display: flex;
            justify-content: flex-start;
            flex-wrap: wrap;
            box-sizing: border-box;
            margin:0 20px;
        }
        div.container div.score{
            width:300px;
            margin:0 20px;
            border:1px solid #999;
            background: #999;
        }

        /*游戏计时器*/
        div.head{
            width:100%;
            height:64px;
            box-sizing: border-box;
            text-align: center;
            position: fixed;
            top: 0;
            background: #999;
            padding:12px;
        }
        div.head span,div.score span{
            font-size: 24px;
            font-weight: bold;
            color:red;
            padding:0 4px
        }

        /*雪人*/
        div.snowman{
            width:80px;
            height:80px;
            margin:10px;
            text-align: center;
            background: url("head.jpg") no-repeat;
            cursor: pointer;
            z-index: 2;
        }

        div.chess-grid{
            width:100px;
            height:100px;
            line-height:100px;
            box-sizing: border-box;
            text-align: center;
            border:1px solid #ccc;
            color: #fff;
        }

        /*雪人的家*/
        div.home{
            width:100px;
            height:80px;
            margin:12px 7px;
            background: url("home.jpg") no-repeat;
        }

        /*控制器*/
        div.control{
            width:100%;
            height:60px;
            line-height:60px;
            text-align: center;
            display: flex;
            justify-content: center;
            position: fixed;
            bottom: 0;
            background: #999;
        }
        div.btn{
            width:200px;
            height:40px;
            line-height: 40px;
            box-sizing: border-box;
            border:1px solid #ccc;
            margin:10px;
            color: #fff;
            cursor: pointer;
        }
        div.auto{
            background: green;
        }
        div.refresh{
            background: red;
        }
        div.game_start_btn{
            margin:0 auto;
        }
    </style>
</head>
<body>
<div id="root">
    <div class="head" v-show="!showControl">
        <div v-show="!showTime" class="game_start_btn btn" @click="game_start">开始游戏</div>
        <div v-show="showTime">倒计时<span>{
   
   {gameTime}}</span>秒 </div>
    </div>

    <div class="container">
        <div class="chess">
            <div class="chess-grid"><div class="snowman" :style="moveStyle" title="按键盘方向键移动我哦"></div></div>
            <div class="chess-grid" v-for="(item,index) in chess" :key="index" :style="{background:item.background}">{
   
   {item.usedScore == 0 ? item.usedScore : item.score}}分</div>
            <div class="chess-grid"><div class="home"></div></div>
        </div>

        <div class="score">
            <p>倒计时设置(10 ~ 60s):<input type="number" v-model="userSetGameTime" min="10" max="60"/></p>
            <hr>
            <p>战绩</p>
            <div v-for="(score,index) in gameScores" :key="index">第{
   
   {index+1}}战得分<span>{
   
   {score}}</span>分</div>
        </div>
    </div>

    <div class="control" v-show="showControl">
        <div class="btn auto" @click="game_review">本局复盘</div>
        <div class="btn refresh" @click="game_update">再来一局</div>
    </div>
</div>

<script>
    new Vue({
        el: "#root",
        data: {
            showControl:false,//是否显示本局复盘、再来一局
            showTime:false,//是否显示倒计时 不显示倒计时的时候会显示开始游戏按钮
            is_get_home:false,
            gameTime:30,//系统设置的游戏时间 30秒一局游戏
            userSetGameTime:30,//用户设置的游戏时间
            gameScores:[],//单机多人游戏 游戏复盘,存储历史得分
            currentScore:0,//当前一局游戏的得分
            moveDown:0,
            moveRitht:0,
            chess:[],//存储随机的分数和背景色数组
            moveStyle:{transform:"translate(0,0)"},//偏移样式
            dictionary:[//棋盘各块偏移量对照字典 最后一格为终点格
                {"score":0," i":0, "r":100, "d":0},
                {"score":0, "i":1, "r":200, "d":0},
                {"score":0,"i":2, "r":300, "d":0},
                {"score":0,"i":3, "r":400, "d":0},
                {"score":0,"i":4, "r":500, "d":0},
                {"score":0,"i":5, "r":600, "d":0},
                {"score":0,"i":6, "r":0, "d":100},
                {"score":0,"i":7, "r":100, "d":100},
                {"score":0,"i":8, "r":200, "d":100},
                {"score":0,"i":9, "r":300, "d":100},
                {"score":0,"i":10, "r":400, "d":100},
                {"score":0,"i":11, "r":500, "d":100},
                {"score":0,"i":12, "r":600, "d":100},
                {"score":0,"i":13, "r":0, "d":200},
                {"score":0,"i":14, "r":100, "d":200},
                {"score":0,"i":15, "r":200, "d":200},
                {"score":0,"i":16, "r":300, "d":200},
                {"score":0,"i":17, "r":400, "d":200},
                {"score":0,"i":18, "r":500, "d":200},
                {"score":0,"i":19, "r":600, "d":200},
                {"score":0,"i":20, "r":0, "d":300},
                {"score":0,"i":21, "r":100, "d":300},
                {"score":0,"i":22, "r":200, "d":300},
                {"score":0,"i":23, "r":300, "d":300},
                {"score":0,"i":24, "r":400, "d":300},
                {"score":0,"i":25, "r":500, "d":300},
                {"score":0,"i":26, "r":600, "d":300},
                {"score":0,"i":27, "r":0, "d":400},
                {"score":0,"i":28, "r":100, "d":400},
                {"score":0,"i":29, "r":200, "d":400},
                {"score":0,"i":30, "r":300, "d":400},
                {"score":0,"i":31, "r":400, "d":400},
                {"score":0,"i":32, "r":500, "d":400},
                {"score":0,"i":33, "r":600, "d":400},
                {"score":0,"i":34, "r":0, "d":500},
                {"score":0,"i":35, "r":100, "d":500},
                {"score":0,"i":36, "r":200, "d":500},
                {"score":0,"i":37, "r":300, "d":500},
                {"score":0,"i":38, "r":400, "d":500},
                {"score":0,"i":39, "r":500, "d":500},
                {"score":0,"i":40, "r":600, "d":500},
                {"score":0,"i":41, "r":0, "d":600},
                {"score":0,"i":42, "r":100, "d":600},
                {"score":0,"i":43, "r":200, "d":600},
                {"score":0,"i":44, "r":300, "d":600},
                {"score":0,"i":45, "r":400, "d":600},
                {"score":0,"i":46, "r":500, "d":600},
                {"score":0,"i":47, "r":600, "d":600}
            ]
        },
        methods: {
            //生成随机分数棋格
            createChess:function(){
                //7*7方格,掐头去尾,需要生成47个随机数。
                var score;
                var bgColor;
                for(var i=0;i<47;i++){
                    // 按奇数偶数对应正负分值
                    if(i%2 ==0){
                        //正数 加分
                        score =Math.round(Math.random()*10)+2;
                        bgColor="#16a05d";
                    }else{
                        //负数 减分
                        score =-Math.round(Math.random()*6)-1;
                        bgColor="#e21918";
                    }
                    this.chess.push({
                        "score":score,
                        "usedScore":100,//随便指定一个现今规则不可能有的一个分数即可
                        "background":bgColor
                    });
                    //同步更新对照字典,存储分值。
                    this.dictionary[i].score = score;
                }
            },

            //键盘事件 四个箭头按键,控制上下左右四个方向的移动。
            letMove:function(e){
                e||event;
                //当游戏倒计时显示时,即游戏还未结束,才能触发键盘事件,开始移动。
                if(this.showTime){
                    switch(e.keyCode){
                        case 39:
                            //向右移动
                            this.moveRitht +=100;
                            break;
                        case 40:
                            //向下移动
                            this.moveDown +=100;
                            break;
                        case 37:
                            //向左移动
                            this.moveRitht -=100;
                            break;
                        case 38:
                            //向上移动
                            this.moveDown -=100;
                            break;
                        default:
                            return;
                    }

                    //判断界限值 不能超出棋盘活动
                    this.moveRitht < 0 ? this.moveRitht = 0 : this.moveRitht;
                    this.moveRitht > 600 ? this.moveRitht = 600 : this.moveRitht;

                    this.moveDown < 0 ? this.moveDown = 0 : this.moveDown;
                    this.moveDown > 600 ? this.moveDown = 600 : this.moveDown;

                    this.moveStyle.transform = "translate("+this.moveRitht+"px,"+this.moveDown+"px)";

                    //根据偏移的位置,统计得分。
                    this.countScore(this.moveRitht,this.moveDown);
                }

            },

            //计算得分
            countScore:function(r,d){
                //遍历偏移量字典,根据当前所在的位置,获取对应的分值。
                //偏移量字典(len=48)比棋格(len=47)多了一个终点的位置信息。
                if(!(r == 600 && d == 600)){
                    //不在家,赋值false 防止回家后再离开的情形
                    this.is_get_home = false;
                    for(var i=0;i<48;i++){
                        if(r == this.dictionary[i].r && d == this.dictionary[i].d){
                            if(this.chess[i].usedScore !=0){
                                this.currentScore += this.dictionary[i].score;
                                //分数一次性有效 走过的分数变为0.
                                //为了复盘,不直接改变分数,新分数存储到 usedScore
                                this.chess[i].usedScore = 0;
                            }
                        }
                    }
                }else{
                    //雪人到家
                    this.is_get_home = true;
                }

            },

            //计时器,每次时间-1,时间单位秒。
            timer:function(){
                this.gameTime -= 1
            },

            //用户点击游戏开始 创建定时器 显示倒计时
            game_start:function(){
                if(this.gameTime != this.userSetGameTime){
                    //系统设置的游戏时长和用户设置的游戏时长冲突,则使用用户设置的时长
                    this.gameTime = this.userSetGameTime;
                }
                this.showTime=true;
                timer1=setInterval(this.timer, 1000);
            },

            game_review:function(){
                this.parameter_reset();
                this.resetUsedScore();
            },

            //恢复棋盘 使用过的分数初始化
            resetUsedScore:function(){
                var len = 47;
                while(len--){
                    this.chess[len].usedScore = 100;
                }
            },

            //本局重玩,只需要重置参数。
            parameter_reset:function(){
                this.showControl=false;
                this.is_get_home = false;
                this.showTime=false;//先不显示倒计时,显示开始游戏按钮。
                this.moveRitht=0;
                this.moveDown=0;
                this.moveStyle.transform = "translate(0,0)";
                this.currentScore=0;
            },

            //页面初始化 游戏重新开始
            game_update:function(){
                this.parameter_reset();
                this.gameScores=[];
                this.chess=[];
                this.createChess();
            }
        },
        watch:{
            //监测游戏时间
            gameTime(){
                if(this.gameTime == 0){
                    clearInterval(timer1);
                    this.showControl=true;
                    this.showTime=false;//倒计时结束,关闭倒计时结果显示
                    if(this.is_get_home){
                        //游戏结束:倒计时结束,雪人进入小屋。当前得分计入。
                        this.gameScores.push(this.currentScore);
                    }else{
                        //游戏失败: 倒计时结束,但雪人未进入小屋。本局得分为0。
                        this.currentScore=0;
                        this.gameScores.push(0);
                    }
                }
            }
        },
        created(){
            //注册键盘事件
            var _this = this;
            document.addEventListener("keydown", _this.letMove);
        },
        mounted(){
            this.game_update();
        }
    })
</script>
</body>
</html>

 

Guess you like

Origin blog.csdn.net/Irene1991/article/details/104969667