什么是游戏2048的最佳算法

问题

我最近偶然发现一款叫2048的游戏。你需要通过上、下、左、右的方向移动来合并值相同的方块(Title)。每一次移动之后,一个新的值为2或者4的方块会随机的出现在某个空的位置。所有位置都塞满方块,并且没有值相同的方块可以移动的时候,游戏结束。游戏的目标是构造一个值为2048的方块。

我需要遵循一套定义良好的策略来实现这个目标。所以我想到写个程序来实现。我当前的算法如下:

while(!game_over)
{
    for each possible move:
        count_no_of_merges_for_2-tiles and 4-tiles
    choose the move with large number of merges
}

我所做的是,在任何时点,我都尝试合并值为2或者4的方块,也就是我会尝试让值为2和4的方块越少越好。如果我尝试那么做,其它的方块会自动的合并,看起来像是个好策略。

但是当我真正使用这套算法的时候,我大概只能得到4000分,游戏就结束了。游戏的最高分应该是20000多点,远超我当前的分数。有比上面策略更好的算法吗?

最佳回答

我是AI程序的作者,前面也有人提到AI程序。你可以看AI的运用或者直接阅读源代码

当前,这套运行在我笔记本浏览器的javascript程序能够达到90%左右的胜率,每次移动的思考时间是100毫秒。尽管不是最完美,但干得还不赖。

既然这个游戏是一个离散状态空间,信息完备的回合制游戏,类似于象棋和国际跳棋,那么我就使用了针对这些游戏的证明过的行之有效的方法。一套叫minimax search的算法,结合了alpha-beta pruning。既然已经有很多信息解释了这套算法,那么我就仅谈谈我在static evaluation function中使用到的两个重要概念。这将会把一些人在这里表达的直觉形式化。

单调性(Monotonicity)

这个概念保证方块的值沿着上下左右方向的,要么增加,要么减少。这个概念单独地解释了一个大家提到的直觉,值较大的方块应该聚集到某一个角落。这将有助于阻止值小的方块被孤立起来,也将让面板保持良好的组织结构,使得值小的方块渐进层叠式的并逐步合并为值大的方块。

下图是一个有完美单调性格子的截屏。我通过运行eval函数被设置为忽略其它概念的算法获得,仅仅考虑单调性。


平滑性(Smoothness)

上面的概念倾向于构造值递减的结构,但如要合并,相邻的方格值必须相同。因此,平滑性衡量相邻方格值的差,并尝试减少差。

Hacker News上的一个评论者用图论给出了一个平滑性的有趣解释。来源于2048的一个优秀分支

下图是个有完美单平滑性的截屏。


空闲方块(Free Tiles)

最后,有一个针对空闲格子过少的惩罚。毕竟面板过于拥挤的时候,选择受限且很快会被用完。

就是这样。扫描游戏格子,同时优化以上标准,这会产生相当好的表现。与明确硬编码的移动策略相比,这种使用通用性的方法有一个优点,这种算法可以找到有趣且难以预料的解决方案。如果你观察它运行,它经常会做出一些惊奇但有效的移动,比如突然转向一个相反的墙或者角落。

修改

这是该方法强大能力的一个展示。我拿掉了方格值大小的限制(到2048之后还可以继续运行,下图是8次尝试中最好一次的截屏,是的,那可是一个4096外加一个2048),那意味着在同一个面板上它完成了3次困难的2048。


原文地址

### RSA2048算法的实现原理 RSA2048是一种基于RSA加密算法的具体实现形式,其主要特点是使用了长度为2048位的密钥。这种密钥长度被认为是当前较为安全的选择之一,在许多现代应用中被广泛采用。 #### 密钥生成过程 RSA2048的核心在于生成一对公私钥对。以下是具体步骤: 1. **选择两个大素数p和q** 随机选取两个足够大的质数 \( p \) 和 \( q \)[^1]。这两个数通常具有相同的比特长度(对于RSA2048来说,\( p \) 和 \( q \) 的乘积应接近于2048位)。 2. **计算模数n** 计算 \( n = p \times q \),其中 \( n \) 是公开参数的一部分。 3. **计算欧拉函数φ(n)** 使用公式 \( φ(n) = (p-1)(q-1) \) 来求得欧拉函数值。 4. **选择公钥指数e** 选定一个小奇数作为公钥指数 \( e \),满足条件 \( 1 < e < φ(n) \) 并且 \( gcd(e, φ(n)) = 1 \)。常用的 \( e \) 值为65537。 5. **计算私钥d** 私钥 \( d \) 可通过扩展欧几里得算法求解方程 \( ed ≡ 1 (\mod φ(n)) \)。 最终得到的公钥为 \( PK = (n, e) \),私钥为 \( SK = (n, d) \)。 --- #### 加密与解密流程 ##### 加密过程 假设明文消息为整数 \( m \) (需小于 \( n \)),则加密后的密文 \( c \) 可表示为: \[ c = m^e \mod n \] ##### 解密过程 接收方收到密文 \( c \) 后,可通过以下公式恢复原始消息 \( m \): \[ m = c^d \mod n \] 由于 \( d \) 是保密的,只有持有私钥的一方才可完成解密操作。 --- ### 示例代码 下面是一个简单的C语言实现示例,展示了如何利用库函数来执行RSA2048加解密操作。此代码依赖OpenSSL库。 ```c #include <openssl/rsa.h> #include <openssl/pem.h> #include <stdio.h> int main() { RSA *rsa = RSA_new(); BIGNUM *bne = BN_new(); // 设置公钥指数e为65537 BN_set_word(bne, RSA_F4); // 生成2048位RSA密钥对 rsa = RSA_generate_key(2048, RSA_F4, NULL, NULL); unsigned char plaintext[] = "Hello, this is a test message!"; int pt_len = sizeof(plaintext) - 1; // 分配缓冲区存储加密数据 unsigned char ciphertext[RSA_size(rsa)]; int ct_len; // 执行加密操作 ct_len = RSA_public_encrypt(pt_len, plaintext, ciphertext, rsa, RSA_PKCS1_PADDING); printf("Encrypted length: %d\n", ct_len); // 分配缓冲区存储解密数据 unsigned char decryptedtext[pt_len]; int dt_len; // 执行解密操作 dt_len = RSA_private_decrypt(ct_len, ciphertext, decryptedtext, rsa, RSA_PKCS1_PADDING); decryptedtext[dt_len] = '\0'; printf("Decrypted text: %s\n", decryptedtext); RSA_free(rsa); BN_free(bne); return 0; } ``` 上述代码实现了完整的RSA2048加解密功能,包括密钥生成、加密以及解密三个部分[^2]。 --- ### 安全性考量 尽管RSA2048目前被认为相对安全,但仍存在一些潜在风险需要注意: - 如果使用的随机数生成器不够强健,则可能导致生成的密钥容易受到攻击。 - 对于低版本的软件实现可能存在漏洞,建议始终更新至最新稳定版开源库。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值