最今在玩2048这款小游戏,游戏逻辑简单,很适合我这样的对于游戏新入行的人来实现逻辑。于是选择了最拿手的ruby语言来实现这款小游戏的主要逻辑。还是挺简单的,加起来4小时左右搞定。

上代码:

require 'optparse'

module Help
HELP_TEXT =<<HELP press buttons for move
l => move to left
r => move to right
t => move to top
b => move to bottom
press e button to exit game you can see this help text if your input ruby ruby_2048.rb --help
HELP
def set_helps
OptionParser.new do |opts|
opts.on_tail("-h", "--help", 'This help text.') do
puts HELP_TEXT
exit!
end
end.parse!
end end class Object
def invoke(need, method)
if need
self.send(method)
else
self
end
end
end class R2048
extend Help attr_reader :chessboard
LEFT = "l"
RIGHT = "r"
TOP = "t"
BOTTOM = "b"
EXIT = "e" def initialize
R2048.set_helps
@chessboard = Array.new(4){|x| Array.new(4){|y| 0}}
@init_moved = false
1.upto(2){|i| generate_init_num}
end def generate_init_num
return false unless @chessboard.flatten.uniq.select{|chess| chess == 0}.count > 0 rand_position = rand(16)
x, y = rand_position/4, rand_position % 4
until @chessboard[x][y] == 0
rand_position = rand(16)
x, y = rand_position/4, rand_position % 4
end
@chessboard[x][y] = [2, 4][rand(2)] end def check_and_merge(transpose, reverse)
moved = false
temp_chessboard = @chessboard.invoke(transpose, :transpose).map do |row|
reversed_row = set_jump_step(row.invoke(reverse, :reverse)).invoke(reverse, :reverse)
moved = true if reversed_row != row.invoke(reverse, :reverse)
reversed_row
end.invoke(transpose, :transpose) if moved
@chessboard = temp_chessboard
true
else
if !@init_moved
@init_moved = true
true
else
false
end
end
end def generate_new_num(transpose, pos)
ungenerated = true right_positions = []
@chessboard.invoke(transpose, :transpose).each_with_index{|row, i| right_positions << i if row[pos] == 0}
right_position = right_positions[rand(right_positions.count)] row_index = 0
@chessboard = @chessboard.invoke(transpose, :transpose).map do |row|
if ungenerated && row_index == right_position
ungenerated = false
row[pos] = [2, 4][rand(2)]
end
row_index += 1
row
end.invoke(transpose, :transpose)
!ungenerated
end def set_jump_step(row)
pured = row.select{|chess| chess != 0 }.inject([]) do |sum, chess|
if sum.last == chess
sum.pop
sum << chess * 2
else
sum << chess
end
end
pured.concat Array.new(4 - pured.count, 0)
end def display
puts "==============================="
@chessboard.each_with_index do |c, row|
puts "#{c[0]} #{c[1]} #{c[2]} #{c[3]}"
puts
end
end def failure_display
puts "you have failed!!!"
end def run
display
key = nil
until key == "e\n"
key = gets
key.gsub!("\n", "")
return if key == EXIT if ![LEFT, RIGHT, TOP, BOTTOM].include? key
puts "input error"
next
end generate = case key
when LEFT
if check_and_merge(false, false)
generate_new_num(false, 3)
else
nil
end
when RIGHT
if check_and_merge(false, true)
generate_new_num(false, 0)
else
nil
end
when TOP
if check_and_merge(true, false)
generate_new_num(true, 3)
else
nil
end
when BOTTOM
if check_and_merge(true, true)
generate_new_num(true, 0)
else
nil
end
end if generate == nil || generate
display
else
failure_display
return
end
end
end
end R2048.new.run

写了一些測试:

require 'ruby_2048'

describe R2048 do
before(:each) do
@r2048 = R2048.new
end
it "should jump to [2, 0, 0, 0] when input [0, 0, 0, 2]" do
@r2048.set_jump_step([0, 0, 0, 2]).should == [2, 0, 0, 0]
end it "should jump to [2, 4, 0, 0] when input [2, 0, 4, 0]" do
@r2048.set_jump_step([2, 0, 4, 0]).should == [2, 4, 0, 0]
end it "should jump to [4, 0, 0, 0] when input [2, 0, 2, 0]" do
@r2048.set_jump_step([2, 0, 2, 0]).should == [4, 0, 0, 0]
end it "should jump to [2, 4, 4, 0] when input [2, 4, 2, 2]" do
@r2048.set_jump_step([2, 4, 2, 2]).should == [2, 4, 4, 0]
end it "should jump to [4, 4, 0, 0] when input [2, 2, 2, 2]" do
@r2048.set_jump_step([2, 2, 2, 2]).should == [4, 4, 0, 0]
end it "should + 1 chess if generate_init_num" do
expect { @r2048.generate_init_num }.to change{@r2048.chessboard.flatten.count{|chess| chess!= 0} }.by(1)
end it "should have already have two chess when inited" do
expect{@r2048.count} == 2
end
end

貌似还不错,最新代码请见github:https://github.com/xumc/ruby_2048

后记:

一篇博客介绍c++版命令行2048居然写了500多行,见http://blog.csdn.net/yc7369/article/details/29416819, 恰恰证明了ruby的简洁。

180行ruby代码搞定游戏2048的更多相关文章

  1. 5行js代码搞定导航吸顶效果

    一.HTML布局 首先写HTML布局 <body> <div id="wrap"></div> </body> 二.CSS样式 给点 ...

  2. 200行Java代码搞定计算器程序

    发现了大学时候写的计算器小程序,还有个图形界面,能够图形化展示表达式语法树,哈哈;) 只有200行Java代码,不但能够计算加减乘除,还能够匹配小括号~ 代码点评: 从朴素的界面配色到简单易懂错误提示 ...

  3. 【备忘】windows环境下20行php代码搞定音频裁剪

    先上图,由于最近的需求需要对语音文件进行处理,所以抽空研究了下php处理音/视频文件的处理,简单的demo处理,截取一个音频文件的前20秒,并保存新的媒体文件. 操作步骤: ①在此站点下载所需的辅助程 ...

  4. 几行JavaScript代码搞定Iframe 自动适应

    场景:Iframe嵌入flash,希望flash能随着页面的resize而resize. 主要代码: 代码 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTM ...

  5. 80行Python代码搞定全国区划代码

    微信搜索:码农StayUp 主页地址:https://gozhuyinglong.github.io 源码分享:https://github.com/gozhuyinglong/blog-demos ...

  6. 3kb jQuery代码搞定各种树形选择。

    自制Jquery树形选择插件. 对付各种树形选择(省市,分类..)90行Jquery代码搞定,少说废话直接上插件代码.稍后介绍使用说明.是之前写的一个插件的精简版. 1.Jquery插件代码 /* * ...

  7. 30行代码搞定WCF并发性能测试

    [以下只是个人观点,欢迎交流] 30行代码搞定WCF并发性能 轻量级测试. 1. 调用并发测试接口 static void Main()         {               List< ...

  8. 10行代码搞定移动web端自定义tap事件

    发发牢骚 移动web端里摸爬滚打这么久踩了不少坑,有一定移动web端经验的同学一定被click困扰过.我也不列外.一路走来被虐的不行,fastclick.touchend.iscroll什么的都用过, ...

  9. 开源作品ThinkJDBC—一行代码搞定数据库操作

    1 简介 ThinkJD,又名ThinkJDBC,一个简洁而强大的开源JDBC操作库.你可以使用Java像ThinkPHP框架的M方法一样,一行代码搞定数据库操作.ThinkJD会自动管理数据库连接, ...

随机推荐

  1. 不显示BOM清单的版本

    应用 Oracle Bill Of   Materiel 层 Level Function 函数名 Funcgtion Name BOM_BOMFDBOM 表单名 Form Name BOMFDBOM ...

  2. WIX 学习笔记- 1 简介

    一个项目 Code Complete 后,程序员们欢欣鼓舞,以为事情到此结束,可以 Happy 了.其实 Code Complete 五十之于百里.一个没有运行在设备上,为人们创造价值的项目是注定失败 ...

  3. poj2823_单调队列简单入门

    题目链接:http://poj.org/problem?id=2823 #include<iostream> #include<cstdio> #define M 100000 ...

  4. Hat's Fibonacci(大数,好)

    Hat's Fibonacci Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  5. 今天,Java编程周末提高班(第一期)正式结束

    Java编程周末提高班(第一期),走过了近两个月历程,一共同拥有68人次学生周末到老师家进行Java学习与交流.近距离的和一群年轻的学习接触,收获非常多,特别是对以后教学的改进.在学习的闲暇.大家自己 ...

  6. 统计分析SQL Server Profiler 跟踪的SQL

    --跟踪文件读入到表中分析 SELECT * INTO ZGSJY FROM fn_trace_gettable('E:\wxxcdbprofiler.trc', default); --某时间内,最 ...

  7. KJFrameForAndroid框架学习----高效设置网络图片

    KJFrameForAndroid框架项目地址:https://github.com/kymjs/KJFrameForAndroid 或备用地址http://git.oschina.net/kymjs ...

  8. 用VIM删除空行

    从网上找了一个 :g/^s*$/d 开始用的挺好,后来遇到一种空格开头的空行,就不好用了. MSDN上说正则匹配空行用/^\s*$/,就试着把上面的命令改为: :g/^\s*$/d 就可以了. 用的操 ...

  9. 关于matlab鼠标响应

    今天看了一下Matlab中响应鼠标的事件,整理如下, (1)函数WindowButtonMotionFcn,当鼠标在窗口上运动的时候就会相应此函数,于是在此函数中可以设置运动时想要的代码,如:改变鼠标 ...

  10. Objective-C中一些 值得程序员注意的地方(转载)

    1.有关于BOOL陷井方面有如下方面: 关于BOOL条件语句中的比较最好是与NO的值来进行比较,因为BOOL的YES与NO值只是约定,并且编译器将BOOL认作8位二进制数据.若是不小心将一个长于1字节 ...