实现一个js的洗牌

一个洗牌的js程序

先定义一个枚举类型的工厂方法

/*
 *  enumeration.js文件
 *  2018年07月20日 02:31
 */

// 这个函数创建一个新的枚举类型,实参对象表示类的每个实例的名字和值(即传入的是一个集合,该集合是名字和值的键值对)
// 返回值是一个构造函数
// 类似于工厂函数,不过这个工厂函数加工的对象是构造函数
// 这个构造函数会抛出异常:不能使用它来创建该类型的新实例
// 返回构造函数包含名/值对的映射表
// 包括由值组成的数组,以及一个foreach()迭代器函数
function enumeration(namesToValues) {
    // 这个虚拟构造函数是返回值
    var enumeration = function(){ throw "can't Instantiate Enumerations"; };

    // 枚举值继承自这个对象
    var proto = enumeration.prototype = {
        constructor: enumeration,   // 说明该函数是由enumeration为原型创建的
        toString: function(){ return this.name; },  // 返回名字
        valueOf: function(){ return this.value; },  // 返回值
        toJSON: function(){ return this.name; },    // 转换为JSON
    };

    enumeration.values = [];    // 用来存放枚举对象的数组

    // 现在创建新类型的实例
    for (name in namesToValues) {   // for/in循环遍历每个值
        var e = Object.create(proto)    // 创建一个代表它的对象
        e.name = name;  // 给他一个名字
        e.value = namesToValues[name];  // 给他一个值
        enumeration[name] = e;  // 将它设置为构造函数的属性 
        enumeration.values.push(e); // 将其储存到值数组中,即保存进上个创建的values的对象中
    };

    // 一个类方法,用来对类的实例进行迭代
    enumeration.foreach = function(f, c) {
        for(var i = 0; i < this.values.length; i++) f.call(c, this.values[i])   // 每次循环调用
    };

    // 返回标识这个新类型的构造函数
    return enumeration;
}

接着使用这个工厂方法实现一个类

/*
 *  使用enumeration()工厂方法实现一个洗牌程序,其中Card为玩牌的类
 *  proker.js
 *  时间:2018/07/21 01:16
 */

// 定义一个表示玩牌的类
function Card(suit, rank) {
    this.suit = suit; // 每张牌都有花色
    this.rank = rank; // 每张牌的点数
};

// 使用枚举类型定义花色和点数
Card.Suit = enumeration({Cluds: 1, Diamonds: 2, Hearts: 3, Spades: 4});
Card.Rank = enumeration({Two: 2, Three: 3, Four: 4, Five: 5, Six: 6, Seven: 7, Eight: 8, Nine: 9, Ten: 10, Jack: 11, Quee: 12, king: 13, Ace: 14});

// 定义用以描述牌面的文本
Card.prototype.toString = function () {
    return this.rank.toString() + ' of ' + this.suit.toString();
};
// 比较扑克牌中两张牌的大小
Card.prototype.compareTo = function (that) {
    if (this.rank < that.rank) return -1;
    if (this.rank > taht.rank) return 1;
    return 0;
};

// 以扑克牌的玩法规则对牌进行排序的函数
Card.orderByRank = function (a, b) {
    return a.compareTo(b);
};

// 以桥牌的玩法规则对扑克牌进行排序的函数
Card.orderBySuit = function (a, b) {
    if (a.suit < b.suit) return -1;
    if (a.suit > b.suit) return 1;
    if (a.rank < b.rank) return -1;
    if (a.rank > b.rank) return 1;
    return 0;
};

// 定义用以表示一副标准扑克牌的类
function Deck() {
    var cards = this.cards = [];    // 一副牌就是由牌组成的数组(这里有个小命名规范,类不加s,而具体的实例加s)
    Card.Suit.foreach(function (s) {    // 初始化这个数组
        Card.Rank.foreach(function (s){     // 其中foreach为其工厂类的一个自定义的一个类方法,这个类方法为一个迭代的方法,其中s为迭代方法中的this.values[i]的值
            Card.Rank.foreach(function (r) {    // 同理r也是,只不过会先将其父的函数存放入栈中
                cards.push(new Card(s, r)); // 将结果推入该对象的cards属性中的数组
            })
        } )     
    })
};

// 洗牌
Deck.prototype.shuffle = function() {
    // 先使用for循环进行遍历,在生成随机数,将遍历到的和随机数进行随机交换
    var deck = this.cards, len = deck.length;   // 先进行数据总的汇总
    for (var i = len - i; i > 0; i--) {
        var r = Math.floor(Math.random() * (i + 1)), temp;  // 随机数的生成
        temp = deck[i], deck[i] = deck[r], deck[r] = temp;
    }
    return this;    // 返回洗牌的程序
};

// 发牌方法,返回牌的数组
Deck.prototype.deal = function (n) {
    if (this.cards.length < n) throw "Out of cards";
    return this.cards.splice(this.cards.length - n, n);
};



运行一下

你可能感兴趣的:(前端,js,前端集散地)