Class: Lifegame::Game

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/lifegame/game.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(x, y) ⇒ Game

Returns a new instance of Game.



7
8
9
10
11
12
# File 'lib/lifegame/game.rb', line 7

def initialize(x, y)
  @x = x
  @y = y
  @lifes = x.times.map { |x| y.times.map { |y| Life.new } }
  @generation = 0
end

Instance Attribute Details

#lifesObject (readonly)

Returns the value of attribute lifes.



113
114
115
# File 'lib/lifegame/game.rb', line 113

def lifes
  @lifes
end

Instance Method Details

#[](x, y) ⇒ Object



14
15
16
17
18
19
# File 'lib/lifegame/game.rb', line 14

def [](x, y)
  return nil if x.negative? || y.negative?
  return nil if x > @x || y > @y

  @lifes.fetch(x, []).fetch(y, nil)
end

#eachObject



21
22
23
24
25
26
27
# File 'lib/lifegame/game.rb', line 21

def each
  @lifes.each.with_index { |line, x|
    line.each.with_index { |life, y|
      yield(life, x: x, y: y)
    }
  }
end

#next!Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/lifegame/game.rb', line 29

def next!
  self.
    # 調べて
    map { |_, point| { live: next_alive?(point[:x], point[:y]), x: point[:x], y: point[:y] } }.
    # 実施
    each do |life_point|
    x = life_point[:x]
    y = life_point[:y]

    if life_point[:live]
      self[x, y].be!
    else
      self[x, y].die!
    end
  end
  @generation += 1
end

#next_alive?(x, y) ⇒ Boolean

あるセルが次のターンに生きてるか確認する

Returns:

  • (Boolean)


48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/lifegame/game.rb', line 48

def next_alive?(x, y)
  target = self[x, y]

  # 隣接セルの座標
  adjoining = [
    [x - 1, y - 1],
    [x    , y - 1],
    [x + 1, y - 1],
    [x - 1, y],
    # [x    , y],
    [x + 1, y],
    [x - 1, y + 1],
    [x    , y + 1],
    [x + 1, y + 1],
  ]

  dead_or_live = adjoining.map { |point|
    n_x, n_y = point
    self[n_x, n_y]&.alive?
  }.compact

  live_count = dead_or_live.count { |live| live }

  if target.dead?
    # 3の時のみ誕生
    live_count == 3
  else
    # 2,3の時のみ生き残る
    (2..3).include?(live_count)
  end
end


88
89
90
91
92
93
# File 'lib/lifegame/game.rb', line 88

def print
  # clear
  s = to_s
  puts "\e[H\e[2J"
  puts s
end

#sow!(alive_frequency = 0.2) ⇒ Object



105
106
107
108
109
110
111
# File 'lib/lifegame/game.rb', line 105

def sow!(alive_frequency = 0.2)
  self.each do |life, _point|
    if alive_frequency > rand
      life.be!
    end
  end
end

#start(wait_time = 0.1) ⇒ Object



95
96
97
98
99
100
101
102
103
# File 'lib/lifegame/game.rb', line 95

def start(wait_time = 0.1)
  loop {
    print
    sleep wait_time
    next!
  }
rescue Interrupt
  puts 'good bye world!'
end

#to_sObject



80
81
82
83
84
85
86
# File 'lib/lifegame/game.rb', line 80

def to_s
  lifes = @lifes.map { |line| line.map {|life| "#{life.to_s}"}.join }.join("\n")
  alives = count { |life| life.alive? }
  deads = count { |life| life.dead? }

  "generation: #{@generation}, x: #{@x}, y: #{@y}, all: #{@x * @y}, alive: #{alives}, dead: #{deads}\n#{lifes}"
end