整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

H5数独游戏开发-按钮控件的实现

H5数独游戏开发-按钮控件的实现

 游戏中的按钮不难实现,但是如何实现按钮点击后的状态改变效果呢?例如:点击游戏中的一个按钮后,按钮凹陷下去,隔了简短的时间间隔后,按钮又弹起来,恢复原来的状态。这节课我们来实现按钮的这种效果,我们在游戏资源加载完毕后,资源进度条显示100%后,在资源进度条下面显示一个按钮,点击这个按钮后,进入游戏,显示游戏主面板。效果如下图所示

  我们来看看游戏代码需要做哪些调整,由于资源加载完毕后并不自动切换到游戏主面板,也就是说资源加载完毕后需要显示资源加载进度条,所以,游戏的状态变量值需要变更,修改如下

  既然游戏状态变量值更改了,那么,很自然,依赖此值绘制游戏场景的代码也需要做相应的调整,修改后的代码如下:

  上节课将消息处理代码handleMessage()放在了drawScene()函数里,严格意义上来说,每一个函数的功能是单一的,所以,这节课将消息处理代码放在html页面里的runGame()函数中,代码如下:

  接着就是今天的主角,游戏按钮类,先看看它的定义

  其中成员变量bDone表示按钮状态是否变更完成;成员变量nState表示按钮当前的状态;成员变量dbClickTime保存按钮按下的时间,将当前时间与此成员变量比较,如超过某一固定时间间隔值,则修改按钮的状态;成员变量fCB保存按钮的回调函数,即点击按钮后将执行此函数,将按钮要实现的功能放在此回调函数中。下面是对相应成员变量操作的函数

  我们接着看看初始化按钮参数的函数代码

  由于点击资源加载进度条下面的按钮后,游戏场景会切换到游戏主面板,所以需要给按钮的回调函数增加相应代码来实现此功能,我将回调函数的代码写在了g_aControlPara参数初始化数组里,代码如下

  此外,我对消息的处理方式进行了调整,如果一条消息已经处理了,那么后续控件将不会再对此消息进行处理,代码如下

  接下来,是三个关键的成员函数,由于我们修改了参数初始化数组变量,所以控件的初始化成员函数需要修改

  因为控件状态变更涉及多个图片,所以需要判断o.name是否是数组对象(保存多个状态使用的图片名称),是的话依次初始化每个图片对象;然后,控件的绘制成员函数需要修改

  需要根据控件当前状态使用相应的图片绘制控件,同时需要变更控件状态并判断状态变更是否完成;最后,控件的消息处理成员函数需要修改,代码如下

  由于涉及控件状态变更,所以需要判断状态变更是否未开始,是的话将状态变更设为开始,同时保存状态变更开始的时间,接着判断状态变更是否完成,是的话将调用控件的回调函数,即实现控件点击后的功能,同时将消息标记为已处理,防止重复处理。最后,将今天的内容录了一个视频,文章未提到的地方可以参看视频。

H5数独游戏开发——按钮控件的实现

  未完待续,敬请关注!后续更精彩,谢谢大家!

数独(及其前身)已经出现了一百多年。当它第一次出现时,人们实际上只能咬着笔抓着头发来解决数独题目。但现在我们有了强大的电脑!(现在的人就能在手机和电脑上做数独题啦!)

在这篇文章中,你会学到如何摇身一变,成为一名数独大师,在几秒钟时间内就能解出一般人要花几小时才能解出的难题。当然,更重要的是,你会一步步的学习如何使用机器学习(Machine Learning)轻松解决每个数独。设想一下,如果有计算机来做数独,谁还需要思考呢,当然,多做数独还是真的可以健脑的。(我没有开挂做数独啊,不要抓我)

我没有开挂

Peter Norvig最先使用Python开发了一个优雅的程序,通过约束网格传播和搜索以此来解出数独。Norvig的解决方案被认为是目前十分经典的一个解决数独的方案,当人们通过编程来解数独时经常被引用。在回顾数独和一些策略之后,本文将逐步分解Norvig的代码,以便你能真正了解它的工作方式。

什么是数独?

数独是源自于18世纪瑞士的一种数学游戏。是一种传统的运用纸、笔进行演算的逻辑游戏。人们需要根据9×9的盘面上的已知数字,一一推理出所有剩余空格的数字,并满足每一行、每一列、每一个九宫格(3*3)内的数字均含1-9,不重复

数独

如图,突出显示在蓝色正方形中的数字不能在与同列同行和宫相对应的任何黄色正方形中重复

如何解数独?

其实一般做数独题的时候,只需要不断做两件事就OK了。要做的第一件事是就是排除行,列和宫中的已知数字。您要做的第二件事就是寻找一个可能填写的候选数。

在下面给出的示例中,每个正方形中的可能填写的数字以较小的字体标注。通过排除出现在同一列,行或宫中的已经重复的数字来确定剩下可能的数字。大多数人仅仅只会一次确定一个宫的可能数量,而不是直接确定整个网格中所有能填写的数字(暗数、候选数)。

所有可能填写的数字

进行排除操作后,你可以寻找仅剩余一种情况的格子。在下面的示例中,两个黄色突出显示的正方形必须包含18,因为其他所有的可能性已被排除,它们填在别的格子中会出现重复。

黄色的格子中只能填一种情况

现在已知以黄色突出显示的两个格子,这又排除了其他格子的更多可能性。现在我们可以知道以蓝色突出显示的格子必须填7。

更多的可能性被排除了

如果你继续不断的按照此法进行排除和确定,最终可能会达到能够完全确定某个3*3的格子或行或列的情况。

一个九宫格被完全约束了

在下面的示例中,我们可以确定以蓝色突出显示的格子的解必须为6,因为数字6不可能出现在黄色宫中的其他任何的格子中。

继续确定格子中的数字

有时,我们在求解的时候可能会遇到这种情况,似乎每个未解决的3*3的格子中有多个可能的值。这意味着我们可以选择多种路径,但至于哪条路才能最终得到结果就不知道了。

在这个选择上,我们必须尝试每个选项。选择一条路并继续求解,直到按这条路走下去最后只能得到“此路不通”的答案。然后,将不得不回溯到分歧点并尝试其它的路。

但是我们可以使用二叉搜索树在计算机上轻松完成此类检索。当有两个不同的数字都可以作为一个3*3的格子的答案时,我们可以尝试引入两种不同的可能性。二叉搜索树将使算法沿选择的一个分支下降,然后尝试不同的选择。

二叉搜索树

现在,我们将了解用上述方法相似的思路来编写的Python代码,以此用来处理数独问题。

Peter Norvig的解数独代码

Peter Norvig在他的解决数独难题的文章中解释了做数独题的方法与他所使用的代码。

www.norvig.com/sudoku.html

有些人可能理解他的解释有些困难,尤其是初学者。本文将分解这些内容,以便让你更轻松地了解Peter Norvig的代码是如何工作的。

在本文中,Peter Norvig的代码已经更新为Python3,以方便的在目前的环境下运行

首先,我们将介绍基本的设置和表示法。Norvig描述了他在代码中所使用的基本符号:

数独拼图是一个由81个方格组成网格;广大爱好者把列1-9、行a-i记为行列标记,把9个方格(列、行或宫)的集合称为一个单位,把共享一个单位的方格称为对等方

这是数独中每个格子的名称:

格子的名称

Norvig将数字,行和列定义为字符串:

digits='123456789'
rows='ABCDEFGHI'
cols=digits

你可能会注意到将cols其设置为与digits相等。尽管它们具有相同的值,但它们表示不同的事物。该digits变量表示走在数独上解决这一难题的数字。而cols变量代表网格的列名。

整个数独盘也被定义为字符串,但是这些字符串是通过以下函数创建的:

def cross(A, B):
 "a中元素与b中元素的叉积。"
 return [a+b for a in A for b in B]
squares=cross(rows, cols)

cross函数([a+b for a in A for b in B])的返回部分只是编写这个代码的一种优秀解决方案:

squares=[]
for a in rows:
 for b in cols:
 squares.append(a+b)

运行此函数后,变量等于所有小方格名称的列表。

['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'E1', 'E2', 'E3', 'E4', 'E5', 'E6', 'E7', 'E8', 'E9', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8', 'G9', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7', 'H8', 'H9', 'I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8', 'I9']

而网格中的每个小格子都有3个单位和20个对等方。小格子的单位是显示在其中的行,列和九宫格。小格子的对等方是单位中的所有其他小格子。例如,以下是小格子C2中的单位和对等方:

单位与对等方

使用cross函数创建每个小格子的所有单位:

unitlist=([cross(rows, c) for c in cols] +
 [cross(r, cols) for r in rows] +
 [cross(rs, cs) for rs in ('ABC','DEF','GHI') for cs in ('123','456','789')])

在Python中,字典是键值对的集合。使用以下代码行创建字典,字典使用小格子的名称作为键,并使用三个单位或20个对等体作为值。

units=dict((s, [u for u in unitlist if s in u]) 
 for s in squares)
peers=dict((s, set(sum(units[s],[]))-set([s]))
 for s in squares)

现在,可以使用来访问“ C2”的所有3个单位,units['C2']并将得到以下结果:

测试结果

接下来,我们需要完整的数独网格的两种表示形式。名为grid的文本将是数独的初始状态。

还需要网格的另一种表示形式来描述数独解题的当前状态。它将跟踪每个格子的所有剩余可能值并命名为values。

与units和peers类似,values将是一个以小格子为键的字典。每个键的值将是一串数字,该串数字是该小格子内的所有可能数字。如果数字是在拼图中给出的或已被找出,则vaules中将只有一位数字。例如,如果存在一个网格,其中A1为6而A2为空,则values的值可能是这样{'A1': '6', 'A2': '123456789', ...}。

解析网格和网格值函数

parse_grid函数(下面的代码)可将网格转换为可能值的字典。grid是给定的数独题目。grid_values函数用来提取数字,0和“.”的重要值。在values字典中,正方形是键,而网格中的给定数字是值。

对于具有给定值的每个格,assign函数用于将值分配给方框并从对等方排除该值。assign函数将在下文介绍。如果发生任何错误,该函数将返回False。

这是parse_gridgrid_values函数的代码。

def parse_grid(grid):
 """将网格转换为可能值的dict,{square:digits},如果检测到错误,则返回false"""
 ## 首先,每个小格子可以是任意数字;然后从网格中赋值。
 values=dict((s, digits) for s in squares)
 for s,d in grid_values(grid).items():
 if d in digits and not assign(values, s, d):
 return False ## (如果我们不能把d赋给格子s,则失败。)
 return values
def grid_values(grid):
 "将网格转换为{square:char}的dict,并用'0'或'.'表示清空。"
 chars=[c for c in grid if c in digits or c in '0.']
 assert len(chars)==81
 return dict(zip(squares, chars))

约束传播(Constraint propagation)

每个方格的初始值将是特定数字(1-9)或为空值。我们可以将约束应用于每个小格子并排除不可能的值。

Norvig使用以下两种策略来帮助确定平方的正确值(与上述策略相对应):

(1)如果一个方格只有一个可能的值,则从该正方形的对等方中排除该值。

(2)如果一个单位只有一个可能的位置放一个值,则将值放在那里。

第一种策略的示例是:如果我们知道A1的值为5,则可以从其所有20个对等方中删除5个。

第二种策略的示例是:如果可以确定A1到A8都不包含9作为可能的值,那么我们可以确定A9的值为9,因为9必须出现在单位中的某个位置。

每次更新网格时,都会导致其所有对等方的可能更新。此过程将连续不断的进行,称为约束传播

分配功能

assign(values, s, d)函数在parse_grid函数内部被调用。它返回更新的值。它接受三个参数:values,s和d。

请记住,values是一个字典,它将每个格子与该格子的所有可能的数字值相关联。s是我们要为其分配值的格子,d是需要分配给该格子的值。D才是我们首先要解决的给定的难题。

它调用函数eliminate(values, s, d)以排除S中除D之外的所有值。

如果存在矛盾,例如两个正方形被分配了相同的数字,则排除函数将返回False。

def assign(values, s, d):
 """从值[s]中排除所有其他值(d除外)并传播。如果存在矛盾,则本函数将返回False。"""
 other_values=values[s].replace(d, '')
 if all(eliminate(values, s, d2) for d2 in other_values):
 return values
 else:
 return False

消除功能

我们看到assign函数调用了eliminate函数。消除函数的调用如下:eliminate(values, s, d2) for d2 in other_values)

eliminate函数将排除使用上述两种策略无法解决的值。第一种策略是,当仅存在一个潜在值s时,该值将从s的对等方中删除。第二种策略是,当值只能存在一个位置时,该值d将从所有对等方中删除。

这是它的全部功能:

def eliminate(values, s, d):
 """从值[s]中删除d;当值或位置<=2时传播。如果存在矛盾,则本函数将返回False。"""
 if d not in values[s]:
 return values ## 已被排除
 values[s]=values[s].replace(d,'')
 ## (1)如果方格s减去一个值d2,则从对等点中消除d2。
 if len(values[s])==0:
 return False ## 矛盾:去掉最后一个值
 elif len(values[s])==1:
 d2=values[s]
 if not all(eliminate(values, s2, d2) for s2 in peers[s]):
 return False
 ##(2)如果一个单位u的值d减少到只剩一个地方,那么就不动它。
 for u in units[s]:
 dplaces=[s for s in u if d in values[s]]
 if len(dplaces)==0:
 return False ## 矛盾:没有这个值的地方
 elif len(dplaces)==1:
 #d只能在一个单元中的其中一个位置;将它分配到那里
 if not assign(values, dplaces[0], d):
 return False
 return values

显示功能

display函数将在调用后显示结果parse_grid

def display(values):
 "将这些值显示为二维网格。"
 width=1+max(len(values[s]) for s in squares)
 line='+'.join(['-'*(width*3)]*3)
 for r in rows:
 print(''.join(values[r+c].center(width)+('|' if c in '36' else '') for c in cols))
 if r in 'CF': 
 print(line)
 print()

这是一个示例,它在解析一个网格之后调用显示函数后,显示的网格依然是个候选数的集合

示例

您会注意到,许多格具有多个候选数,而有些则完全解决了。上面的网格是上面两种策略死记硬背应用的结果。但是正如你所看到的,仅凭这些策略还不足以完全解决数独。

搜索(Search)

解决数独问题的??方法有很多,但有些方法效率更高。Norvig建议使用一种特定类型的搜索算法。

搜索算法可以做这些事情。首先,它可以确保还没有找到解决方案。然后,它选择一个未填充的正方形,并考虑所有可能的值。最后,它一次一次尝试为格子分配每个值,然后从结果位置再次进行搜索。

可变顺序用于选择要开始搜索的格子。这是Norvig的描述方式:

我们将使用一种称为最小剩余值的通用启发式方法,这意味着我们将选择具有最小可能值数量的格子(或其中之一)。为什么?考虑上面的grid。假设我们首先选择了B3。它有7种可能性(1256789),因此我们期望以6/7的概率猜测错误。如果取而代之,我们选择G2,它只有2种可能性(89),那么我们期望错的概率只有1/2。因此,我们选择可能性最小,直接得到正确答案的期望也就越大。

这些数值按自然数顺序排列。

这是本search函数以及solve解析初始网格并调用的函数search

def solve(grid): return search(parse_grid(grid))
def search(values):
 "使用深度优先搜索和传播,尝试所有可能的值。"
 if values is False:
 return False ## 失败了
 if all(len(values[s])==1 for s in squares): 
 return values ## 解出来辣!
 ## 选择可能性最小的未填充正方形
 n,s=min((len(values[s]), s) for s in squares if len(values[s]) > 1)
 return some(search(assign(values.copy(), s, d)) 
 for d in values[s])

根据数独的规则,当每个格子只有一个值时, 问 题 就解决了。该search函数将递归调用,直到解决难题为止。它通过values复制以避免复杂。

some是用于检查尝试是否成功解决难题的函数。

def some(seq):
 "返回seq的某个元素,该元素为true。"
 for e in seq:
 if e: return e
 return False

完整代码(在Python3.x下测试通过)

这些代码组合起来将会让你变成数独大师,以下给出完整代码。

def cross(A, B):
 "a中元素与b中元素的叉积。"
 return [a+b for a in A for b in B]
digits='123456789'
rows='ABCDEFGHI'
cols=digits
squares=cross(rows, cols)
unitlist=([cross(rows, c) for c in cols] +
 [cross(r, cols) for r in rows] +
 [cross(rs, cs) for rs in ('ABC','DEF','GHI') for cs in ('123','456','789')])
units=dict((s, [u for u in unitlist if s in u])
 for s in squares)
peers=dict((s, set(sum(units[s],[]))-set([s]))
 for s in squares)
def parse_grid(grid):
 """将网格转换为可能值的dict,{square:digits},如果检测到错误,则返回false"""
 ## 首先,每个小格子可以是任意数字;然后从网格中赋值。
 values=dict((s, digits) for s in squares)
 for s,d in grid_values(grid).items():
 if d in digits and not assign(values, s, d):
 return False ## (如果我们不能把d赋给格子s,则失败。)
 return values
def grid_values(grid):
 "将网格转换为{square:char}的dict,并用'0'或'.'表示清空。"
 chars=[c for c in grid if c in digits or c in '0.']
 assert len(chars)==81
 return dict(zip(squares, chars))
def assign(values, s, d):
 """从值[s]中排除所有其他值(d除外)并传播。如果存在矛盾,则本函数将返回False。"""
 other_values=values[s].replace(d, '')
 if all(eliminate(values, s, d2) for d2 in other_values):
 return values
 else:
 return False
def eliminate(values, s, d):
 """从值[s]中删除d;当值或位置<=2时传播。如果存在矛盾,则本函数将返回False。"""
 if d not in values[s]:
 return values ## ## 已被排除
 values[s]=values[s].replace(d,'')
## (1)如果方格s减去一个值d2,则从对等点中消除d2。
 if len(values[s])==0:
 return False ## 矛盾:去掉最后一个值
 elif len(values[s])==1:
 d2=values[s]
 if not all(eliminate(values, s2, d2) for s2 in peers[s]):
 return False
 ##(2)如果一个单位u的值d减少到只剩一个地方,那么就不动它。
 for u in units[s]:
 dplaces=[s for s in u if d in values[s]]
 if len(dplaces)==0:
 return False ## 矛盾:没有这个值的地方
 elif len(dplaces)==1:
 #d只能在一个单元中的其中一个位置;将它分配到那里
 if not assign(values, dplaces[0], d):
 return False
 return values
def solve(grid): return search(parse_grid(grid))
def search(values):
 "使用深度优先搜索和传播,尝试所有可能的值。"
 if values is False:
 return False ## 已False
 if all(len(values[s])==1 for s in squares):
 return values ## 解出来拉!
 ## 以最少的可能性选择未填充的正方形
 n,s=min((len(values[s]), s) for s in squares if len(values[s]) > 1)
 return some(search(assign(values.copy(), s, d))
 for d in values[s])
def display(values):
 "Display these values as a 2-D grid."
 width=1+max(len(values[s]) for s in squares)
 line='+'.join(['-'*(width*3)]*3)
 for r in rows:
 print(''.join(values[r+c].center(width)+('|' if c in '36' else '') for c in cols))
 if r in 'CF':
 print(line)
 print()
def some(seq):
 "返回seq的某个元素,该元素为true。"
 for e in seq:
 if e: return e
 return False

调试

测试用Grid数独题,同时它也是一个最小数独(供读者自己测试python时调试用):

grid='4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......'

测试结果如图

苦逼作者码字不易,各位看官老爷们给个关注吧!

寻找非周期性平铺方案和相关瓷砖的过程,如同打碎一个花瓶然后再复原它。不过,研究者希望花瓶碎裂后形成的是均匀的碎片,且破碎的纹理是“非周期性的”。这样的瓷砖即使铺满全世界,拼接图案也不会重复。

能否寻找到一块这样的瓷砖,即使用它铺满全世界,其拼接图案也永不重复?

近日,数学界的“莫扎特”、华裔数学家、菲尔兹奖得主、美国加州大学洛杉矶分校数学系教授陶哲轩(Terence Tao)在个人博客上宣布,推翻了“周期性平铺猜想”。

他们在超高维空间中找到一块这样的“瓷砖”。

预印本网站arXiv显示,陶哲轩与合作者合著的相关论文于2022年11月29日凌晨上传。

但实际上,陶哲轩提前了两个多月就在其博客上宣布了上述消息;并在9月18日凌晨,他们向arXiv网站提交了一篇缩略的“公告”论文——announcement,全文共13页。

而完整版论文共48页。论文标题是《周期性平铺猜想的一个反例》(A counterexample to the periodic tiling conjecture)。

该论文的合著者是原美国加州大学洛杉矶分校数学系Hedrick助理教授、现美国普林斯顿高等研究院数学学院成员雷切尔·格林菲尔德(Rachel Greenfeld)。她是陶哲轩的博士后。

诺贝尔奖和永不重复的拼图

什么是周期性平铺猜想?

设想用相同大小的正方形瓷砖,去铺满一个方方正正房间的地面,这似乎难度不大。人们只要像“复制黏贴”一样,不留空隙地将一块块大小合适的瓷砖平铺下去就行。在这样的地板上,图案的周期性显而易见:如果你将部分图案平移到另一个位置,就跟没有移动过一样。

这或许是最容易的“施工方案”之一,被称为周期性平铺。

周期性平铺和非周期性平铺产生的不同效果。截图来自《Aperiodic Texture Mapping》

六年前,2016年2月18日,来自印度孟买塔塔基础研究所数学院的数学家悉达多·巴塔查里亚(Siddhartha Bhattacharya)在arXiv网站上传预印本论文“Periodicity and decidability of tilings of ?^2”,宣布其在二维平面上证明了“周期平铺猜想”——通过平移,单个瓷砖在平面上只能进行周期性平铺,无法进行非周期性平铺。

数学家们推测,在二维以上更高维度上,也不存在用同一种就实现非周期性平铺的瓷砖。这一假设被称为“周期性平铺猜想”。

换句话说,“周期性平铺猜想”断言,如果只能以平移的方式平铺或填充,那么在任意维度上(二维及以上),不存在一块能以非周期性的方式铺满整个表面或填充整个空间的特殊瓷砖。即使设计出来这样一块瓷砖,那么它也只能以周期性的方式平铺或填满相应的空间。

但“周期性平铺猜想”似乎只在二维平面上成立。

彭罗斯瓷砖样式之一。截图自Eureka 39(1978) 16-32

早在六十年前,1960年左右,在牛津大学任教的华裔数学家王浩在对美国新泽西州的贝尔电话实验室进行学术访问期间,研究了周期性平铺问题,并提出“王砖”(或王氏砖、王浩瓷砖,aka Wang squares)模型。

部分王浩瓷砖。来自Parcly Taxel

四年后,一种似乎更高级的方案出现了:非周期性平铺。它虽然也是很多块瓷砖拼接在一起,密密麻麻地铺满整个地板,但其拼接的图案永不重复,即使铺满整个世界也不重复。1964年,王浩的学生Robert Berger提出最早的非周期性平铺方案,需要20426块瓷砖组合。

用“王砖”进行的一种非周期性平铺。来自Claudio Rocchini

随后,英国数学物理学家、牛津大学数学系名誉教授罗杰·彭罗斯(Roger Penrose)把需要的瓷砖组合减少到5种,最后只用2种形状的瓷砖组合,比如一大一小两个菱形,就可以在二维平面上实现非周期性平铺。这种瓷砖被称为彭罗斯瓷砖。它成为数学艺术的象征之一,被铺在牛津大学数学系等知名大学相关建筑物的地板上。相关平铺样式被称为彭罗斯平铺,或彭罗斯镶嵌、彭罗斯密铺、彭罗斯拼图、彭罗斯几何拼图等。

平面上的非周期图案具有一个奇特的性质,排布位置的信息似乎能够通过某种方式跨过很大距离进行传递,防止数百(甚至数千、数百万)块之外的瓷砖出现某种排列类型。阿肯色大学助理教授埃蒙德·哈里斯(Edmund Harriss)的博士论文主题就是彭罗斯贴砖。他说:“局部约束鬼使神差地拓展为全局约束。”

而彭罗斯瓷砖不只在数学界很有名,在建筑装潢领域甚至材料科学领域也成功圈粉,给人们带来新的启示。

彭罗斯瓷砖或拼图的样式之一。来自Taktaal

1982年,在美国正进行学术休假的以色列材料科学家丹·谢特曼(Dan Shechtman),在实验室里观察到合金的奇特衍射图样,不符合此前人们关于晶体的印象,缺乏标准的对称。它们原子排列的样子,跟彭罗斯地砖拼接的图案一样,是非重复、非周期性的。他后来称之为“准晶体”(quasicrystal)。

丹·谢特曼拍摄到的电子衍射图片。截图自Phys. Rev. Lett. Vol. 53(20),1984

丹·谢特曼的论文和他的发现引起了极大的争议和攻击。直到20多年后,2011年,他因“发现准晶体”,被授予诺贝尔化学奖。

准晶体的电子衍射图片。来自nobelprize.org

此外,彭罗斯也是诺贝尔奖得主之一。

1965年1月18日,彭罗斯在《物理评论快报》(Physical Review Letters)发表论文,阐述了彭罗斯奇点定理。斯蒂芬·霍金(Stephen Hawking)与彭罗斯一起研究奇点后,以彭罗斯定理颠覆了有关宇宙起源的理论。奇点后来被人们熟知,称为“黑洞”。

2020年,89岁的彭罗斯被授予诺贝尔物理学奖,表彰他“发现黑洞的形成是对广义相对论的有力预测”。他独享一半奖金,与“在银河系的中心发现了一个超大质量致密天体”的德国科学家赖因哈德·根策尔(Reinhard Genzel)和美国科学家安德烈娅·盖兹(Andrea Ghez)分享了2020年的诺贝尔物理学奖。

但问题是,一直没人用一块瓷砖完成非周期平铺“游戏”。直到最近,陶哲轩和合作者在超高维空间找到一块这样奇特的“瓷砖”。

用数独、俄罗斯方块游戏寻找一个反例

寻找非周期性平铺方案和相关瓷砖的过程,如同打碎一个花瓶然后再复原它。不过,研究者希望花瓶碎裂后形成的是均匀的碎片,且破碎的纹理是“非周期性的”。

从在二维平面“拼图”到更高维空间里“堆积木”,陶哲轩希望找到一块能够实现非周期性地堆叠的单一“瓷砖”。

立方形密铺。来自Tomruen

在解释其最新证明策略和方法的博客文章中,陶哲轩提到数独和俄罗斯方块游戏,还有电脑编程。

在印度数学家悉达多·巴塔查里亚证明“周期平铺猜想”在二维平面上成立三年后,2019年,格林菲尔德以博士后身份来到加州大学洛杉矶分校。随后,她和陶哲轩用不同于悉达多·巴塔查里亚的另一种方法,再次证明了二维平面中的“周期平铺猜想”。但是,当他们想推进到在三维空间中也证明这一猜想时,碰壁了。

陶哲轩说,无法在更高维度上证明这个猜想成立也许是有原因的,应该开始寻找反例。

2021年8月,他们第一次接近目标:他们在超高维空间找到了两块可以实现非周期性填充的瓷砖,但不是一块。

2021年8月17日,格林菲尔德在arXiv网站上传她和陶哲轩共同署名的论文,标题是“Undecidable translational tilings with only two tiles, or one nonabelian tile”。六天后,她上传了更新版。

“2非常接近了,但还不够。” 格林菲尔德说。

像“俄罗斯方块游戏”一样消行。截图自陶哲轩2022年9月19日的博客文章

2022年9月19日,陶哲轩在其博客文章中表示,“格林菲尔德和我刚刚将我们的公告——‘周期性平铺猜想的反例’上传到 arXiv。这是我们目前正在撰写(并希望在几周内发布)的一篇更长的论文的公告。其中,我们推翻了 Grünbaum-Shephard 和 Lagarias-Wang 的周期性平铺猜想。”

在上述博客文章中,陶哲轩写道,他们创建了一种“平铺语言”(“tiling language”),使用平铺方程组来描述非周期函数。“这个证明,让人强烈地联想到解决数独谜题所需的推理类型,因此,我们在论点中采用了一些类似数独的术语来提供直觉和视觉效果。一个关键步骤是,对拼图进行剪切变换……然后执行消除常量行的‘俄罗斯方块’移动以得出次级数独谜题,然后依次分析该谜题。正是这个过程的迭代最终生成了非周期性p-adic结构。”

在其两个月后、11月29日的博客文章中,陶哲轩写道:“格林菲尔德和我刚刚将论文上传到 arXiv。这是我几个月前在这个博客上公布的结果的完整版本……这篇论文完成的时间比预期的要长一些,这是由于我们在发布公告时没有意识到的一个技术问题需要个解决方法。”

陶哲轩进一步解释说,如公告中所述,最初的策略是构建一种“平铺语言”——一种能够用来编码“P进数数独谜题”(P-adic Sudoku puzzle)的语言;然后证明如果P是一个足够大的素数,那么后一种类型的谜题只有非周期性的解决方案。“事实证明,该策略的后半部分成功了。”“在编程过程中,我们还发现,一旦引入‘可表达属性’和‘弱表达属性’两个新定义,证明的编码部分将变得更加模块化和概念化。”

陶哲轩和格林菲尔德将他们的方程式系统看作一个计算机程序:每一行代码或方程式都是一个命令,这些命令组合起来可以生成一个实现特定目标的程序。

最终,他们在一个非常高维度的空间中,尚未被详细计算,但大约2^100^100维里,找到一块目标“瓷砖”——一块非常复杂、弯弯曲曲、充满孔洞的“瓷砖”。

此外,陶哲轩表示,使用他们最新创造的“语言”应该能创造一个无法判定的谜题。“(比如)可能存在一些瓷砖,我们永远也无法证明,它是否能铺满它所在的空间。”

既无法证明也无法反驳,数学中充满了这样的“不可判定”(undecidable)的陈述。为了证明一个陈述是不可判定的,数学家通常证明它等价于另一个已知不可判定的问题。所以,如果平铺问题被证明是不可判定的,它将可以作为新工具,证明更多其他问题的不可判定性。

格林菲尔德的简历显示,其研究课题“平移平铺和正交系统指数”(translational tiling and orthogonal systems exponentials)获得了美国国家科学基金会(NSF)11.7056万的资助,编号是DMS-2242871,资助期限是2022年到2025年。

参考资料:

1.https://www.quantamagazine.org/nasty-geometry-breaks-decades-old-tiling-conjecture-20221215/#newsletter

2.https://nautil.us/impossible-cookware-and-other-triumphs-of-the-penrose-tile-rp-234895/?_sp=1048d065-5002-434f-85c5-fa868cbccae2.1671370700212

3.https://huanqiukexue.com/a/qianyan/cailiao__huaxue/2017/0527/27301.html

4.https://terrytao.wordpress.com/2022/09/19/a-counterexample-to-the-periodic-tiling-conjecture/

5.https://arxiv.org/abs/1602.05738


上一篇:require.js 禁用缓存
下一篇:HTML5 拖放