1. 程式人生 > >逆序數-拼圖遊戲必備知識

逆序數-拼圖遊戲必備知識

要去 排列 工程 基礎 就是 基準 所在 拼圖遊戲 但是

近兩天準備出個拼圖遊戲的教程,準備時候遇到一些問題,收集保存分享下來,一來自己用,二來漲點知識,三來有需要的小夥伴剛好也看看。

事情起因很簡單,比如下面這個拼圖(矩陣):

1 2

3 空

這樣一個2*2矩陣,是標準原始矩陣,但是變一下:

3 1

2 空

這樣是可還原的(空和附近的可以換位置,空2,空3,空1,空2即可)。

但下面這個呢?

1 3

2 空

你還能還原嗎?

這個不是怪你,是真的沒法還原。

當時腦子裏面過了一下,就發現不行,然後查了查資料,真的有前輩搞過相關的問題,並且有了靠譜的答案。

假如兩個矩陣,從左到右,從上到下排序,兩個矩陣的逆序數+空所在行+空所在列數的值的奇偶性相同,則可以還原或者說等價;若不同,那就無法還原。

又上面說的問題,嘗試去玩了幾個拼圖遊戲,發現這些家夥都是雞賊,各個塊可以直接點擊與任意位置的互換,那就不存在無解的問題了啊……

問題是,這樣遊戲本身的難度就幾乎沒了,遊戲性簡直不能看……

哦,對了,忘了說啥是“逆序數”,逆序數解釋如下:

比如1234排列是基準,然後兩個排序分別是4321、3214。

逆序數說的是在原有排序基礎上,在新排列出現與基礎排序順序前後順序不同則算一個逆序數。

那麽分析那4321。43、42、41三個,32、31兩個,21一個,所以逆序數是1 + 2 + 3 = 6個;而3214,31、32兩個,21一個,所以逆序數是2 + 1 = 3個。1234為基準,即0個。所以4321與1234是等價的,可解;3214與1234不等價,不可解。

那最上面的對比,123是基準,312逆序數為2,132逆序數為1,所以132不可解。

算起來很復雜,但是通過雙層循環來處理,只要不是太多的數字都還可以接受,畢竟是給人玩得遊戲,就算10*10的矩陣,時間復雜度頂天了也就O^2,優化成OlgO也不是不行,所以還是可以搞搞的。

具體算法代碼如下:

// 基準就是自然排序,遞增是正常的,就是後面一定比前面的都大。

const cal = num => {
  let arr
  if(typeof num === ‘number‘) {
    let strs = String(num)
    arr = Array.from(strs, str => Number(str) || 0) // 安全處理,轉換錯誤給0
  } else arr = num
  let length = arr.length
  let reverse = 0

  for(let i = 0; i < length - 1; i++) {
    let n = arr[i]
    for(let j = i + 1; j < length; j++) {
      let m = arr[j]
      if(n > m) reverse += 1
    }
  }

  console.log(reverse)
}

cal(4321) // 6
cal(3214) // 3
cal(312) // 2
cal(132) // 1

cal(54321) // 10
cal([10, 14, 21, 7, 3, 12, 0]) // 15

這樣就好了,下次要寫拼圖遊戲時候,只要去專註業務邏輯就行,遊戲初始化的問題就用這個代碼拓展即可。

還有一種方法就是初始化的時候按照標準序模擬合法移動N次,然後在逆向工程即可。但是這個方案拓展性幾乎為0,所以放棄。

寫業務要註意這種陷進邏輯哈,祝你玩的開心。


喜歡文章的話,請關註一波,定期更新技術文章,滿滿的都是幹貨。

逆序數-拼圖遊戲必備知識