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



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

def initialize
  self.init
end

Instance Attribute Details

#connectionsArray<Connection> (readonly)

Returns the board’s connections.

Returns:

  • (Array<Connection>)

    the board’s connections



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

def connections
  @connections
end

#fieldsArray<Array<Field>> (readonly)

Returns the board’s fields.

Returns:

  • (Array<Array<Field>>)

    the board’s fields



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

def fields
  @fields
end

Instance Method Details

#==(another_board) ⇒ Object



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

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



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

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



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

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



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

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



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

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



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

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)



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

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:



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

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

#initObject

Initializes the board with swamps



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

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



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

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



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

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/



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

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



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

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



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

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)



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

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

#to_sObject



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

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