方格遊戲

年後復工,寫了一個方格遊戲練練手。

最開始想的遊戲名字是雪人回家,找不到合適的雪人頭像,就簡單的稱呼爲方格遊戲吧,哈哈。

 

項目地址(打開就能玩)

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

目前沒有移動版本,只能在PC上玩。

 

遊戲說明:

使用鍵盤上下左右四個箭頭按鍵移動小女孩,在倒計時結束前到達小房子的位置即遊戲挑戰成功。

每次限制移動一格,紅綠方格代表正負分值,走過的方格不再積分。

倒計時,系統設置時間爲30秒,可以自行修改時間,調節遊戲難度。

遊戲比的是限定時間內的得分高低。當然,遊戲時間結束了還沒回家,就是0分。哈哈。

遊戲覆盤功能,棋盤不變,可以重走一遍。戰績記錄每次重玩的得分,快來和小夥伴一較高低!

不想玩本局了,還可以再來一局,棋盤則會重新生成,每格分數隨機。

 

遊戲實現思路

h5+vue+js實現

移動原理是css的位置偏移 translate(x,y)

 

難點

1、獲取當前移動到達的目標格的分值。

初始化一個方格字典數組。在棋盤創建時,同步更新字典中記錄的對應方格分值。每次移動累積偏移量,都去遍歷字典數組,通過比較偏移量,確定目標方格,從而獲取目標方格的分值。

 

2、遊戲覆盤。

確保方格顯示的分值不變,上次走過並置爲0的方格需要復原。在棋盤數組中,記錄兩個分值,一個是隨機出的方格分值 score ,一個是修改過的分值 usedScore 。score 在一局遊戲中始終不變,usedScore 的值動態改變,記錄失效後的分值0。棋盤的顯示,usedScore 爲0就顯示 usedScore,否則顯示 score 。

 

遊戲源碼分享

<!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>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章