ruby_terminal_games 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/bin/ruby_terminal_games +3 -0
- data/lib/ruby_terminal_games/hangman/game.rb +2 -2
- data/lib/ruby_terminal_games/snake/board.rb +1 -1
- data/lib/ruby_terminal_games/sudoku/board.rb +117 -0
- data/lib/ruby_terminal_games/sudoku/game.rb +77 -0
- data/lib/ruby_terminal_games/sudoku/puzzle.rb +105 -0
- data/lib/ruby_terminal_games/sudoku/puzzles.txt +5 -0
- data/lib/ruby_terminal_games/sudoku.rb +5 -0
- data/lib/ruby_terminal_games/version.rb +1 -1
- data/lib/ruby_terminal_games.rb +1 -0
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: daca2f7a086e3e6efb02744675de934890622b86
|
4
|
+
data.tar.gz: 643e9c2bff3684d7b92216db2201c787b8f889c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 28f69c1ec650b408448ceabbe874aaccea983d82b20194352eaa4e95227457ee2159dbda7b4ca4afcb964e1c242986e5a270bdebfc3acf9b352737a46e236b9a
|
7
|
+
data.tar.gz: 88d4f3e4bb29d61df49e62b566d19fabafeba42fba533afe488d53c17065cf44dcb1cbaf5f5f13aa5f8ff537d253ce3ec5baed6372def84e718c453bc501c385
|
data/README.md
CHANGED
data/bin/ruby_terminal_games
CHANGED
@@ -17,6 +17,7 @@ if command =~ /list/
|
|
17
17
|
Games:
|
18
18
|
- Snake (play snake)
|
19
19
|
- Hangman (play hangman)
|
20
|
+
- Sudoku (play sudoku)
|
20
21
|
EOT
|
21
22
|
exit
|
22
23
|
end
|
@@ -31,6 +32,8 @@ when /snake/
|
|
31
32
|
RubyTerminalGames::Snake::Game.new
|
32
33
|
when /hangman/
|
33
34
|
RubyTerminalGames::Hangman::Game.new
|
35
|
+
when /sudoku/
|
36
|
+
RubyTerminalGames::Sudoku::Game.new
|
34
37
|
end
|
35
38
|
|
36
39
|
if game
|
@@ -3,7 +3,7 @@ require_relative 'word'
|
|
3
3
|
|
4
4
|
module RubyTerminalGames
|
5
5
|
module Hangman
|
6
|
-
class Game
|
6
|
+
class Game < RubyTerminalGames::Game
|
7
7
|
attr_reader :word, :guess_total, :board, :input_index,
|
8
8
|
:wrong_guesses
|
9
9
|
|
@@ -48,7 +48,7 @@ module RubyTerminalGames
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def game_interval!
|
51
|
-
sleep(0.
|
51
|
+
sleep(0.1)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module RubyTerminalGames
|
2
|
+
module Sudoku
|
3
|
+
class Board < RubyTerminalGames::Board
|
4
|
+
def print_board(game)
|
5
|
+
clear!
|
6
|
+
print_top_border!
|
7
|
+
print_middle_borders!
|
8
|
+
print_bottom_border!
|
9
|
+
print_instructions!
|
10
|
+
|
11
|
+
user_inputs = game.user_inputs
|
12
|
+
user_input_index = game.user_input_index
|
13
|
+
state = game.puzzle.state
|
14
|
+
|
15
|
+
user_inputs.each_with_index do |input, index|
|
16
|
+
highlight = (input == user_inputs[user_input_index])
|
17
|
+
row, col = input
|
18
|
+
number = (state[index] || " ").to_s
|
19
|
+
|
20
|
+
if game.puzzle.locked_position?(index)
|
21
|
+
if highlight
|
22
|
+
output = number.colorize(
|
23
|
+
background: :green,
|
24
|
+
color: :white
|
25
|
+
)
|
26
|
+
else
|
27
|
+
output = number.colorize(color: :green)
|
28
|
+
end
|
29
|
+
else
|
30
|
+
output = number
|
31
|
+
|
32
|
+
if highlight
|
33
|
+
output = number
|
34
|
+
.colorize(background: :light_yellow, color: :black)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
write(output, row: row, col: col)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def corner_cols
|
45
|
+
[
|
46
|
+
2, 3, 4, 5, 6, 8,
|
47
|
+
9, 10, 11, 12, 14,
|
48
|
+
15, 16, 17, 18
|
49
|
+
]
|
50
|
+
end
|
51
|
+
|
52
|
+
def middle_rows
|
53
|
+
[
|
54
|
+
2, 3, 4, 5, 6,
|
55
|
+
8, 9, 10, 11, 12,
|
56
|
+
14, 15, 16, 17, 18
|
57
|
+
]
|
58
|
+
end
|
59
|
+
|
60
|
+
def middle_columns
|
61
|
+
[
|
62
|
+
2, 3, 4,
|
63
|
+
6, 7, 8,
|
64
|
+
10, 11, 12
|
65
|
+
]
|
66
|
+
end
|
67
|
+
|
68
|
+
def print_top_border!
|
69
|
+
write("┌", row: 1, col: 1)
|
70
|
+
write("┬", row: 1, col: 7)
|
71
|
+
write("┬", row: 1, col: 13)
|
72
|
+
write("┐", row: 1, col: 19)
|
73
|
+
end
|
74
|
+
|
75
|
+
def print_middle_borders!
|
76
|
+
write("├", row: 5, col: 1)
|
77
|
+
write("┼", row: 5, col: 7)
|
78
|
+
write("┼", row: 5, col: 13)
|
79
|
+
write("┤", row: 5, col: 19)
|
80
|
+
write("├", row: 9, col: 1)
|
81
|
+
write("┼", row: 9, col: 7)
|
82
|
+
write("┼", row: 9, col: 13)
|
83
|
+
write("┤", row: 9, col: 19)
|
84
|
+
|
85
|
+
middle_rows.each do |col|
|
86
|
+
write("┈", row: 5, col: col)
|
87
|
+
write("┈", row: 9, col: col)
|
88
|
+
end
|
89
|
+
|
90
|
+
middle_columns.each do |row|
|
91
|
+
write("┊", row: row, col: 7)
|
92
|
+
write("┊", row: row, col: 13)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def print_bottom_border!
|
97
|
+
write("└", row: 13, col: 1)
|
98
|
+
write("┴", row: 13, col: 7)
|
99
|
+
write("┴", row: 13, col: 13)
|
100
|
+
write("┘", row: 13, col: 19)
|
101
|
+
end
|
102
|
+
|
103
|
+
def print_bottom_line!
|
104
|
+
write("─"*width, row: 14, col: 1)
|
105
|
+
end
|
106
|
+
|
107
|
+
def print_instructions!
|
108
|
+
print_bottom_line!
|
109
|
+
text = 'Use 0 to clear input'
|
110
|
+
write(text, row: 15, col: 1)
|
111
|
+
|
112
|
+
exit_text = 'Press Q to exit'
|
113
|
+
write(exit_text, row: 15, col: width - exit_text.length)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require_relative 'puzzle'
|
2
|
+
require_relative 'board'
|
3
|
+
|
4
|
+
module RubyTerminalGames
|
5
|
+
module Sudoku
|
6
|
+
class Game < RubyTerminalGames::Game
|
7
|
+
attr_reader :board, :puzzle, :user_input_index, :user_input
|
8
|
+
def initialize
|
9
|
+
@puzzle = Puzzle.new
|
10
|
+
@board = Board.new
|
11
|
+
@user_input_index = 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def play!
|
15
|
+
@playing = true
|
16
|
+
Keyboard.capture(detect_direction: true) do |key|
|
17
|
+
begin
|
18
|
+
@playing = false if key =~ /q/
|
19
|
+
if direction_key?(key)
|
20
|
+
move_user_input(key)
|
21
|
+
else
|
22
|
+
if allowed_input?(key)
|
23
|
+
add_user_input(key.to_i)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
rescue
|
27
|
+
Keyboard.stop_capture
|
28
|
+
@playing = false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
while @playing
|
33
|
+
board.print_board(self)
|
34
|
+
sleep(0.1)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def user_inputs
|
39
|
+
@user_inputs ||= begin
|
40
|
+
inputs = []
|
41
|
+
[2, 3, 4, 6, 7, 8, 10, 11, 12].each do |row|
|
42
|
+
[2, 4, 6, 8, 10, 12, 14, 16, 18].each do |col|
|
43
|
+
inputs << [row, col]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
inputs
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def direction_key?(key)
|
51
|
+
[UP, LEFT, RIGHT, DOWN].include?(key)
|
52
|
+
end
|
53
|
+
|
54
|
+
def move_user_input(key)
|
55
|
+
moved = case key
|
56
|
+
when UP
|
57
|
+
[user_input_index - 9, 0].max
|
58
|
+
when RIGHT
|
59
|
+
[user_input_index + 1, 80].min
|
60
|
+
when LEFT
|
61
|
+
[user_input_index - 1, 0].max
|
62
|
+
when DOWN
|
63
|
+
[user_input_index + 9, 80].min
|
64
|
+
end
|
65
|
+
@user_input_index = moved
|
66
|
+
end
|
67
|
+
|
68
|
+
def allowed_input?(key)
|
69
|
+
('0'..'9').include?(key)
|
70
|
+
end
|
71
|
+
|
72
|
+
def add_user_input(input)
|
73
|
+
puzzle.add_input(input, user_input_index)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module RubyTerminalGames
|
2
|
+
module Sudoku
|
3
|
+
class Puzzle
|
4
|
+
attr_reader :state, :locked_positions
|
5
|
+
def initialize
|
6
|
+
@locked_positions = []
|
7
|
+
@state = build_puzzle
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_input(input, user_input_index)
|
11
|
+
return if locked_position?(user_input_index)
|
12
|
+
input = nil if input.zero?
|
13
|
+
previous = state[user_input_index]
|
14
|
+
@state[user_input_index] = input
|
15
|
+
return true if valid?
|
16
|
+
@state[user_input_index] = previous
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def locked_position?(user_input_index)
|
21
|
+
locked_positions.include?(user_input_index)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def puzzle_string
|
27
|
+
path = File.expand_path(
|
28
|
+
File.join(File.dirname(__FILE__), "puzzles.txt"))
|
29
|
+
|
30
|
+
File.readlines(path)
|
31
|
+
.map { |line|
|
32
|
+
line.strip
|
33
|
+
}.reject { |w| w.empty? }.sample
|
34
|
+
end
|
35
|
+
|
36
|
+
def build_puzzle
|
37
|
+
puzzle_string.chars.each_with_index.map do |char, index|
|
38
|
+
number = char.to_i
|
39
|
+
@locked_positions << index unless number.zero?
|
40
|
+
number.zero? ? nil : number
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def valid?
|
45
|
+
valid_rows? && valid_columns? && valid_squares?
|
46
|
+
end
|
47
|
+
|
48
|
+
def valid_rows?
|
49
|
+
rows.each do |row|
|
50
|
+
return false if row.compact.size != row.compact.uniq.size
|
51
|
+
end
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
def valid_columns?
|
56
|
+
columns.each do |col|
|
57
|
+
return false if col.compact.size != col.compact.uniq.size
|
58
|
+
end
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
def valid_squares?
|
63
|
+
squares.each do |square|
|
64
|
+
return false if square.compact.size != square.compact.uniq.size
|
65
|
+
end
|
66
|
+
true
|
67
|
+
end
|
68
|
+
|
69
|
+
def rows
|
70
|
+
(0..8).map do |i|
|
71
|
+
start = i * 9
|
72
|
+
(start..start+8).map { |j| state[j] }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def columns
|
77
|
+
(0..8).map do |i|
|
78
|
+
(0..9).map do |n|
|
79
|
+
state[n*9 + i]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def squares
|
85
|
+
[
|
86
|
+
[0, 1, 2],
|
87
|
+
[3, 4, 5],
|
88
|
+
[6, 7, 8],
|
89
|
+
[27, 28, 29],
|
90
|
+
[30, 31, 32],
|
91
|
+
[33, 34, 35],
|
92
|
+
[54, 55, 56],
|
93
|
+
[57, 58, 59],
|
94
|
+
[60, 61, 62]
|
95
|
+
].map do |group|
|
96
|
+
group.map { |i|
|
97
|
+
[0, 9, 18].map { |j|
|
98
|
+
state[i + j]
|
99
|
+
}.flatten
|
100
|
+
}.flatten
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
009006080000457210021389465150802937090003801873005604980534006400701398300068540
|
2
|
+
630100009700030600490607130050300090947865000103000400829000570060798301071056000
|
3
|
+
810000000000100304050706018140300062005009800000000000020900405093810700406500000
|
4
|
+
008003000301000200029005000200070000000506400100040008000020000000090100000000800
|
5
|
+
000000700000000600300000100000006000000010000000070001000060500000000000000000000
|
data/lib/ruby_terminal_games.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_terminal_games
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Alves
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-07-
|
11
|
+
date: 2015-07-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: curses
|
@@ -89,6 +89,11 @@ files:
|
|
89
89
|
- lib/ruby_terminal_games/snake/board.rb
|
90
90
|
- lib/ruby_terminal_games/snake/game.rb
|
91
91
|
- lib/ruby_terminal_games/snake/snake.rb
|
92
|
+
- lib/ruby_terminal_games/sudoku.rb
|
93
|
+
- lib/ruby_terminal_games/sudoku/board.rb
|
94
|
+
- lib/ruby_terminal_games/sudoku/game.rb
|
95
|
+
- lib/ruby_terminal_games/sudoku/puzzle.rb
|
96
|
+
- lib/ruby_terminal_games/sudoku/puzzles.txt
|
92
97
|
- lib/ruby_terminal_games/version.rb
|
93
98
|
homepage: https://github.com/alvesdan/ruby_terminal_games
|
94
99
|
licenses:
|
@@ -110,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
115
|
version: '0'
|
111
116
|
requirements: []
|
112
117
|
rubyforge_project:
|
113
|
-
rubygems_version: 2.
|
118
|
+
rubygems_version: 2.2.2
|
114
119
|
signing_key:
|
115
120
|
specification_version: 4
|
116
121
|
summary: Ruby Terminal Games
|