Ruby 学以致用,2048 的记录反查

qqrrm · 2014年05月21日 · 最后由 admins 回复于 2014年07月21日 · 6512 次阅读
本帖已被管理员设置为精华贴

一直很喜欢 ruby,也来这里很久了,平时也写过一些 ruby 代码,当然了,都烂的要命,还是没有养成 ruby 甚至说程序员思维。今天弄了一天,做了个 2048 通过记录反向查询状态的程序,大家轻点打击,要保护新人啊。

#coding: UTF-8

#58640。2048我打的最大分,别人问,你到底最高多少啊。只有最高纪录分数看不到状态,干脆写个程序,告诉别人自己到底打到多少吧,我其实只记得自己是4096+1024,其他的分数忘记了,不过使用这个程序,很容易就分析出来了。

#测试人员写的程序,不是ruby思维,看到勿喷

#2048是在合成的时候记录分数,比如4和4合成8,记录8分,类似这个样子。新出现的2或者4是不计分数的。所以可以通过递归,获得块数合成时候的分数。

def total(n)  #假设全部的数都是2,2的n次方得到的分数,比如n=10,2**10=1024得到的纪录分数
  return 4 if n == 2
  2 * total( n - 1 ) + 2 ** n
end


def total_plus(n)  #随机2或4,比例9:1,获得的分数。
    i = 0
    (2 ** n / 2).times { i += 1 if rand(10) == 0}
    if total(n) >= i * 4
      total(n) - i * 4
    else
      0
    end
end

#{2=>4, 3=>16, 4=>48, 5=>128, 6=>320, 7=>768, 8=>1792, 9=>4096, 10=>9216, 11=>20480, 12=>45056, 13=>98304, 14=>212992, 15=>458752, 16=>983040} # 只有2的时候2**n对应的的得分

@h = {}
(2..16).each {|n| @h[n] = total_plus(n)}  #据传说,不能大于2**16次方
puts @h  # 做一个对应表,2的n次方对应的可能得分数


def max_n(score) #录入一个分数,小于此分数的最大对应n,比如得到5124分,查表得到最大可能的n是9,也就是说盘面最大是2**9=512。
  temp = []
  @h.each  do |k, v|      
    temp << k if v <= score   
  end
  temp.max 
end

def score_to_n(score, temp = []) #输入记录,反查组成此记录的n值数组
  max = max_n(score)
  return  temp << @h.key(score) if @h.key(score) == max #score在hash表内的时候,直接返回
  return temp if @h[max].zero?   #因为有4存在,所以可能会有0,去除0,要不后面就会报错
  div = score.divmod(@h[max])  #求余数
  div[0].times {temp << max } #多个的时候,写入temp多个n
  score_to_n(div[1], temp)
  temp.compact 
end


score = 58640

p score_to_n(score).map {|n| 2 ** n} # 最终的状态集合,可以检查一下是否和自己的状态一致
p [score, score_to_n(score).map {|n| @h[n] } .inject(:+)] #录入分数和校验分数的比较,可能不一样噢




最近我也是玩这游戏玩的无法自拔啊😆

珍爱大拇指,远离 2048

有意思!做个视觉化的出来吧

这个是视觉化的,直接就是 html,随便 copy 到哪里都可以。

在线地址: http://qqrrm.github.io/2048.html

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!--原框架作者信息<title>2048网页版(html+css+js) By:黄岩</title> -->
<title>2048记录反查网页版(html+css+js) By:pyp</title>
<style type="text/css">

#div {
    width: 318px;
    height: 400px;
    background-color: #f0f0f0;
    margin: auto;
}

.box1 {
    font-size: 24px;
    text-align: center;
    line-height: 72px;
    width: 72px;
    height: 72px;
    float: left;
    background-color: #CDC2B3;
    position: relative;
}

#score {
    left: 10px;
    top: 70px;
    position: relative;
    float: left;
}

</style>



<script language="javascript" type="text/javascript">

var bg;
var oBox;//元素
var result = new Array();   
var h = new Array();  //根据2的n次方对应的可能得分数组


function total(n) { //假设全部的数都是2,2的n次方得到的分数,比如n=10,2**10=1024得到的纪录分数
    if(n == 2)
        return 4 ;
    else
        return 2 * total(n - 1) + Math.pow(2, n);
}


function total_plus(n) { //随机2或4,比例9:1,获得的分数。
    var j = 0;
    var sum = Math.pow(2, n) / 2;
    for(var i = 0; i < sum; i++) {
        if (Math.random() > 0.9)
            j += 1;
   }
    if(total(n) > j * 4)
        return total(n) - j * 4;
    else
        return 0; 
}


function max_n(score){
    for(var i = 2 ; i < 17; i++){
        if( h[i] > score ){
            return i - 1;
        } 
        else if ( h[i] === score){
            return i
        }
    }
}


function divmod(x, y){  //ruby中的函数,就是进行div,形成结果和余数的数组
    var a, b;
    var temp = new Array();

    if(x > y){
        a = Math.floor(x / y);      
        b = x - y * a;
    } 

    temp.push(a);
    temp.push(b);
    return temp;
}


function score_to_n(score){  //通过得分递归获得拆分组合结果

    var max = max_n(score);
    var div = new Array();

    if(h[max] == score){
      result.push(max); 
      return result;
    } 

    if (h[max] == 0){
        return result;
    }

    div = divmod(score, h[max]);

    for(var i = 0; i < div[0]; i++){
        result.push(max);
    }

    score_to_n(div[1]); 
    return result;  
}

function initGame(){//游戏初始化

    bg = new Array();   

    for(var i = 0; i < 4; i++){
        bg[i] = new Array();
        for(var j = 0; j < 4; j++){
            bg[i][j] = 0;
        }
    }   
}


function paintGame(){//游戏绘图

    var i, str="";

    for(var m = 0;m < 4; m++){
        for(var n = 0;n < 4; n++){

            i = m * 4 + n + 1;

            oBox[i].innerHTML = bg[m][n];

            switch(bg[m][n]){
                case 0:str="#CDC2B3";break;
                case 2:str="#eee4da";break;
                case 4:str="#ede0c8";break;
                case 8:str="#f2b179";break;
                case 16:str="#f59563";break;
                case 32:str="#f67c5f";break;
                case 64:str="#f65e3b";break;
                case 128:str="#edcf72";break;
                case 256:str="#edcc61";break;
                case 512:str="#edc850";break;
                case 1024:str="#edc53f";break;
                case 2048:str="#edc22e";break;

                default:str="#ffc22e";
            }
            oBox[i].style.background = str;
        }
    }   
}

function btn(){  //按钮事件

  var temp = new Array();
  var score = document.getElementById("score_value").value;    

  if ((score > 950000) || (score % 1 !== 0))
    alert("大哥大姐,别耍我啊");
  else {    
      initGame();   

      for(var i = 2; i < 17; i++){  //生成得分数组
          h[i] = total_plus(i);  
        } 

        temp = score_to_n(score);   

        bg[3][3] = (temp[0]===undefined) ? 2 : Math.pow(2, temp[0]);  //个人习惯右下角最大,接着按大小蛇形排序,我玩2048就是这样的规律玩的
        bg[3][2] = (temp[1]===undefined) ? 2 : Math.pow(2, temp[1]);
        bg[3][1] = (temp[2]===undefined) ? 2 : Math.pow(2, temp[2]);
        bg[3][0] = (temp[3]===undefined) ? 2 : Math.pow(2, temp[3]);
        bg[2][0] = (temp[4]===undefined) ? 2 : Math.pow(2, temp[4]);
        bg[2][1] = (temp[5]===undefined) ? 2 : Math.pow(2, temp[5]);
        bg[2][2] = (temp[6]===undefined) ? 2 : Math.pow(2, temp[6]);
        bg[2][3] = (temp[7]===undefined) ? 2 : Math.pow(2, temp[7]);
        bg[1][3] = (temp[8]===undefined) ? 2 : Math.pow(2, temp[8]);
        bg[1][2] = (temp[9]===undefined) ? 2 : Math.pow(2, temp[9]);
        bg[1][1] = (temp[10]===undefined) ? 2 : Math.pow(2, temp[10]);
        bg[1][0] = (temp[11]===undefined) ? 2 : Math.pow(2, temp[11]);
        bg[0][0] = (temp[12]===undefined) ? 2 :  Math.pow(2, temp[12]);
        bg[0][1] = (temp[13]===undefined) ? 2 : Math.pow(2, temp[13]);
        bg[0][2] = (temp[14]===undefined) ? 2 : Math.pow(2, temp[14]);
        bg[0][3] = (temp[15]===undefined) ? 2 : Math.pow(2, temp[15]);

        paintGame();        

                temp.length = 0;
      }
  }
};


window.onload=function(){
    var j, k = 0;

    oBox = document.getElementsByTagName('div');

    for(var i = 1;i < 17;i++){
        k = (i-1)%4;
        oBox[i].style.left=((k+1)*6)+'px';
        j = (i-1)/4;
        oBox[i].style.top=((j+1)*6-2*k)+'px';
    }

};

</script>
</head>

<body>
<div id="div">

        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>
        <div class="box1"></div>

        <div id="score">
                <input type="text" id="score_value" value="58640" />
                <input type="button"  value="记录反查" onclick="btn()" />
        </div>

</div>
</body>
</html>

#4 楼 @qqrrm 手点的好累啊

需要 登录 后方可回复, 如果你还没有账号请 注册新账号