Skip to content

Instantly share code, notes, and snippets.

@lnit
Created May 9, 2026 14:51
Show Gist options
  • Select an option

  • Save lnit/8ab63ec5a2287608a35ab1a6e336f277 to your computer and use it in GitHub Desktop.

Select an option

Save lnit/8ab63ec5a2287608a35ab1a6e336f277 to your computer and use it in GitHub Desktop.
Spinelで動くSnake Game
class SnakeGame
WIDTH = 20
HEIGHT = 10
MAX_SNAKE_LENGTH = 200
def initialize
@field = []
@snake_x = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
@snake_y = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
@snake_length = 3
@direction = 2 # 0=上, 1=下, 2=右, 3=左
@food_x = 0
@food_y = 0
@score = 0
@game_over = 0
@running = 1
# フィールド初期化(0=空, 1=壁, 2=ヘビ, 3=餌)
y = 0
while y < HEIGHT
x = 0
while x < WIDTH
value = (y == 0 || y == HEIGHT - 1 || x == 0 || x == WIDTH - 1) ? 1 : 0
@field << value
x += 1
end
y += 1
end
# ヘビの初期位置(中央)
@snake_x[0] = 10
@snake_y[0] = 5
@snake_x[1] = 9
@snake_y[1] = 5
@snake_x[2] = 8
@snake_y[2] = 5
place_food
end
def run
setup_terminal
clear_screen
# 初期描画
draw_game
while @running == 1
# 非ブロッキングでキー入力チェック
key = read_key_nonblocking
if key == "q"
@running = 0
elsif key == "w"
@direction = 0 if @direction != 1 # 下向きでなければ上に変更可
elsif key == "s"
@direction = 1 if @direction != 0 # 上向きでなければ下に変更可
elsif key == "d"
@direction = 2 if @direction != 3 # 左向きでなければ右に変更可
elsif key == "a"
@direction = 3 if @direction != 2 # 右向きでなければ左に変更可
end
if @game_over == 0
move_snake
draw_game
else
@running = 0
end
flush_sleep(0.2)
end
restore_terminal
print "\r\n\r\nゲーム終了!\r\n"
print "最終スコア: "
print @score
print "\r\n"
end
private
def setup_terminal
system("stty raw -echo")
end
def restore_terminal
system("stty -raw echo")
end
def clear_screen
system("clear")
end
def flush_sleep(seconds)
system("")
system("sleep 0.2")
end
def read_key_nonblocking
# bashのread -tコマンドでタイムアウト付き読み取り
# -t 0.01 = 0.01秒でタイムアウト、-n 1 = 1文字読み取り
result = `bash -c 'read -t 0.01 -n 1 key 2>/dev/null && echo $key'`
result.chomp
end
def get_field(x, y)
@field[y * WIDTH + x]
end
def set_field(x, y, value)
@field[y * WIDTH + x] = value
end
def place_food
# ランダムな位置に餌を配置
loop do
# spinelではrand(n)で0〜n-1の整数を返す
@food_x = rand(WIDTH - 2) + 1
@food_y = rand(HEIGHT - 2) + 1
# ヘビと重ならない位置を探す
occupied = 0
i = 0
while i < @snake_length
if @snake_x[i] == @food_x && @snake_y[i] == @food_y
occupied = 1
end
i += 1
end
if occupied == 0
set_field(@food_x, @food_y, 3)
break
end
end
end
def move_snake
# 新しい頭の位置を計算
new_x = @snake_x[0]
new_y = @snake_y[0]
if @direction == 0
new_y -= 1
elsif @direction == 1
new_y += 1
elsif @direction == 2
new_x += 1
elsif @direction == 3
new_x -= 1
end
# 壁との衝突チェック
if get_field(new_x, new_y) == 1
@game_over = 1
return
end
# 自分との衝突チェック
i = 0
while i < @snake_length
if @snake_x[i] == new_x && @snake_y[i] == new_y
@game_over = 1
return
end
i += 1
end
# 餌を食べたかチェック
ate_food = 0
if new_x == @food_x && new_y == @food_y
ate_food = 1
@score += 10
@snake_length += 1
end
# ヘビを移動(後ろから前に)
i = @snake_length - 1
while i > 0
@snake_x[i] = @snake_x[i - 1]
@snake_y[i] = @snake_y[i - 1]
i -= 1
end
@snake_x[0] = new_x
@snake_y[0] = new_y
# フィールド更新
update_field
# 餌を食べたら新しい餌を配置
if ate_food == 1
place_food
end
end
def update_field
# フィールドをクリア(壁以外)
i = 0
while i < WIDTH * HEIGHT
if @field[i] != 1
@field[i] = 0
end
i += 1
end
# ヘビを配置
i = 0
while i < @snake_length
set_field(@snake_x[i], @snake_y[i], 2)
i += 1
end
# 餌を配置
set_field(@food_x, @food_y, 3)
end
def draw_game
# 画面クリアとカーソルをホームに移動
print "\033[2J\033[H"
print "=== スネークゲーム ===\r\n"
print "WASD: 移動, Q: 終了\r\n"
print "スコア: "
print @score
print "\r\n"
print "\r\n"
# フィールド描画
y = 0
while y < HEIGHT
x = 0
while x < WIDTH
cell = get_field(x, y)
if cell == 1
print "ロ"
elsif cell == 2
print "巳"
elsif cell == 3
print "飯"
else
print " "
end
x += 1
end
print "\r\n"
y += 1
end
if @game_over == 1
print "\r\n"
print "ゲームオーバー!\r\n"
end
system("") # フラッシュ
end
end
# ゲーム実行
begin
game = SnakeGame.new
game.run
rescue Interrupt
system("stty -raw echo")
print "\r\n\r\n割り込みで終了\r\n"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment