Life of xhu

About

写了一个2048

Jul 09, 2014

  |   #Ruby

半个月不写代码果然生疏了,居然在if里出现了=,而且还检查了好久才发现。。。

这是一个跑在终端里的2048游戏,本来想用C++写的,但是想了想和Ruby相比C++处理字符串不要太蛋疼,所以就用Ruby写了一个,果然轻松随意~

游戏的实现还是比较简单的,上下左右键操作,q退出,操作后按回车确定。

如果按下没反应,请自行修改方向键的判断字符串。

实现了2048游戏的大部分功能,还有两个地方没有解决:

  1. 成功玩到2048,没有相应的提示。其实我已经写好了判断胜利的方法,但是我目前还没有玩到过,就懒得调用这个方法了。

  2. 游戏失败的判断方法没有完成。我现在只写了一个判断又没有空格的语句,实际的2048游戏在格子被填满后,还要判断是否有相邻的相同的数字,如果有就不算失败,略麻烦懒得写了。

当然,这次写这个小游戏还是有点小收获的,比如Ruby的清屏方法,找到了两个:

exec 'clear'
system('clear')  

这两个方法是有区别的,同样是清空shell的当前窗口,第一个相当于在shell中输入clear,会结束掉当前shell语句的进程;而第二个,仅仅只是把输出内容清空,并不会结束掉语句。

话不多说,代码如下:

class Game2048
  attr_reader :board, :win_flag, :lose_flag, :move_flag
  def initialize
    @board = Array.new(16, '-')
    pos1 = (rand * 100).to_i % 16
    pos2 = (rand * 100).to_i % 16
    while pos2 == pos1
      pos2 = (rand * 100).to_i % 16
    end
    num1 = ((rand * 100).to_i % 2 + 1) * 2
    num2 = ((rand * 100).to_i % 2 + 1) * 2
    @board[pos1] = num1
    @board[pos2] = num2
    @cal_arr = Array.new
  end
  
  def print_borad
    system('clear') 
    puts "\n\n     ======== 2048 by TDFJ =======\n\n"
    0.upto(3) do |i1|
      ((4 * i1)..(4 * i1 + 3)).each do |i2| 
        (4 - @board[i2].to_s.length).times { print ' ' }
        print @board[i2], '       ' 
      end
      print "\n\n\n\n"
    end
  end
  
  def create_piece
    empty_place = Array.new
    (0..15).each do |i|
      empty_place.push(i) if @board[i] == '-'
    end
    create_place = (rand * 100).to_i % empty_place.length
    @board[empty_place[create_place]] = ((rand * 100).to_i % 2 + 1) * 2
  end
  
  def win?
    @win_flag = false
    (0..15).each { |i| @win_flag = true if @board[i] == 2048 }
    @win_flag
  end
  
  def lose?
    @lose_flag = true
    (0..15).each { |i| @lose_flag = false if @board[i] == '-' }
    @lose_flag
  end
  
  def cal
    0.upto(@cal_arr.length - 2) do |i|
      if @cal_arr[i] != '-' && @cal_arr[i] == @cal_arr[i + 1]
        @move_flag = true
        @cal_arr[i] = @cal_arr[i] * 2
        @cal_arr.delete_at(i + 1)
        @cal_arr.push('-')
      end
    end
    (4 - @cal_arr.length).times { @cal_arr.push('-') }
  end
  
  def step(ori)
    @move_flag = false
    case ori
    when 'up' then
      (0..3).each do |i1|
        @cal_arr.clear
        0.step(12, 4) { |i2| @cal_arr.push(@board[i1 + i2]) if @board[i1 + i2] != '-' }
        @move_flag = true if @board[i1 + 0] == '-' && @cal_arr.length != 0
        self.cal
        0.step(12, 4) { |i2| @board[i1 + i2] = @cal_arr[i2 / 4] }
      end
    when 'down' then
      (0..3).each do |i1|
        @cal_arr.clear
        12.step(0, -4) { |i2| @cal_arr.push(@board[i1 + i2]) if @board[i1 + i2] != '-' }
        @move_flag = true if @board[i1 + 12] == '-' && @cal_arr.length != 0
        self.cal
        12.step(0, -4) { |i2| @board[i1 + i2] = @cal_arr[(12 - i2) / 4] }
      end
    when 'left' then
      0.step(12, 4) do |i1|
        @cal_arr.clear
        0.upto(3) { |i2| @cal_arr.push(@board[i1 + i2]) if @board[i1 + i2] != '-' }
        @move_flag = true if @board[i1] == '-' && @cal_arr.length != 0
        self.cal
        0.upto(3) { |i2| @board[i1 + i2] = @cal_arr[i2] }
      end
    when 'right' then
      0.step(12, 4) do |i1|
        @cal_arr.clear
        3.downto(0) { |i2| @cal_arr.push(@board[i1 + i2]) if @board[i1 + i2] != '-' }
        @move_flag = true if @board[i1 + 3] == '-' && @cal_arr.length != 0
        self.cal
        3.downto(0) { |i2| @board[i1 + i2] = @cal_arr[3 - i2] }
      end
    end
  end
end

game2048 = Game2048.new
game2048.print_borad
input = gets.chomp
while input != 'q'
  case input
  when "\e[A" then
    game2048.step('up')
  when "\e[B" then
    game2048.step('down')
  when "\e[D" then
    game2048.step('left')
  when "\e[C" then
    game2048.step('right')
  end
  game2048.create_piece if game2048.move_flag
  game2048.print_borad
  input = gets.chomp
end