Faire un simulateur de bulles

23

Les bulles sont un divertissement de niveau maximum. Tout le monde peut en convenir.

Désormais, vous pourrez même profiter d'ordinateurs à bulles.

Spécifications

Vous recevrez deux nombres entiers, w et h (chacun étant respectivement largeur et hauteur)

Votre programme devrait sortir toutes les phases w * h en attendant 1 seconde entre chacune et se terminer.

Chaque emballage à bulles commence avec toutes les cellules pleines.

Par exemple, un emballage à bulles 4 * 6 commence comme:

O_O_
_O_O
O_O_
_O_O
O_O_
_O_O

Et à chaque phase, une cellule aléatoire non éclatée est éclatée. Par exemple,

O_O_
_O_O
O_X_
_O_O
O_O_
_O_O

Le programme doit se terminer lorsque toutes les cellules sont sautées. alias.

X_X_
_X_X
X_X_
_X_X
X_X_
_X_X

Exemples

(4,6)
(5,5)
(6,2)
(10,10)
(7,9)
Matthew Roh
la source
Pouvons-nous utiliser 1et 0au lieu de Oet X?
Pavel
1
NEEDZ BUBBLEZ pls envoyer de l'aide
Christopher
3
Est-il acceptable pour a (1,1)de ne pas avoir de bulles (par exemple, la "cellule" en haut à gauche est toujours un trait de soulignement)?
Jonathan Allan
1
@JonathanAllan Oui.
Matthew Roh
1
@KevinCruijssen Il n'est pas nécessaire que ce soit un programme complet.
Matthew Roh

Réponses:

7

C (Windows), 260 248 octets

#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);}

entrez la description de l'image ici

Steadybox
la source
Notez qu'il existe une fonction de veille dans la bibliothèque de threads, qui est incluse dans C ++ 11.
Matthew Roh
@MatthewRoh Oui, mais c'est plus court, et system("cls")c'est aussi spécifique à Windows, donc le code ne serait pas plus portable avec la bibliothèque de threads non plus. Et avec C ++, je devrais également inclure iostreamou cstdio.
Steadybox
btw vous n'avez pas besoin de réinitialiser l'écran. cela le raccourcira.
Matthew Roh
5

Python 3 , 222 220 octets

C'est la première fois que je réponds, alors soyez gentil (et signalez les erreurs que j'ai commises).

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)

Essayez-le en ligne!

Comment ça marche:

  1. Enchaînez beaucoup de «0 _» ensemble
  2. Couper en parties '0_0 _... \ n' et '_0_0 ... \ n' et concaténer
  3. Générer des indices aléatoires jusqu'à ce que le caractère à l'index soit un «0»
  4. Créer une nouvelle chaîne avec le caractère à l'index généré est remplacé par un 'X' (Damn you python for non-mutable strings!)
  5. Répétition r*c+r%2*c%2: il y a des r*cbulles dans le motif, sauf si r et c sont tous les deux impairs, auquel cas il y en a r*c+1.
Nil
la source
1
Bienvenue chez PPCG!
AdmBorkBork
1
C'est plutôt mineur, mais votre largeur et votre hauteur sont inversées. Bonne réponse cependant! (Changez-le simplement f(c,r)et tout ira bien).
rassar
@rassar Woops, merci!
nil
4

MATL , 37 octets

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

Le coin supérieur gauche est toujours un trait de soulignement (autorisé par le défi).

L'écran est effacé entre les phases. Je pourrais économiser un octet en n'effaçant pas l'écran, mais cela semble mieux de cette façon.

Le programme se termine avec une erreur ( autorisée par défaut ) après avoir affiché toutes les phases.

Essayez-le sur MATL Online! (Si cela ne fonctionne pas après quelques secondes, veuillez actualiser la page et réessayer).

Luis Mendo
la source
4

Mathematica (145 octets)

Fonction anonyme, prend la hauteur et la largeur en entrée (dans cet ordre - si c'est un problème, remplacez {##}par {#2,#}au milieu du code pour 2 octets supplémentaires).

Code:

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

Explication:

  • ""<>Riffle[Array["_"["O"][[Mod[#+#2,2]]]&,{##}],"\n"] crée l'habillage à bulles initial et non nettoyé, en créant un tableau de «_» et de «O», puis en les joignant par chaîne entre les sauts de ligne.
  • NestList[RandomChoice@StringReplaceList[#,"O"->"X"]&,..., Floor[##/2]]choisit à plusieurs reprises l'un des "O" à remplacer par un "X", autant de fois qu'il y a de "O" (qui est Floor [largeur * hauteur / 2] - merci à @JonathanAllan pour l'idée de mettre "_ "au lieu de" O "dans le coin supérieur gauche, sinon ce serait à la Ceilingplace et donc 2 octets de plus).
  • Monitor[Do[Pause@1,{i,...}],i]fait iprendre les valeurs de la liste que nous venons de calculer, pendant 1 seconde chacune, et imprime dynamiquement i.

Exemple de sortie:

GIF de papier bulle à éclater Mathematica

Pas un arbre
la source
3

Gelée , 30 29 octets

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

Exemple d'exécution

Appelle le lien en tant que dyade avec les arguments du programme, puis quitte avec un message (dont le code est çṛ“\'=ṙMḋḌẓ(ėo»)

Nuance: la "cellule" en bas à droite sera toujours une bulle (plutôt qu'en haut à gauche comme dans l'exemple de la question), c'est pour s'assurer que lorsque toutes les bulles sont sautées, le choix aléatoire renvoie 0 qui sera le "X"au fin de la liste - le remplacer ne modifie alors pas la valeur et rompt la boucle.

Remarque: n'efface pas l'écran (n'a pas été spécifié et je ne sais pas comment le faire).

Comment?

=”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)
Jonathan Allan
la source
@ ГригорийПерельман l'a écrit.
Jonathan Allan
2

Scala , 764 octets

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
    }
  }
}

Comment ça marche

L'algorithme remplit d'abord une séquence 2D avec de fausses valeurs. Il détermine combien d'itérations (boîtes ouvertes) existent en fonction des arguments de ligne de commande insérés. Il crée un pli avec cette valeur comme limite supérieure. La valeur entière du repli n'est utilisée qu'implicitement comme moyen de compter le nombre d'itérations pour lesquelles l'algorithme doit s'exécuter. La séquence remplie que nous avons créée précédemment est la séquence de départ du pli. Ceci est utilisé pour générer une nouvelle séquence 2D de fausses valeurs avec leurs indécies co-répondantes.

Par exemple,

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

Sera transformé en

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

Notez que toutes les listes qui sont complètement vraies (ont une longueur de 0) sont omises de la liste des résultats. L'algorithme prend ensuite cette liste et sélectionne une liste aléatoire dans la liste la plus externe. La liste aléatoire est choisie pour être la ligne aléatoire que nous choisissons. À partir de cette ligne aléatoire, nous trouvons à nouveau un nombre aléatoire, un index de colonne. Une fois que nous avons trouvé ces deux indices aléatoires, nous dormons le thread sur lequel nous sommes pendant 1000 millisecondes.

Après avoir dormi, nous effaçons l'écran et créons un nouveau tableau avec une truevaleur mise à jour dans les indices aléatoires que nous avons créés.

Pour l'imprimer correctement, nous l'utilisons mapet le compressons avec l'index de la carte, nous l'avons donc dans notre contexte. Nous utilisons la valeur de vérité de la séquence pour savoir si nous devons imprimer un Xou un Oou ou _. Pour choisir ce dernier, nous utilisons la valeur de l'indice comme guide.

Choses intéressantes à noter

Pour déterminer s'il doit imprimer un Oou un _, le conditionnel ((r._2 % 2) + c._2) % 2 == 0est utilisé. r._2fait référence à l'index de ligne actuel tandis que c._2fait référence à la colonne actuelle. Si l'un est sur une ligne impaire, r._2 % 2sera 1, donc compensé c._2par un au conditionnel. Cela garantit que sur les lignes impaires, les colonnes sont déplacées de 1 comme prévu.

L'impression de la chaîne "\033[H\033[2J\n", selon une réponse de Stackoverflow que j'ai lue, efface l'écran. Il écrit des octets sur le terminal et fait des trucs géniaux que je ne comprends pas vraiment. Mais j'ai trouvé que c'était la manière la plus simple de s'y prendre. Cependant, cela ne fonctionne pas sur l'émulateur de console d'Intellij IDEA. Vous devrez l'exécuter à l'aide d'un terminal standard.

Une autre équation que l'on pourrait trouver étrange lors de la première lecture de ce code est (l * k) / 2 - (l * k + 1) % 2. Tout d'abord, démystifions les noms de variables. lfait référence aux premiers arguments passés dans le programme tandis que kfait référence au second. Pour le traduire, (first * second) / 2 - (first * second + 1) % 2. Le but de cette équation est de trouver le nombre exact d'itérations nécessaires pour obtenir une séquence de tous les X. La première fois que j'ai fait ça, j'ai fait (first * second) / 2comme ça avait du sens. Pour chaque nélément de chaque sous-liste, il y a des n / 2bulles que nous pouvons faire éclater. Cependant, cela casse lorsqu'il s'agit d'entrées telles que(11 13). Nous devons calculer le produit des deux nombres, le rendre impair s'il est pair et même s'il est impair, puis prendre le mod de cela par 2. Cela fonctionne parce que les lignes et les colonnes qui sont impaires nécessiteront une itération de moins pour arriver au résultat final.

mapest utilisé à la place d'un forEachcar il contient moins de caractères.

Des choses qui peuvent probablement être améliorées

Une chose qui me dérange vraiment dans cette solution est l'utilisation fréquente de zipWithIndex. Cela prend tellement de personnages. J'ai essayé de faire en sorte que je puisse définir ma propre fonction à un caractère qui fonctionnerait simplement zipWithIndexavec la valeur transmise. Mais il s'avère que Scala ne permet pas à une fonction anonyme d'avoir des paramètres de type. Il y a probablement une autre façon de faire ce que je fais sans utiliser, zipWithIndexmais je n'ai pas trop réfléchi à une façon intelligente de le faire.

Actuellement, le code s'exécute en deux passes. La première génère une nouvelle carte tandis que la deuxième passe l'imprime. Je pense que si l'on devait combiner ces deux passes en une seule, cela économiserait quelques octets.

C'est le premier golf de code que j'ai fait, donc je suis sûr qu'il y a beaucoup de place pour l'amélioration. Si vous souhaitez voir le code avant d'optimiser autant que possible les octets, le voici.

Stefan Aleksić
la source
1

JavaScript (ES6), 246 229 octets

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>

Neil
la source
La largeur n'était pas en termes de cellules, mais incluait des espaces vides (soulignés).
Matthew Roh
@MatthewRoh Désolé, je me suis souvenu de le fixer pour la hauteur mais j'ai oublié de vérifier la largeur.
Neil
Hmm .. cette partie ne peut-elle pas `${`_O`.repeat(w).slice(w)} ${`O_`.repeat(w).slice(w)}être combinée d'une manière ou d'une autre? Peut-être un drapeau booléen pour déterminer d'abord _Oou O_, puis faire le .repeat(w).slice(w)?
Kevin Cruijssen
1
@KevinCruijssen J'avais perdu 16 octets à cause d'une correction de bogue rapide que je n'avais pas eu le temps de jouer au golf à l'époque. Depuis, j'ai jeté un nouveau coup d'œil et trouvé une économie de 17 octets,
Neil
1

Python - 290 octets

Je n'en ai jamais fait auparavant - donc toute critique constructive serait appréciée :)

L'astuce principale ici est juste des compréhensions de listes emboîtées. Je pourrais sauver quelques personnages en n'ayant pas de nouvelle ligne entre les pops mais ça a l'air moche.

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)
Arya
la source
Salut, bienvenue chez PPCG! Le défi était de prendre le wet hcomme entrée (via STDIN, comme entrée de fonction, ou quelque chose de similaire), au lieu d'avoir un code dur H=4 W=6. De plus, même si je n'ai jamais programmé en Python, je pense que vous pouvez jouer au golf dans certains espaces de votre code actuel. Des conseils pour jouer au golf en Python peuvent également être intéressants à lire pour vous donner des idées sur la façon de le jouer plus loin. Profitez de votre séjour! :)
Kevin Cruijssen
En outre, en ce qui concerne votre commentaire: " Je pourrais enregistrer quelques caractères en n'ayant pas de nouvelle ligne entre les pops, mais cela a l'air moche. " autant d'octets que possible. Le plus court et le plus laid, mieux c'est. ;)
Kevin Cruijssen
@KevinCruijssen le Python3 au-dessus de moi l'a juste en fonction de w, h, est-ce autorisé?
Arya
1
Ok - je l'ai fait une fonction de H et W maintenant.
Arya
1

Charbon de bois , 49 46 39 octets (sans concurrence)

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

Verbeux

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)
}
ASCII uniquement
la source
1

APL (Dyalog) , 61 59 octets

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

⎕← sortie
m←m , où m est
'O_'[... ] ces caractères indexés par ...
2| la division-reste-quand-divisée par deux de
-/¨ la différence entre chacune de
 toutes les coordonnées (indices) dans un tableau de forme
 entrée numérique (le nombre de lignes et de colonnes )

(... )[... ]←'X' classer le caractère X à l' un des ... par
b/ cas filtré b (à définir)
,m éléments effiloché de m, en particulier ...
? un élément aléatoire (numéro de lit.) dans une plage de
+/ la somme de
b←b , où b est
'O'= booléenne car où la lettre est égale à
,mm défilée

⎕DL 1D e l ay une seconde

→2 Passez à la ligne 2
/⍨ si (lit. filtré par)
'O'∊ si la lettre est membre de
⎕←m la valeur sortie, où la valeur sortie est m

Essayez-le en ligne!


À partir de la version 16.0, il sera plus court:

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

Adam
la source
1

Python 3, 195 188 octets

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)

Utiliser bytearrayet decodesemble être plus court que trancher et réassembler une chaîne à la 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()
RootTwo
la source
0

Java 7, 317 octets

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()));}}

Explication:

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 de test (4,6)

entrez la description de l'image ici

Kevin Cruijssen
la source
0

Perl, 148 octets

146 octets de code + -pldrapeaux.

$_=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

Pour l'exécuter:

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"
Dada
la source
0

MATLAB (R2016b), 172 octets

Code:

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

Les recommandations sont toujours les bienvenues! Essayez-le en ligne!

Sortie du programme:

entrez la description de l'image ici

Explication:

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
Grant Miller
la source