尼姆游戏

✍ dations ◷ 2024-12-23 15:17:38 #数学游戏,组合博弈论,趣味数学,包含证明的条目

尼姆游戏(英语:Nim),又译为拈,是一种两个人玩的回合制数学战略游戏。游戏者轮流从几排棋子(或者任何道具)中选择一排,再由这一排中取走一个或者多个,依规则不同,拿走最后一个的可能是输家,也有可能是赢家。当指定相应数量时,一堆这样的棋子称作一个尼姆堆。古代就有许多尼姆游戏的变体。最早欧洲有关尼姆游戏的参考资料是在16世纪,目前使用的名称是由哈佛大学的Charles L. Bouton命名,他也在1901年提出了此游戏的完整理论,不过没有说明名称的由来。

尼姆游戏最常见的玩法是拿到最后一个棋子的人输(misère game)。尼姆游戏也可以改为拿到最后一个棋子的人赢(normal play)。大部分类似的游戏都是最后一个棋子的人赢,不过这不是尼姆游戏最常见的玩法。不论哪一种玩法,只要刚好剩下一排的棋子是二个或二个以上(其他排可能没有棋子,或是只有一个),下一个游戏者可以轻易的获胜。下一个游戏者可以将数量最多的这排棋子全部拿走或只留一个。剩下的各排都只有一个棋子。若是misère版本,下一个游戏者下完之后,只要留下奇数排就会胜利,若是normal版本,下一个游戏者下完之后,只要留下偶数排就会胜利。

normal版本的尼姆游戏(也就是尼姆数糸统)是斯普莱格–格隆第定理的基础,其中提到在normal版本中,每一个normal版本的无偏博弈(从任何一个局势出发,双方可以采取完全相同的行动,也就是说棋盘上没有颜色的区分)都等价于一个特定大小的尼姆堆。所有的normal版本的无偏博弈都可以给与尼姆值,但misère版本的就不一定。只有温驯游戏(英语:Genus theory)才能用misère版本尼姆的策略来进行。尼姆游戏是一种特殊的偏序游戏(英语:poset game),其中的偏序关系包括了不交集的全序关系(堆)。三排棋子尼姆游戏的演进图和Ulam-Warburton自动机(英语:Ulam-Warburton automaton)演进图的三个分支相同。

normal版本是由二位游戏者一起玩,有三排棋子,各排的棋子为任意正整数。二位游戏者轮流选一排棋子,拿走上面至少一个棋子,也可以拿同一排的多个棋子。normal版本的目的是要拿到最后一个棋子。misère版本的目的就是要让对方被迫拿走最后一个棋子(拿到最后一个棋子的人输)。

以下是normal版本的游戏,由爱丽丝与鲍伯二个人玩,三排棋子分别有三个、四个及五个棋子。

尼姆游戏的策略就是在拿完棋子后,使棋子个数符合以下任何一个组态,接下来再轮到时,一定可以再拿走适当数量的棋子,使棋子个数仍符合以下任何一个组态。normal版本和misere版本的差别只在最后一两步,前面都相同:

*只在normal版本有效

**只在misere版本有效

其中有出现和,是任何正整数,和可以相同。

尼姆游戏在数学上是已解游戏,针对任意排数及个数的初始状态都已有解法,而且有简单的方式可以判断哪一个游戏者会胜利,并且此游戏者要如何取子才会胜利。

这游戏理论的关键是在各排个数在二进制下XOR位操作的结果,此操作也称为是在GF(2)中的向量加法(在模数2以下的位元加法)。在组合博弈论中常称为是“尼姆和”(nim-sum),以下也使用此一名称。和的尼姆和会写成 ⊕ ,以和一般的和区别 + 。像3, 4, 5的尼姆和计算如下:

另一个等效,比较容易心算的作法,是将三排的个数分别表示为相异二次幂的和,再设法消除成对的次幂,再将最后留下的数字相加即可:

3 = 0 + 2 + 1 =     2   1      A排4 = 4 + 0 + 0 = 4              A排5 = 4 + 0 + 1 = 4       1      A排--------------------------------------------------------------------2 =                 2          1和4都消去了, 剩下的是2

在normal版本(拿到最后一个棋子的赢)中,胜利的策略就是在取走棋子后,使尼姆和为0。只要取走棋子前,尼姆和不为0,一定有办法取走部分棋子使尼姆和为0。另一个游戏者无论怎么拿,取走棋子后尼姆和都不会为0。以此策略,只要在取棋子时照策略进行,一定会胜利。要找到要拿走的棋子,可以令X是原来各排棋子数的尼姆和,游戏策略是要分别计算各排棋子数和X的尼姆和,找到尼姆和比该排棋子数少的那一排,接下来就要取走这一排的棋子,使该排棋子数等于尼姆和。以上例中,原来各排棋子数的尼姆和是 = 3 ⊕ 4 ⊕ 5 = 2。A=3、B=4、C=5且X=2,因此得到

因此下一步是取走A排的棋子,使其数量变1(拿走二个棋子)。

有一个特别简单的例子,是只剩二排的情形,其策略是在个数较多的那牌拿走部分棋子,使两者数量相同。接下来对手不论怎么下,都继续使二排的数量相同,最后即可胜利。

若是玩misère版本。前面的策略都一样,只到只剩一排的棋子超过一个(二个或二个以上)时才有不同。此时的策略都是针对超过一个棋子的那排棋子取子,使留下来的每一排都只有一个棋子。接下来玩的人只能从这几排中选一排拿走。取子可能是那排全部取完,或是只剩一个,视游戏版本而定,在玩misère版本(拿到最后一个棋子的输)时,要使留下来的排数是单数(因此对方会拿到最后一个棋子),在玩normal版本游戏时,要使留下来的排数是偶数。(因此自己会拿到最后一个棋子)。

以下是棋子数分别是3, 4, 5个,在misère版本的玩法:

上述的策略可以写成程式,以下就是Python的范例:

import functoolsMISERE = 'misere'NORMAL = 'normal'def nim(heaps, game_type):    """Computes next move for Nim, for both game types normal and misere.    if there is a winning move:        return tuple(heap_index, amount_to_remove)    else:        return "You will lose :("    - mid-game scenarios are the same for both game types    >>> print(nim(, MISERE))    misere  You will lose :(    >>> print(nim(, NORMAL))    normal  You will lose :(    >>> print(nim(, MISERE))    misere  (2, 1)    >>> print(nim(, NORMAL))    normal  (2, 1)    - endgame scenarios change depending upon game type    >>> print(nim(, MISERE))    misere  You will lose :(    >>> print(nim(, NORMAL))    normal  (0, 1)    >>> print(nim(, MISERE))    misere  (0, 1)    >>> print(nim(, NORMAL))    normal  You will lose :(    >>> print(nim(, MISERE))    misere  (1, 5)    >>> print(nim(, NORMAL))    normal  (1, 4)    """    print(game_type, heaps, end=' ')    is_misere = game_type == MISERE    is_near_endgame = False    count_non_0_1 = sum(1 for x in heaps if x > 1)    is_near_endgame = (count_non_0_1 <= 1)    # nim sum will give the correct end-game move for normal play but    # misere requires the last move be forced onto the opponent    if is_misere and is_near_endgame:        moves_left = sum(1 for x in heaps if x > 0)        is_odd = (moves_left % 2 == 1)        sizeof_max = max(heaps)        index_of_max = heaps.index(sizeof_max)        if sizeof_max == 1 and is_odd:            return "You will lose :("        # reduce the game to an odd number of 1's        return index_of_max, sizeof_max - int(is_odd)    nim_sum = functools.reduce(lambda x, y: x ^ y, heaps)    if nim_sum == 0:        return "You will lose :("    # Calc which move to make    for index, heap in enumerate(heaps):        target_size = heap ^ nim_sum        if target_size < heap:            amount_to_remove = heap - target_size            return index, amount_to_removeif __name__ == "__main__":    import doctest    doctest.testmod()

必胜策略的证明

以下是必胜策略的证明,由C. Bouton所提出。

定理:在normal版本的尼姆游戏中,第一个玩家有必胜的策略,当且仅当各排棋子数的尼姆和不为零。炻则,第二个玩家有必胜的策略。

:注意尼姆和(⊕)遵守一般加法的结合律及交换律,还有另外一个性质 ⊕  = 0。

1, ..., 是移动前的各排棋子数,1, ..., 是移动后的各排棋子数。令  = 1 ⊕ ... ⊕ 且  = 1 ⊕ ... ⊕ 。若这次是移动第排的棋子,可得 = 针对所有  ≠ ,且 > 。依照⊕的性质,可得

     = 0 ⊕       =  ⊕  ⊕       =  ⊕ (1 ⊕ ... ⊕ ) ⊕ (1 ⊕ ... ⊕ )      =  ⊕ (11) ⊕ ... ⊕ ( ⊕ )      =  ⊕ 0 ⊕ ... ⊕ 0 ⊕ ( ⊕ ) ⊕ 0 ⊕ ... ⊕ 0      =  ⊕  ⊕  (*)  =  ⊕  ⊕ .

此定理会由以下二个引理推导而来。

引理1:若 = 0,则无论如何移动,接下来 ≠ 0。

:若没有任何可以移动的棋子,此引理空虚的真(英语:vacuous truth)(依定义,接下来要玩的游戏者输,因为在他前一手的游戏者拿了最后一个棋子)。否则,任何排的移动都会因为(*),造成  =  ⊕ 。因为 ≠ ,上述数字不为0。

引理2:若 ≠ 0,有可能让 = 0.

:令是二进制表示法中最左边1的位置,选择使的第位元也不是零。(这个一定存在,不然的第位元都是零了)令 =  ⊕ ,可以声称  < :和所有d左边的位元都相同,位元从1变为0(数值减少2),剩下位元的变化最多是2−1。因此接下来的游戏者可以在第xkyk

 =  ⊕  ⊕            (by (*))  =  ⊕  ⊕ ( ⊕ )  = 0.

misère版本的策略刚刚已经看过,只有在只剩一排的棋子是二个或二个以上时才不同。在这种情形 ≠ 0,接下来玩的人有必胜策略,若是normal版本,就是设法留下偶数排的棋子,每排都只有一个棋子,misère版本则反过来,设法留下奇数排的棋子,每排都只有一个棋子。

在1939年纽约世界博览会中,西屋电气有展示一个机器,会玩尼姆游戏的Nimatron(英语:Nimatron)。自1940年的5月11日到10月27日为止,在六周的周期内只有少数的人可以打败Nimatron:若他们胜了,会得到一个称为Nim Champ的硬币。尼姆游戏也是最早电脑化的游戏。Ferranti(英语:Ferranti)曾制作可以玩尼姆游戏的Nimrod电脑,在1951年的英国节(英语:Festival of Britain)上展示。1952年时,W. L. Maxon公司的工程师Herbert Koppel、 Eugene Grant和Howard Bailer开发了重达23千克(50英磅)的机器,可以和人玩尼姆游戏,而且多半会赢。Tinkertoy(英语:Tinkertoy)也可以制作尼姆游戏机。

尼姆游戏是马丁·加德纳在《科学美国人》(Scientific American)杂志中,1958年2月〈数学游戏专栏(英语:Mathematical Games column)〉的主题。在1961年法国新浪潮电影《去年在马伦巴》中,有玩过特定版本的尼姆游戏,而且有象征的重要性。

另一个有点类似的游戏称为subtraction game(英语:subtraction game),会先列出总数,以及每一次可以拿走的最大数量。可能每一次只能拿走1个、2个...至k个。例如在《Survivor: Thailand(英语:Survivor: Thailand)》节目中的Thai 21,就是 = 3的版本。

若棋子只有一排,共有个棋子,其必胜策略当且仅当

21游戏一般会用拿到最后一个棋子的人输的玩法。可以有数个游戏者参与。第一个游戏者说1,其他的游戏者可以在前一个人的数字加1,2或是3。数到21的游戏者输。若是二个游戏者玩,有必胜的策略,就是让加完的数字维持是4的倍数。这可以使另一方最后一定会数到21。

The 21 game can also be played with different numbers, like "Add at most 5; lose on 34".

以下是一个21游戏的例子,第二个游戏者使用必胜的策略:

遊戲者     數字  1           1  2           4  1        5, 6 或 7  2           8  1       9, 10 或 11  2          12  1      13, 14 或 15  2          16  1      17, 18 或 19  2          20  1          21

100游戏

另一个类似的游戏是100游戏:从0开始加,每一次可以加1到10之间的任一个整数,数到100的人胜利。必胜的策略是抢到类似01、12、23、34……、89的数字,接下来另一游戏者不论加多少,都设法抢到下一个01、12、23、34……、89的数字(因为这些数字之间的差是11,不论对方加1到10之间的哪一个数字,都可以可以再加数字,使二人加的数字总计为11)。只要到89之后,接下来不论对方加多少,都可以再加数字使结果为100,因此必胜。

另一个版本的尼姆,是允许在每一排中取走相同数量的棋子。

另一种尼姆的变体是循环尼姆(英语:Kayles),将一定数量的棋子摆成圆形,二个游戏者轮流取棋子,可以取相邻的一个、二个或三个棋子。以下是一个例子:

. . . . . . . . . .

一开始取走三个棋子

_ . . . . . . . _ _

接下来又取走三个棋子


_ . _ _ _ . . . _ _

又拿走一个棋子

_ . _ _ _ . . _ _ _

最后剩下三个棋子,但是不相邻,无法一次取走。

Grundy游戏(英语:Grundy's game)也是尼姆游戏的变体,一开始有一排特定数量的棋子,游戏者要轮流将某一排棋子分为二排数量不同,且都不为0的棋子。例如6个棋子可以分为5+1、4+2,但不能分为3+3。此游戏可以让最后一个人赢或是输。

相关

  • 导尿管导尿管是一种辅助排尿的医疗设备。其一般经由尿道插入膀胱,进而引出尿液出来。导尿管的结构中,其头端有一个气囊,用于固定导尿管,使其得以留在膀胱内防止脱出。 导尿管型号,按照
  • 白斑病口腔白斑(英语:Leukoplakia,又可称口腔白斑症)通常是指一种紧附于口腔黏膜上发生的白色斑块的症状,且和口腔癌的形成有所关连。发生斑块的伤口周围形状通常不规则,且其外观有可能
  • 可持续农业永续农业(英语:Sustainable agriculture)亦称可持续农业,是采用生态学原则的农耕方法,在学术上指探讨生物与其环境互动的一门学科。于荷兰举办的"可持续农业和农村发展会议" ,发
  • 闰年闰年是公历中的名词。闰年分为普通闰年和世纪闰年。 普通闰年:公历年份是4的倍数的,且不是100的倍数,为闰年。(如2004年就是闰年); 世纪闰年:公历年份是整百数的,必须是400的倍数
  • 巴西柔术巴西柔术(葡萄牙语:Jiu-jitsu brasileiro, 英语:Brazilian Jiu-Jitsu缩写为BJJ),一种巴西武术,创始于巴西的格雷西家族,又称格雷西柔术(葡萄牙语:Gracie Jiu-Jitsu, 缩写为GJJ)。它起
  • 柏饼柏饼(かしわもち)是和菓子的一种,流行于日本关东地区,外型像中国的茶果,呈圆形或半圆形,以洗净的粳米(蓬莱米)干燥后磨成的上新粉(中间粗度的粉)制成,包入甜馅料,做好后加上日语称为“柏
  • 波纹短须石首鱼波纹短须石首鱼(学名:Umbrina cirrosa)为辐鳍鱼纲鲈形目鲈亚目石首鱼科的其中一种,分布东大西洋区,从法国比斯开湾至摩洛哥海域,栖息深度可达100米,体长可达73公分,栖息在沙底质或岩
  • 缨唇蝠属缨唇蝠属(缨唇蝠),哺乳纲、翼手目、叶口蝠科的一属,而与缨唇蝠属(缨唇蝠)同科的动物尚有美洲假吸血蝠属(美洲假吸血蝠)、圆耳蝠属(圆耳蝠)、矛吻蝠属(矛吻蝠)等之数种哺乳动物。
  • 美食侦探 明智五郎《美食侦探 明智五郎》(日语:美食探偵 明智五郎)为日本漫画家东村明子创作的推理漫画作品。首集于集英社《Cocohana》2015年8月号连载;同时于该杂志连载的漫画为《海月姬》、《
  • 董重董重(?-189年),字子高,汉灵帝母董太后其兄之子。皇太后窦妙逝世后,董太后开始干预朝政,让汉灵帝卖官求货,自纳金钱,盈满堂室。中平五年(公元188年),卫尉脩侯董重被任命为骠骑将军,领兵千余