成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

華容道游戲(下)

BicycleWarrior / 805人閱讀

摘要:華容道游戲看似簡(jiǎn)單,但求解需要設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu)比較復(fù)雜,還牽涉到棋類游戲的棋局判斷,所以整個(gè)過(guò)程還是挺費(fèi)勁的。

此為《算法的樂(lè)趣》讀書筆記,我用javascript(ES6)重新實(shí)現(xiàn)算法。

華容道游戲看似簡(jiǎn)單,但求解需要設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu)比較復(fù)雜,還牽涉到棋類游戲的棋局判斷,所以整個(gè)過(guò)程還是挺費(fèi)勁的。我盡量用面向?qū)ο蟮乃枷雭?lái)進(jìn)行封裝,整個(gè)過(guò)程將分成幾個(gè)部分記錄下來(lái),今天是最后一部分,棋局的廣度搜索。
廣度搜索

棋局的搜索空間是一個(gè)樹狀關(guān)系空間,廣度優(yōu)先搜索能夠首先找到最優(yōu)解,因?yàn)槭紫日业降慕馍疃仁亲顪\的。

游戲定義

我們對(duì)算法的要求是:給定一個(gè)華容道游戲的開局布局,可以得到這個(gè)開局的所有解決方法以及相應(yīng)的武將移動(dòng)步驟,要求算法具有能用性,能處理任何一種開局的華容道游戲。

class HrdGame{
    constructor(caoIdx, heroes){                
        this.caoIdx = caoIdx;                        //曹操在武將列表中的序號(hào)
        var startState = new HrdGameState();         //新建開局棋局
        startState.initState(heroes)                 //開局棋局初始化
        this.states = []                             //存儲(chǔ)所有棋局狀態(tài),廣度搜索的狀態(tài)空間
        this.zhash = {}                              //棋局及其鏡像哈希,判重空間
        this.result = 0;                             //解的總數(shù)
        addNewStatePattern(this,startState)          //開局處理,相當(dāng)于游戲初始化
    }
}
算法思路及代碼

游戲的求解過(guò)程就是棋局的搜索過(guò)程,每移動(dòng)一個(gè)棋子就會(huì)生成一個(gè)新的棋局,對(duì)每一個(gè)棋局我們都要生成其所有的后續(xù)棋局。結(jié)束條件:在生成每一個(gè)新棋局時(shí),判斷是否為解,是則該狀態(tài)終止;另一方面,每一個(gè)棋局若其后續(xù)棋局?jǐn)?shù)為空,也自動(dòng)終止。

解的判定
function isEscaped(game, gameState){            //曹操的位置到達(dá)(1,3)
    return (gameState.heroes[game.caoIdx -1].left == CAO_ESCAPE_LEFT) && (gameState.heroes[game.caoIdx - 1].top == CAO_ESCAPE_TOP)
}
棋局搜索
function resolveGame(game)                                     //廣度搜索主函數(shù)
{
    let index = 0;
    while(index < game.states.length){
        gameState = game.states[index];                        //依次選定棋局狀態(tài)
        if(isEscaped(game, gameState)){                        //找到解,輸出
            game.result++;
            console.log("result:"+game.result+" step--"+gameState.step+" index:"+index)
        }
        else{
            searchNewGameStates(game, gameState);             //選定棋局搜索所有新棋局
        }
        index++;
    }
    return (game.result > 0);
}
搜索新棋局

武將移動(dòng)產(chǎn)生新棋局。

function searchNewGameStates(game, gameState)                   //搜索新棋局
{
    for(let i = 0; i < gameState.heroes.length; i++)            //遍歷武將
    {
        for(let j = 0; j < MAX_MOVE_DIRECTION; j++)             //遍歷所有方向
        {
            trySearchHeroNewState(game, gameState, i, j);       //移動(dòng)武將產(chǎn)生新棋局
        }
    }
}
新棋局生成

根據(jù)華容道規(guī)則,對(duì)一個(gè)武將棋子連續(xù)移動(dòng)只算一步,因此在每一步移動(dòng)成功后,需要繼續(xù)對(duì)該棋子嘗試移動(dòng),但是移動(dòng)的方向有限制,不能向原方向移動(dòng)。

function trySearchHeroNewState(game, gameState, heroIdx, dirIdx)
{
    let newState = moveHeroToNewState(gameState, heroIdx, dirIdx);    //新棋局產(chǎn)生
    if(newState) {
        if(addNewStatePattern(game, newState))                        //處理新棋局,判重,添加到狀態(tài)鏈中
        {
             /*嘗試連續(xù)移動(dòng),根據(jù)華容道游戲規(guī)則,連續(xù)的移動(dòng)也只算一步*/
            tryHeroContinueMove(game, newState, heroIdx, dirIdx);
            return;
        }
    }
}
移動(dòng)武將
function moveHeroToNewState(gameState, heroIdx, dirIdx)
{
    if(canHeroMove(gameState, heroIdx, dirIdx))                //能夠移動(dòng)
    {
        var newState = new HrdGameState();                     //新建棋局
        if(newState)
        {
            copyGameState(gameState, newState);                //用父棋局初始化新棋局
            var hero = newState.heroes[heroIdx];               //取得武將
            const dir = DIRECTION[dirIdx];                     //取得方向

            clearPosition(newState, hero.type, hero.left, hero.top); //清除父棋局信息
            takePosition(newState, heroIdx, hero.type, hero.left + dir[0], hero.top + dir[1]);            //新棋局?jǐn)?shù)據(jù)生成
            hero.left = hero.left + dir[0];                    //武將新位置設(shè)定
            hero.top = hero.top + dir[1];

            newState.step = gameState.step + 1;                //移動(dòng)步數(shù)加一
            newState.parent = gameState;                       //形成因果鏈
            newState.move.heroIdx = heroIdx;                   //記錄移動(dòng)方法
            newState.move.dirIdx = dirIdx;
            return newState;                                   //返回新棋局
        }
    }
    return null;
}
處理棋局
function addNewStatePattern(game, gameState)
{
    var l2rHash = getZobristHash(zobHash, gameState);            //計(jì)算棋局哈希值
    if(!game.zhash[l2rHash])                                     //棋局不存在
    {
        game.zhash[l2rHash] = l2rHash;                           //棋局哈希存儲(chǔ)
        var r2lHash = getMirrorZobristHash(zobHash, gameState);
        game.zhash[r2lHash] = r2lHash;                           //棋局鏡像哈希存儲(chǔ)
        game.states.push(gameState);                             //棋局存儲(chǔ)

        return true;
    }

    return false;                                                //棋局已經(jīng)存在,忽略
}
開局及解 橫刀立馬

定義:

var hs =[new Warrior(WARRIOR_TYPE.HT_VBAR,0,0),          
          new Warrior(WARRIOR_TYPE.HT_BOX,1,0),
          new Warrior(WARRIOR_TYPE.HT_VBAR,3,0),
          new Warrior(WARRIOR_TYPE.HT_VBAR,0,2),
          new Warrior(WARRIOR_TYPE.HT_HBAR,1,2),
          new Warrior(WARRIOR_TYPE.HT_VBAR,3,2),
          new Warrior(WARRIOR_TYPE.HT_BLOCK,0,4),
          new Warrior(WARRIOR_TYPE.HT_BLOCK,1,3),
          new Warrior(WARRIOR_TYPE.HT_BLOCK,2,3),
          new Warrior(WARRIOR_TYPE.HT_BLOCK,3,4)
]

四個(gè)解:

result:1 step--81 index:11930
result:2 step--85 index:12123
result:3 step--98 index:12337
result:4 step--101 index:12348
指揮若定

定義:

var hs = [new Warrior(WARRIOR_TYPE.HT_VBAR,0,0),          //構(gòu)建武將列表,初始棋局
          new Warrior(WARRIOR_TYPE.HT_BOX,1,0),
          new Warrior(WARRIOR_TYPE.HT_VBAR,3,0),
          new Warrior(WARRIOR_TYPE.HT_BLOCK,0,2),
          new Warrior(WARRIOR_TYPE.HT_HBAR,1,2),
          new Warrior(WARRIOR_TYPE.HT_BLOCK,3,2),
          new Warrior(WARRIOR_TYPE.HT_VBAR,0,3),
          new Warrior(WARRIOR_TYPE.HT_BLOCK,1,3),
          new Warrior(WARRIOR_TYPE.HT_BLOCK,2,3),
          new Warrior(WARRIOR_TYPE.HT_VBAR,3,3)
]

四個(gè)解:

result:1 step--73 index:11391
result:2 step--84 index:12207
result:3 step--86 index:12263
result:4 step--89 index:12306
兵分三路

定義:

var hs = [new Warrior(WARRIOR_TYPE.HT_BLOCK,0,0),          //構(gòu)建武將列表,初始棋局
          new Warrior(WARRIOR_TYPE.HT_BOX,1,0),
          new Warrior(WARRIOR_TYPE.HT_BLOCK,3,0),
          new Warrior(WARRIOR_TYPE.HT_VBAR,0,1),
          new Warrior(WARRIOR_TYPE.HT_HBAR,1,2),
          new Warrior(WARRIOR_TYPE.HT_VBAR,3,1),
          new Warrior(WARRIOR_TYPE.HT_VBAR,0,3),
          new Warrior(WARRIOR_TYPE.HT_BLOCK,1,3),
          new Warrior(WARRIOR_TYPE.HT_BLOCK,2,3),
          new Warrior(WARRIOR_TYPE.HT_VBAR,3,3)
]

四個(gè)解:

result:1 step--74 index:7767
result:2 step--80 index:9212
result:3 step--94 index:10921
result:4 step--97 index:11157
完整代碼

文中是主要代碼分析,完整代碼托管在開源中國(guó),其中的hyd.js即華容道解法。

https://gitee.com/zhoutk/test
小結(jié)

終于完成了,其中遇到一個(gè)坑,就是zobrist的空間問(wèn)題,《算法的樂(lè)趣》書中是說(shuō)用32位整數(shù),但其提供的源碼是左移15位,我覺(jué)得也應(yīng)該夠,就用了15位整數(shù)。結(jié)果搜索不到解,各種調(diào)試、跟蹤,感覺(jué)哪哪都是對(duì)的,曹操就是下不來(lái),郁悶一晚。突然想到會(huì)不會(huì)是zobrist空間太小,若空間太小,新的棋局會(huì)與舊棋局沖突,這樣應(yīng)該會(huì)導(dǎo)致很多狀態(tài)被忽略。清晨起床一試,爽!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/79353.html

相關(guān)文章

  • 容道游戲(中)

    摘要:棋類游戲一般需要行數(shù)列數(shù)狀態(tài)數(shù)個(gè)狀態(tài),以華容道為例,需要為個(gè)狀態(tài)分配編碼值。對(duì)于華容道游戲來(lái)說(shuō),這種左右鏡像的情況對(duì)于滑動(dòng)棋子尋求結(jié)果的影響是一樣的。 此為《算法的樂(lè)趣》讀書筆記,我用javascript(ES6)重新實(shí)現(xiàn)算法。 華容道游戲看似簡(jiǎn)單,但求解需要設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu)比較復(fù)雜,還牽涉到棋類游戲的棋局判斷,所以整個(gè)過(guò)程還是挺費(fèi)勁的。我盡量用面向?qū)ο蟮乃枷雭?lái)進(jìn)行封裝,整個(gè)過(guò)程將分成幾...

    Jason 評(píng)論0 收藏0
  • 容道游戲(上)

    摘要:華容道游戲看似簡(jiǎn)單,但求解需要設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu)比較復(fù)雜,還牽涉到棋類游戲的棋局判斷,所以整個(gè)過(guò)程還是挺費(fèi)勁的。華容道游戲介紹華容道游戲據(jù)說(shuō)來(lái)源于三國(guó)故事諸葛亮智算華容,關(guān)云長(zhǎng)義釋曹操。 此為《算法的樂(lè)趣》讀書筆記,我用javascript(ES6)重新實(shí)現(xiàn)算法。 華容道游戲看似簡(jiǎn)單,但求解需要設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu)比較復(fù)雜,還牽涉到棋類游戲的棋局判斷,所以整個(gè)過(guò)程還是挺費(fèi)勁的。我盡量用面向?qū)ο蟮?..

    xi4oh4o 評(píng)論0 收藏0
  • 用React寫一個(gè)數(shù)字容道,你需要知道的秘密

    摘要:還在上班很無(wú)聊數(shù)字華容道暢玩地址開發(fā)源碼地址這個(gè)叫前言年末了。光隨機(jī)生成一個(gè)亂序數(shù)列是不夠的,還得保證這個(gè)數(shù)列的逆序數(shù)為偶數(shù),嗦嘎。所以,我們直接將交換的次數(shù),記為數(shù)列逆序數(shù)個(gè)數(shù),就達(dá)到了想要的效果。 還在上班?很無(wú)聊?數(shù)字華容道暢玩地址 開發(fā)源碼地址 這個(gè)叫前言 年末了。哦,不,要過(guò)年了。以前只能一路站到公司的我,今早居然是坐著過(guò)來(lái)的。新的一年,總要學(xué)一個(gè)新東西來(lái)迎接新的未來(lái)吧,所以...

    Jason 評(píng)論0 收藏0
  • 一只青蛙跳

    這是一個(gè)關(guān)于獨(dú)立鉆石的游戲 獨(dú)立鉆石起源于法國(guó),是一種風(fēng)靡世界的益智游戲與中國(guó)發(fā)明的華容道、匈牙利人發(fā)明的魔方, 并稱為智力游戲界的三大不可思議它類似于跳棋,但不能走步,只能跳。走棋時(shí)棋子跳過(guò)相鄰的棋子到空位上,并把跳過(guò)的棋子吃掉。棋子可以沿棋盤的格線橫跳、縱跳,但不能斜跳 了解更多 游戲截圖 showImg(https://segmentfault.com/img/bVAdq3); 游戲地址 游...

    鄒強(qiáng) 評(píng)論0 收藏0
  • UCloud攜手廣東移動(dòng)、中興通訊國(guó)內(nèi)率先5G云游戲測(cè)試

    摘要:近日,優(yōu)刻得科技股份有限公司以下簡(jiǎn)稱聯(lián)合中國(guó)移動(dòng)廣東公司中興通訊股份有限公司,以及云游戲合作伙伴北京念力科技有限公司,進(jìn)行了實(shí)驗(yàn)室環(huán)境下云游戲體驗(yàn)測(cè)試。近日,優(yōu)刻得科技股份有限公司(以下簡(jiǎn)稱UCloud)聯(lián)合中國(guó)移動(dòng)廣東公司、中興通訊股份有限公司,以及云游戲合作伙伴北京念力科技有限公司,進(jìn)行了5G實(shí)驗(yàn)室環(huán)境下云游戲體驗(yàn)測(cè)試。這項(xiàng)測(cè)試將為云游戲在5G網(wǎng)絡(luò)環(huán)境下的發(fā)展提供實(shí)驗(yàn)室參考,為5G技術(shù)的...

    wing324 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<