女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

簡(jiǎn)述游戲中常用的兩種隨機(jī)算法(上)

jf_78858299 ? 來源:labuladong ? 作者:labuladong ? 2023-04-12 11:43 ? 次閱讀

沒事兒的時(shí)候我喜歡玩玩那些經(jīng)典的 2D 網(wǎng)頁(yè)小游戲,我發(fā)現(xiàn)很多游戲都要涉及地圖的隨機(jī)生成,比如掃雷游戲中地雷的位置應(yīng)該是隨機(jī)分布的:

圖片

再比如經(jīng)典炸彈人游戲,障礙物的位置也是有一定隨機(jī)性的:

圖片

這些 2D 游戲相較現(xiàn)在的大型 3D 游戲雖然看起來有些簡(jiǎn)陋,但依然用到很多有趣算法技巧,本文就來深入研究一下地圖的隨機(jī)生成算法。

2D 游戲的地圖肯定可以抽象成一個(gè)二維矩陣,就拿掃雷舉例吧,我們可以用下面這個(gè)類表示掃雷的棋盤:

class Game {
    int m, n;
    // 大小為 m * n 的二維棋盤
    // 值為 true 的地方代表有雷,false 代表沒有雷
    boolean[][] board;
}

如果你想在棋盤中隨機(jī)生成k個(gè)地雷,也就是說你需要在board中生成k個(gè)不同的(x, y)坐標(biāo),且這里面x, y都是隨機(jī)生成的。

對(duì)于這個(gè)需求, 首先一個(gè)優(yōu)化就是對(duì)二維矩陣進(jìn)行「降維打擊」,把二維數(shù)組轉(zhuǎn)化成一維數(shù)組

class Game {
    int m, n;
    // 長(zhǎng)度為 m * n 的一維棋盤
    // 值為 true 的地方代表有雷,false 代表沒有雷
    boolean[] board;

    // 將二維數(shù)組中的坐標(biāo) (x, y) 轉(zhuǎn)化為一維數(shù)組中的索引
    int encode(int x, int y) {
        return x * n + y;
    }

    // 將一維數(shù)組中的索引轉(zhuǎn)化為二維數(shù)組中的坐標(biāo) (x, y)
    int[] decode(int index) {
        return new int[] {index / n, index % n};
    }
}

這樣,我們只要在[0, m * n)中選取一個(gè)隨機(jī)數(shù),就相當(dāng)于在二維數(shù)組中隨機(jī)選取了一個(gè)元素。

但問題是,我們現(xiàn)在需要隨機(jī)選出k個(gè)不同的位置放地雷。你可能說,那在[0, m * n)中選出來k個(gè)隨機(jī)數(shù)不就行了?

是的,但實(shí)際操作起來有些麻煩,因?yàn)槟愫茈y保證隨機(jī)數(shù)不重復(fù)。如果出現(xiàn)重復(fù)的隨機(jī)數(shù),你就得再隨機(jī)選一次,直到找到k個(gè)不同的隨機(jī)數(shù)。

如果k比較小m * n比較大,那出現(xiàn)重復(fù)隨機(jī)數(shù)的概率還比較低,但如果km * n的大小接近,那么出現(xiàn)重復(fù)隨機(jī)數(shù)的概率非常高,算法的效率就會(huì)大幅下降。

那么,我們有沒有更好的辦法能夠在線性的時(shí)間復(fù)雜度解決這個(gè)問題?其實(shí)是有的,而且有很多種解決方案。

洗牌算法

第一個(gè)解決方案,我們可以換個(gè)思路,避開「在數(shù)組中隨機(jī)選擇k個(gè)元素」這個(gè)問題,把問題轉(zhuǎn)化成「如何隨機(jī)打亂一個(gè)數(shù)組」

現(xiàn)在想隨機(jī)初始化k顆地雷的位置,你可以先把這k顆地雷放在board開頭,然后把board數(shù)組隨機(jī)打亂,這樣地雷不就隨機(jī)分布到board數(shù)組的各個(gè)地方了嗎?

洗牌算法,或者叫隨機(jī)亂置算法就是專門解決這個(gè)問題的,我們可以看下力扣第 384 題「打亂數(shù)組」:

圖片

這個(gè)shuffle函數(shù)是算法的關(guān)鍵,直接看解法代碼吧:

class Solution {
    private int[] nums;
    private Random rand = new Random();
    
    public Solution(int[] nums) {
        this.nums = nums;
    }
    
    public int[] reset() {
        return nums;
    }
    
    // 洗牌算法
    public int[] shuffle() {
        int n = nums.length;
        int[] copy =  Arrays.copyOf(nums, n);
        for (int i = 0 ; i < n; i++) {
            // 生成一個(gè) [i, n-1] 區(qū)間內(nèi)的隨機(jī)數(shù)
            int r = i + rand.nextInt(n - i);
            // 交換 nums[i] 和 nums[r]
            swap(copy, i, r);
        }
        return copy;
    }
    
    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

洗牌算法的時(shí)間復(fù)雜度是 O(N),而且邏輯很簡(jiǎn)單,關(guān)鍵在于讓你證明為什么這樣做是正確的。排序算法的結(jié)果是唯一可以很容易檢驗(yàn)的,但隨機(jī)亂置算法不一樣,亂可以有很多種,你怎么能證明你的算法是「真的亂」呢?

分析洗牌算法正確性的準(zhǔn)則:產(chǎn)生的結(jié)果必須有n!種可能 。這個(gè)很好解釋,因?yàn)橐粋€(gè)長(zhǎng)度為n的數(shù)組的全排列就有n!種,也就是說打亂結(jié)果總共有n!種。算法必須能夠反映這個(gè)事實(shí),才是正確的。

有了這個(gè)原則再看代碼應(yīng)該就容易理解了:

對(duì)于nums[0],我們把它隨機(jī)換到了索引[0, n)上,共有n種可能性;

對(duì)于nums[1],我們把它隨機(jī)換到了索引[1, n)上,共有n - 1種可能性;

對(duì)于nums[2],我們把它隨機(jī)換到了索引[2, n)上,共有n - 2種可能性;

以此類推,該算法可以生成n!種可能的結(jié)果,所以這個(gè)算法是正確的,能夠保證隨機(jī)性。

水塘抽樣算法

學(xué)會(huì)了洗牌算法,掃雷游戲的地雷隨機(jī)初始化問題就解決了。不過別忘了,洗牌算法只是一個(gè)取巧方案,我們還是得面對(duì)「在若干元素中隨機(jī)選擇k個(gè)元素」這個(gè)終極問題。

要知道洗牌算法能夠生效的前提是你使用數(shù)組這種數(shù)據(jù)結(jié)構(gòu),如果讓你在一條鏈表中隨機(jī)選擇k個(gè)元素,肯定不能再用洗牌算法來蒙混過關(guān)了。

再比如,假設(shè)我們的掃雷游戲中棋盤的長(zhǎng)和寬非常大,已經(jīng)不能在內(nèi)存中裝下一個(gè)大小為m * nboard數(shù)組了,我們只能維護(hù)一個(gè)大小為k的數(shù)組記錄地雷的位置:

class Game {
    // 棋盤的行數(shù)和列數(shù)(非常大)
    int m, n;
    // 長(zhǎng)度為 k 的數(shù)組,記錄 k 個(gè)地雷的一維索引
    int[] mines;

    // 將二維數(shù)組中的坐標(biāo) (x, y) 轉(zhuǎn)化為一維數(shù)組中的索引
    int encode(int x, int y) {
        return x * n + y;
    }

    // 將一維數(shù)組中的索引轉(zhuǎn)化為二維數(shù)組中的坐標(biāo) (x, y)
    int[] decode(int index) {
        return new int[] {index / n, index % n};
    }
}

這樣的話,我們必須想辦法在[0, m*n)中隨機(jī)選取k個(gè)不同的數(shù)字了。

這就是常見的隨機(jī)抽樣場(chǎng)景,常用的解法是水塘抽樣算法(Reservoir Sampling) 。水塘抽樣算法是一種隨機(jī)概率算法,會(huì)者不難,難者不會(huì)。

我第一次見到這個(gè)算法問題是谷歌的一道算法題:給你一個(gè)未知長(zhǎng)度的單鏈表,請(qǐng)你設(shè)計(jì)一個(gè)算法, 只能遍歷一次 ,隨機(jī)地返回鏈表中的一個(gè)節(jié)點(diǎn)。

這里說的隨機(jī)是均勻隨機(jī)(uniform random),也就是說,如果有n個(gè)元素,每個(gè)元素被選中的概率都是1/n,不可以有統(tǒng)計(jì)意義上的偏差。

一般的想法就是,我先遍歷一遍鏈表,得到鏈表的總長(zhǎng)度n,再生成一個(gè)[0,n-1)之間的隨機(jī)數(shù)為索引,然后找到索引對(duì)應(yīng)的節(jié)點(diǎn)。但這不符合只能遍歷一次鏈表的要求。

這個(gè)問題的難點(diǎn)在于隨機(jī)選擇是「動(dòng)態(tài)」的,比如說你現(xiàn)在你已經(jīng)遍歷了 5 個(gè)元素,你已經(jīng)隨機(jī)選取了其中的某個(gè)元素a作為結(jié)果,但是現(xiàn)在再給你一個(gè)新元素b,你應(yīng)該留著a還是將b作為結(jié)果呢?以什么邏輯做出的選擇,才能保證你的選擇方法在概率上是公平的呢?

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 算法
    +關(guān)注

    關(guān)注

    23

    文章

    4695

    瀏覽量

    94576
  • 游戲
    +關(guān)注

    關(guān)注

    2

    文章

    765

    瀏覽量

    26627
收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    簡(jiǎn)述兩種示波器測(cè)量眼圖的差別

    簡(jiǎn)述兩種示波器測(cè)量眼圖的差別 中心議題: 力科示波器進(jìn)行眼圖測(cè)量 新舊款軟件包使用方法不同 力科示波器捕獲了50MS的數(shù)據(jù),并一次性地
    發(fā)表于 04-21 16:52 ?3974次閱讀
    <b class='flag-5'>簡(jiǎn)述</b><b class='flag-5'>兩種</b>示波器測(cè)量眼圖的差別

    電容式感應(yīng)在電玩游戲中的應(yīng)用

    。由于游戲桿具備的卓越模擬功能性,讓其在最新的控制器重現(xiàn)生機(jī)。電容式感測(cè)技術(shù)(電容式觸控感應(yīng))是最新的接口技術(shù),能提高游戲控制器的可用性,以及最炫的機(jī)械設(shè)計(jì)。   電容式感測(cè)技術(shù)概觀   電容式感測(cè)最
    發(fā)表于 09-12 16:43

    兩種典型的ADRC算法介紹

    前言??上篇中詳細(xì)闡述了經(jīng)典的自抗擾控制算法的原理,本篇將圍繞兩種ADRC算法展開,針對(duì)擴(kuò)張狀態(tài)觀測(cè)器的參數(shù)整定問題進(jìn)行詳解,同時(shí),對(duì)跟蹤微分器的幾個(gè)重要應(yīng)用進(jìn)行介紹。兩種典型的ADR
    發(fā)表于 09-07 08:02

    智能插座常用兩種通信協(xié)議是什么?

    智能插座常用兩種通信協(xié)議是什么?
    發(fā)表于 09-26 09:18

    網(wǎng)絡(luò)中常用的隊(duì)列管理方法比較

    本文主要介紹了網(wǎng)絡(luò)中常用兩種隊(duì)列管理方法:先進(jìn)先出(FIFO)和隨機(jī)提前檢測(cè)(RED),并且通過實(shí)驗(yàn)比較了這兩種隊(duì)列管理方法在解決網(wǎng)絡(luò)擁塞控制方面的表現(xiàn),體現(xiàn)了研究
    發(fā)表于 05-25 11:24 ?9次下載

    基于游戲中NPC路徑規(guī)劃的混合算法

    路徑規(guī)劃是游戲人工智能領(lǐng)域的核心問題,如何建立一高效的路徑規(guī)劃方法仍是研究的熱點(diǎn)之一。針對(duì)游戲中NPC的路徑規(guī)劃問題,將A*算法與改進(jìn)的人工勢(shì)場(chǎng)法相結(jié)合,提出了一
    發(fā)表于 11-14 14:55 ?7次下載

    帕塞瓦定理的兩種常見形式

    帕塞瓦定理的兩種常見形式, 在我的《隨機(jī)信號(hào)分析》里面作為附錄4, 即帕塞瓦定理的兩種常見形式, 第三形式即不常用的形式, 明天再給讀者介
    的頭像 發(fā)表于 04-02 11:13 ?1w次閱讀

    Wincc如何與PLC進(jìn)行通訊兩種常用的方式介紹

    西門子WINCC與SiemensPLC通訊連接有多種方式,下面介紹兩種常用的通訊方式。
    的頭像 發(fā)表于 02-17 09:27 ?3.1w次閱讀
    Wincc如何與PLC進(jìn)行通訊<b class='flag-5'>兩種</b><b class='flag-5'>常用</b>的方式介紹

    單片機(jī)常用兩種延時(shí)控制方式

    單片機(jī)中常用的延時(shí)控制方式有兩種。一是采用編程的方式達(dá)到延時(shí)的目的,另一方法則是通過單片機(jī)中的個(gè)定時(shí)器T0和T1進(jìn)行計(jì)時(shí)達(dá)到延時(shí)的目的
    發(fā)表于 07-17 10:22 ?6359次閱讀
    單片機(jī)<b class='flag-5'>常用</b>的<b class='flag-5'>兩種</b>延時(shí)控制方式

    常用的hdl語(yǔ)言有哪兩種

    Verilog HDL和VHDL是目前兩種常用的硬件描述語(yǔ)言,同時(shí)也都是IEEE標(biāo)準(zhǔn)化的HDL語(yǔ)言。
    發(fā)表于 08-25 09:14 ?9555次閱讀

    說透游戲中常用兩種隨機(jī)算法

    這些 2D 游戲相較現(xiàn)在的大型 3D 游戲雖然看起來有些簡(jiǎn)陋,但依然用到很多有趣算法技巧,本文就來深入研究一下地圖的隨機(jī)生成算法
    的頭像 發(fā)表于 11-09 11:17 ?1284次閱讀

    詳解PMSM中常用兩種坐標(biāo)變換

    期介紹了Clarke的Park變化的基本原理,但是經(jīng)過這兩種變換后會(huì)存在兩種系數(shù),相信大家都很迷惑,這是什么原因? 主要原因是存在兩種遵循的方式:1、變換前后電流所產(chǎn)生的旋轉(zhuǎn)磁場(chǎng)等
    的頭像 發(fā)表于 01-19 15:52 ?3082次閱讀
    詳解PMSM<b class='flag-5'>中常用</b>的<b class='flag-5'>兩種</b>坐標(biāo)變換

    簡(jiǎn)述游戲中常用兩種隨機(jī)算法(下)

    沒事兒的時(shí)候我喜歡玩玩那些經(jīng)典的 2D 網(wǎng)頁(yè)小游戲,我發(fā)現(xiàn)很多游戲都要涉及地圖的隨機(jī)生成,比如掃雷游戲中地雷的位置應(yīng)該是隨機(jī)分布的:
    的頭像 發(fā)表于 04-12 11:43 ?902次閱讀
    <b class='flag-5'>簡(jiǎn)述</b><b class='flag-5'>游戲中常用</b>的<b class='flag-5'>兩種</b><b class='flag-5'>隨機(jī)</b><b class='flag-5'>算法</b>(下)

    基于Python實(shí)現(xiàn)隨機(jī)森林算法

    機(jī)器學(xué)習(xí)算法是數(shù)據(jù)挖掘、數(shù)據(jù)能力分析和數(shù)學(xué)建模必不可少的一部分,而隨機(jī)森林算法和決策樹算法是其中較為常用
    的頭像 發(fā)表于 09-21 11:17 ?1530次閱讀
    基于Python實(shí)現(xiàn)<b class='flag-5'>隨機(jī)</b>森林<b class='flag-5'>算法</b>

    PCBA加工中常見的兩種焊接方式詳解

    ,在PCBA行業(yè)中經(jīng)常被使用。接下來深圳PCBA加工廠家為大家詳細(xì)介紹PCBA加工手工焊接的兩種方式,為您揭秘行業(yè)內(nèi)的技術(shù)細(xì)節(jié)。 PCBA加工過程中常用焊接方式 第一方式是傳統(tǒng)手工焊接。這種方式主要依靠技術(shù)工人的手動(dòng)操作進(jìn)行焊
    的頭像 發(fā)表于 06-14 09:18 ?849次閱讀