Class: Board

Inherits:
Object
  • Object
show all
Defined in:
lib/software_challenge_client/board.rb

Overview

A representation of a twixt game board

Author:

  • Ralf-Tobias Diekert

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(init) ⇒ Board

Initializes the board

Parameters:

  • init (Boolean)

    if ‘true’, then the board will be initialized with swamps, otherwise the board will be completely empty



27
28
29
# File 'lib/software_challenge_client/board.rb', line 27

def initialize
  self.init
end

Instance Attribute Details

#connectionsArray<Connection> (readonly)

Returns the board’s connections.

Returns:

  • (Array<Connection>)

    the board’s connections



18
19
20
# File 'lib/software_challenge_client/board.rb', line 18

def connections
  @connections
end

#fieldsArray<Array<Field>> (readonly)

Returns the board’s fields.

Returns:

  • (Array<Array<Field>>)

    the board’s fields



15
16
17
# File 'lib/software_challenge_client/board.rb', line 15

def fields
  @fields
end

Instance Method Details

#==(another_board) ⇒ Object



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/software_challenge_client/board.rb', line 297

def ==(another_board)
  for x in 0..(Constants.SIZE - 1)
    for y in 0..(Constants.SIZE - 1)
      if self.fields[x][y] != another_board.fields[x][y]
        return false;
      end
    end
  end
  if self.connections.length != another_board.connections.length
    return false;
  end
  for c in another_board.connections
    if self.connections.include?(c)
      return false
    end
  end

  return true;
end

#checkPossibleWire(x1, y1, x2, y2) ⇒ Boolean

checks, if a wire can be placed at specified coordinates

Parameters:

  • x1 (Integer)

    x-coordinate starting point

  • y1 (Integer)

    y-coordinate starting point

  • x2 (Integer)

    x-coordinate ending point

  • y2 (Integer)

    y-coordinate ending point

Returns:

  • (Boolean)

    ‘true’, if a wire can be placed at specified coordinates



167
168
169
170
171
172
173
174
# File 'lib/software_challenge_client/board.rb', line 167

def checkPossibleWire(x1, y1, x2, y2)
  if x2 < Constants::SIZE && y2 < Constants::SIZE && x2 >= 0 && y2 >= 0
    if self.fields[x2][y2].ownerColor == self.fields[x1][y1].ownerColor
      return !self.existsBlockingWire(x1, y1, x2, y2)
    end
  end
  return false
end

#createNewWires(x, y) ⇒ Object

creates wires at the coordinate (x, y), if it is possible

Parameters:

  • x (Integer)

    x-coordinate

  • y (Integer)

    y-coordinate



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/software_challenge_client/board.rb', line 122

def createNewWires(x, y)
  if self.checkPossibleWire(x, y, x - 2, y - 1)
    self.createWire(x, y, x - 2, y - 1)
  end
  if self.checkPossibleWire(x, y, x - 1, y - 2)
    self.createWire(x, y, x - 1, y - 2)
  end
  if self.checkPossibleWire(x, y, x - 2, y + 1)
    self.createWire(x, y, x - 2, y + 1)
  end
  if self.checkPossibleWire(x, y, x - 1, y + 2)
    self.createWire(x, y, x - 1, y + 2)
  end
  if self.checkPossibleWire(x, y, x + 2, y - 1)
    self.createWire(x, y, x + 2, y - 1)
  end
  if self.checkPossibleWire(x, y, x + 1, y - 2)
    self.createWire(x, y, x + 1, y - 2)
  end
  if self.checkPossibleWire(x, y, x + 2, y + 1)
    self.createWire(x, y, x + 2, y + 1)
  end
  if self.checkPossibleWire(x, y, x + 1, y + 2)
    self.createWire(x, y, x + 1, y + 2)
  end

end

#createWire(x1, y1, x2, y2) ⇒ Object

creates a new wire

Parameters:

  • x1 (Integer)

    x-coordinate starting point

  • y1 (Integer)

    y-coordinate starting point

  • x2 (Integer)

    x-coordinate ending point

  • y2 (Integer)

    y-coordinate ending point



156
157
158
# File 'lib/software_challenge_client/board.rb', line 156

def createWire(x1, y1, x2, y2)
  self.connections.push(Connection.new(x1, y1, x2, y2, self.fields[x1][y1].ownerColor))
end

#doIntersect(p1x, p1y, q1x, q1y, p2x, p2y, q2x, q2y) ⇒ Object



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/software_challenge_client/board.rb', line 246

def doIntersect(p1x,p1y, q1x,q1y, p2x,p2y, q2x,q2y)
  o1 = orientation(p1x,p1y, q1x,q1y, p2x,p2y)
  o2 = orientation(p1x,p1y, q1x,q1y, q2x,q2y)
  o3 = orientation(p2x,p2y, q2x,q2y, p1x,p1y)
  o4 = orientation(p2x,p2y, q2x,q2y, q1x,q1y)

  if o1 != o2 && o3 != o4
    return true
  end

  if o1 == 0 && onSegment(p1x,p1y, p2x,p2y, q1x,q1y)
    return true
  end

  if o2 == 0 && onSegment(p1x,p1y, q2x,q2y, q1x,q1y)
    return true
  end

  if o3 == 0 && onSegment(p2x,p2x, p1x,p1y, q2x,q2y)
    return true
  end

  if o4 == 0 && onSegment(p2x,p2y, q1x,q1y, q2x,q2y)
    return true
  end

  return false
end

#existsBlockingWire(x1, y1, x2, y2) ⇒ Boolean

checks, if a blocking wire exists

Parameters:

  • x1 (Integer)

    x-coordinate starting point

  • y1 (Integer)

    y-coordinate starting point

  • x2 (Integer)

    x-coordinate ending point

  • y2 (Integer)

    y-coordinate ending point

Returns:

  • (Boolean)

    ‘true’, if another wire would block the creation of a new wire at specified coordinates



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/software_challenge_client/board.rb', line 183

def existsBlockingWire(x1, y1, x2, y2)
  smallerX, biggerX = [x1, x2].minmax
  smallerY, biggerY = [y1, y2].minmax
  for x in smallerX..biggerX
    for y in smallerY..biggerY # checks all 6 Fields, from
      # where there could be
      # blocking connections
      if !self.fields[x][y].ownerColor.nil? && (x != x1 || y != y1) &&
          (x != x2 || y != y2) # excludes the Fields with no owner and
        # the fields (x1, y2), (x2, y2)
        # themselves.
        if self.isWireBlocked(x1, y1, x2, y2, x, y)
          return true
        end
      end
    end
  end
  return false
end

#getConnections(x, y) ⇒ Array

gets connections for the coordinate (x, y)

Parameters:

  • x (Integer)

    x-coordinate

  • y (Integer)

    y-coordinate

Returns:

  • (Array)

    Array of connections from field (x, y)



208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/software_challenge_client/board.rb', line 208

def getConnections(x, y)
  xyConnections = Array.new
  if !self.connections.nil?
    for c in self.connections
      if c.x1 == x && c.y1 == y
        xyConnections.push(Connection.new(x, y, c.x2, c.y2, c.ownerColor))
      end
      if c.x2 == x && c.y2 == y
        xyConnections.push(Connection.new(x, y, c.x1, c.y1, c.ownerColor))
      end
    end
  end
  return xyConnections
end

#getOwnerColor(x, y) ⇒ PlayerColor

gets the owner’s color for the field at the coordinate (x, y)

Parameters:

  • x (Integer)

    x-coordinate

  • y (Integer)

    y-coordinate

Returns:



103
104
105
# File 'lib/software_challenge_client/board.rb', line 103

def getOwnerColor(x, y)
  return self.fields[x][y].ownerColor
end

#initObject

Initializes the board with swamps



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/software_challenge_client/board.rb', line 36

def init
  @fields = Array.new(Constants::SIZE) {Array.new(Constants::SIZE)}
  @fields[0][0] = Field.new(FieldType::SWAMP, 0, 0)
  @fields[0][Constants::SIZE - 1] = Field.new(FieldType::SWAMP, 0, Constants::SIZE - 1)
  @fields[Constants::SIZE - 1][0] = Field.new(FieldType::SWAMP, Constants::SIZE - 1, 0)
  @fields[Constants::SIZE - 1][Constants::SIZE - 1] = Field.new(FieldType::SWAMP, Constants::SIZE - 1, Constants::SIZE - 1)
  for x in 1..(Constants::SIZE - 2)
    @fields[x][0] = Field.new(FieldType::RED, x, 0);
    @fields[x][Constants::SIZE - 1] = Field.new(FieldType::RED, x, Constants::SIZE - 1);
  end
  for y in 1..(Constants::SIZE - 2)
    @fields[0][y] = Field.new(FieldType::BLUE, 0, y);
    @fields[Constants::SIZE - 1][y] = Field.new(FieldType::BLUE, Constants::SIZE - 1, y);
  end
  for x in 1..(Constants::SIZE - 2)
    for y in 1..(Constants::SIZE - 2)
      @fields[x][y] = Field.new(FieldType::NORMAL, x, y);
    end
  end
  self.placeSwamps()
  @connections = Array.new;
end

#isWireBlocked(x1, y1, x2, y2, x, y) ⇒ Boolean

checks for the wire (x1, y1) -> (x2, y2), if it is blocked by any connection going out from (x,y).

Parameters:

  • x1 (Integer)

    x-coordinate starting point

  • y1 (Integer)

    y-coordinate starting point

  • x2 (Integer)

    x-coordinate ending point

  • y2 (Integer)

    y-coordinate ending point

  • x (Integer)

    x-coordinate comparison field

  • y (Integer)

    y-coordinate comparison field

Returns:

  • (Boolean)

    ‘true’, if another wire would block the creation of a new wire at specified coordinates



284
285
286
287
288
289
290
291
# File 'lib/software_challenge_client/board.rb', line 284

def isWireBlocked(x1, y1, x2, y2, x, y)
  for c in getConnections(x, y)
    if self.doIntersect(x1, y1, x2, y2, x, y, c.x2, c.y2)
      return true
    end
  end
  return false
end

#makeClearBoardObject

creates a cleared board



93
94
95
96
# File 'lib/software_challenge_client/board.rb', line 93

def makeClearBoard
  @fields = Array.new(Constants::SIZE) {Array.new(Constants::SIZE)}
  @connections = Array.new
end

#onSegment(px, py, qx, qy, rx, ry) ⇒ Object

following functions are helper functions for the blocking wire check www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/



225
226
227
228
229
230
231
# File 'lib/software_challenge_client/board.rb', line 225

def onSegment(px,py,qx,qy,rx,ry)
  if qx <= [px, rx].max && qx >= [px, rx].min &&
      qy <= [py, ry].max && qy >= [py, ry].min
    return true
  end
  return false
end

#orientation(px, py, qx, qy, rx, ry) ⇒ Object



233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/software_challenge_client/board.rb', line 233

def orientation(px,py,qx,qy,rx,ry)
  val = (qy - py) * (rx - qx) -
    (qx - px) * (ry - qy)

  if val == 0
    return 0
  end
  if val > 0
    return 1
  end
  return 2
end

#placeSwampsObject

Places swamps at random coordinates



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
# File 'lib/software_challenge_client/board.rb', line 60

def placeSwamps
  # big swamp
  x = 1 + SecureRandom.random_number(Constants::SIZE - 4)
  y = 1 + SecureRandom.random_number(Constants::SIZE - 4)
  for i in x..(x + 2)
    for j in y..(y + 2)
      self.fields[i][j].type = FieldType::SWAMP
    end
  end
  # first medium swamp
  x = 1 + SecureRandom.random_number(Constants::SIZE - 3)
  y = 1 + SecureRandom.random_number(Constants::SIZE - 3)
  for i in x..(x + 1)
    for j in y..(y + 1)
      self.fields[i][j].type = FieldType::SWAMP
    end
  end
  # second medium swamp
  x = 1 + SecureRandom.random_number(Constants::SIZE - 3)
  y = 1 + SecureRandom.random_number(Constants::SIZE - 3)
  for i in x..(x + 1)
    for j in y..(y + 1)
      self.fields[i][j].type = FieldType::SWAMP
    end
  end
  # little swamp
  x = 1 + SecureRandom.random_number(Constants::SIZE - 2)
  y = 1 + SecureRandom.random_number(Constants::SIZE - 2)
  self.fields[x][y].type = FieldType::SWAMP
end

#put(x, y, player) ⇒ Object

sets the owner’s color for the field at the coordinate (x, y)

Parameters:

  • x (Integer)

    x-coordinate

  • y (Integer)

    y-coordinate

  • player (Player)

    new owner of field (x, y)



113
114
115
116
# File 'lib/software_challenge_client/board.rb', line 113

def put(x, y, player)
  self.fields[x][y].owner = player.color;
  self.createNewWires(x, y);
end

#to_sObject



293
294
295
# File 'lib/software_challenge_client/board.rb', line 293

def to_s
  return self.fields.map { |f| f.map {|i| (i.ownerColor==PlayerColor::RED ? 'R' : (i.ownerColor==PlayerColor::BLUE ? 'B' : (i.type==FieldType::SWAMP ? 'S' : (i.type==FieldType::RED ? 'r' : (i.type==FieldType::BLUE ? 'b' : ' '))))) }.join(",")}.join("\n")
end