snakes 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc78d31fc1e7b1a82a7d8fa4169835dc53cde3be9c2826afcb6ffb29b4960c99
4
- data.tar.gz: 3abd2b3f6153cc48198a8559360778a9990580b13ff4dbdbbe931a726659130e
3
+ metadata.gz: ba7d24f2b0258fb0f6eb0eb19aa8de9527dbb2d3a9b52fe3d86bc1e5aa226faa
4
+ data.tar.gz: 6a9dd99f563da54e60c88c49645d848367ac5b716585ea36a6e0843908cee46c
5
5
  SHA512:
6
- metadata.gz: b8cc205575d0d2bda27d4c99c105eeca39fe349ed3aaf44cde9b77d97783dbedbc45bf6a3de6f99dfc21d6f7b879484359dacdff1eebfe58326cd779817f36f5
7
- data.tar.gz: 2b3870c18c1677053850b48f2bb485edb843a83e2df081ca0b1913097369be78e68f9f9093b1afd130f2ed2361ea855f1b3b5c32b35d3942f89c5d02a73001cf
6
+ metadata.gz: cd28636c959481e634b4a7eb6d4d5cb84ee9eeef87383edce063f7aece6472b76d103cded0e4ae6fb4515f265399bcdadb3fd5f8dfdf27f824a25c70929d3fe1
7
+ data.tar.gz: 45294ee4a69b57c14dcf4b74531f46a1a1e511f4a5220920f1c216f4b1b0aedcc785f25c781d0381e8a6545c48b63d585d4a93568dbd7b9054580bdd0e9ba075
data/.idea/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ # Default ignored files
2
+ /shelf/
3
+ /workspace.xml
4
+ # Editor-based HTTP Client requests
5
+ /httpRequests/
6
+ # Datasource local storage ignored files
7
+ /dataSources/
8
+ /dataSources.local.xml
data/.idea/misc.xml ADDED
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectRootManager" version="2" project-jdk-name="asdf: 2.7.4" project-jdk-type="RUBY_SDK" />
4
+ </project>
data/.idea/modules.xml ADDED
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/snakes.iml" filepath="$PROJECT_DIR$/.idea/snakes.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
data/.idea/snakes.iml ADDED
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="RUBY_MODULE" version="4">
3
+ <component name="ModuleRunConfigurationManager">
4
+ <shared />
5
+ </component>
6
+ <component name="NewModuleRootManager">
7
+ <content url="file://$MODULE_DIR$" />
8
+ <orderEntry type="jdk" jdkName="asdf: 3.1.0" jdkType="RUBY_SDK" />
9
+ <orderEntry type="sourceFolder" forTests="false" />
10
+ <orderEntry type="library" scope="PROVIDED" name="ast (v2.4.2, asdf: 3.1.0) [gem]" level="application" />
11
+ <orderEntry type="library" scope="PROVIDED" name="bundler (v2.3.3, asdf: 3.1.0) [gem]" level="application" />
12
+ <orderEntry type="library" scope="PROVIDED" name="minitest (v5.15.0, asdf: 3.1.0) [gem]" level="application" />
13
+ <orderEntry type="library" scope="PROVIDED" name="parallel (v1.21.0, asdf: 3.1.0) [gem]" level="application" />
14
+ <orderEntry type="library" scope="PROVIDED" name="parser (v3.0.3.2, asdf: 3.1.0) [gem]" level="application" />
15
+ <orderEntry type="library" scope="PROVIDED" name="rainbow (v3.0.0, asdf: 3.1.0) [gem]" level="application" />
16
+ <orderEntry type="library" scope="PROVIDED" name="rake (v13.0.6, asdf: 3.1.0) [gem]" level="application" />
17
+ <orderEntry type="library" scope="PROVIDED" name="regexp_parser (v2.2.0, asdf: 3.1.0) [gem]" level="application" />
18
+ <orderEntry type="library" scope="PROVIDED" name="rexml (v3.2.5, asdf: 3.1.0) [gem]" level="application" />
19
+ <orderEntry type="library" scope="PROVIDED" name="rubocop (v1.24.1, asdf: 3.1.0) [gem]" level="application" />
20
+ <orderEntry type="library" scope="PROVIDED" name="rubocop-ast (v1.15.1, asdf: 3.1.0) [gem]" level="application" />
21
+ <orderEntry type="library" scope="PROVIDED" name="ruby-progressbar (v1.11.0, asdf: 3.1.0) [gem]" level="application" />
22
+ <orderEntry type="library" scope="PROVIDED" name="unicode-display_width (v2.1.0, asdf: 3.1.0) [gem]" level="application" />
23
+ </component>
24
+ </module>
data/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
+ </component>
6
+ </project>
data/Gemfile CHANGED
@@ -5,8 +5,7 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in snakes.gemspec
6
6
  gemspec
7
7
 
8
+ gem "curses", "~> 1.4.4"
8
9
  gem "rake", "~> 13.0"
9
-
10
10
  gem "minitest", "~> 5.0"
11
-
12
11
  gem "rubocop", "~> 1.21"
data/Gemfile.lock CHANGED
@@ -7,25 +7,26 @@ GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  ast (2.4.2)
10
+ curses (1.4.4)
10
11
  minitest (5.15.0)
11
12
  parallel (1.21.0)
12
- parser (3.0.3.2)
13
+ parser (3.1.1.0)
13
14
  ast (~> 2.4.1)
14
- rainbow (3.0.0)
15
+ rainbow (3.1.1)
15
16
  rake (13.0.6)
16
- regexp_parser (2.2.0)
17
+ regexp_parser (2.2.1)
17
18
  rexml (3.2.5)
18
- rubocop (1.24.1)
19
+ rubocop (1.25.1)
19
20
  parallel (~> 1.10)
20
- parser (>= 3.0.0.0)
21
+ parser (>= 3.1.0.0)
21
22
  rainbow (>= 2.2.2, < 4.0)
22
23
  regexp_parser (>= 1.8, < 3.0)
23
24
  rexml
24
25
  rubocop-ast (>= 1.15.1, < 2.0)
25
26
  ruby-progressbar (~> 1.7)
26
27
  unicode-display_width (>= 1.4.0, < 3.0)
27
- rubocop-ast (1.15.1)
28
- parser (>= 3.0.1.1)
28
+ rubocop-ast (1.16.0)
29
+ parser (>= 3.1.1.0)
29
30
  ruby-progressbar (1.11.0)
30
31
  unicode-display_width (2.1.0)
31
32
 
@@ -33,10 +34,11 @@ PLATFORMS
33
34
  x86_64-linux
34
35
 
35
36
  DEPENDENCIES
37
+ curses (~> 1.4.4)
36
38
  minitest (~> 5.0)
37
39
  rake (~> 13.0)
38
40
  rubocop (~> 1.21)
39
41
  snakes!
40
42
 
41
43
  BUNDLED WITH
42
- 2.3.3
44
+ 2.3.4
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Snakes
1
+ b# Snakes
2
2
 
3
3
  Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/snakes`. To experiment with that code, run `bin/console` for an interactive prompt.
4
4
 
data/exe/snakes ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../lib/snakes"
4
+
5
+ Snakes::Game.new.run
@@ -0,0 +1,349 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Snakes
4
+ require "curses"
5
+
6
+ Curses.init_screen
7
+ Curses.cbreak
8
+ Curses.noecho
9
+ Curses.curs_set(0) # Invisible cursor
10
+ Curses.stdscr.keypad = true
11
+
12
+ exit_game = lambda do
13
+ Game.stop
14
+ puts "Good Bye! :D"
15
+ exit 130
16
+ end
17
+
18
+ trap("INT") { exit_game.call }
19
+ at_exit { exit_game.call }
20
+
21
+ class Game
22
+ def initialize
23
+ @snake_head_icon = "o" #"*"
24
+ @snake_node_icon = "·" # "#"
25
+ @food_icon = "+" # "#"
26
+
27
+ @game_speed = 5
28
+ @game_update_time = 1.0 / @game_speed
29
+
30
+ @non_block_timeout = 0.001
31
+
32
+ @frame = nil
33
+ @board = nil
34
+
35
+ @window_width = nil
36
+ @window_height = nil
37
+
38
+ @board_width = nil
39
+ @board_height = nil
40
+
41
+ @pause = false
42
+ @game_status = :RUN # :RUN ,:PAUSE, :GAME_OVER
43
+
44
+ @direction = [:UP, :DOWN, :LEFT, :RIGHT]
45
+ @current_direction = @direction.sample
46
+
47
+ self.init_game_board
48
+
49
+ @snake = (1..2).map { |i| [(@board_height / 2).to_i + i, (@board_width / 2).to_i] }
50
+
51
+ @food = [@board_height / 2 + 2, @board_width / 2 + 2]
52
+
53
+ @press = nil
54
+ @score = 0
55
+ @speed = 1
56
+ end
57
+
58
+ def init_game_board
59
+
60
+ # Window Frame
61
+ @window_height = Curses.lines
62
+ @window_width = Curses.cols
63
+
64
+ @board_height = (@window_height * 0.8).to_i
65
+ @board_width = (@window_width * 0.6).to_i
66
+
67
+ @info_board_height = (@window_height * 0.5).to_i
68
+ @info_board_width = (@window_width * 0.3).to_i
69
+
70
+ @frame = Curses::Window.new(@window_height, @window_width, 0, 0)
71
+
72
+ title = "Snakes"
73
+ @frame.setpos(0, @board_width / 2 - title.length / 2)
74
+ @frame.addstr(title)
75
+ @frame.refresh
76
+
77
+ @board = @frame.subwin(@board_height, @board_width, 1, 1)
78
+ @board.keypad = true
79
+ @board.timeout = @non_block_timeout
80
+
81
+ @board.box(0, 0)
82
+ @board.refresh
83
+
84
+ @info_board = @frame.subwin(
85
+ @info_board_height,
86
+ @info_board_width,
87
+ 1,
88
+ @board_width + 1
89
+ )
90
+ @info_board.box(0, 0)
91
+ @info_board.refresh
92
+ end
93
+
94
+ def create_food
95
+ @food = [rand(2..@board_height - 2), rand(2..@board_width - 2)]
96
+
97
+ unless is_safe_food?
98
+ @food = [rand(2..@board_height - 2), rand(2..@board_width - 2)]
99
+ end
100
+ end
101
+
102
+ def is_safe_food?
103
+ return !@snake.include?(@food)
104
+ end
105
+
106
+ def inc_speed
107
+ speed = @game_speed + 1
108
+ if speed >= 30
109
+ @game_speed = 30
110
+ else
111
+ @game_speed = speed
112
+ end
113
+
114
+ self.update_tick
115
+ end
116
+
117
+ def dec_speed
118
+ speed = @game_speed - 1
119
+ if speed <= 5
120
+ @game_speed = 5
121
+ else
122
+ @game_speed = speed
123
+ end
124
+
125
+ self.update_tick
126
+ end
127
+
128
+ def render_game_info
129
+ # Press Key
130
+ @info_board.setpos(1, 1)
131
+ @info_board.addstr("[Press]: #{@current_direction.to_s}")
132
+
133
+ # score
134
+ @info_board.setpos(3, 1)
135
+ @info_board.addstr("[Score]: #{@score}")
136
+
137
+ # speed
138
+ @info_board.setpos(5, 1)
139
+ @info_board.addstr("[Speed]: #{@game_speed}")
140
+
141
+ # tick time
142
+ @info_board.setpos(7, 1)
143
+ @info_board.addstr("[Tick]: #{@game_update_time}")
144
+
145
+ # status
146
+ @info_board.setpos(9, 1)
147
+ @info_board.addstr("[Status]: #{@game_status}")
148
+ end
149
+
150
+ def render_food
151
+ food_y, food_x = @food
152
+ @board.setpos(food_y, food_x)
153
+ @board.addch(@food_icon)
154
+ end
155
+
156
+ def render_snake
157
+ snake_path = @snake.dup
158
+
159
+ head_y, head_x = snake_path.shift
160
+
161
+ @board.setpos(head_y, head_x)
162
+ @board.addch(@snake_head_icon)
163
+
164
+ snake_path.each do |node_pos|
165
+ node_y, node_x = node_pos
166
+ @board.setpos(node_y, node_x)
167
+ @board.addstr(@snake_node_icon)
168
+ end
169
+ end
170
+
171
+ def check_game(next_point)
172
+ if @snake.include?(next_point)
173
+ @game_status = :GAME_OVER
174
+ return false
175
+ end
176
+
177
+ next_y, next_x = next_point
178
+
179
+ if !(next_x > 0 && next_x < @board_width && next_y > 0 && next_y < @board_height)
180
+ @game_status = :GAME_OVER
181
+ return false
182
+ end
183
+
184
+ food_y, food_x = @food
185
+ if food_y == next_y && food_x == next_x
186
+ @score += 1
187
+ @snake.unshift(@food)
188
+ self.create_food
189
+ end
190
+ return true
191
+ end
192
+
193
+ def add_step
194
+ head_y, head_x = @snake.first.dup
195
+
196
+ if @current_direction == :UP
197
+ head_y -= 1
198
+ if head_y <= 0
199
+ head_y = 1
200
+ end
201
+ elsif @current_direction == :DOWN
202
+ head_y += 1
203
+ if head_y >= @board_height
204
+ head_y = @board_height - 1
205
+ end
206
+ elsif @current_direction == :LEFT
207
+ head_x -= 1
208
+ if head_x <= 0
209
+ head_x = 1
210
+ end
211
+ elsif @current_direction == :RIGHT
212
+ head_x += 1
213
+ if head_x >= @board_width
214
+ head_x = @board_width - 1
215
+ end
216
+ else
217
+ return
218
+ end
219
+
220
+ next_point = [head_y, head_x]
221
+
222
+ result = self.check_game(next_point)
223
+ if result
224
+ @snake.unshift(next_point)
225
+ @snake.pop
226
+ end
227
+ end
228
+
229
+ def _event_listener
230
+ while true
231
+ c = @board.getch
232
+ if c
233
+ @press = c
234
+ end
235
+
236
+ head_y, head_x = @snake.first.dup
237
+
238
+ if c == Curses::KEY_UP || c == "w"
239
+ @current_direction = :UP
240
+ elsif c == Curses::KEY_DOWN || c == "s"
241
+ @current_direction = :DOWN
242
+ elsif c == Curses::KEY_LEFT || c == "a"
243
+ @current_direction = :LEFT
244
+ elsif c == Curses::KEY_RIGHT || c == "d"
245
+ @current_direction = :RIGHT
246
+ elsif c == Curses::KEY_BACKSPACE || c == "p"
247
+ @game_status = @game_status == :PAUSE ? :RUN : :PAUSE
248
+ elsif c == "m"
249
+ self.inc_speed
250
+ elsif c == "n"
251
+ self.dec_speed
252
+ else
253
+ return # 这里其实断掉了。其实接住了外循环,每次读取数据
254
+ end
255
+ end
256
+ end
257
+
258
+ def reset_game
259
+ self.initialize
260
+ end
261
+
262
+ def update_tick
263
+ @game_update_time = (1.0 / @game_speed).round(2)
264
+ end
265
+
266
+ def check_speed
267
+ @game_speed = @score % 5 + 5
268
+ self.update_tick
269
+ end
270
+
271
+ def main_loop
272
+ loop do
273
+ self.init_game_board
274
+ self.reset_game
275
+ game_result = catch(:end_game) do
276
+ while @game_status != :GAME_OVER
277
+ self._event_listener
278
+
279
+ @board.clear
280
+ @info_board.clear
281
+ @board.box(0, 0)
282
+ @info_board.box(0, 0)
283
+
284
+ if @game_status == :RUN
285
+ self.add_step
286
+ end
287
+ self.check_speed
288
+ self.render_food
289
+ self.render_snake
290
+ self.render_game_info
291
+
292
+ @board.refresh
293
+ @info_board.refresh
294
+ sleep @game_update_time
295
+ end
296
+
297
+ throw :end_game, :GAME_OVER
298
+ end
299
+
300
+ next_status = catch(:next_action) do
301
+ if game_result == :GAME_OVER
302
+ @board.timeout = -1
303
+ @board.clear
304
+ @board.box(0, 0)
305
+ @board.setpos(@board_height / 2, @board_width / 2 - 10)
306
+ @board.addstr("GAME OVER")
307
+ @board.setpos(@board_height / 2 + 2, @board_width / 2 - 10)
308
+ @board.addstr("Play Again?")
309
+ @board.setpos(@board_height / 2 + 3, @board_width / 2 - 10)
310
+ @board.addstr("Y:Yes/ N: Exit")
311
+ @board.refresh
312
+ @board.timeout = -1
313
+
314
+ next_goto = nil
315
+ while next_goto != "y"
316
+ next_goto = @board.getch
317
+ if next_goto == "n"
318
+ exit 0
319
+ elsif next_goto == "y"
320
+ @board.setpos(@board_height / 2 + 4, @board_width / 2 - 10)
321
+ @board.addstr(next_goto)
322
+ @board.refresh
323
+
324
+ throw :next_action, :RUN
325
+ end
326
+ end
327
+ end
328
+ end
329
+
330
+ @game_status = next_status
331
+ end
332
+ end
333
+
334
+ def run
335
+ self.main_loop
336
+ end
337
+
338
+ class << self
339
+ def run
340
+ @app = self.new
341
+ @app.run
342
+ end
343
+
344
+ def stop
345
+ Curses.close_screen
346
+ end
347
+ end
348
+ end
349
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Snakes
4
- VERSION = "0.0.1"
4
+ VERSION = "0.1.0"
5
5
  end
data/lib/snakes.rb CHANGED
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  require_relative "snakes/version"
3
+ require_relative "./snakes/game"
4
4
 
5
5
  module Snakes
6
6
  class Error < StandardError; end
7
- puts "hello world this is snakes game"
8
- # Your code goes here...
9
7
  end
metadata CHANGED
@@ -1,22 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snakes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark24
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-06 00:00:00.000000000 Z
11
+ date: 2022-02-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Snakes game power by Ruby.
14
14
  email:
15
15
  - mark.zhangyoung@qq.com
16
- executables: []
16
+ executables:
17
+ - snakes
17
18
  extensions: []
18
19
  extra_rdoc_files: []
19
20
  files:
21
+ - ".idea/.gitignore"
22
+ - ".idea/misc.xml"
23
+ - ".idea/modules.xml"
24
+ - ".idea/snakes.iml"
25
+ - ".idea/vcs.xml"
20
26
  - ".rubocop.yml"
21
27
  - CHANGELOG.md
22
28
  - Gemfile
@@ -26,7 +32,9 @@ files:
26
32
  - Rakefile
27
33
  - bin/console
28
34
  - bin/setup
35
+ - exe/snakes
29
36
  - lib/snakes.rb
37
+ - lib/snakes/game.rb
30
38
  - lib/snakes/version.rb
31
39
  - sig/snakes.rbs
32
40
  - snakes.gemspec