最今在玩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 [email protected]_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
180行ruby代码搞定游戏2048
时间: 2024-11-25 16:47:08