1votos

Planeta Wa-Tor en C#

por josejuan hace 6 años

La gracia de este problema, es que las reglas de concurrencia están enrevesadas. Hay muchas formas de enfocarlo, todas ellas dependen de la plataforma en que se implemente; por ejemplo, hacerlo de forma distribuida es muy diferente a concurrente localmente, etc...

El planeta Wa-Tor es un mundo acuático, toroidal y reticulado de dimensión 20x20. Este mundo está habitado por peces y tiburones de ambos sexos.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
enum Sex {Male, Female} 
 
enum Kind {Fish, Shark} 
 
class Specimen { 
 
  private Point p; 
  private Kind k; 
  private Sex s; 
  private bool d; 
  private Random r; 
 
  public Kind Kind { get {return k;} } 
  public Sex Sex { get {return s;} } 
  public bool Dead { get {return d;} set {d = value;} } 
  public Point Position { get {return p;} } 
 
  public void Move() { 
    p.X += r.Next() % 3 - 1; 
    p.Y += r.Next() % 3 - 1; 
 
  public Specimen(Kind kind, Sex sex, Point position) { 
    k = kind; 
    s = sex; 
    d = false; 
    r = new Random(); 
    p = position; 
 
 
class Cell { 
 
  private List<Specimen> g = new List<Specimen>(); 
 
  private void drop(Specimen c) { 
    g.Remove(c); 
 
  private void kill(Specimen c) { 
    drop(c); 
    c.Dead = true; 
 
  public Specimen Enter(Specimen s) { 
    Specimen d = null; 
    lock(this) 
      if(!s.Dead) {//no se ha dado cuenta que esta muerto 
        var contrincante = g.FirstOrDefault(c => s.Kind == c.Kind && s.Sex == c.Sex); 
        if(contrincante != null) 
          kill(new Random().Next() % 2 == 0 ? s : contrincante); 
        else { 
          g.Add(s); 
          if(s.Kind == Kind.Shark) 
            foreach(var f in g.Where(c => c.Kind == Kind.Fish).ToArray()) 
              kill(f); 
          if(g.Any(c => s.Kind == c.Kind && s.Sex != c.Sex)) 
            g.Add(d = new Specimen(s.Kind, new Random().Next() % 2 == 0 ? Sex.Male : Sex.Female, s.Position)); 
    return d; 
 
  public void Leave(Specimen s) { 
    lock(this) 
      drop(s); 
 
  public Cell() { 
 
 
class Wator { 
  private int s; 
  private Cell [] c; 
  private List<Specimen> f; 
 
  public int C(int c) { 
    return (s + (c % s)) % s; 
 
  private Cell Cell(Point p) { 
    return c [s * C(p.Y) + C(p.X)]; 
 
  private static void SpecimentController(object args) { 
    var s = (Specimen) ((object []) args) [0]; 
    var w = (Wator) ((object []) args) [1]; 
    while(!s.Dead) { 
      var c = w.Cell(s.Position).Enter(s); 
      if(c != null) 
        w.CreateLife(c); 
      Thread.Sleep(200); 
      w.Cell(s.Position).Leave(s); 
      s.Move(); 
    lock(w.f) 
      w.f.Remove(s); 
 
  public void CreateLife(Specimen c) { 
    lock(f) 
      f.Add(c); 
    new Thread(new ParameterizedThreadStart(SpecimentController)).Start(new object [] { c, this }); 
 
  public void CreateLife(Kind kind, Sex sex) { 
    CreateLife(new Specimen(kind, sex, new Point(new Random().Next(), new Random().Next()))); 
 
  public Specimen [] GetSnapShot() { 
    lock(f) 
      return f.Select(s => new Specimen(s.Kind, s.Sex, s.Position)).ToArray(); 
 
  public Wator(int size) { 
    s = size; 
    c = Enumerable.Range(0, s * s).Select(_ => new Cell()).ToArray(); 
    f = new List<Specimen>(); 
 
  public int Size { 
    get { 
      return s; 
2 comentarios
0votos

Escrito por ZeroRendan hace 6 años

amigo una pregunta estoy tratando de replicar tu programa que using utilizaste? era de consola o de windowsform o utilizaste mono?
0votos

Escrito por josejuan hace 6 años

Es una clase que encapsula el funcionamiento, puedes usarla donde mejor convenga.

Algo como:

var myWorld = new Wator( 50 );

Enumerable.
  Range(0, 50).
  ToList().
  ForEach(n =>
    myWorld.
    CreateLife(
      n % 3 == 0 ? Kind.Shark : Kind.Fish,
      n % 2 == 0 ? Sex.Male : Sex.Female
    )
  );

while(!Console.HasKey) {
  Thread.Sleep(500);
  // hacer algo con myWorld.GetSnapShot()
}


Yo hice un window.form que mostraba en tiempo real la evolución del sistema y permitía ir añadiendo especímenes, pero no se si lo tengo por ahí. Vere...

Comenta la solución

Tienes que identificarte para poder publicar tu comentario.