制作气泡包装模拟器


23

气泡包装纸是最高级别的娱乐活动。每个人都可以同意。

现在,您甚至可以使计算机享受泡沫包装。

眼镜

您将得到两个整数w和h(分别是宽度和高度)

您的程序应输出所有w * h阶段,每阶段之间等待1秒钟,然后终止。

每次气泡包装都从所有细胞充满开始。

例如,一个4 * 6的气泡包装开始如下:

O_O_
_O_O
O_O_
_O_O
O_O_
_O_O

每个阶段都会弹出一个随机未弹出的单元格。

O_O_
_O_O
O_X_
_O_O
O_O_
_O_O

当所有单元格都弹出时,程序应终止。又名

X_X_
_X_X
X_X_
_X_X
X_X_
_X_X

例子

(4,6)
(5,5)
(6,2)
(10,10)
(7,9)

我们可以使用10代替Oand X吗?
帕维尔

1
NEEDZ BUBBLEZ请把帮助
克里斯托弗·

3
(1,1)没有气泡是可以接受的(例如,左上角的“单元格”始终是下划线)吗?
乔纳森·艾伦

1
@JonathanAllan是的。
马修·罗

1
@KevinCruijssen不必是一个完整的程序。
马修·鲁

Answers:


7

C(视窗),260个 248字节

#import<windows.h>
i,j,l,r;b(w,h){char*s=malloc(l=w*h+h);for(i=h;i--;*s++=10)for(j=w;j--;*s++=i%2^j%2?79:45);*(s-1)=0;s-=l;for(srand(time(0));j>system("cls")+puts(s)-2;j>-1?s[j]=88:0)for(Sleep(1000),r=rand(),j=-2,i=r+l*2;--i-r;j=s[i%l]==79?i%l:j);}

在此处输入图片说明


请注意,线程库中有一个sleep函数,该函数包含在C ++ 11中。
马修·鲁

@MatthewRoh是的,但是它更短,并且system("cls")也是Windows特定的,因此代码也不会更容易地与线程库一起使用。使用C ++时,我还需要包含iostreamcstdio
Steadybox

顺便说一句,您不需要重置屏幕。这将使其更短。
马修·罗

5

Python 3中222个 220字节

这是我第一次回答,请保持温柔(并指出我犯的错误)。

import time,random as t
def f(c,r):
 p=print;a='0_'*c;d=((a[:c]+'\n'+a[1:c+1]+'\n')*r)[:-~c*r]
 for i in[1]*((r*c+r%2*c%2)//2):
  p(d);k=1
  while d[k]!='0':k=t.randrange(len(d))
  d=d[:k]+'X'+d[k+1:];time.sleep(1)
 p(d)

在线尝试!

怎么运行的:

  1. 将许多'0_'链接在一起
  2. 分成“ 0_0 _... \ n”和“ _0_0 ... \ n”两部分并串联
  3. 生成随机索引,直到索引处的字符为“ 0”为止
  4. 用生成的索引处的char创建新字符串将替换为'X'(该死的python,不可更改的字符串!)
  5. 重复r*c+r%2*c%2次数:模式中有r*c气泡,除非r和c都为奇数,否则为r*c+1

1
欢迎来到PPCG!
AdmBorkBork

1
这相当小,但是宽度和高度却相反。很好的答案!(只需将其更改为f(c,r),您就可以了)。
rassar

@rassar哎呀,谢谢!
尼罗河

4

MATL,37字节

:!i:+o`T&Xxt3:q'_OX'XEcD2y1=ft&v1Zr(T

左上角始终是下划线(挑战允许)。

在各阶段之间将清除屏幕。我可以通过不清除屏幕来节省一个字节,但是这样看起来更好。

显示所有阶段后,程序退出并显示错误(默认情况下允许)。

MATL在线上尝试一下(如果几秒钟后仍然无法使用,请刷新页面,然后重试)。


4

Mathematica(145字节)

匿名功能,需要的高度和宽度为输入(以该顺序-如果这是一个问题,替换{##}{#2,#}的代码的中间,但需要额外2个字节)。

码:

Monitor[Do[Pause@1,{i,NestList[RandomChoice@StringReplaceList[#,"O"->"X"]&,""<>Riffle["_"["O"][[Mod[#+#2,2]]]&~Array~{##},"
"],Floor[##/2]]}],i]&

说明:

  • ""<>Riffle[Array["_"["O"][[Mod[#+#2,2]]]&,{##}],"\n"] 通过创建数组“ _”和“ O”,然后在换行符之间进行StringJoining来创建初始的,未弹出的气泡包装。
  • NestList[RandomChoice@StringReplaceList[#,"O"->"X"]&,..., Floor[##/2]]重复选择“ O”之一替换为“ X”,次数是“ O”的次数(即Floor [width * width / height / 2])–感谢@JonathanAllan提出的“ _ ”,而不是左上角的“ O”,否则应Ceiling改为2字节)。
  • Monitor[Do[Pause@1,{i,...}],i]使i我们刚才计算的列表中的值各1秒钟,并动态打印i

输出示例:

Mathematica的GIF弹出气泡包装


3

果冻30 29 字节

=”OTX
+þ⁹++µị⁾_OYµṄœS1”XǦµÐL

运行示例

使用程序参数将链接作为对偶调用,然后退出并显示一条消息(其代码为çṛ“\'=ṙMḋḌẓ(ėo»

细微差别:右下“小区”将始终是一个气泡(而不是左上象问题的示例),这是为了确保当所有气泡被弹出的随机选择返回0,这将是"X"在列表的结尾-替换后,该值将保持不变,并中断循环。

注意:不会清除屏幕(未指定,我不确定该怎么做)。

怎么样?

=”OTX - Link 1, choose a random O index or 0: string   e.g. "_O_\nX_O"
 ”O   - "O"
=     - equals (vectorises over the string)            e.g. [0,1,0,0,0,0,1]
   T  - truthy indexes                                 e.g. [2,7]
    X - random choice (if empty this returns 0)

+þ⁹++µị⁾_OYµṄœS1”XǦµÐL - Main link: w, h              e.g. 3, 2
                        - left argument (implicit), w  e.g. 3
  ⁹                     - right argument, h            e.g. 2
 þ                      - outer product with
+                       -     addition                 e.g. [[2,3,4],[3,4,5]]
                        - left argument (implicit), w  e.g. 3
   +                    - add                          e.g. [[5,6,7],[6,7,8]]
                        - right argument (implicit), h e.g. 2
    +                   - add                          e.g. [[7,8,9],[8,9,10]]
     µ                  - monadic chain separation
       ⁾_O              - "_O"
      ị                 - index into (1-based & mod)   e.g. [['_','O','_'],['O','_','O']]
                        -     note: the additions above assure the last entry is an 'O'.
          Y             - join with line feeds         e.g. ['_','O','_','\n','O','_','O']
           µ        µ   - monadic chain separations
                     ÐL - loop until the results are no longer unique:
            Ṅ           -     print with a trailing line feed and yield
             œS1        -     sleep for 1 second and yield
                   ¦    -     apply to index
                  Ç     -         given by calling the last link (1) as a monad 
                        -                 (a random O index or 0 if none exists)
                ”X      -         an "X"  (      ... which will be an X already)

@ГригорийПерельман写下来。
乔纳森·艾伦

2

Scala,764字节

object B{
  def main(a: Array[String]):Unit={
    val v=false
    val (m,l,k,r,n)=(()=>print("\033[H\033[2J\n"),a(0)toInt,a(1)toInt,scala.util.Random,print _)
    val e=Seq.fill(k, l)(v)
    m()
    (0 to (l*k)/2-(l*k+1)%2).foldLeft(e){(q,_)=>
      val a=q.zipWithIndex.map(r => r._1.zipWithIndex.filter(c=>
        if(((r._2 % 2) + c._2)%2==0)!c._1 else v)).zipWithIndex.filter(_._1.length > 0)
      val f=r.nextInt(a.length)
      val s=r.nextInt(a(f)._1.length)
      val i=(a(f)._2,a(f)._1(s)._2)
      Thread.sleep(1000)
      m()
      val b=q.updated(i._1, q(i._1).updated(i._2, !v))
      b.zipWithIndex.map{r=>
        r._1.zipWithIndex.map(c=>if(c._1)n("X")else if(((r._2 % 2)+c._2)%2==0)n("O")else n("_"))
        n("\n")
      }
      b
    }
  }
}

怎么运行的

该算法首先用错误值填充2D序列。它根据所输入的命令行参数确定存在多少次迭代(打开的框)。它使用此值作为上限创建折叠。fold的整数值仅隐式用作计算算法应运行多少次迭代的方式。我们之前创建的填充序列是折叠的起始序列。它用于生成带有对应指数的新2D假值序列。

例如,

[[false, true],
 [true, false],
 [true, true]]

将变成

[[(false, 0)], [(false, 1)]]

请注意,结果列表中将省略所有完全正确的列表(长度为0)。然后,算法获取此列表,并从最外面的列表中选择一个随机列表。选择随机列表作为我们选择的随机行。从该随机行中,我们再次找到一个随机数,即列索引。一旦找到了这两个随机索引,我们就将进入的线程休眠1000毫秒。

睡眠完成后,我们清除屏幕并创建一个新板,并在创建true的随机索引中更新其值。

为了正确打印出来,我们使用map地图索引并将其与地图索引一起压缩,以便在上下文中使用。我们使用序列的真值决定是否打印an XOor或_。要选择后者,我们使用索引值作为指导。

有趣的事情要注意

要确定是否应打印an O或an _,请使用条件((r._2 % 2) + c._2) % 2 == 0r._2引用当前行索引,而c._2引用当前列。如果一个在奇数行上,r._2 % 2将为1,因此c._2在条件中偏移一。这样可以确保在奇数行上,列按预期移动1。

"\033[H\033[2J\n"根据我阅读的一些Stackoverflow答案,打印出字符串可以清除屏幕。它正在向终端写入字节,并做一些我不太了解的时髦事情。但是我发现它是最简单的方法。但是,它在Intellij IDEA的控制台模拟器上不起作用。您必须使用常规终端运行它。

第一次查看此代码时,可能会发现另一个方程式很奇怪(l * k) / 2 - (l * k + 1) % 2。首先,让我们对变量名称进行神秘化。l引用传递给程序的第一个参数,而k引用第二个。要翻译它,(first * second) / 2 - (first * second + 1) % 2。该方程式的目的是提出获得所有X序列所需的确切迭代次数。我第一次这样做,就是那样(first * second) / 2做。对于n每个子列表中的每个元素,都有n / 2气泡可以弹出。但是,在处理诸如(11 13)。我们需要计算两个数字的乘积,如果它是偶数,即使它是奇数,也要使其为奇数,然后将其乘以2。这是可行的,因为奇数的行和列将需要更少的迭代以获得最终结果。

map用代替a,forEach因为它的字符较少。

可能需要改进的地方

关于此解决方案的真正困扰我的一件事是频繁使用zipWithIndex。它占用了很多字符。我试图这样做,以便可以定义自己的一个字符函数,该函数仅zipWithIndex使用传入的值来执行。但是事实证明,Scala不允许匿名函数具有类型参数。不使用zipWithIndex我可能正在做的事情还有另一种方法,但是我没有想过一个聪明的方法。

当前,代码分两步运行。第一个生成一个新板,而第二个遍将其打印出来。我认为,如果将这两个通道合并为一个通道,则将节省几个字节。

这是我完成的第一个代码高尔夫球,因此我确信还有很多改进的空间。如果您想在我尽可能优化字节之前看到代码,就在这里。


1

JavaScript的(ES6),246个 229字节

document.write(`<pre id=o></pre>`)
setInterval(_=>{(a=o.innerHTML.split(/(O)/))[1]?a[Math.random()*~-a.length|1]=`X`:0;o.innerHTML=a.join``},1e3)
f=(w,h)=>o.innerHTML=[...Array(h)].map((_,i)=>`O_`.repeat(w+h).substr(i,w)).join`
`
<div oninput=f(+w.value,+h.value)><input id=w type=number min=1><input id=h type=number min=1>


宽度不是以像元为单位,而是包括空格(下划线)。
马修·罗

@MatthewRoh对不起,我记得要固定好高度,但是忘了检查宽度。
尼尔

嗯..这部分不能:`${`_O`.repeat(w).slice(w)} ${`O_`.repeat(w).slice(w)}以某种方式结合吗?可能是一个布尔标志,首先要确定_OO_,然后再确定.repeat(w).slice(w)
凯文·克鲁伊森

1
@KevinCruijssen由于快速修正错误,我当时没有时间打高尔夫球,因此我丢失了16个字节。从那以后,我又看了一眼,节省了17个字节,
Neil

1

Python-290字节

我以前从未做过其中之一-因此,任何建设性的批评将不胜感激:)

这里的主要技巧只是令人讨厌的嵌套列表推导。通过在流行音乐之间没有换行符,我可以节省一些字符,但这看起来很难看。

r=range
q=print
import random as n,time
def f(H,W):
    def p(b):
        q("\n".join(["".join(["O"if(i,j)in b else"X"if(i,j)in X else"_"for j in r(H)])for i in r(W)]));time.sleep(1);q()
    b=[(i,h)for h in r(H)for i in r(h%2,W,2)];n.shuffle(b);X=[]
    while len(b)>0:
        p(b);X+=[b.pop()]
    p(b)

嗨,欢迎来到PPCG!挑战是采用wh作为输入(通过STDIN,作为函数输入或类似输入),而不是进行硬编码H=4 W=6。另外,尽管我从未用Python编程,但我认为您可以在当前代码中打些空间。阅读Python高尔夫技巧可能也很有趣,以便为您提供进一步打高尔夫球的想法。入住愉快!:)
Kevin Cruijssen

另外,关于您的评论:“ 我可以通过在流行音乐之间没有换行符来保存一些字符,但这看起来很丑陋。 ”无论现实生活中编程多么丑陋或不怎么做,codegolf都将其保存为尽可能多的字节。越短越丑越好。;)
Kevin Cruijssen

@KevinCruijssen我上面的Python3只是具有w,h的功能,可以吗?
艾莉亚


1
好的-我现在使其成为H和W的函数。
艾莉亚

1

木炭49 46 39字节(无竞争)

UONNO_¶_OAKAαA№αOβHWψβ«A§α§⌕AαO‽βXA№αOβ

详细

Oblong(InputNumber(), InputNumber(), "O_\n_O")
Assign(PeekAll(), a)
Assign(Count(a, "O"), b)
RefreshWhile (k, b) {
    AssignAtIndex(a, AtIndex(FindAll(a, "O"), Random(b)), "X")
    Assign(Count(a, "O"), b)
}

1

APL(Dyalog)61 59字节

⎕←m'O_'[2|-/¨⍳⎕]
(b/,m)[?+/b'O'=,m]←'X'
DL 1
2/⍨'O'∊⎕←m

⎕← 输出
m←m,其中m
'O_'[] 这些字符被…索引…  形状 数字输入数组(行和列的数量)中所有坐标(索引)中的 每个坐标 之间的差
2| 除以二 )
-/¨

(……  将字符X分配给)[...中]←'X'的一个,… 被b
b/  过滤(待定义)  m的斜线元素,特别是…  一个随机元素(点数),范围为1至 b  的总和 ,其中b是  布尔值字母等于 m的地方
,m
?
+/
b←
'O'=
,m

⎕DL 1d Ë AY1秒

→2
/⍨ 如果
'O'∊ 字母(是否过滤) 是
⎕←m 输出值的成员, 则 转到第2行 ,其中输出值为m

在线尝试!


从16.0版开始,它将更短:

{0::→⋄'X'@(⊂(?∘≢⊃⊢)⍸'O'=⍵⊣⎕DL 1)⊢⎕←⍵}⍣≡'O_'[2|-/¨⍳⎕]


1

Python 3中,195个 188字节

import time,random
def f(w,h):
 a=bytearray(b'0-'*w*h);b=[*range(0,w*h,2)];random.shuffle(b);
 while 1:print(*(a.decode()[w*i:w*i+w]for i in range(h)),sep='\n');a[b.pop()]=88;time.sleep(1)

使用bytearraydecode似乎比对弦进行切片和重新组装要短a[:i]+'X'+a[i+1:]

import time,random
def f(w,h):
 x=[*range(1,h*w,2)];random.shuffle(x)
 while 1:
  for i in range(w*h):
   print('-X0'[(i%w%2!=i//w%2)+(i in x)],end='\n'[i%w<w-1:])
  print();time.sleep(1);x.pop()

0

Java 7,317字节

void c(int w,int h)throws Exception{String r="";int x=0,j=0,i;for(;j++<h;x^=1,r+="\n")for(i=0;i<w;r+=(i+++x)%2<1?"_":"O");for(System.out.println(r);r.contains("O");System.out.println(r=r.substring(0,x)+'X'+r.substring(x+1))){Thread.sleep(1000);for(x=0;r.charAt(x)!='O';x=new java.util.Random().nextInt(r.length()));}}

说明:

void c(int w, int h) throws Exception{                     // Method with two integer parameters (throws Exception is required for the Thread.sleep)
  String r = "";                                           //  String we build to print
  int x=0, j=0, i;                                         //  Some temp values and indexes we use
  for(; j++<h;                                             //  Loop over the height 
      x^=1,                                                //    After every iteration change the flag `x` every iteration from 0 to 1, or vice-versa
      r += "\n")                                           //    And append the String with a new-line
    for(i=0; i<w;                                          //   Inner loop over the width
        r += (i++ + x)%2 < 1 ? "_" : "O")                  //    Append the String with either '_' or 'O' based on the row and flag-integer
    ;                                                      //   End inner width-loop (implicit / no body)
                                                           //  End height-loop (implicit / single-line body)
  for(                                                     //  Loop
    System.out.println(r);                                 //   Start by printing the starting wrap
    r.contains("O");                                       //   Continue loop as long as the String contains an 'O'
    System.out.println(r=                                  //   Print the changed String after every iteration
        r.substring(0,x)+'X'+r.substring(x+1))){           //    After we've replaced a random 'O' with 'X'
      Thread.sleep(1000);                                  //   Wait 1 second
      for(x=0; r.charAt(x) != 'O';                         //   Loop until we've found a random index containing still containing an 'O'
          x = new java.util.Random().nextInt(r.length()))  //    Select a random index in the String
      ;                                                    //   End loop that determines random index containing 'O' (implicit / no body)
  }                                                        //  End loop
}                                                          // End method

测试gif(4,6)

在此处输入图片说明


0

Perl,148个字节

146个字节的代码+ -pl标志。

$_=O x($x=$_+1);s/O\K./_/g;for$i(1..($y=<>)){$b.=($i%2?$_:_.s/.$//r).$/}}print$_="\e[H$b";while(/O/){$r=0|rand$y*$x+3;s/.{$r}\KO/X/s||redo;sleep 1

要运行它:

perl -ple '$_=O x($x=$_+1);s/O\K./_/g;for$i(1..($y=<>)){$b.=($i%2?$_:_.s/.$//r).$/}}print$_="\e[H$b";while(/O/){$r=0|rand$y*$x+3;s/.{$r}\KO/X/s||redo;sleep 1' <<< "6
4"

0

MATLAB(R2016b),172个字节

码:

x=input('');m=[eye(x(2),x(1)) ''];m(:)='O';m(1:2:end,2:2:end)='_';m(2:2:end,1:2:end)='_';o=find(m=='O');r=o(randperm(nnz(o)));disp(m);for i=r';pause(1);m(i)='X';disp(m);end

总是欢迎提出建议!在线尝试!

程序输出:

在此处输入图片说明

说明:

x = input( '' );                    % Input
m = [ eye( x( 2 ), x( 1 ) ) '' ];   % Character Matrix
m( : ) = 'O';                       % Fill Matrix with "Bubbles"

m( 1:2:end, 2:2:end ) = '_';        % Alternate Spaces Between Bubbles (Part 1)
m( 2:2:end, 1:2:end ) = '_';        % Alternate Spaces Between Bubbles (Part 2)

o = find( m == 'O' );               % Index Bubble Locations
r = o( randperm( nnz( o ) ) );      % Randomize Bubble Locations

disp( m );                          % Display Initial Bubble Wrap Phase

for i = r'
    pause( 1 );                     % Pause for 1 Second
    m( i ) = 'X';                   % Pop Bubble
    disp( m );                      % Display Subsequent Bubble Wrap Phase
end
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.