zoukankan      html  css  js  c++  java
  • 用 React 编写2048游戏

    1.代码

      1 <!DOCTYPE html>
      2 <html lang="zh-cn">
      3 <head>
      4     <meta charset="UTF-8">
      5     <title>万能的React</title>
      6     <style>
      7         .app{
      8             margin:10px;
      9             font-family: arial;
     10         }
     11         .board{
     12             display:block;
     13             position:relative;
     14             margin:10px 0px 10px 0px;
     15             border:1px solid #ccc;
     16             width:215px;
     17             height:215px;
     18             padding:5px;
     19         }
     20         .board span{
     21             font-family: arial;
     22             letter-spacing: -1px;
     23             display:block;
     24             width:50px;
     25             height:36px;
     26             position:absolute;
     27             text-align:center;
     28             color:white;
     29             font-weight:bold;
     30             font-size:20px;
     31             padding-top:14px;
     32             background-color:#ebe76f;
     33             border-radius: 5px;
     34             transition: all 100ms linear;
     35         }
     36         .a1, .b1, .c1, .d1{ left:5px; }
     37         .a2, .b2, .c2, .d2{ left:60px; }
     38         .a3, .b3, .c3, .d3{ left:115px; }
     39         .a4, .b4, .c4, .d4{ left:170px; }
     40         .a1, .a2, .a3, .a4{ top:5px; }
     41         .b1, .b2, .b3, .b4{ top:60px; }
     42         .c1, .c2, .c3, .c4{ top:115px; }
     43         .d1, .d2, .d3, .d4{ top:170px; }
     44         span.value2{ background-color:#ebb26f; }
     45         span.value4{ background-color:#ea6feb; }
     46         span.value8{ background-color:#eb6fa3; }
     47         span.value16{ background-color:#7a6feb; }
     48         span.value32{ background-color:#af6feb; }
     49         span.value64{ background-color:#6febcf; }
     50         span.value128{ background-color:#6fbeeb; }
     51         span.value256{ background-color:#afeb6f; }
     52         span.value512{ background-color:#7aeb6f; }
     53         span.value1024{ background-color:#e4eb6f; }
     54     </style>
     55 </head>
     56 <body>
     57     <script src="./react-0.13.2/react-0.13.2/build/react.js"></script>
     58     <script src="./react-0.13.2/react-0.13.2/build/JSXTransformer.js"></script>
     59     <script type="text/jsx">
     60         var initial_board = {
     61             a1:null,a2:null,a3:null,a4:null,
     62             b1:null,b2:null,b3:null,b4:null,
     63             c1:null,c2:null,c3:null,c4:null,
     64             d1:null,d2:null,d3:null,d4:null
     65         };
     66 
     67         function available_spaces(board){
     68             return Object.keys(board).filter(function(key){
     69                 return board[key] == null
     70             });
     71         }
     72 
     73         function used_spaces(board){
     74             return Object.keys(board).filter(function(key){
     75                 return board[key] !== null
     76             });
     77         }
     78 
     79         function score_board(board){
     80             return used_spaces(board).map(function(key){
     81                 return (board[key].values.reduce(function(a, b) {
     82                     return a + b; //sum tile values
     83                 })) - board[key].values[0]; //don't count initial value
     84             }).reduce(function(a,b){return a+b}, 0);
     85         }
     86 
     87         function tile_value(tile){
     88             return tile ? tile.values[tile.values.length-1] : null;
     89         }
     90 
     91         function can_move(board){
     92             var new_board = [up,down,left,right].reduce(function(b, direction){
     93                 return fold_board(b, direction);
     94             }, board);
     95             return available_spaces(new_board).length > 0
     96         }
     97 
     98         function same_board(board1, board2){
     99             return Object.keys(board1).reduce(function(ret, key){
    100                 return ret && board1[key] == board2[key];
    101             }, true);
    102         }
    103 
    104         function fold_line(board, line){
    105             var tiles = line.map(function(key){
    106                 return board[key];
    107             }).filter(function(tile){
    108                  return tile !== null
    109             });   
    110             var new_tiles = [];
    111             if(tiles){
    112                 //must loop so we can skip next if matched
    113                 for(var i=0; i < tiles.length; i++){
    114                    var tile = tiles[i];
    115                    if(tile){
    116                        var val = tile_value(tile);
    117                        var next_tile = tiles[i+1];
    118                         if(next_tile && val == tile_value(next_tile)){
    119                             //skip next tile;
    120                             i++;
    121                             new_tiles.push({
    122                                 id: next_tile.id, //keep id
    123                                 values: tile.values.concat([val * 2])
    124                             });
    125                         }
    126                         else{
    127                             new_tiles.push(tile);
    128                         }
    129                     }
    130                 }
    131             }
    132             var new_line = {};
    133             line.forEach(function(key, i){
    134                 new_line[key] = new_tiles[i] || null;
    135             });
    136             return new_line;
    137         }
    138 
    139         function fold_order(xs, ys, reverse_keys){
    140             return xs.map(function(x){
    141                 return ys.map(function(y){
    142                     var key = [x,y];
    143                     if(reverse_keys){
    144                         return key.reverse().join("");
    145                     }
    146                     return key.join("");
    147                 });
    148             });
    149         }
    150 
    151         function fold_board(board, lines){
    152             //copy reference
    153             var new_board = board;
    154             lines.forEach(function(line){
    155                 var new_line = fold_line(board, line);
    156                 Object.keys(new_line).forEach(function(key){
    157                     //mutate reference while building up board
    158                     new_board = set_tile(new_board, key, new_line[key]);
    159                 });
    160             });
    161             return new_board;
    162         }
    163 
    164         var tile_counter = 0;
    165         function new_tile(initial){
    166             return {
    167                 id: tile_counter++,
    168                 values: [initial]
    169             };
    170         }
    171 
    172         function set_tile(board, where, tile){
    173             //do not destory the old board
    174             var new_board = {};
    175             Object.keys(board).forEach(function(key, i){
    176                 //copy by reference for structual sharing
    177                 new_board[key] = (key == where) ? tile : board[key];
    178             });
    179             return new_board;
    180         }
    181 
    182         var left = fold_order(["a","b","c","d"], ["1","2","3","4"], false);
    183         var right = fold_order(["a","b","c","d"], ["4","3","2","1"], false);
    184         var up = fold_order(["1","2","3","4"], ["a","b","c","d"], true);
    185         var down = fold_order( ["1","2","3","4"], ["d","c","b","a"], true);
    186 
    187         var GameBoard = React.createClass({
    188             getInitialState: function(){
    189                 return this.addTile(this.addTile(initial_board));
    190             },
    191             keyHandler:function(e){
    192                 var directions = {
    193                     37: left,
    194                     38: up,
    195                     39: right,
    196                     40: down
    197                 };
    198                 if(directions[e.keyCode]
    199                 && this.setBoard(fold_board(this.state, directions[e.keyCode]))
    200                 && Math.floor(Math.random() * 30, 0) > 0){
    201                     setTimeout(function(){
    202                          this.setBoard(this.addTile(this.state));
    203                     }.bind(this), 100);
    204                 }
    205             },
    206             setBoard:function(new_board){
    207                 if(!same_board(this.state, new_board)){
    208                     this.setState(new_board);
    209                     return true;
    210                 }
    211                 return false;
    212             },
    213             addTile:function(board){
    214                 var location = available_spaces(board).sort(function() {
    215                   return .5 - Math.random();
    216                 }).pop();
    217                 if(location){
    218                     var two_or_four = Math.floor(Math.random() * 2, 0) ? 2 : 4;
    219                     return set_tile(board, location, new_tile(two_or_four));
    220                 }
    221                 return board;
    222             },
    223             newGame:function(){
    224                 this.setState(this.getInitialState());
    225             },
    226             componentDidMount:function(){
    227                 window.addEventListener("keydown", this.keyHandler, false);
    228             },
    229             render:function(){
    230                 var status = !can_move(this.state)?" - Game Over!":"";
    231                 return <div className="app">
    232                     <span className="score">
    233                         Score: {score_board(this.state)}{status}
    234                     </span>
    235                     <Tiles board={this.state}/>
    236                     <button onClick={this.newGame}>New Game</button>
    237                 </div>
    238             }
    239         });
    240 
    241         var Tiles = React.createClass({
    242             render: function(){
    243                 var board = this.props.board;
    244                 //sort board keys first to stop re-ordering of DOM elements
    245                 var tiles = used_spaces(board).sort(function(a, b) {
    246                     return board[a].id - board[b].id;
    247                 });
    248                 return <div className="board">{
    249                     tiles.map(function(key){
    250                         var tile = board[key];
    251                         var val = tile_value(tile);
    252                         return <span key={tile.id} className={key + " value" + val}>
    253                                 {val}
    254                                </span>;
    255                 })}</div>
    256             }
    257         });
    258 
    259         React.render(<GameBoard />, document.body);
    260     </script>
    261 </body>
    262 </html>

    2.结果

  • 相关阅读:
    IoC 中 car 对象的配置如下,现在要添加 user 对象,并且将 car 注入到 user 中,正确的配置是?
    说说 IoC 中的继承和 Java 继承的区别
    bean 的 scope 有几种类型?请详细列举。
    简单谈谈 IoC 容器的原理
    谈谈你对 Spring IoC 和 DI 的理解,它们有什么区别?
    day13-14 内置函数
    day12 生成器(重要)
    day11 闭包和迭代器
    day10 函数进阶
    day09 函数
  • 原文地址:https://www.cnblogs.com/shamgod/p/5076930.html
Copyright © 2011-2022 走看看