Conway'in Hayat Oyununu uygulamanın kapalı programlama yolları nelerdir [kapalı]


12

Geçenlerde Javascript (aslında kahve ama aynı şey) eğlenceli Conway'in Hayat Oyunu için uygulandı . Javascript işlevsel bir dil olarak kullanılabileceğinden spektrumun sonuna kadar kalmaya çalışıyordum. Sonuçlarımdan memnun değildim. Oldukça iyi bir OO programcısıyım ve çözümüm aynı-eskiden-eskisine takıldı. Uzun soru kısa: bunu (pseudocode) işlevsel tarzı nedir?

İşte benim girişim için Pseudocode:

class Node
  update: (board) ->
    get number_of_alive_neighbors from board
    get this_is_alive from board
    if this_is_alive and number_of_alive_neighbors < 2 then die
    if this_is_alive and number_of_alive_neighbors > 3 then die
    if not this_is_alive and number_of_alive_neighbors == 3 then alive

class NodeLocations
  at: (x, y) -> return node value at x,y
  of: (node) -> return x,y of node

class Board
  getNeighbors: (node) -> 
   use node_locations to check 8 neighbors 
   around node and return count

nodes = for 1..100 new Node
state = new NodeState(nodes)
locations = new NodeLocations(nodes)
board = new Board(locations, state)

executeRound:
  state = clone state
  accumulated_changes = for n in nodes n.update(board)
  apply accumulated_changes to state
  board = new Board(locations, state)


@ Depresyonda kafamın üstünde. Temel kavramları tanıyorum ama sadece zar zor
George Mauer

Başımın üzerinden de ... Özel bir dil ustasının neler yapabileceğine bir örnek olarak yayınladım. Hepimiz için ilham kaynağı olarak adlandırın :)
Oded

@GeorgeMauer "aslında kahve ama aynı şey" bu üzücü bir gün
Raynos

Yanıtlar:


11

Birkaç fikir. FP'de uzman değilim, ama ...

BoardBir oyun durumunu temsil eden bir tipe sahip olmamız gerektiği açıktır . Uygulamanın temeli bir tür evolveişlev olmalıdır evolve :: Board -> Board; yani Boardoyunun kurallarını uygulamaktan a üretir Board.

Nasıl uygulamalıyız evolve? A Boardmuhtemelen Cells'nin nxm matrisi olmalıdır . Bir ve onun komşusuna verilen durumu bir sonraki yinelemede hesaplayan cellEvolvetipte bir fonksiyon uygulayabiliriz .cellEvolve :: Cell -> [Cell] -> CellCellCellCell

Ayrıca bir getCellNeighborskomşuyu Cella Board. Bu yöntemin imzasından tam olarak emin değilim; nasıl uyguladığınıza Cellve Boardörneğin getCellNeighbors :: Board -> CoordElem -> CoordElem -> [Cell], bir Tahta ve iki koordinat ( CoordElema'daki dizinleri indekslemek için kullanılan tür olurdu Board) verdiğinize bağlı olarak, size komşuların değişken uzunluklu bir listesini verir (karttaki tüm hücrelerde aynı sayıda komşu köşesinde 3 komşu, sınır 5 ve diğer herkes, 8) vardır.

evolveböylece, birleştirilerek cellEvolveve karttaki getCellNeighborstüm hücreler için uygulanabilir , yine kesin uygulama nasıl uyguladığınıza bağlı olacaktır Boardve Cellancak "mevcut karttaki tüm hücreler için komşularını alın ve bunları hesaplamak için kullanın" gibi bir şey olmalıdır. Yeni kartın karşılık gelen hücresi "Bu," kartın hücre fonksiyonu üzerinden harita "kullanılarak bu fonksiyonların tüm kart üzerinde genel bir uygulamayla yapılabilmesi gerekir.

Diğer düşünceler:

  • cellEvolveBir parametre olarak GameRulesoyunun kurallarını kodlayan bir tür alması için gerçekten uygulamanız gerekir - (State,[(State,NumberOfNeighbors)],State)belirli bir durum için söylenen bir grup listesi ve her eyaletteki komşuların sayısını, bir sonraki yinelemede durum olması gerektiğini söyleyin . cellEvolveimzası olabilircellEvolve :: GameRules -> Cell -> [Cell] -> Cell

  • Bu, mantıksal olarak evolve :: Board -> Boarddönüşüme girmenizi sağlar evolve :: GameRules -> Board -> Board, böylece evolvefarklı ile değişmeden kullanabilirsiniz GameRules, ancak bir adım daha ileri gidebilir ve cellEvolveyerine takılabilir yapabilirsiniz GameRules.

  • getCellNeighborsSizinle oynamak aynı zamanda 'topolojisi evolveile ilgili genel Boardolabilir- her getCellNeighborsiki tahta kenarları, 3d panoları, vb etrafında sarmak olabilir .


9

Life'ın işlevsel bir programlama sürümünü yazıyorsanız, Gosper'ın Algoritması hakkında bilgi edinmek için kendinize borçlusunuz. Bir tarafta trilyonlarca karede panolarda saniyede trilyonlarca nesil elde etmek için fonksiyonel programlamadan fikirler kullanır . Kulağa imkansız geliyor biliyorum ama tamamen mümkün; Kolayca bir tarafta kare panoları 2 ^ 64 kareleri işleyen C # güzel bir küçük uygulama var.

İşin püf noktası, zaman ve mekân boyunca Yaşam panolarının muazzam öz benzerliklerinden yararlanmaktır. Tahtanın büyük bölümlerinin gelecekteki durumunu hatırlayarak büyük bölümleri aynı anda hızla ilerletebilirsiniz.

Uzun yıllardır Gosper'ın Algoritması'na yeni başlayan bir giriş yazmayı planlıyorum, ama hiç zamanım olmadı. Sonunda bunu yaparsam, buraya bir bağlantı göndereceğim.

Gosper'ın Hipergeometrik toplamları hesaplamak için kullanılan Algoritmasını değil, Gosper'ın Yaşam için Algoritmasını hesaplamak istediğinizi unutmayın .


ilginç görünüyor - yine de bu bağlantıyı bekliyor ...;)
jk.


3

İlham almak için RosettaCode'daki uygulamalara bakmak isteyebilirsiniz .

Örneğin, grafiksel OCaml sürümü iki dizi kullanır ve bunları dönüşümlü olarak hız için güncellerken, her bir dönüşe bir öncekine yeni bir kart oluşturan işlevsel Haskell ve OCaml sürümleri vardır.

Uygulamaların bazıları kurulu ayrıştırmak güncelleme için fonksiyonlar içine fonksiyonu sayma , mahalle uygulayarak yaşam kuralı ve yineleme tahtası üzerinde. Bunlar fonksiyonel bir tasarımı temel alan yararlı bileşenler gibi görünüyor. Diğer her şeyi saf işlevler olarak koruyarak yalnızca kartı değiştirmeyi deneyin.


1

İşte Clojure'da tamamen işlevsel bir kısa versiyon. Tüm kredi, bunu blog yazısında yayınlayan Christophe Grand'a gidiyor: Conway'in Hayat Oyunu

(defn neighbours [[x y]]
  (for [dx [-1 0 1] 
        dy (if (zero? dx) [-1 1] [-1 0 1])]
    [(+ dx x) (+ dy y)]))

(defn step [cells]
  (set (for [[loc n] (frequencies (mapcat neighbours cells))
             :when (or (= n 3) (and (= n 2) (cells loc)))]
         loc)))

Oyun daha sonra bir dizi hücreye "adım" işlevini tekrar tekrar uygulayarak oynanabilir, örneğin:

(step #{[1 0] [1 1] [1 2]})
=> #{[2 1] [1 1] [0 1]}

Akıllılık (mapcat komşu hücreleri) kısmıdır - bunun yaptığı, aktif hücrelerin her biri için sekiz komşunun bir listesini oluşturmak ve hepsini bir araya getirmektir. Daha sonra, bu listede her hücrenin kaç kez göründüğü (frekanslar ....) ile sayılabilir ve son olarak doğru frekans sayımına sahip olanlar onu bir sonraki nesle aktarır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.