zoukankan      html  css  js  c++  java
  • Game2048

    GameBoard.js

    /**
     * The examples provided by Facebook are for non-commercial testing and
     * evaluation purposes only.
     *
     * Facebook reserves all rights not expressly granted.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
     * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * @providesModule GameBoard
     * @flow
     */
    'use strict';
    
    // NB: Taken straight from: https://github.com/IvanVergiliev/2048-react/blob/master/src/board.js
    //     with no modification except to format it for CommonJS and fix lint/flow errors
    
    var rotateLeft = function (matrix) {
      var rows = matrix.length;
      var columns = matrix[0].length;
      var res = [];
      for (var row = 0; row < rows; ++row) {
        res.push([]);
        for (var column = 0; column < columns; ++column) {
          res[row][column] = matrix[column][columns - row - 1];
        }
      }
      return res;
    };
    
    var Tile = function (value?: number, row?: number, column?: number) {
      this.value = value || 0;
      this.row = row || -1;
    
      this.column = column || -1;
      this.oldRow = -1;
      this.oldColumn = -1;
      this.markForDeletion = false;
      this.mergedInto = null;
      this.id = Tile.id++;
    };
    
    Tile.id = 0;
    
    Tile.prototype.moveTo = function (row, column) {
      this.oldRow = this.row;
      this.oldColumn = this.column;
      this.row = row;
      this.column = column;
    };
    
    Tile.prototype.isNew = function () {
      return this.oldRow === -1 && !this.mergedInto;
    };
    
    Tile.prototype.hasMoved = function () {
      return (this.fromRow() !== -1 && (this.fromRow() !== this.toRow() || this.fromColumn() !== this.toColumn())) ||
        this.mergedInto;
    };
    
    Tile.prototype.fromRow = function () {
      return this.mergedInto ? this.row : this.oldRow;
    };
    
    Tile.prototype.fromColumn = function () {
      return this.mergedInto ? this.column : this.oldColumn;
    };
    
    Tile.prototype.toRow = function () {
      return this.mergedInto ? this.mergedInto.row : this.row;
    };
    
    Tile.prototype.toColumn = function () {
      return this.mergedInto ? this.mergedInto.column : this.column;
    };
    
    var Board = function () {
      this.tiles = [];
      this.cells = [];
      for (var i = 0; i < Board.size; ++i) {
        this.cells[i] = [this.addTile(), this.addTile(), this.addTile(), this.addTile()];
      }
      this.addRandomTile();
      this.setPositions();
      this.won = false;
    };
    
    Board.prototype.addTile = function () {
      var res = new Tile();
      Tile.apply(res, arguments);
      this.tiles.push(res);
      return res;
    };
    
    Board.size = 4;
    
    Board.prototype.moveLeft = function () {
      var hasChanged = false;
      for (var row = 0; row < Board.size; ++row) {
        var currentRow = this.cells[row].filter(function (tile) { return tile.value !== 0; });
        var resultRow = [];
        for (var target = 0; target < Board.size; ++target) {
          var targetTile = currentRow.length ? currentRow.shift() : this.addTile();
          if (currentRow.length > 0 && currentRow[0].value === targetTile.value) {
            var tile1 = targetTile;
            targetTile = this.addTile(targetTile.value);
            tile1.mergedInto = targetTile;
            var tile2 = currentRow.shift();
            tile2.mergedInto = targetTile;
            targetTile.value += tile2.value;
          }
          resultRow[target] = targetTile;
          this.won = this.won || (targetTile.value === 2048);
          hasChanged = hasChanged || (targetTile.value !== this.cells[row][target].value);
        }
        this.cells[row] = resultRow;
      }
      return hasChanged;
    };
    
    Board.prototype.setPositions = function () {
      this.cells.forEach(function (row, rowIndex) {
        row.forEach(function (tile, columnIndex) {
          tile.oldRow = tile.row;
          tile.oldColumn = tile.column;
          tile.row = rowIndex;
          tile.column = columnIndex;
          tile.markForDeletion = false;
        });
      });
    };
    
    Board.fourProbability = 0.1;
    
    Board.prototype.addRandomTile = function () {
      var emptyCells = [];
      for (var r = 0; r < Board.size; ++r) {
        for (var c = 0; c < Board.size; ++c) {
          if (this.cells[r][c].value === 0) {
            emptyCells.push({r: r, c: c});
          }
        }
      }
      var index = Math.floor(Math.random() * emptyCells.length);
      var cell = emptyCells[index];
      var newValue = Math.random() < Board.fourProbability ? 4 : 2;
      this.cells[cell.r][cell.c] = this.addTile(newValue);
    };
    
    Board.prototype.move = function (direction) {
      // 0 -> left, 1 -> up, 2 -> right, 3 -> down
      this.clearOldTiles();
      for (var i = 0; i < direction; ++i) {
        this.cells = rotateLeft(this.cells);
      }
      var hasChanged = this.moveLeft();
      for (var i = direction; i < 4; ++i) {
        this.cells = rotateLeft(this.cells);
      }
      if (hasChanged) {
        this.addRandomTile();
      }
      this.setPositions();
      return this;
    };
    
    Board.prototype.clearOldTiles = function () {
      this.tiles = this.tiles.filter(function (tile) { return tile.markForDeletion === false; });
      this.tiles.forEach(function (tile) { tile.markForDeletion = true; });
    };
    
    Board.prototype.hasWon = function () {
      return this.won;
    };
    
    Board.deltaX = [-1, 0, 1, 0];
    Board.deltaY = [0, -1, 0, 1];
    
    Board.prototype.hasLost = function () {
      var canMove = false;
      for (var row = 0; row < Board.size; ++row) {
        for (var column = 0; column < Board.size; ++column) {
          canMove = canMove || (this.cells[row][column].value === 0);
          for (var dir = 0; dir < 4; ++dir) {
            var newRow = row + Board.deltaX[dir];
            var newColumn = column + Board.deltaY[dir];
            if (newRow < 0 || newRow >= Board.size || newColumn < 0 || newColumn >= Board.size) {
              continue;
            }
            canMove = canMove || (this.cells[row][column].value === this.cells[newRow][newColumn].value);
          }
        }
      }
      return !canMove;
    };
    
    module.exports = Board;

    index.android.js

    /**
     * The examples provided by Facebook are for non-commercial testing and
     * evaluation purposes only.
     *
     * Facebook reserves all rights not expressly granted.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
     * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * @providesModule Game2048
     * @flow
     */
    'use strict';
    
    var React = require('react-native');
    var {
      AppRegistry,
      StyleSheet,
      Text,
      View,
    } = React;
    
    var Animated = require('Animated');
    var GameBoard = require('GameBoard');
    var TouchableBounce = require('TouchableBounce');
    
    var BOARD_PADDING = 3;
    var CELL_MARGIN = 4;
    var CELL_SIZE = 60;
    
    class Cell extends React.Component {
      render() {
        return <View style={styles.cell} />;
      }
    }
    
    class Board extends React.Component {
      render() {
        return (
          <View style={styles.board}>
            <View style={styles.row}><Cell/><Cell/><Cell/><Cell/></View>
            <View style={styles.row}><Cell/><Cell/><Cell/><Cell/></View>
            <View style={styles.row}><Cell/><Cell/><Cell/><Cell/></View>
            <View style={styles.row}><Cell/><Cell/><Cell/><Cell/></View>
            {this.props.children}
          </View>
        );
      }
    }
    
    class Tile extends React.Component {
      state: any;
    
      static _getPosition(index): number {
        return BOARD_PADDING + (index * (CELL_SIZE + CELL_MARGIN * 2) + CELL_MARGIN);
      }
    
      constructor(props: {}) {
        super(props);
    
        var tile = this.props.tile;
    
        this.state = {
          opacity: new Animated.Value(0),
          top: new Animated.Value(Tile._getPosition(tile.toRow())),
          left: new Animated.Value(Tile._getPosition(tile.toColumn())),
        };
      }
    
      calculateOffset(): {top: number; left: number; opacity: number} {
        var tile = this.props.tile;
    
        var offset = {
          top: this.state.top,
          left: this.state.left,
          opacity: this.state.opacity,
        };
    
        if (tile.isNew()) {
          Animated.timing(this.state.opacity, {
            duration: 100,
            toValue: 1,
          }).start();
        } else {
          Animated.parallel([
            Animated.timing(offset.top, {
              duration: 100,
              toValue: Tile._getPosition(tile.toRow()),
            }),
            Animated.timing(offset.left, {
              duration: 100,
              toValue: Tile._getPosition(tile.toColumn()),
            }),
          ]).start();
        }
        return offset;
      }
    
      render() {
        var tile = this.props.tile;
    
        var tileStyles = [
          styles.tile,
          styles['tile' + tile.value],
          this.calculateOffset(),
        ];
    
        var textStyles = [
          styles.value,
          tile.value > 4 && styles.whiteText,
          tile.value > 100 && styles.threeDigits,
          tile.value > 1000 && styles.fourDigits,
        ];
    
        return (
          <Animated.View style={tileStyles}>
            <Text style={textStyles}>{tile.value}</Text>
          </Animated.View>
        );
      }
    }
    
    class GameEndOverlay extends React.Component {
      render() {
        var board = this.props.board;
    
        if (!board.hasWon() && !board.hasLost()) {
          return <View/>;
        }
    
        var message = board.hasWon() ?
          '恭喜你顺利成为第930315个祝樊菲生日快乐的人!' : 'Game Over';
    
        return (
          <View style={styles.overlay}>
            <Text style={styles.overlayMessage}>{message}</Text>
            <TouchableBounce onPress={this.props.onRestart} style={styles.tryAgain}>
              <Text style={styles.tryAgainText}>Try Again?</Text>
            </TouchableBounce>
          </View>
        );
      }
    }
    
    class Game2048 extends React.Component {
      startX: number;
      startY: number;
      state: any;
    
      constructor(props: {}) {
        super(props);
        this.state = {
          board: new GameBoard(),
        };
        this.startX = 0;
        this.startY = 0;
      }
    
      restartGame() {
        this.setState({board: new GameBoard()});
      }
    
      handleTouchStart(event: Object) {
        if (this.state.board.hasWon()) {
          return;
        }
    
        this.startX = event.nativeEvent.pageX;
        this.startY = event.nativeEvent.pageY;
      }
    
      handleTouchEnd(event: Object) {
        if (this.state.board.hasWon()) {
          return;
        }
    
        var deltaX = event.nativeEvent.pageX - this.startX;
        var deltaY = event.nativeEvent.pageY - this.startY;
    
        var direction = -1;
        if (Math.abs(deltaX) > 3 * Math.abs(deltaY) && Math.abs(deltaX) > 30) {
          direction = deltaX > 0 ? 2 : 0;
        } else if (Math.abs(deltaY) > 3 * Math.abs(deltaX) && Math.abs(deltaY) > 30) {
          direction = deltaY > 0 ? 3 : 1;
        }
    
        if (direction !== -1) {
          this.setState({board: this.state.board.move(direction)});
        }
      }
    
      render() {
        var tiles = this.state.board.tiles
          .filter((tile) => tile.value)
          .map((tile) => <Tile ref={tile.id} key={tile.id} tile={tile} />);
    
        return (
          <View
            style={styles.container}
            onTouchStart={(event) => this.handleTouchStart(event)}
            onTouchEnd={(event) => this.handleTouchEnd(event)}>
            <Board>
              {tiles}
            </Board>
            <GameEndOverlay board={this.state.board} onRestart={() => this.restartGame()} />
          </View>
        );
      }
    }
    
    var styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
      },
      board: {
        padding: BOARD_PADDING,
        backgroundColor: '#bbaaaa',
        borderRadius: 5,
      },
      overlay: {
        position: 'absolute',
        top: 0,
        bottom: 0,
        left: 0,
        right: 0,
        backgroundColor: 'rgba(221, 221, 221, 0.5)',
        flex: 1,
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'center',
      },
      overlayMessage: {
        fontSize: 40,
        marginBottom: 20,
      },
      tryAgain: {
        backgroundColor: '#887761',
        padding: 20,
        borderRadius: 5,
      },
      tryAgainText: {
        color: '#ffffff',
        fontSize: 20,
        fontWeight: '500',
      },
      cell: {
         CELL_SIZE,
        height: CELL_SIZE,
        borderRadius: 5,
        backgroundColor: '#ddccbb',
        margin: CELL_MARGIN,
      },
      row: {
        flexDirection: 'row',
      },
      tile: {
        position: 'absolute',
         CELL_SIZE,
        height: CELL_SIZE,
        backgroundColor: '#ddccbb',
        borderRadius: 5,
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
      },
      value: {
        fontSize: 24,
        color: '#776666',
        fontFamily: 'Verdana',
        fontWeight: '500',
      },
      tile2: {
        backgroundColor: '#eeeeee',
      },
      tile4: {
        backgroundColor: '#eeeecc',
      },
      tile8: {
        backgroundColor: '#ffbb87',
      },
      tile16: {
        backgroundColor: '#ff9966',
      },
      tile32: {
        backgroundColor: '#ff7755',
      },
      tile64: {
        backgroundColor: '#ff5533',
      },
      tile128: {
        backgroundColor: '#eecc77',
      },
      tile256: {
        backgroundColor: '#eecc66',
      },
      tile512: {
        backgroundColor: '#eecc55',
      },
      tile1024: {
        backgroundColor: '#eecc33',
      },
      tile2048: {
        backgroundColor: '#eecc22',
      },
      whiteText: {
        color: '#ffffff',
      },
      threeDigits: {
        fontSize: 20,
      },
      fourDigits: {
        fontSize: 18,
      },
    });
    
    AppRegistry.registerComponent('Game2048', () => Game2048);
    
    module.exports = Game2048;
  • 相关阅读:
    Winform—C#读写config配置文件
    C# 中Web.config文件的读取与写入
    Redis配置文件详解
    三层架构之泛型抽象
    Linq To Sql语法及实例大全
    junit单元测试(keeps the bar green to keeps the code clean)
    观 GT Java语言管理系统的感悟
    java考核完的心得
    15个C++项目列表
    C++文件操作(fstream)
  • 原文地址:https://www.cnblogs.com/LoganChen/p/6720438.html
Copyright © 2011-2022 走看看