sea_battle 0.1.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +60 -35
- data/lib/sea_battle/board.rb +65 -8
- data/lib/sea_battle/cell.rb +9 -0
- data/lib/sea_battle/gui.rb +122 -56
- data/lib/sea_battle/random_ship.rb +2 -7
- data/lib/sea_battle/support.rb +15 -0
- data/lib/sea_battle/version.rb +1 -1
- data/lib/sea_battle.rb +20 -0
- data/spec/sea_battle/board_spec.rb +60 -13
- data/spec/sea_battle/gui_spec.rb +1 -1
- data/spec/sea_battle_spec.rb +22 -1
- metadata +3 -2
data/README.md
CHANGED
@@ -18,55 +18,80 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
Initialize board of the game
|
21
|
+
### Initialize board of the game
|
22
22
|
|
23
23
|
$ require "sea_battle"
|
24
24
|
|
25
25
|
$ board = SeaBattle::Board.new.board
|
26
26
|
$ board[0][3].is_attacked?
|
27
27
|
|
28
|
-
Add random ship on the board
|
28
|
+
### Add random ship on the board
|
29
29
|
|
30
30
|
$ require "random_ship"
|
31
31
|
...
|
32
32
|
|
33
33
|
SeaBattle::RandomBoard.new(board, 3).add_ship
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
$ sea_battle
|
38
|
-
|
39
|
-
#=> SEA BATTLE
|
40
|
-
|
41
|
-
#=> A B C D E F G H I J A B C D E F G H I J
|
42
|
-
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
43
|
-
#=> 0 │ │ │ │ │ │ │ │ ◯ │ │ │ 0 │ │ │ │ │ │ │ │ │ │ │
|
44
|
-
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
45
|
-
#=> 1 │ ◯ │ │ │ │ │ │ │ │ │ ◯ │ 1 │ │ │ │ │ │ │ │ │ │ │
|
46
|
-
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
47
|
-
#=> 2 │ ◯ │ │ │ │ │ │ │ │ │ ◯ │ 2 │ │ │ │ │ │ │ • │ • │ │ │
|
48
|
-
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
49
|
-
#=> 3 │ ◯ │ │ ⬤ │ ⬤ │ │ │ │ │ │ │ 3 │ │ │ │ │ │ │ │ • │ │ │
|
50
|
-
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
51
|
-
#=> 4 │ ⬤ │ │ │ │ │ ◯ │ │ │ │ │ 4 │ │ │ │ │ │ • │ │ │ │ │
|
52
|
-
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
53
|
-
#=> 5 │ │ │ ◯ │ │ │ ◯ │ │ │ │ ◯ │ 5 │ │ │ │ │ │ │ │ │ │ │
|
54
|
-
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
55
|
-
#=> 6 │ ◯ │ │ │ │ │ │ │ ◯ │ │ │ 6 │ │ │ │ │ │ │ │ │ │ │
|
56
|
-
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
57
|
-
#=> 7 │ │ │ ◯ │ │ │ │ │ ◯ │ │ │ 7 │ │ │ │ │ │ │ │ │ │ │
|
58
|
-
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
59
|
-
#=> 8 │ │ │ ◯ │ │ │ │ │ ◯ │ │ │ 8 │ │ │ │ │ │ │ │ │ │ │
|
60
|
-
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
61
|
-
#=> 9 │ │ │ ◯ │ │ │ │ │ │ │ │ 9 │ │ │ │ │ │ │ │ │ │ │
|
62
|
-
|
63
|
-
#=> 4a, ... - select part of ship
|
64
|
-
#=> (e)xit of game
|
65
|
-
|
66
|
-
Use class SeaBattle
|
35
|
+
### Use class SeaBattle
|
67
36
|
|
68
37
|
$ require "sea_battle"
|
69
38
|
|
70
39
|
$ first_board = SeaBattle::Board.new
|
71
40
|
$ second_board = SeaBattle::Board.new
|
72
|
-
$ SeaBattle.new(first_board, second_board)
|
41
|
+
$ sea_battle = SeaBattle.new(first_board, second_board)
|
42
|
+
|
43
|
+
#### Game is activated?
|
44
|
+
$ sea_battle.is_activated?
|
45
|
+
|
46
|
+
#### You can get which player is active
|
47
|
+
$ sea_battle.active_user #=> :first_player
|
48
|
+
|
49
|
+
#### Ship on position row, column is sunken?
|
50
|
+
$ sea_battle.is_sunken_ship?(3, 7) #=> false
|
51
|
+
|
52
|
+
#### You can attack position (row, column)
|
53
|
+
$ sea_battle.move(:second_player, :attack, 2, 9)
|
54
|
+
|
55
|
+
#### When game is over you can see winner
|
56
|
+
$ sea_battle.winner_is #=> :first_player
|
57
|
+
|
58
|
+
### Play on console (min 92x40)
|
59
|
+
|
60
|
+
$ sea_battle
|
61
|
+
|
62
|
+
#=> SEA BATTLE
|
63
|
+
|
64
|
+
#=> A B C D E F G H I J A B C D E F G H I J
|
65
|
+
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
66
|
+
#=> 0 │ □ │ │ │ │ │ │ │ │ │ □ │ 0 │ │ │ │ │ │ │ │ │ │ │
|
67
|
+
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
68
|
+
#=> 1 │ □ │ │ □ │ │ □ │ │ │ ⬤/│ │ □ │ 1 │ │ │ │ │ │ • │ ⬤/│ │ │ │
|
69
|
+
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
70
|
+
#=> 2 │ □ │ │ │ │ ■ │ │ │ │ │ □ │ 2 │ │ │ │ │ │ │ ⬤/│ • │ • │ │
|
71
|
+
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
72
|
+
#=> 3 │ □ │ • │ │ │ □ │ • │ • │ │ │ │ 3 │ • │ │ │ │ │ │ ⬤/│ • │ • │ │
|
73
|
+
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
74
|
+
#=> 4 │ │ │ • │ │ │ │ │ □ │ │ │ 4 │ │ │ │ ⬤/│ ⬤/│ │ │ │ • │ │
|
75
|
+
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
76
|
+
#=> 5 │ │ • │ │ │ │ │ │ □ │ │ │ 5 │ │ │ │ │ │ │ │ • │ ⬤/│ │
|
77
|
+
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
78
|
+
#=> 6 │ │ │ • │ │ │ • │ │ │ • │ • │ 6 │ │ │ │ │ │ │ • │ │ • │ │
|
79
|
+
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
80
|
+
#=> 7 │ │ │ │ • │ │ │ │ • │ ■ │ │ 7 │ │ │ │ │ │ │ │ │ │ │
|
81
|
+
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
82
|
+
#=> 8 │ ⬤ │ │ │ • │ │ │ □ │ │ □ │ │ 8 │ │ • │ │ • │ ⬤/│ • │ │ │ │ │
|
83
|
+
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
84
|
+
#=> 9 │ ⬤ │ │ │ │ □ │ │ │ │ │ • │ 9 │ │ │ │ │ • │ │ │ │ │ │
|
85
|
+
#=> ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼
|
86
|
+
|
87
|
+
#=> 09:49:09 Computer: Moved on position 6j
|
88
|
+
#=> 09:49:11 You: Moved on position 9e
|
89
|
+
#=> 09:49:13 Computer: Moved on position 3b
|
90
|
+
#=> 09:49:15 You: Used incorrect command: a
|
91
|
+
#=> ____________________________________________________________
|
92
|
+
#=> ⬤/ - sunk ship; ■ - hit ship; □ - selected ship; • - mishit
|
93
|
+
|
94
|
+
#=> (r)andom position into attack
|
95
|
+
#=> 4a, 8i, ... - select part of ship
|
96
|
+
#=> (e)xit of game
|
97
|
+
#=> #=>
|
data/lib/sea_battle/board.rb
CHANGED
@@ -2,37 +2,77 @@
|
|
2
2
|
|
3
3
|
require_relative "cell"
|
4
4
|
require_relative "random_ship"
|
5
|
+
require_relative "support"
|
5
6
|
|
6
7
|
class SeaBattle
|
7
8
|
# It's Board of game Sea Battle
|
8
9
|
class Board
|
10
|
+
include ::SeaBattle::Support
|
9
11
|
|
10
12
|
attr_reader :board, :vertical, :horizontal, :status
|
11
13
|
|
12
14
|
def initialize(board = "1" * 100, status = :initialized)
|
13
|
-
@
|
14
|
-
|
15
|
-
|
16
|
-
@horizontal = 10
|
17
|
-
@vertical = 10
|
15
|
+
@horizontal, @vertical = 10, 10
|
16
|
+
|
17
|
+
load_board(board)
|
18
18
|
|
19
19
|
@status = status
|
20
|
-
@quantity_ships = {1 => 4, 2 => 3, 3 => 2, 4 => 1}
|
21
20
|
check_board
|
22
21
|
end
|
23
22
|
|
24
|
-
|
23
|
+
# When all ships are on board then board can be activated
|
24
|
+
# Return true when board was activated
|
25
|
+
def activate_board
|
26
|
+
result = 0
|
27
|
+
@board.flatten.each do |cell|
|
28
|
+
result += 1 if cell.is_in_ship?
|
29
|
+
end
|
30
|
+
return false unless result == 20
|
25
31
|
@status = :activated
|
32
|
+
true
|
26
33
|
end
|
27
34
|
|
28
35
|
def attack(row, column)
|
29
|
-
|
36
|
+
if @status == :activated
|
37
|
+
board[row][column].attack
|
38
|
+
is_sunken_ship?(row, column)
|
39
|
+
is_finished?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def is_attacked?(row, column)
|
44
|
+
board[row][column].is_attacked?
|
30
45
|
end
|
31
46
|
|
32
47
|
def is_in_ship?(row, column)
|
33
48
|
board[row][column].is_in_ship?
|
34
49
|
end
|
35
50
|
|
51
|
+
# Return true if on position (row, column) is the ship which is sunked
|
52
|
+
# Return false if on position (row, column) is not the ship which is sunked
|
53
|
+
# or don't exist the ship
|
54
|
+
def is_sunken_ship?(row, column)
|
55
|
+
positions = ship_positions(row, column)
|
56
|
+
return false if positions.empty?
|
57
|
+
is_sunk = true
|
58
|
+
positions.each do |position_row, position_column|
|
59
|
+
is_sunk = false unless board[position_row][position_column].is_attacked?
|
60
|
+
end
|
61
|
+
if is_sunk
|
62
|
+
positions.each do |position_row, position_column|
|
63
|
+
board[position_row][position_column].sunk
|
64
|
+
end
|
65
|
+
end
|
66
|
+
is_sunk
|
67
|
+
end
|
68
|
+
|
69
|
+
# Return position to attack (have not attacked)
|
70
|
+
def random_position
|
71
|
+
mixed_board_positions.each do |row, column|
|
72
|
+
return [row, column] unless is_attacked?(row, column)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
36
76
|
# Set ships on the board (random positions)
|
37
77
|
def random_ships
|
38
78
|
return unless @status == :initialized
|
@@ -57,6 +97,17 @@ class SeaBattle
|
|
57
97
|
raise "The board is not Array class" unless @board.size == 10
|
58
98
|
end
|
59
99
|
|
100
|
+
def is_finished?
|
101
|
+
is_finished = true
|
102
|
+
board.each do |line|
|
103
|
+
line.each do |cell|
|
104
|
+
is_finished = false if cell.is_in_ship? and not cell.is_sunk?
|
105
|
+
end
|
106
|
+
end
|
107
|
+
@status = :finished if is_finished
|
108
|
+
is_finished
|
109
|
+
end
|
110
|
+
|
60
111
|
# it should return array of ship position
|
61
112
|
# for horizontal line with position [row, column]
|
62
113
|
def horizontal_ship_position(row, column)
|
@@ -72,6 +123,12 @@ class SeaBattle
|
|
72
123
|
result
|
73
124
|
end
|
74
125
|
|
126
|
+
def load_board(board)
|
127
|
+
@board = board.split("").map do |status|
|
128
|
+
Cell.new(status.to_i)
|
129
|
+
end.each_slice(10).to_a
|
130
|
+
end
|
131
|
+
|
75
132
|
def reset_board
|
76
133
|
board.each do |line|
|
77
134
|
line.each do |cell|
|
data/lib/sea_battle/cell.rb
CHANGED
@@ -11,6 +11,7 @@ class SeaBattle
|
|
11
11
|
# 2 -> field is part of ship
|
12
12
|
# 4 -> attacked field
|
13
13
|
# 8 -> is only selected by user
|
14
|
+
#16 -> is sunk
|
14
15
|
# 6 -> attacked field and exsist ship
|
15
16
|
def initialize(status = 1)
|
16
17
|
@status = status
|
@@ -24,6 +25,10 @@ class SeaBattle
|
|
24
25
|
@status += 4 unless is_attacked?
|
25
26
|
end
|
26
27
|
|
28
|
+
def sunk
|
29
|
+
@status += 16 unless is_sunk?
|
30
|
+
end
|
31
|
+
|
27
32
|
def switch_select
|
28
33
|
is_selected? ? @status -= 8 : @status += 8
|
29
34
|
end
|
@@ -44,6 +49,10 @@ class SeaBattle
|
|
44
49
|
@status & 8 == 8
|
45
50
|
end
|
46
51
|
|
52
|
+
def is_sunk?
|
53
|
+
@status & 16 == 16
|
54
|
+
end
|
55
|
+
|
47
56
|
def reset_cell
|
48
57
|
@status = 1
|
49
58
|
end
|
data/lib/sea_battle/gui.rb
CHANGED
@@ -12,26 +12,26 @@ class SeaBattle
|
|
12
12
|
@user_board = ::SeaBattle::Board.new
|
13
13
|
@computer_board = ::SeaBattle::Board.new
|
14
14
|
@computer_board.random_ships
|
15
|
-
@computer_board.
|
15
|
+
@computer_board.activate_board
|
16
16
|
@sea_battle = ::SeaBattle.new(@user_board, @computer_board)
|
17
17
|
set_default_keyboard
|
18
|
+
push_message("Initialized SeaBattle")
|
18
19
|
end
|
19
20
|
|
20
21
|
def play
|
21
22
|
while true and not @keyboard[:exit]
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
update_screen
|
24
|
+
user_command
|
25
|
+
next if @keyboard[:error]
|
25
26
|
if @keyboard[:position]
|
26
|
-
|
27
|
-
|
28
|
-
show_boards
|
27
|
+
attack_on(@row, @column, :first_player)
|
28
|
+
break unless @sea_battle.winner_is.nil?
|
29
29
|
while @sea_battle.active_user == :second_player
|
30
30
|
sleep 1 + rand
|
31
|
-
|
32
|
-
|
33
|
-
show_boards
|
31
|
+
row, column = @computer_board.random_position
|
32
|
+
attack_on(row, column, :second_player)
|
34
33
|
end
|
34
|
+
break unless @sea_battle.winner_is.nil?
|
35
35
|
@keyboard[:position] = false
|
36
36
|
end
|
37
37
|
end
|
@@ -39,73 +39,139 @@ class SeaBattle
|
|
39
39
|
|
40
40
|
private
|
41
41
|
|
42
|
+
def all_positions
|
43
|
+
(0..9).to_a.product(
|
44
|
+
(0..9).to_a.map do |column|
|
45
|
+
(column + 97).chr
|
46
|
+
end
|
47
|
+
).map { |row, column| "#{row}#{column}" }
|
48
|
+
end
|
49
|
+
|
50
|
+
def attack_on(row, column, active_player)
|
51
|
+
player_name = (active_player == :first_player ? "You" : "Computer")
|
52
|
+
@sea_battle.move(active_player, :attack, row, column)
|
53
|
+
push_message("Moved on position #{row}#{(97 + column).chr}", player_name)
|
54
|
+
if @sea_battle.is_sunken_ship?(row, column, active_player)
|
55
|
+
push_message("Sunk ship", player_name)
|
56
|
+
end
|
57
|
+
if @sea_battle.winner_is == active_player
|
58
|
+
push_message("WIN!!!", player_name)
|
59
|
+
end
|
60
|
+
update_screen
|
61
|
+
end
|
62
|
+
|
63
|
+
def board_line(board, index, player)
|
64
|
+
board.board[index].map do |cell|
|
65
|
+
if cell.is_attacked? and cell.is_in_ship?
|
66
|
+
unless cell.is_sunk?
|
67
|
+
" ■ "
|
68
|
+
else
|
69
|
+
" ⬤ "
|
70
|
+
end
|
71
|
+
elsif cell.is_attacked? and not cell.is_in_ship?
|
72
|
+
" • "
|
73
|
+
elsif not cell.is_attacked? and cell.is_in_ship? and player == :first_player
|
74
|
+
" □ "
|
75
|
+
else
|
76
|
+
" \u205f "
|
77
|
+
end
|
78
|
+
end.join("│")
|
79
|
+
end
|
80
|
+
|
81
|
+
def info_command
|
82
|
+
puts "⬤/ - sunk ship; ■ - hit ship; □ - selected ship; • - mishit"
|
83
|
+
puts ""
|
84
|
+
unless @sea_battle.is_activated?
|
85
|
+
puts "(r)andom your ships on board"
|
86
|
+
puts "(a)ctivate your game if all ships are at properly place"
|
87
|
+
else
|
88
|
+
puts "(r)andom position into attack"
|
89
|
+
puts "4a, 8i, ... - select part of ship"
|
90
|
+
end
|
91
|
+
puts "(e)xit of game"
|
92
|
+
print "#=> "
|
93
|
+
end
|
94
|
+
|
42
95
|
def set_default_keyboard
|
43
96
|
@keyboard = {
|
44
97
|
exit: false,
|
45
|
-
|
46
|
-
|
98
|
+
position: nil,
|
99
|
+
error: false
|
47
100
|
}
|
48
101
|
end
|
49
102
|
|
50
|
-
def
|
103
|
+
def update_screen
|
104
|
+
system "clear"
|
51
105
|
show_title
|
106
|
+
column_position = "A B C D E F G H I J"
|
107
|
+
end_of_board = "┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼"
|
52
108
|
|
53
|
-
puts ""
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
elsif cell.is_attacked? and not cell.is_in_ship?
|
60
|
-
" • "
|
61
|
-
elsif not cell.is_attacked? and cell.is_in_ship?
|
62
|
-
" ◯ "
|
63
|
-
else
|
64
|
-
" "
|
65
|
-
end
|
66
|
-
end.join("│")
|
67
|
-
computer_line = @computer_board.board[index].map do |cell|
|
68
|
-
if cell.is_attacked? and cell.is_in_ship?
|
69
|
-
" ⬤ "
|
70
|
-
elsif cell.is_attacked? and not cell.is_in_ship?
|
71
|
-
" • "
|
72
|
-
else
|
73
|
-
" "
|
74
|
-
end
|
75
|
-
end.join("│")
|
76
|
-
puts " ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼ ┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼"
|
77
|
-
puts "#{index} │#{user_line}│ #{index} │#{computer_line}│"
|
109
|
+
puts " #{column_position} #{column_position}"
|
110
|
+
(0..9).each do |index|
|
111
|
+
user_line = board_line(@user_board, index, :first_player)
|
112
|
+
computer_line = board_line(@computer_board, index, :second_player)
|
113
|
+
puts " #{end_of_board} #{end_of_board}"
|
114
|
+
puts " #{index} │#{user_line}│ #{index} │#{computer_line}│"
|
78
115
|
end
|
116
|
+
puts " #{end_of_board} #{end_of_board}\n \n"
|
117
|
+
show_messages
|
79
118
|
end
|
80
119
|
|
81
120
|
def show_title
|
82
121
|
puts ""
|
83
122
|
puts "#{' '*10}SEA BATTLE ver#{VERSION}"
|
123
|
+
puts ""
|
84
124
|
end
|
85
125
|
|
86
|
-
def
|
87
|
-
|
88
|
-
puts "4a, ... - select part of ship"
|
89
|
-
unless @keyboard[:activate]
|
90
|
-
puts "(r)andom your ships on board"
|
91
|
-
puts "(a)ctivate your game if all ships are at properly place"
|
92
|
-
end
|
93
|
-
puts "(e)xit of game"
|
126
|
+
def user_command
|
127
|
+
info_command
|
94
128
|
keyboard = gets.chomp
|
95
129
|
@keyboard[:exit] = true if keyboard == "e"
|
96
|
-
if
|
97
|
-
@keyboard[:
|
98
|
-
|
99
|
-
|
100
|
-
|
130
|
+
if @sea_battle.is_activated?
|
131
|
+
@keyboard[:error] = false
|
132
|
+
if all_positions.include?(keyboard)
|
133
|
+
@row, @column = keyboard.split("")
|
134
|
+
@column = @column.ord - 97
|
135
|
+
@row = @row.to_i
|
136
|
+
@keyboard[:position] = true
|
137
|
+
#if @computer_board.is_attacked?(@row, @column)
|
138
|
+
# @keyboard[:error] = true
|
139
|
+
# @keyboard[:position] = false
|
140
|
+
# push_message("Used incorrect command: #{keyboard}")
|
141
|
+
#end
|
142
|
+
elsif keyboard == "r"
|
143
|
+
@row, @column = @computer_board.random_position
|
144
|
+
@keyboard[:position] = true
|
145
|
+
else
|
146
|
+
@keyboard[:error] = true
|
147
|
+
push_message("Used incorrect command: #{keyboard}")
|
148
|
+
end
|
149
|
+
else
|
150
|
+
if keyboard == "a"
|
151
|
+
if @user_board.activate_board
|
152
|
+
push_message("Activated game")
|
153
|
+
else
|
154
|
+
push_message("Don't activated game!!!")
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
if keyboard == "r"
|
159
|
+
@user_board.random_ships
|
160
|
+
push_message("Random ships")
|
161
|
+
end
|
101
162
|
end
|
102
|
-
|
163
|
+
end
|
103
164
|
|
104
|
-
|
105
|
-
|
165
|
+
def push_message(message, player = "You")
|
166
|
+
@messages ||= []
|
167
|
+
@messages = @messages.rotate(1)
|
168
|
+
@messages[3] = " #{Time.now.strftime("%H:%M:%S")} #{player}: #{message}"
|
169
|
+
end
|
106
170
|
|
107
|
-
|
108
|
-
@
|
171
|
+
def show_messages
|
172
|
+
@messages ||= []
|
173
|
+
puts @messages.compact.join("\n")
|
174
|
+
puts "_"*60
|
109
175
|
end
|
110
176
|
|
111
177
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require_relative "support"
|
3
4
|
|
4
5
|
class SeaBattle
|
5
6
|
# It's random positions for new ship
|
6
7
|
class RandomShip
|
8
|
+
include ::SeaBattle::Support
|
7
9
|
|
8
10
|
def initialize(board, length = 1)
|
9
11
|
@board = board.board
|
@@ -50,13 +52,6 @@ class SeaBattle
|
|
50
52
|
vertical_range.product(horizontal_range)
|
51
53
|
end
|
52
54
|
|
53
|
-
def mixed_board_positions
|
54
|
-
offset = Random.rand(@horizontal * @vertical)
|
55
|
-
(0...@vertical).to_a.product(
|
56
|
-
(0...@horizontal).to_a
|
57
|
-
).rotate(offset)
|
58
|
-
end
|
59
|
-
|
60
55
|
def add_ship_of(direct)
|
61
56
|
mixed_board_positions.each do |row, column|
|
62
57
|
next if direct.eql?(:vertical) and row + @length - 1 >= @vertical
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class SeaBattle
|
4
|
+
# Common methods
|
5
|
+
module Support
|
6
|
+
|
7
|
+
def mixed_board_positions
|
8
|
+
offset = Random.rand(@horizontal * @vertical)
|
9
|
+
(0...@vertical).to_a.product(
|
10
|
+
(0...@horizontal).to_a
|
11
|
+
).rotate(offset)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
data/lib/sea_battle/version.rb
CHANGED
data/lib/sea_battle.rb
CHANGED
@@ -28,12 +28,26 @@ class SeaBattle
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
def is_activated?
|
32
|
+
not first_status.eql?(:initialized) and not second_status.eql?(:initialized)
|
33
|
+
end
|
34
|
+
|
35
|
+
def is_sunken_ship?(row, column, player)
|
36
|
+
if player == :first_player
|
37
|
+
@second_board.is_sunken_ship?(row, column)
|
38
|
+
else
|
39
|
+
@first_board.is_sunken_ship?(row, column)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
31
43
|
def last_attack_move
|
32
44
|
return if @last_attack_move.nil?
|
33
45
|
@last_attack_move.join(";")
|
34
46
|
end
|
35
47
|
|
36
48
|
def move(player, type, row, column)
|
49
|
+
return false unless winner_is.nil?
|
50
|
+
|
37
51
|
return false unless [:first_player, :second_player].include?(player)
|
38
52
|
return false unless [:choose, :attack, :mark].include?(type)
|
39
53
|
|
@@ -52,6 +66,12 @@ class SeaBattle
|
|
52
66
|
true
|
53
67
|
end
|
54
68
|
|
69
|
+
def winner_is
|
70
|
+
return :second_player if first_status.eql? :finished
|
71
|
+
return :first_player if second_status.eql? :finished
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
55
75
|
private
|
56
76
|
|
57
77
|
def first_status
|
@@ -1,10 +1,26 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require "sea_battle"
|
4
|
+
|
4
5
|
describe SeaBattle::Board do
|
5
6
|
|
6
7
|
let(:klass) { SeaBattle::Board }
|
7
8
|
|
9
|
+
let(:raw_board) {
|
10
|
+
"1111111121" +
|
11
|
+
"1222211121" +
|
12
|
+
"1111111111" +
|
13
|
+
"1111112112" +
|
14
|
+
"2112112111" +
|
15
|
+
"1111112111" +
|
16
|
+
"1111111111" +
|
17
|
+
"1222111111" +
|
18
|
+
"1111122112" +
|
19
|
+
"1211111112"
|
20
|
+
}
|
21
|
+
|
22
|
+
let(:board) { SeaBattle::Board.new(raw_board) }
|
23
|
+
|
8
24
|
it "should properly initialize class" do
|
9
25
|
expect { SeaBattle::Board.new }.to_not raise_error
|
10
26
|
end
|
@@ -13,28 +29,28 @@ describe SeaBattle::Board do
|
|
13
29
|
expect { SeaBattle::Board.new("") }.to raise_error
|
14
30
|
end
|
15
31
|
|
32
|
+
context "should check method #activate_board" do
|
33
|
+
it "for empty board" do
|
34
|
+
SeaBattle::Board.new.activate_board.should be_false
|
35
|
+
end
|
36
|
+
|
37
|
+
it "for properly arranged ships on board" do
|
38
|
+
SeaBattle::Board.new(raw_board).activate_board.should be_true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
16
42
|
context "should check method ship_positions"do
|
17
43
|
|
18
44
|
it "for non-ship" do
|
19
|
-
board
|
20
|
-
board[2] = "2"
|
21
|
-
board[3] = "2"
|
22
|
-
|
23
|
-
klass.new(board).ship_positions(1, 2).should eq([])
|
45
|
+
board.ship_positions(6, 2).should eq([])
|
24
46
|
end
|
25
47
|
|
26
48
|
it "for horizontal ship" do
|
27
|
-
board
|
28
|
-
board[2] = "2"
|
29
|
-
board[3] = "2"
|
30
|
-
klass.new(board).ship_positions(0, 2).should eq([[0, 2], [0, 3]])
|
49
|
+
board.ship_positions(7, 2).should eq([[7, 1], [7, 2], [7, 3]])
|
31
50
|
end
|
32
51
|
|
33
52
|
it "for vertical ship" do
|
34
|
-
board
|
35
|
-
board[23] = "2"
|
36
|
-
board[33] = "2"
|
37
|
-
klass.new(board).ship_positions(2, 3).should eq([[2, 3] ,[3, 3]])
|
53
|
+
board.ship_positions(5, 6).should eq([[3, 6] ,[4, 6], [5, 6]])
|
38
54
|
end
|
39
55
|
|
40
56
|
end
|
@@ -52,4 +68,35 @@ describe SeaBattle::Board do
|
|
52
68
|
result.should eq(20)
|
53
69
|
end
|
54
70
|
end
|
71
|
+
|
72
|
+
context "should check method attack"do
|
73
|
+
|
74
|
+
it "for non-ship" do
|
75
|
+
board.activate_board
|
76
|
+
board.attack(0, 8)
|
77
|
+
board.board[0][8].is_sunk?.should be_false
|
78
|
+
board.attack(1, 8)
|
79
|
+
board.board[0][8].is_sunk?.should be_true
|
80
|
+
board.board[1][8].is_sunk?.should be_true
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
context "should random new position into attack" do
|
86
|
+
let(:active_board) do
|
87
|
+
result = raw_board
|
88
|
+
result[12] = "6"
|
89
|
+
result
|
90
|
+
end
|
91
|
+
|
92
|
+
let(:board) { SeaBattle::Board.new(active_board) }
|
93
|
+
|
94
|
+
it "for simply type" do
|
95
|
+
board.activate_board
|
96
|
+
Random.stub(:rand) { 12 }
|
97
|
+
board.random_position.should eql([1, 3])
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
55
102
|
end
|
data/spec/sea_battle/gui_spec.rb
CHANGED
data/spec/sea_battle_spec.rb
CHANGED
@@ -29,6 +29,7 @@ describe SeaBattle do
|
|
29
29
|
"1111122112" +
|
30
30
|
"1211111112"
|
31
31
|
}
|
32
|
+
|
32
33
|
it "should properly initialize class" do
|
33
34
|
expect { SeaBattle.new(board.new, board.new) }.to_not raise_error
|
34
35
|
end
|
@@ -64,7 +65,6 @@ describe SeaBattle do
|
|
64
65
|
end
|
65
66
|
|
66
67
|
context "for active game and first player correctly attacked competition ship then" do
|
67
|
-
|
68
68
|
let(:board_zero) { board.new(first_raw_board, :activated) }
|
69
69
|
let(:board_one) { board.new(first_raw_board, :activated) }
|
70
70
|
let(:sea_battle) { SeaBattle.new(board_zero, board_one, "first_player;1;1") }
|
@@ -85,4 +85,25 @@ describe SeaBattle do
|
|
85
85
|
|
86
86
|
end
|
87
87
|
|
88
|
+
context "for method winer_is" do
|
89
|
+
let(:first_board) { board.new(first_raw_board, :activated) }
|
90
|
+
let(:second_board) { board.new(first_raw_board, :activated) }
|
91
|
+
let(:sea_battle) { SeaBattle.new(first_board, second_board, nil) }
|
92
|
+
|
93
|
+
it "should return nil if no one win of game" do
|
94
|
+
sea_battle.winner_is.should be_nil
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should return :first_player if first player win of game" do
|
98
|
+
first_board.stub(:status) { :finished }
|
99
|
+
sea_battle.winner_is.should eq(:second_player)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should return :second_player if second player win of game" do
|
103
|
+
second_board.stub(:status) { :finished }
|
104
|
+
sea_battle.winner_is.should eq(:first_player)
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
88
109
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sea_battle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -95,6 +95,7 @@ files:
|
|
95
95
|
- lib/sea_battle/cell.rb
|
96
96
|
- lib/sea_battle/gui.rb
|
97
97
|
- lib/sea_battle/random_ship.rb
|
98
|
+
- lib/sea_battle/support.rb
|
98
99
|
- lib/sea_battle/version.rb
|
99
100
|
- sea_battle.gemspec
|
100
101
|
- spec/sea_battle/board_spec.rb
|