4 votes

Jeu de la vie en Ruby avec Gosu - action de mise à jour ne fonctionne pas

Je crée Game of Life en Ruby en utilisant Gosu. Mon code est ci-dessous. Pour l'instant, lorsque j'exécute 'ruby gosu.rb', il ouvre la fenêtre avec les bonnes dimensions et le Monde pré-peuplé comme il se doit.

Mais dès que je dé-commente '@game.tick!' dans le fichier gosu file update action, en exécutant 'ruby gosu.rb', j'obtiens l'écran noir sans le Monde pré-peuplé que je ne peux pas fermer. Pourquoi est-ce que cela se produit et comment réparer cela ?

Vous pouvez trouver le dépôt GitHub avec le reste du code ici. Toute aide est appréciée.

Voici mon game_of_life.rb

class Game
  attr_accessor :world

  def initialize(world=World.new, seeds=[])
    @world = world
    seeds.each do |seed|
      world.cell_board[seed[0]][seed[1]].alive = true
    end
  end

  def tick!
    next_round_live_cells = []
    next_round_dead_cells = []

    world.cells.each do |cell|
      # Règle 1: 
      # Toute cellule vivante avec moins de deux voisins vivants meurt
      if cell.alive? && world.live_neighbours_around_cell(cell).count < 2
        next_round_dead_cells << cell
      end
      # Règle 2:
      # Toute cellule vivante avec deux ou trois voisins vivants survit à la génération suivante
      if cell.alive? && world.live_neighbours_around_cell(cell).count == (2 || 3)
        next_round_live_cells << cell
      end
      # Règle 3:
      # Toute cellule vivante avec plus de trois voisins vivants meurt
      if cell.alive? && world.live_neighbours_around_cell(cell).count > 3
        next_round_dead_cells << cell
      end
      # Règle 4:
      # Toute cellule morte avec exactement trois voisins vivants devient une cellule vivante
      if cell.dead? && world.live_neighbours_around_cell(cell).count == 3
        next_round_live_cells << cell
      end
    end

    next_round_live_cells.each do |cell|
      cell.revive!
    end
    next_round_dead_cells.each do |cell|
      cell.die!
    end
  end
end

class World
  attr_accessor :rows, :cols, :cell_board, :cells

  # Schéma de matrice de monde initialisée par défaut
  #------------------------
  #     0     1     2
  # 0 [ mort, mort, mort ]
  # 1 [ mort, vivant, mort ]
  # 2 [ mort, mort, mort ]
  #-----------------------

  def initialize(rows=3, cols=3)
    @rows = rows
    @cols = cols
    @cells = []

    @cell_board = Array.new(rows) do |row|
      Array.new(cols) do |col|
        Cell.new(col, row) # notez que col est en 1er, puis row
      end
    end

    cell_board.each do |row|
      row.each do |element|
        if element.is_a?(Cell)
          cells << element
        end
      end
    end
  end

  def live_cells
    cells.select { |cell| cell.alive }
  end

  def dead_cells
    cells.select { |cell| cell.alive == false }
  end

  def live_neighbours_around_cell(cell)
    live_neighbours = []
    live_cells.each do |live_cell|
      # Voisin au Nord
      if live_cell.x == cell.x - 1 && live_cell.y == cell.y
        live_neighbours << live_cell
      end
      # Voisin au Nord-Est
      if live_cell.x == cell.x - 1 && live_cell.y == cell.y + 1
        live_neighbours << live_cell
      end
      # Voisin à l'Est
      if live_cell.x == cell.x && live_cell.y == cell.y + 1
        live_neighbours << live_cell
      end
      # Voisin au Sud-Est
      if live_cell.x == cell.x + 1 && live_cell.y == cell.y + 1
        live_neighbours << live_cell
      end
      # Voisin au Sud
      if live_cell.x == cell.x + 1 && live_cell.y == cell.y
        live_neighbours << live_cell
      end
      # Voisin au Sud-Ouest
      if live_cell.x == cell.x + 1 && live_cell.y == cell.y - 1
        live_neighbours << live_cell
      end
      # Voisin à l'Ouest
      if live_cell.x == cell.x && live_cell.y == cell.y - 1
        live_neighbours << live_cell
      end
      # Voisin au Nord-Ouest
      if live_cell.x == cell.x - 1 && live_cell.y == cell.y - 1
        live_neighbours << live_cell
      end
    end
    live_neighbours
  end

  def randomly_populate
    cells.each do |cell|
      cell.alive = [true, false].sample
    end
  end

end

class Cell
  attr_accessor :x, :y, :alive #, :height, :width

  def initialize(x=0, y=0)
    @x = x
    @y = y
    @alive = false

    # Gosu
    # @height = height
    # @width = width
  end

  def alive?
    alive
  end

  def dead?
    !alive
  end

  def die!
    @alive = false
  end

  def revive!
    @alive = true # same as > self.alive = true
  end

Voici mon code gosu

require 'gosu'
require_relative 'gol.rb'

class GameOfLifeWindow < Gosu::Window

  def initialize(height=800, width=600)

    # Basics
    @height = height
    @width = width
    super height, width, false, 500
    self.caption = 'My Game of Life'

    # Colors
    @white = Gosu::Color.new(0xffededed)
    @black = Gosu::Color.new(0xff121212)

    # Game world
    @rows = height/10
    @cols = width/10
    world = World.new(@cols, @rows)
    @game = Game.new(world)
    @row_height = height/@rows
    @col_width = width/@cols
    @game.world.randomly_populate

    @generation = 0
  end

  def update
#    unless @game.world.live_cells.count == 0
#      @game.tick!
      @generation += 1
#    end
  end

  def draw
    @game.world.cells.each do |cell|
      if cell.alive?
        draw_quad(cell.x * @col_width, cell.y * @row_height, @black,
                  cell.x * @col_width + @col_width, cell.y * @row_height, @black,
                  cell.x * @col_width + @col_width, cell.y * @row_height + @row_height, @black,
                  cell.x * @col_width, cell.y * @row_height + @row_height, @black)
      end
    end
  end

  def button_down(id)
    case id
    when Gosu::KbSpace
      @game.world.randomly_populate
    when Gosu::KbEscape
      close
    end
  end

  def draw_background
    draw_quad(0, 0, @white,
              width, 0, @white,
              width, height, @white,
              0, height, @white)
  end

end

window = GameOfLifeWindow.new
window.show

2voto

oFca Points 751

D'accord, je sais maintenant que le code est correct, il faut juste beaucoup de cycles pour passer la méthode tick!.

J'ai réalisé des tutoriels vidéo couvrant la création du Game of Life en Ruby en utilisant TDD avec la bibliothèque de jeux Rspec et Gosu, vous pouvez les consulter ici > http://svenduplic.com/2013/03/25/conways-game-of-life-in-ruby.html

ils contiennent la création du jeu du début à la fin, avec des explications sur chaque ligne. À la fin, j'explique pourquoi ce code prend beaucoup de temps à s'exécuter et comment l'optimiser correctement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X