標籤:des blog http os 2014 for
最今在玩2048這款小遊戲,遊戲邏輯簡單,非常適合我這種對於遊戲新入行的人來實現邏輯。於是選擇了最拿手的ruby語言來實現這款小遊戲的主要邏輯。還是挺簡單的,加起來4小時左右搞定。
上代碼:
require 'optparse'module HelpHELP_TEXT =<<HELPpress buttons for move l => move to left r => move to right t => move to top b => move to bottompress e button to exit gameyou can see this help text if your input ruby ruby_2048.rb --helpHELPdef set_helpsOptionParser.new do |opts|opts.on_tail("-h", "--help", 'This help text.') do puts HELP_TEXTexit!endend.parse!endendclass Objectdef invoke(need, method)if needself.send(method) elseselfendendendclass R2048extend Helpattr_reader :chessboardLEFT = "l"RIGHT = "r"TOP = "t"BOTTOM = "b"EXIT = "e"def initializeR2048.set_helps @chessboard = Array.new(4){|x| Array.new(4){|y| 0}} @init_moved = false1.upto(2){|i| generate_init_num}enddef generate_init_numreturn false unless @chessboard.flatten.uniq.select{|chess| chess == 0}.count > 0rand_position = rand(16)x, y = rand_position/4, rand_position % 4until @chessboard[x][y] == 0rand_position = rand(16)x, y = rand_position/4, rand_position % 4 end @chessboard[x][y] = [2, 4][rand(2)]enddef check_and_merge(transpose, reverse)moved = falsetemp_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_rowend.invoke(transpose, :transpose)if moved@chessboard = temp_chessboard trueelseif [email protected]_moved@init_moved = truetrueelse falseendendenddef generate_new_num(transpose, pos)ungenerated = trueright_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_positionungenerated = falserow[pos] = [2, 4][rand(2)]endrow_index += 1rowend.invoke(transpose, :transpose)!ungeneratedenddef 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)enddef display puts "===============================" @chessboard.each_with_index do |c, row| puts "#{c[0]}#{c[1]}#{c[2]}#{c[3]}" puts endenddef failure_displayputs "you have failed!!!"enddef rundisplaykey = niluntil key == "e\n"key = getskey.gsub!("\n", "")return if key == EXITif ![LEFT, RIGHT, TOP, BOTTOM].include? keyputs "input error" nextendgenerate = case keywhen LEFTif check_and_merge(false, false)generate_new_num(false, 3)elsenilendwhen RIGHTif check_and_merge(false, true)generate_new_num(false, 0)elsenilendwhen TOPif check_and_merge(true, false)generate_new_num(true, 3)elsenilendwhen BOTTOMif check_and_merge(true, true)generate_new_num(true, 0)elsenilendendif generate == nil || generate displayelse failure_display returnendendendendR2048.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 endend
貌似還不錯,最新代碼請見github:https://github.com/xumc/ruby_2048