逆序数-拼图游戏必备知识

近两天准备出个拼图游戏的教程,准备时候遇到一些问题,收集保存分享下来,一来自己用,二来涨点知识,三来有需要的小伙伴刚好也看看。

事情起因很简单,比如下面这个拼图(矩阵):

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,所以放弃。

写业务要注意这种陷进逻辑哈,祝你玩的开心。


喜欢文章的话,请关注一波,定期更新技术文章,满满的都是干货。

原文地址:https://www.cnblogs.com/ZweiZhao/p/9783935.html

时间: 2024-10-17 00:29:48

逆序数-拼图游戏必备知识的相关文章

拼图小游戏的逆序数

逆序数 首先前言:逆序数和拼图有啥关系呢,逆序数是啥 在拼图中,逆序数为偶数,才能拼图成功,奇数是不能成功的!! 逆序数:通过百度查询,得知:一个排序中所有逆序的总数和叫做逆序数; 比如: 4132 > 这是一个4小块的拼图 它这里的倒序有 41,43,42,32 所以这里的逆序数就是4(偶数); 所以,我们只需要关注逆序数就可以,它的前提就是 前面大于后面! let arr3 = []; let a = 0; for(let i = 0;i<this.len;i++){ arr3.push(

拼图游戏中逆序数的实现的三种方式

一.定义 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数.如2431中,21,43,41,31是逆序,逆序数是4. 二.计算方法 逆序数的计算方法主要有直接计算,归并和树状数组三种,下面将一一介绍. 2.1 直接计算 即根据定义用枚举的方法求逆序数.对于数列中的每一个数a[i],遍历数列中的数a[j] (其中j < i),若a[i] < a[j],则逆序数加1,这样就能统计出该数列的逆序数总和. 该方

拼图游戏(数码还原游戏)算法的研究

将问题一般化,在M*N的方格里有M*N-1个不同元素和一个空元素,只有空元素可以与上下左右相邻的元素交换位置.M*N方格中M*N-1个元素和一个空元素的位置确定一个图形.拼图游戏的问题是:一个图形经过一连串的交换能否得到另一个图形,如何得到.从交换方式的可逆性看出这种关系满足等价三性质,如果图形A通过交换变成图形B我们则称它们是等价的.把M*N-1个元素用1至M*N-1编号,空元素编号0.然后展成一个排列.每个图形对应一个排列.确定了展开方式,图形和排列是一一对应的.这里用到的展开方式是行优先的

拼图游戏(数码还原游戏)的实现

一.游戏规则 首先,这里的拼图游戏是滑块拼图,类似于华容道,游戏者通过移动拼图块将拼图还原为初始形状.关于拼图,常见的有3x3,4x4,多的以至于有16x16不等.一般块数越多拼图越复杂. 这里对游戏规则进行较严格的定义: 1. 游戏初始化时,将图形分为nxn个正方形块,随机摆放在原图形位置.一般以原图形右下角的一块为空白块,已进行移动.这里初始化时,也令新图形的右下角为空. 2. 游戏中,拼图的移动只能向空白块移动.从移动方向来说,有两种情况,分别是横移与纵移. 3. 游戏的胜利条件是将打乱的

拼图游戏的数学原理

一.线性代数基础知识 1.逆序的定义: 逆序是一个与排列相关的概念.        由自然数1,2-,n组成的不重复的每一种有确定次序的排列,称为一个n级排列(简称为排列):或者一般的,n个互不同元素排成一列称为"一个n级排列".例如,1234和4312都是4级排列,而24315是一个5级排列.        在一个n级排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个"逆序". 一个排列中逆序的总数就称为这个排列的逆序数. 逆序

NYOJ-求逆序数 ----------------待解决,WA

描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 现在,给你一个N个元素的序列,请你判断出它的逆序数是多少. 比如 1 3 2 的逆序数就是1. 输入 第一行输入一个整数T表示测试数据的组数(1<=T<=5)每组测试数据的每一行是一个整数N表示数列中共有N个元素(2〈=N〈=1000000)随后的一行共有N个整数Ai(0<=Ai<1000000000),表示数列中的所有元素. 数据保

拼图游戏---需求分析

各位领导/投资人/用户/合作伙伴:我们的产品--趣拼图是为了游戏中的暴力因素以及无聊.,我们有独特的办法制作一个游戏,它能给用户带来更多好处,比如生活知识的普及,智力的开发等,同时我们有更高效率的一传十,十传百的方法,能让更多用户知道我们的产品,并进一步的传播. 在经过众多假设以及实践,我们组决定做一个开发智力的拼图游戏.我发现现在大多数游戏都是按部就班,玩家需要按照游戏制定的规则来活动,那这样,游戏除了娱乐也就没有其他的意义.经过调查,发现现在人,喜欢玩一些格斗[比如拳皇].跑酷[比如神庙逃亡

atitit.html5 拼图游戏的解决之道.

atitit.html5 拼图游戏的解决之道. 1. 拼图游戏的操作(点击法and 拖动法) 1 1. 支持键盘上.下.左.右键移动: 1 2. 支持点击空白模块中的上下左右箭头移动: 1 3. 支持点击空白模块的临近模块移动. 1 4. 还是点击法好,兼容性好...手机and电脑 1 2. 注释:无解的问题(逆序和判别法) 2 5. 3*3的大概50%无解 2 6. Grid 旋转的问题.. 2 7. 要应用测试成功的api 2 8. 测试图片数字化,为轻松的测试.. 2 3. 能使用的 2

拼图游戏-从基础到应用玩转手势变化。

小方块相关的类 主界面的布局 打开图片选择图片 拼图的各个小方块的形成过程 小方块的点击事件和手势判断过程 游戏开始打乱方块以及游戏结束时弹出Toast提示的方法 相信大家在小的时候都玩过拼图游戏,现如今,手机普及,能在手机上玩的游戏越来越多,于是乎,重温小时候,编写这个简易拼图游戏,而且也能进一步加深android的一些基础知识. 老规矩,先是效果图~: 这里我把为了演示效果,把图片打乱的很少,在代码里可以更改. 首先,有个默认的图片,可以用来拼图,也可以选择你喜欢的图片进行拼图,拼图的过程会