最今在玩 2048 这款小游戏,游戏逻辑简单,非常适合我这种对于游戏新入行的人来实现逻辑。于是选择了最拿手的 ruby 语言来实现这款小游戏的主要逻辑。还是挺简单的,加起来 4 小时左右搞定。 blog 见:http://blog.csdn.net/codelifeofme/article/details/37406173
如有错误,还望斧正。
我也来一个,请无视逻辑部分
$score = 0
$changed = false
lines = []; 4.times { lines << [nil, nil, nil, nil] }
helper = -> {
puts "┌───────────────┐"
puts "│ Use your keyborad. │"
puts "│ W: Up A:Left S:Down D:Right │"
puts "│ Return: Next step │"
puts "└───────────────┘"
}
score = -> {
puts "┌───────────────┐"
puts "│Score: #{"%016d" % $score}│"
puts "└───────────────┘"
}
header = -> { puts "┌───┬───┬───┬───┐" }
block = -> n { "_#{"_" * (4 - n.to_s.length)}#{n}_│" }
liner = -> a { s = "│" ; a.each {|i| s += block.call i }; puts s}
footer = -> { puts "└───┴───┴───┴───┘" }
new_num = -> {
loop do
x, y = rand(4), rand(4)
if lines[x][y].nil?
lines[x][y] = rand < 0.8 ? 2 : 4
break
end
end
}
start = -> { 2.times { new_num.call } }
restart = -> {
loop do
puts "Play again? (Y/N)"
str = gets
case str.rstrip.to_sym
when :Y, :y
lines.clear; 4.times { lines << [nil, nil, nil, nil] }
$score = 0; new_num.call
break
when :N, :n; exit; end
end
}
game_over = -> {
puts "┌───────────────┐"
puts "│ Game Over! │"
puts "└───────────────┘"
restart.call
}
congrulations = -> {
puts "┌───────────────┐"
puts "│Congrulations!You've got 2048!│"
puts "└───────────────┘"
restart.call
}
refresh = -> { score.call; header.call; lines.each {|l| liner.call l }; footer.call}
complement = -> l { (4 - l.size).times { l << nil } if l.size < 4 }
arrange = -> line {#, size {
case line.size
# when 0, 1
when 2
if line[0] == line[1]
line[0] += line[1]; line[1] = nil; $score += line[0]
end
when 3
if line[0] == line[1]
line[0] += line[1]; line[1], line[2] = line[2], nil; $score += line[0]
elsif line[1] == line[2]
line[1] += line[2]; line[2] = nil; $score += line[1]
end
when 4
if line[0] == line[1]
line[0] += line[1]; line[1], line[2], line[3] = line[2], line[3], nil; $score += line[0]
end
if line[1] == line[2]
line[1] += line[2]; line[2], line[3] = line[3], nil; $score += line[1]
end
if !line[2].nil? && line[2] == line[3]
line[2] += line[3]; line[3] = nil; $score += line[2]
end
end
}
process = -> args {
rows = []
if args[0]
rows = lines
else
4.times { |i| rows << [ lines[3][i], lines[2][i], lines[1][i], lines[0][i] ] }
end
rows.each do |row|
row.reverse! if args[1]
row.compact!
arrange.call row
complement.call row
row.reverse! if args[1]
4.times { |i| lines[3][i], lines[2][i], lines[1][i], lines[0][i] = rows[i] } unless args[0]
end
}
left = -> { process.call [ true, false] }
down = -> { process.call [false, false] }
right = -> { process.call [ true, true] }
up = -> { process.call [false, true] }
check = -> {
lines.each { |l| l.each { |b| congrulations.call if b == 2048 } }
size = 0; lines.each { |line| size += line.compact.size }
game_over.call if size == 16
}
game = -> {
helper.call
start.call
loop do
$nums = 0
image = []; lines.each { |l| image << l.clone }
refresh.call
str = gets
case str.rstrip.to_sym
when :a; left.call
when :s; down.call
when :d; right.call
when :w; up.call;
else next; end
check.call
new_num.call if image != lines
end
}
game.call
Ruby 其实可以写的更简单
https://gist.github.com/swordray/a04e9fda23107f26f284
class Game2048
def initialize
@array = 4.times.map { [ nil ] * 4 }
2.times { fill }
end
def fill
i, j = rand(4), rand(4)
return fill if @array[i][j]
@array[i][j] = [2, 2, 2, 2, 4].shuffle.first
end
def move(direction)
@array = @array.transpose if %w[up down].include?(direction)
@array.each(&:reverse!) if %w[right down].include?(direction)
4.times do |i|
a = @array[i].compact
4.times { |x| a[x], a[x + 1] = a[x] * 2, nil if a[x].to_i == a[x + 1] }
@array[i] = a.compact.concat([ nil ] * 4)[0..3]
end
@array.each(&:reverse!) if %w[right down].include?(direction)
@array = @array.transpose if %w[up down].include?(direction)
end
def play
puts @array.map { |line| "[%5s] " * 4 % line }
move({ a: 'left', s: 'down', d: 'right', w: 'up' }[gets.strip.to_sym])
fill && play if @array.flatten.include?(nil)
end
end
Game2048.new.play