查看: 2396|回复: 4

[通用发布] 2048 on Ruby

[复制链接]
梦石
0
星屑
66
在线时间
1641 小时
注册时间
2011-9-26
回帖
302
发表于 2014-4-11 22:17:32 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 Shy07 于 2015-8-24 20:46 编辑

2048 都知道吧,这游戏跟 TETRIS 一样戳中消除强迫症的弱点,玩起来根本停不下来

施工完毕,建议使用 Ace ,并开启控制台运行,当然原生 Ruby 更方便

20140416     修正输入方向后,数字没有移动时,会产生新数字的 bug

[pre lang="ruby" line="1"]
=begin
puts "#------------------------------#"
puts "| Use your keyborad.           |"
puts "| W: Up A:Left S:Down D:Right  |"
puts "| Return: Next step            |"
puts "#------------------------------#"
puts "#------------------------------#"
puts "|Score:        0000000000000000|"
puts "#------------------------------#"
puts "#------+------+------+------#"
puts "|____2_|____2_|____2_|____2_|"
puts "├------+------+------+------┤"
puts "|____2_|____2_|____2_|____2_|"
puts "├------+------+------+------┤"
puts "|____2_|____2_|____2_|____2_|"
puts "├------+------+------+------┤"
puts "|_2048_|____2_|____2_|____2_|"
puts "#------+------+------+------#"
=end

$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 { puts a.inject("|") {|m, i| m + block.call(i) }}
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 {
                    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], lines[2], lines[1], lines[0] ] }
                    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], lines[2], lines[1], lines[0] = rows } 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 } }
              game_over.call if lines.inject(0) {|mem, line| mem + line.compact.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
[/pre]

评分

参与人数 6星屑 +307 收起 理由
卡奥尼特 + 15 我很赞同
喵呜喵5 + 120 精品文章
satgo1546 + 120 为什么我要给这么多糖
无脑之人 + 20 控制台简直丧心病狂w
余烬之中 + 20 虽然不怎么玩但是点赞
kuerlulu + 12 赞

查看全部评分

愿善用者善用之
https://github.com/Shy07/SINRGE2

…あたしは天

梦石
0
星屑
2308
在线时间
4033 小时
注册时间
2010-10-4
回帖
10548

开拓者贵宾

发表于 2014-4-13 17:12:23 | 显示全部楼层
一堆lambda简直丧心病狂~ 界面挺漂亮
小建议:控制台的输入直接使用Win32API接收方向键。我也拿控制台写过,感觉这样效果还不错~
            每一步之后可以先用 cls 命令清掉控制台
回复

使用道具 举报

梦石
0
星屑
66
在线时间
1641 小时
注册时间
2011-9-26
回帖
302
 楼主| 发表于 2014-4-14 19:25:54 | 显示全部楼层
taroxd 发表于 2014-4-13 17:12
一堆lambda简直丧心病狂~ 界面挺漂亮
小建议:控制台的输入直接使用Win32API接收方向键。我也拿控制台写过 ...

哈哈,我就知道会有人吐槽 lambda :-D
不用 Win32API 是考虑到原生 Ruby 的兼容性(我工作用的系统是 Mac OS,helper 里回车写成 return 而不是 enter 也是这原因)
清掉控制台感觉没什么必要,作为历史记录看看自己哪一步犯错也是不错的
愿善用者善用之
https://github.com/Shy07/SINRGE2
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部