software_challenge_client 19.1.0 → 20.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,17 +0,0 @@
1
- # coding: utf-8
2
- # frozen_string_literal: true
3
-
4
- # Ein Koordinatenpaar für ein zweidimensionales Koordinatensystem.
5
- class Coordinates
6
-
7
- # X-Koordinate
8
- attr_reader :x
9
- # Y-Koordinate
10
- attr_reader :y
11
-
12
- # Erstellt ein neues Koordinatenpaar aus X- und Y-Koordinate.
13
- def initialize(x, y)
14
- @x = x
15
- @y = y
16
- end
17
- end
@@ -1,30 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'typesafe_enum'
4
- # Der Typ eines Feldes des Spielbrettes. Es gibt folgende Typen:
5
- # - EMPTY
6
- # - RED
7
- # - BLUE
8
- # - OBSTRUCTED
9
- #
10
- # Zugriff z.B. mit FieldType::RED
11
- class FieldType < TypesafeEnum::Base
12
- new :EMPTY, '~'
13
- new :RED, 'R'
14
- new :BLUE, 'B'
15
- new :OBSTRUCTED, 'O'
16
-
17
- # @param field_type [FieldType] Der Feldtyp, zu dem die Spielerfarbe ermittelt werden soll.
18
- # @return [PlayerColor] Die zum Feldtyp gehörende Spielerfarbe, also PlayerColor::RED für FieldType::RED und PlayerColor::BLUE für FieldType::BLUE. In allen anderen Fällen PlayerColor::NONE.
19
- # @see PlayerColor#field_type
20
- def self.player_color(field_type)
21
- case field_type
22
- when FieldType::RED
23
- PlayerColor::RED
24
- when FieldType::BLUE
25
- PlayerColor::BLUE
26
- else
27
- PlayerColor::NONE
28
- end
29
- end
30
- end
@@ -1,126 +0,0 @@
1
- # coding: utf-8
2
- # frozen_string_literal: true
3
-
4
- require_relative './util/constants'
5
- require_relative 'direction'
6
- require_relative 'coordinates'
7
- require_relative 'line_direction'
8
-
9
- # Ein Iterator, der alle Koordinatenpaare auf einer Linie des Spielbrettes enthält.
10
- class Line
11
- include Enumerable
12
- include Constants
13
-
14
- # Erzeugt einen neuen Iterator.
15
- #
16
- # @param start [Coordinates]
17
- # @param direction [LineDirection]
18
- def initialize(start, direction)
19
- @direction = direction
20
- @start = start
21
- # we will iterate from left to right, so find the leftmost field on the line
22
- # inside the field note that (0,0) is the lowest, leftmost point, x-axis
23
- # goes to the right, y-axis goes up
24
- case @direction
25
- when LineDirection::HORIZONTAL
26
- leftmost_x = 0
27
- leftmost_y = @start.y
28
- when LineDirection::VERTICAL
29
- leftmost_x = @start.x
30
- leftmost_y = SIZE - 1
31
- when LineDirection::RISING_DIAGONAL
32
- # for rising diagonals, we have to decrease x and y
33
- shift = [@start.x, @start.y].min
34
- leftmost_x = @start.x - shift
35
- leftmost_y = @start.y - shift
36
- when LineDirection::FALLING_DIAGONAL
37
- # for falling diagonals, we have to decrease x and increase y
38
- shift = [@start.x, (SIZE - 1) - @start.y].min
39
- leftmost_x = @start.x - shift
40
- leftmost_y = @start.y + shift
41
- end
42
- @xi = leftmost_x
43
- @yi = leftmost_y
44
-
45
- @members = []
46
- while @xi >= 0 && @yi >= 0 && @xi < SIZE && @yi < SIZE
47
- @members << Coordinates.new(@xi, @yi)
48
- # horizontal lines and diagonals move right
49
- if [LineDirection::HORIZONTAL,
50
- LineDirection::RISING_DIAGONAL,
51
- LineDirection::FALLING_DIAGONAL].include? @direction
52
- @xi += 1
53
- end
54
- # vertical lines and falling diagonals move down
55
- if [LineDirection::VERTICAL,
56
- LineDirection::FALLING_DIAGONAL].include? @direction
57
- @yi -= 1
58
- elsif @direction == LineDirection::RISING_DIAGONAL
59
- # rising diagonals move up
60
- @yi += 1
61
- end
62
- end
63
- end
64
-
65
- def each(&block)
66
- @members.each(&block)
67
- end
68
-
69
- # Begrenzt den Iterator auf Koordinatenpaare von Feldern innerhalb der gegebenen beiden Koordinatenpaare (exklusive).
70
- # Kann als Filter verwendet werden.
71
- #
72
- # @example
73
- # Line.new(
74
- # Coordinates.new(2, 3), LineDirection::HORIZONTAL
75
- # ).select do |c|
76
- # Line.between(Coordinates.new(2, 3), Coordinates.new(5, 3), LineDirection::HORIZONTAL).call(c)
77
- # end
78
- def self.between(start, bound, direction)
79
- lower_x = [start.x, bound.x].min
80
- lower_y = [start.y, bound.y].min
81
- higher_x = [start.x, bound.x].max
82
- higher_y = [start.y, bound.y].max
83
- proc do |f|
84
- case direction
85
- when LineDirection::HORIZONTAL
86
- f.x > lower_x && f.x < higher_x
87
- when LineDirection::VERTICAL
88
- f.y > lower_y && f.y < higher_y
89
- when LineDirection::RISING_DIAGONAL, LineDirection::FALLING_DIAGONAL
90
- f.x > lower_x && f.x < higher_x && f.y > lower_y && f.y < higher_y
91
- else
92
- throw `unknown direction ${direction}`
93
- end
94
- end
95
- end
96
-
97
- # @param line_direction [LineDirection] Ausrichtung der Linie
98
- # @return [Array<Direction>] Die beiden Bewegungsrichtungen, die auf einer Linie mit der Ausrichtung möglich sind.
99
- def self.directions_for_line_direction(line_direction)
100
- case line_direction
101
- when LineDirection::HORIZONTAL
102
- [Direction::LEFT, Direction::RIGHT]
103
- when LineDirection::VERTICAL
104
- [Direction::UP, Direction::DOWN]
105
- when LineDirection::RISING_DIAGONAL
106
- [Direction::UP_RIGHT, Direction::DOWN_LEFT]
107
- when LineDirection::FALLING_DIAGONAL
108
- [Direction::UP_LEFT, Direction::DOWN_RIGHT]
109
- end
110
- end
111
-
112
- # @param line_direction [Direction] Bewegungsrichtung
113
- # @return [Array<Direction>] Die Ausrichtung einer Linie, die auf der Bewegungsrichtung liegt.
114
- def self.line_direction_for_direction(direction)
115
- case direction
116
- when Direction::LEFT, Direction::RIGHT
117
- LineDirection::HORIZONTAL
118
- when Direction::UP, Direction::DOWN
119
- LineDirection::VERTICAL
120
- when Direction::UP_RIGHT, Direction::DOWN_LEFT
121
- LineDirection::RISING_DIAGONAL
122
- when Direction::UP_LEFT, Direction::DOWN_RIGHT
123
- LineDirection::FALLING_DIAGONAL
124
- end
125
- end
126
- end
@@ -1,84 +0,0 @@
1
- # encoding: utf-8
2
- require_relative 'debug_hint'
3
-
4
- # Ein Spielzug. Er ist definiert durch das Koordinatenpaar des Ausgangsfeldes (ein Fisch des Spielers, der den Zug machen will) und eine Bewegungsrichtung.
5
- class Move
6
- # @!attribute [r] x
7
- # @return [Integer] X-Koordinate des Fisches, der bewegt werden soll. Die Spalte ganz links auf dem Spielbrett hat X-Koordinate 0, die ganz rechts 9.
8
- attr_reader :x
9
-
10
- # @!attribute [r] y
11
- # @return [Integer] Y-Koordinate des Fisches, der bewegt werden soll. Die Zeile ganz unten auf dem Spielbrett hat Y-Koordinate 0, die ganz oben 9.
12
- attr_reader :y
13
-
14
- # @!attribute [r] direction
15
- #
16
- # @return [Direction] Die Richtung, in die bewegt werden soll.
17
- attr_reader :direction
18
-
19
- # @!attribute [r] hints
20
- # @return [Array<DebugHint>] Hinweise, die an den Zug angeheftet werden sollen. Siehe {DebugHint}.
21
- attr_reader :hints
22
-
23
- # Erstellt einen neuen Zug.
24
- # @param x [Integer]
25
- # @param y [Integer]
26
- # @param direction [Direction]
27
- def initialize(x, y, direction)
28
- @x = x
29
- @y = y
30
- @direction = direction
31
- @hints = []
32
- end
33
-
34
- # @param hint [DebugHint]
35
- def add_hint(hint)
36
- @hints.push(hint)
37
- end
38
-
39
- def ==(other)
40
- x == other.x && y == other.y && direction == other.direction
41
- end
42
-
43
- def to_s
44
- "Move: (#{x},#{y}) #{direction}"
45
- end
46
-
47
- # @return [Coordinates] Die Koordinaten des Ausgangsfeldes des Zuges als Koordinatenpaar.
48
- def from_field
49
- Coordinates.new(x, y)
50
- end
51
-
52
- # Überprüft, ob der Zug in dem gegebenen Spielzustand regelkonform ausgeführt werden kann.
53
- # @param gamestate [GameState]
54
- # @return [Boolean]
55
- def valid?(gamestate)
56
- GameRuleLogic.valid_move?(self, gamestate.board, gamestate.current_player_color)
57
- end
58
-
59
- # Führt den Zug in dem gegebenen Spielzustand aus. Sollte dabei gegen Spielregeln verstossen werden, wird eine InvalidMoveException geworfen.
60
- # @param gamestate [GameState]
61
- def perform!(gamestate)
62
- if GameRuleLogic.valid_move?(self, gamestate.board, gamestate.current_player_color)
63
- type = gamestate.board.field(x, y).type
64
- target = GameRuleLogic.move_target(self, gamestate.board)
65
- gamestate.board.change_field(x, y, FieldType::EMPTY)
66
- gamestate.board.change_field(target.x, target.y, type)
67
- else
68
- raise InvalidMoveException.new('Invalid move', self)
69
- end
70
- # change the state to the next turn
71
- gamestate.last_move = self
72
- gamestate.turn += 1
73
- gamestate.switch_current_player
74
- gamestate.condition = GameRuleLogic.winning_condition(gamestate)
75
- end
76
-
77
-
78
- # Ermittelt die Koordinaten des Zielfeldes des Zuges mit einer gegebenen Zugweite.
79
- # @param speed [Integer] Die Zugweite. Entspricht normalerweise der Anzahl der Fische auf der Bewegungslinie.
80
- # @return [Coordinates] Koordinaten des Zielfeldes. Eventuell ausserhalb des Spielbrettes.
81
- def target_field(speed)
82
- direction.translate(from_field, speed)
83
- end
84
- end