扫雷在工作


18

每个人都知道Windows XP附带的旧扫雷游戏。这是一个简单的网格,具有9x9的单元格矩阵,其中包含一个数字(指示与之相邻的地雷数量)或一个地雷。

在此处输入图片说明

挑战在于,如果您自己实施PRNG,则要生成一个随机的9x9网格,其中包含10个炸弹,给出任意整数种子(取决于您的计算机/语言最大的int)并带有布朗尼点。

示例输出:单元格包含地雷的数字0-8或*

*101*1000
110111000
123210000
1***10000
123210011
00000002*
00000114*
000112*3*
0001*2121

以字节为单位的最短代码获胜。标准规则等。


3
您应该指出数字的含义:)
Nathan Merrill

4
微软的Minesweeper 比XP古老得多,类似minesweeper的游戏至少可以追溯到60年代。
AdmBorkBork

11
另外,我在工作时没有时间玩《扫雷》-我在忙于PPCG。;-)
AdmBorkBork

1
到底什么才算PRNG?它必须能够生产多少种不同的配置?如果我们的语言具有自动初始化为“随机”种子的PRNG,我们可以使用种子而是每次都生成不同的配置吗?
路易斯·门多

1
@TimmyD但是XP的版本是第一个具有9x9网格的版本。任何较早的版本都会为初学者使用8x8网格。#outnerded;)
mbomb007'9

Answers:


3

Dyalog APL,40个字节

⎕rl←1⋄(1,¨a)⍕¨{⍉3+/0,⍵,0}⍣2⊢a←9 9⍴9≥?⍨81

(假设⎕io←0

1⎕rl←1是种子

从右到左:

?⍨8181?81-随机排列相同

9≥ 导致位掩码在随机位置包含十个1,其余为0

a←9 9⍴ 重塑为9 x 9的正方形,并将其称为“ a”

{ }⍣2 两次执行以下操作:

⍉3+/0,⍵,0 滑动窗口的3列总和(假设外面为0),然后转置

(1,¨a)⍕¨分别是格式(转换为字符串)。的左参数指定结果中的字符总数和小数字符总数。如果无法按照该规范进行格式化,则会输出*-幸运的巧合。a地雷所在的位置将为1-试图将整个和小数部分装入单个char中是不可能的,因此这些将显示为*s。


你能解释这个⎕io←0假设吗?我不熟悉Dyalog APL ...
Aaron

1
默认情况下,Dyalog中的数组索引基于1。将⎕io(“ 索引原点 ”)设置为0会使它们从0开始,并相应地更改一些原语,例如⍳3will be 0 1 2not 1 2 3。可以通过编程(⎕io←0)或从GUI中的首选项完成。拥有这个选择是一个有50年历史的错误,至今仍然分裂了微小的APL社区。
ngn

5

MATLAB,94 93字节

rng(input(''));x(9,9)=~1;x(randperm(81,10))=1;y=[conv2(+x,ones(3),'s')+48 ''];y(x)=42;disp(y)

运行示例(代码后的第一行是用户键入的输入):

>> rng(input(''));x(9,9)=~1;x(randperm(81,10))=1;y=[conv2(+x,ones(3),'s')+48 ''];y(x)=42;disp(y)
99
*10001*2*
220001232
*201111*1
*312*1111
12*211000
011211000
0001*1000
000112110
000001*10

说明

rng(input(''));

接受一个整数并将其用作种子。(这在现代MATLAB版本中有效。旧版本可能需要不同的语法。)

x(9,9)=~1;

将逻辑0false(通过逻辑否定获得1)分配给(9,9)矩阵的项x。其余条目也将自动初始化为逻辑0

x(randperm(81,10))=1; 

将随机选择的 条目分配1(自动转换为1true),而不进行替换。这些条目是包含炸弹的条目。1081x

conv2(+x,ones(3),'s')

是的缩写conv2(+x,ones(3),'same')。它使用3×3邻域卷积矩阵x(需要使用对其进行强制转换)。这将计算每个条目附近有多少枚炸弹。对于包含炸弹的条目,该炸弹包括该炸弹,但以后的值将被覆盖。double+1

y=[...+48 ''];

将值加48,以将数字转换为ASCII码。与空矩阵连接将这些ASCII代码转换为char。

y(x)=42;

'*'炸弹位置分配42(的ASCII码)。这些位置由给出x,在此用作逻辑索引。

disp(y)

显示结果。


4

Javascript(ES6),204或198字节

自定义PRNG(204字节)

s=>(p=-1,S=n=>(x=p%9-(n+=p)%9)*x-64&&b[n]=='*',T=n=>S(n)+S(-n),b=[...'*00000000'.repeat(9)]).sort(_=>(s=(22695477*s+1)>>>0)&1||-1).map(c=>(p++,c=='0'?T(1)+T(8)+T(9)+T(10):c)).join``.match(/.{9}/g).join`
`

该代码使用带有乘数22695477和增量的线性同余生成器1(这是Borland C / C ++实现)。

由于PRNG在预热阶段效率低下,因此我必须每排放置一枚炸弹(而不是在未洗牌的阵列开始时放置10枚炸弹,或在未整理的阵列结束时放置10枚炸弹)。因此,只有9枚炸弹。我稍后可能会尝试解决该问题。

另外,必须有一种更简单/更短的方法来处理“外来”支票,(x=p%9-(n+=p)%9)*x-64但我现在无法确定。

使用Math.random()(198字节)

s=>(p=-1,S=n=>(x=p%9-(n+=p)%9)*x-64&&b[n]=='*',T=n=>S(n)+S(-n),b=[...'**********'+'0'.repeat(71)]).sort(_=>Math.random()-.5).map(c=>(p++,c=='0'?T(1)+T(8)+T(9)+T(10):c)).join``.match(/.{9}/g).join`
`

根据要求,这包括十个地雷。

演示版

let f =
_=>(p=-1,S=n=>(x=p%9-(n+=p)%9)*x-64&&b[n]=='*',T=n=>S(n)+S(-n),b=[...'**********'+'0'.repeat(71)]).sort(_=>Math.random()-.5).map(c=>(p++,c=='0'?T(1)+T(8)+T(9)+T(10):c)).join``.match(/.{9}/g).join`
`
console.log(f())


'**********'+'0'等于'**********'+0; 在198字节版本上节省了两个字节。
Paul Schmitz

@PaulSchmitz-不幸的是,这'0'应该被重复,并且0.repeat()不起作用。
Arnauld

糟糕,我虽然会像这样执行...('**********'+0).repeat(71)。抱歉。
Paul Schmitz

3

Python 2中,269个 266 264字节

from random import*
seed(input())
z=1,0,-1
n=range(9)
m=[[0]*9 for _ in n]
for x,y in sample([[x,y]for x in n for y in n],10):
 m[x][y]=-9
 for a in z:
  for b in z:
    if 0<=x+a<9>0<=y+b<9:m[x+a][y+b]+=1 # it gets displayed as 4 spaces, but the beginning of this line is a single tab
print("\n".join("".join([`c`,'*'][c<0]for c in l)for l in m))

在ideone.com上尝试

多亏了Aaron,节省了2个字节。

很可能仍然是高尔夫。

说明

random被导入用于seed播种PRNG并sample随机选择十个炸弹位置。m是一个9 x 9矩阵,可节省电路板。对于每个炸弹位置,的对应条目m设置为-9,所有相邻条目都递增。这种方式m最终包含非炸弹细胞的相邻炸弹计数和炸弹细胞的负数。最终print打印整个板通过所有行迭代lm所有细胞cl


确切地说,“随机”到底是做什么用的?
clismique 2016年

@ Qwerp-Derp可能会播种由sample()
Patrick Roberts

通过混合for a in z:块内的制表符缩进来节省2个字节(仅python 2.x)
Aaron

3

R,187字节

set.seed();x=1:121;y=x[!(x%%11 %in% 0:1|(x-1)%/%11 %in% c(0,10))];z=sample(y,10);x=x*0;for(t in z){p=t+c(-10:-12,-1,1,10:12);x[p]=x[p]+1};x[z]=9;m=data.frame(matrix(x[y],9));m[m==9]='*';m

在Ideone上尝试

说明:

set.seed() 拿一个CST种子。

x 是11 * 11矩阵的索引

y 是11 * 11矩阵中9 * 9矩阵的索引

z 是炸弹的索引

x=x*0 初始化矩阵值

如果相邻的炸弹,循环将x加1。


1
我认为您必须将set.seed()的参数作为输入。
BLT

2

JavaScript ES6,244个字节

f=(a=[...Array(11)].map(_=>Array(11).fill(0)),n=10,r=_=>Math.random()*9|0,x=r(),y=r())=>a[x+1][y+1]>8||[0,1,2].map(i=>[0,1,2].map(j=>a[x+i][y+j]++),a[x+1][y+1]=9)&&--n?f(a,n):a.slice(1,-1).map(a=>a.slice(1,-1).map(n=>n<9?n:`*`).join``).join`
`
;o.textContent=f()
<pre id=o>


您可能需要详细说明代码的哪一部分。
NoOneIsHere

@NoOneIsHere前244个字节,希望是;-)第一行应该是242个字节长,然后是换行符和`字符。
尼尔

1

红宝石181 194 183 + 1 = 184个字节

忘了实际设置种子,哎呀。使用-n标志。

在线尝试!

srand$_.to_i
a=[0]*81
[*0..80].sample(10).map{|i|w=i%9;h=i/9;a[i]=-99
(r=-1..1).map{|x|x+=w
x<0||x>8?0:r.map{|y|y+=h
y<0||y>8?0:a[9*y+x]+=1}}}
puts a.map{|c|c<0??*:c}.join.scan /.{9}/

0

Python 2,172字节

from random import*
seed(input())
r=range
b=set(sample(r(81),10))
for j in r(9):print''.join([[`len({x-10,x-9,x-8,x-1,x+1,x+8,x+9,x+10}&b)`,'*'][x in b]for x in r(j,81,9)])

在线尝试!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.