查看: 2873|回复: 5

[RMVA发布] 【小游戏】《2048~》RMVA版v0.2

[复制链接]
梦石
0
星屑
632
在线时间
464 小时
注册时间
2011-4-4
回帖
54
发表于 2014-3-26 09:31:10 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 swebok 于 2014-3-31 21:05 编辑

最近《2048~》这个小游戏挺火的,昨晚思考了一下写了这么个脚本,算法是自己琢磨的。本人RUBY初学者,写的不好请多多包涵,如果出现问题了请@我。
得分和界面功能还没有实现,有时间再填上。


原游戏地址:
http://gabrielecirulli.github.io/2048/


游戏规则:
HOW TO PLAY:Use yourarrow keysto move the tiles. When two tiles with the same number touch, theymerge into one!
NOTE:This site is the official version of 2048. You can play it on your phone via.All other apps or sites are derivatives or fakes, and should be used with caution.
Created by Gabriele Cirulli.Based on 1024 by Veewo Studioand conceptually similar to Threes by Ashe Vollmer.[1]
游戏规则很简单,每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方乱数出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。系统给予的数字方块不是2就是4,玩家要想办法在这小小的16格范围中凑出“2048”这个数字方块。


工程下载:
http://pan.baidu.com/s/1hqomlt6


2014.3.30更新
参照taroxd的建议修改了工程,具体代码见1L&2L。


[pre lang="ruby" line="1"]#==============================================================================
# □ Scene_Game2048
# 2048小游戏,RMVA版作者:swebok,转载需保留该信息!
# http://rpg.blue/thread-357532-1-1.html
#==============================================================================
class Scene_Game2048 < Scene_Base
  #--------------------------------------------------------------------------
  # ● 开始处理
  #--------------------------------------------------------------------------
  def start
    super
    init_game
    draw_box
  end
  #--------------------------------------------------------------------------
  # ● 结束处理
  #--------------------------------------------------------------------------
  def terminate
    super
    @background_sprite.dispose
  end
  #--------------------------------------------------------------------------
  # ● 刷新处理
  #--------------------------------------------------------------------------
  def update
    super
    if Input.trigger?(:LEFT)
      @game2048.move(:left)
      judge
      clear_box
      Sound.play_cursor
      draw_box
    end
    if Input.trigger?(:RIGHT)
      @game2048.move(:right)
      judge
      clear_box
      Sound.play_cursor
      draw_box
    end
    if Input.trigger?(:UP)
      @game2048.move(:up)
      judge
      clear_box
      Sound.play_cursor
      draw_box
    end
    if Input.trigger?(:DOWN)
      @game2048.move(:down)
      judge
      clear_box
      Sound.play_cursor
      draw_box
    end
  end
  #--------------------------------------------------------------------------
  # ● 初始化
  #--------------------------------------------------------------------------
  def init_game
    @game2048 = Game2048.new
    @background_sprite = Sprite.new
    @background_sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height)
    draw_box
  end
  #--------------------------------------------------------------------------
  # ● 擦除格子
  #--------------------------------------------------------------------------
  def clear_box
    @background_sprite.bitmap.clear
  end
  #--------------------------------------------------------------------------
  # ● 描画格子
  #--------------------------------------------------------------------------
  def draw_box
    for i in 0...4
      for j in 0..4
        if @game2048.[](i, j) != nil
          @background_sprite.bitmap.draw_text(130+80*j, 100+60*i, 60, 24, @game2048.[](i, j), 1)
        end
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 判定结束
  #--------------------------------------------------------------------------
  def judge
    if @game2048.lose?
      clear_box
      draw_box
      @background_sprite.bitmap.draw_text(120, 320, 300, 24, "无法移动,你失败了!", 1)
      $data_system.gameover_me.play
      abs_wait(180)
      SceneManager.goto(Scene_Map)
    end
    if @game2048.win?
      clear_box
      draw_box
      @background_sprite.bitmap.draw_text(120, 320, 300, 24, "达到2048,恭喜您胜利!", 1)
      $game_system.battle_end_me.play
      abs_wait(180)
      SceneManager.goto(Scene_Map)
    end
  end
  #--------------------------------------------------------------------------
  # ● 等待(快进无效)
  #--------------------------------------------------------------------------
  def abs_wait(duration)
    duration.times {|i| update_for_wait }
  end
  #--------------------------------------------------------------------------
  # ● 更新画面(等待用)
  #--------------------------------------------------------------------------
  def update_for_wait
    update_basic
  end
end[/pre]


预计更新:
游戏界面;自定义文字、图片信息(比如可以做成2个包子合成一个馒头啦)。
(最近比较忙,预计会龟速更新,但愿别太监就行...)

点评

就是定义每一个方格里写什么【大概这样】只是提一下而已……  发表于 2014-3-31 19:38
更新  发表于 2014-3-31 08:48
更新了一下2L和4L,欢迎使用  发表于 2014-3-30 13:14
其实我本来就是想做命令行版2048,做完就把核心代码扔过来了  发表于 2014-3-27 18:32

评分

参与人数 2星屑 +600 收起 理由
fux2 + 500 好顶赞
喵呜喵5 + 100 精品文章

查看全部评分


老塞风流史

…あたしは天

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

开拓者贵宾

发表于 2014-3-27 08:44:20 | 显示全部楼层
本帖最后由 taroxd 于 2014-3-31 18:45 编辑

写了个纯Ruby类,用来处理2048(然后自己做了个命令行版本),仅供参考。

得分功能只要修改move_left即可。楼主可以看一下move_right等方法是怎么写的

目测 @Max 要被坑

[pre lang="ruby" line="1"]

class Game2048

  include Enumerable
  attr_reader :size

  def initialize(size = 4, max = 2048)
    @size, @Max = size, max
    @data = Array.new(size) { Array.new(size) }
    2.times { generate }
  end

  def move(direction)
    last = to_a
    send :"move_#{direction}"
    return if last == to_a
    generate
    self
  end

  def [](i, j)
    @data[j]
  end

  def each
    return to_enum(__method__) { @size**2 } unless block_given?
    @data.each {|row| row.each {|n| yield n } }
  end

  def each_index
    return to_enum(__method__) { @size**2 } unless block_given?
    @size.times {|i| @size.times {|j| yield i, j } }
  end

  def each_with_index
    return to_enum(__method__) { @size**2 } unless block_given?
    each_index {|i, j| yield @data[j], i, j }
  end

  def to_a
    @data.flatten
  end

  def lose?
    each_with_index.all? do |n, i, j|
      n && @data[j + 1] != n && (i >= @size - 1 || @data[i + 1][j] != n)
    end
  end

  def win?
    any? {|n| n && n >= @max }
  end

  private

  def move_left
    @data.each do |row|
      row.compact!
      (@size - 1).times do |i|
        if row && row == row[i + 1]
          row = merge_value(row)
          row.delete_at(i + 1)
        end
      end
      row.push(nil) until row.size >= @size
    end
  end

  def move_right
    reverse { move_left }
  end

  def move_up
    transpose { move_left }
  end

  def move_down
    transpose { move_right }
  end

  def transpose
    @data = @data.transpose
    yield
  ensure
    @data = @data.transpose
  end

  def reverse
    @data.each(&:reverse!)
    yield
  ensure
    @data.each(&:reverse!)
  end

  def generate
    i, j = each_index.select {|m, n| @data[m][n].nil? }.sample
    @data[j] = first_value if i
  end

  def first_value
    rand < 0.8 ? 2 : 4
  end

  def merge_value(n)
    n * 2
  end
end
[/pre]               

点评

因为并不会脚本所以……  发表于 2014-3-31 19:37
好厉害!学习中......  发表于 2014-3-27 17:38
回复

使用道具 举报

梦石
0
星屑
15070
在线时间
1581 小时
注册时间
2012-7-24
回帖
1246
发表于 2014-3-27 14:54:13 | 显示全部楼层
沙发了过来膜拜大神早就听说这个游戏很好玩了,虽然我是没有玩过啦

欢迎大家加我
回复

使用道具 举报

…あたしは天

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

开拓者贵宾

发表于 2014-3-27 18:46:09 | 显示全部楼层
本帖最后由 taroxd 于 2014-3-30 13:11 编辑

看了一下楼主的代码
draw_box方法为什么不用循环?
另外,失败条件并不是场上没有空格,还是无法进行下一次的移动

欢迎楼主直接用2L的代码做这个场景,我觉得会好很多。公有方法都写在上面了。(我是用nil来表示空格子的)
如果要使用的话,把每个 to_enum 后面跟的{ @size ** 2 } 去掉。这个block是给ruby2.0用的

点评

已经参照修改了~  发表于 2014-3-30 16:01
回复

使用道具 举报

…あたしは天

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

开拓者贵宾

发表于 2014-3-30 16:03:06 | 显示全部楼层
本帖最后由 taroxd 于 2014-3-31 18:45 编辑

[pre lang="ruby" line="1"]
  def draw_box
    for i in 0...4
      for j in 0..4
        if @game2048.[](i, j) != nil
          @background_sprite.bitmap.draw_text(130+80*j, 100+60*i, 60, 24, @game2048.[](i, j), 1)
        end
      end
    end
  end[/pre]

汗,明明定义了each_with_index还这样玩……而且j的范围还打错了(虽然没什么大碍)

美观大方~
[pre lang="ruby" line="1"]
  def draw_box
    @game2048.each_with_index do |n, i, j|
      @background_sprite.bitmap.draw_text(130+80*j, 100+60*i, 60, 24, n, 1) if n
    end
  end
[/pre]

另外 @game2048.[](i, j) 写成 @game2048[i, j] 就好

还有update方法可以写简单点, 改起来也方便~ 比如加个移动失败的功能
[pre lang="ruby" line="1"]
  def update
    super
    [:left, :right, :up, :down].each do |dir|
      if Input.trigger? dir.upcase
        if @game2048.move dir
          judge
          clear_box
          Sound.play_cursor
          draw_box
        else
          Sound.play_buzzer # 移动失败
        end
      end
    end
  end
[/pre]

然后,如果要加得分功能的话,可以对merge_value重定义,来增加@score即可
当然score要初始化为零,并且做好attr_reader :score

点评

学习了。  发表于 2014-3-31 09:08
回复

使用道具 举报

梦石
0
星屑
2017
在线时间
1019 小时
注册时间
2011-6-19
回帖
592

极短24参与开拓者

发表于 2014-3-30 19:16:05 | 显示全部楼层
仰望,话说RM的键盘操作特适合移植这个啊,不过不知道能不能加入让使用者自定义文字信息的功能?目前扫了一眼,似乎……没发现orz

点评

没加密的游戏直接改脚本不就好了?  发表于 2014-3-31 13:07
自定义文字信息?  发表于 2014-3-31 09:09
回复

使用道具 举报

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

本版积分规则

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

在本版发帖返回顶部