烦请督促我的游戏功课喔!

游戏夜读 | Two Sum问题的八个解

文/良宵听雨。授权“游戏夜读”发表。

打开LeetCode找到一个小游戏

\1. Two Sum

Easy

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

自助使用Python3款答题纸

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:

开始答题……其他略。题目中有两个假设:

1 有且仅有一个解;

2 同一个元素不能被使用两次。

尝试的5种方法,失败了4次

        # 方法1:循环遍历列表中的数,一个一个找
        # for i in nums:
        #     for j in nums:
        #         if nums.index(i) != nums.index(j):
        #             if (i+j)==target:
        #                 return [nums.index(i), nums.index(j)]
        # 上述方法1有个漏洞:当i=j,比如遇到[3,3],.index()的判断就不好用了

        
        # 方法2:基于方法1,循环遍历列表的索引,这样就避免数值相同的bug啦
        # for i in range(len(nums)):
        #     for j in range(len(nums)):
        #         if i != j:
        #             if nums[i] + nums[j] == target:
        #                 return [i, j]
        # 上述方法2虽然可行,但是Time Limit Exceeded,说明效率太低,被淘汰了
        
        
        # 方法3:根据题目中说的假设(恰有一个答案),直接匹配差值是否在列表中,并对相同值的情况做处理
        # for i in nums:
        #     if (target - i) in nums:
        #         if i == (target - i):
        #             return [nums.index(i), nums.index(i, nums.index(i)+1)]
        #         else:
        #             return [nums.index(i), nums.index(target-i)]
        # 上述方法3有漏洞:相同的值被取了两次实际却只有一个,遇到[3,2,4]就歇菜了,i=3没有两个3返回null
        
                
        # 方法4:基于方法3,加一个符合条件的数值数量的判断,弥补漏洞
        # for i in nums:
        #     if (target - i) in nums:
        #         if i == (target - i) and nums.count(i) > 1:
        #             return [nums.index(i), nums.index(i, nums.index(i)+1)]
        #         else:
        #             return [nums.index(i), nums.index(target-i)]
        # 上述方法4还是有漏洞,遇到[3,2,4]没有歇菜,但是返回了[0,0],判断条件没搞清楚逻辑,画NS图自救,
        # 发现是漏掉了i==(target-i) and .count(i)<1 这一类情况,应当continue,而不是直接进上述的else
        
        
        # 方法5:基于方法3和方法4,围绕不能复用的条件,进行两层判断:先挖坑,再网鱼,步骤有先后手
        for i in nums:
            if (target - i) in nums:
                if i == (target-i):
                    if nums.count(i) > 1:
                        return [nums.index(i), nums.index(i, nums.index(i)+1)]
                else:
                    return [nums.index(i), nums.index(target-i)]
        # 成功accepted了!
        # Runtime: 788 ms, faster than 35.47% of Python3 online submissions for Two Sum.
        # Memory Usage: 13.8 MB, less than 70.43% of Python3 online submissions for Two Sum.

上述方法小结

  1. 总体思路混乱,语无伦次,可悲。
  2. 冷静一下,算法的思路主要分两大类:
    2.1 直接查找计算法(找到一个i和一个j,判断相应和是否为target);
    2.2 间接查找问询法(找到一个i,再判断target与i的差值是否存在)。
  3. 再冷静一下,查找的思路主要分两大类:
    3.1 基于item
    3.2 基于index

综上,在已有的认知范围内,理论上有四个方法可以解决LeetCode这个“Two Sum”的问题,分别是:

(1) 基于item的直接查找计算法

        for i in nums:
            for j in nums:
                # find it!
                if (i+j)==target:
                    # maybe twice?
                    if i==j:
                        # more than 1 elements!
                        if nums.count(i)>1:
                            # don't forget find the 2nd one's index
                            return [nums.index(i), nums.index(i, nums.index(i)+1)]
                    # not twice
                    else:        
                        return [nums.index(i), nums.index(j)]

果然啊!成功!
Runtime: 4604 ms, faster than 25.25% of Python3 online submissions for Two Sum.
Memory Usage: 13.8 MB, less than 68.81% of Python3 online submissions for Two Sum.

(2) 基于index的直接查找计算法

        for i in range(len(nums)):
            for j in range(len(nums)):
                if (nums[i]+nums[j])==target:
                    if i==j:
                        if nums.count(nums[i])>1:
                            return [i, nums.index(nums[i], i+1)]
                    else:
                        return [i, j]

果然啊!成功!就是慢了点。
Runtime: 7688 ms, faster than 5.01% of Python3 online submissions for Two Sum.
Memory Usage: 13.8 MB, less than 73.03% of Python3 online submissions for Two Sum.

(3) 基于item的间接查找问询法

        for i in nums:
            if (target-i) in nums:
                if i == (target-i):
                    if nums.count(i)>1:
                        return [nums.index(i), nums.index(i, nums.index(i)+1)]
                else:
                    return [nums.index(i), nums.index(target-i)]

果然啊!成功!快了不少。
Runtime: 776 ms, faster than 37.75% of Python3 online submissions for Two Sum.
Memory Usage: 13.8 MB, less than 67.25% of Python3 online submissions for Two Sum.

(4) 基于index的间接查找问询法

        for i in range(len(nums)):
            if (target - nums[i]) in nums:
                if i==nums.index(target-nums[i]):
                    if nums.count(nums[i])>1:
                        return [i, nums.index(nums[i], i+1)]
                else:
                    return [i, nums.index(target-nums[i])]

果然啊!成功!保持在高水准。
Runtime: 788 ms, faster than 35.47% of Python3 online submissions for Two Sum.
Memory Usage: 13.7 MB, less than 85.58% of Python3 online submissions for Two Sum.

####做一个回顾

首先恭喜自己,顺利通关。分数还行,Top 65%的位置,770ms,13.8MB,拿到了一颗星。

上述的四个方法,不管是“一手抓一手再抓”,还是“一手抓一手在摸”,在具体比较的时候都是“凭空”的,没有放在一个篮子或者秤上进行操作,总而言之就是有不可控的黑洞。

字典dictionary是一个比较喜欢的篮子。此外,几年前看过一个跷跷板的方法,结合起来:

(5) 基于item的字典dict跷跷板

        dict = {}
        for i in nums:
            if i in dict.keys():
                if i == dict.get(i):
                    return [nums.index(i), nums.index(i, nums.index(i)+1)]
                else:
                    # follow the queue number
                    return [nums.index(dict.get(i)), nums.index(i)]
            else:
                dict.update({target-i: i})

厉害了!成功!
Runtime: 36 ms, faster than 94.69% of Python3 online submissions for Two Sum.
Memory Usage: 14.2 MB, less than 50.40% of Python3 online submissions for Two Sum.

(6) 基于index的字典dict跷跷板

        dict = {}
        for i in range(len(nums)):
            if nums[i] in dict.keys():
                # ensure index return by the same number
                if i == nums.index(dict.get(nums[i])):
                    return [i, nums.index(dict.get(nums[i]), i+1)]
                else:
                    # follow the queue number
                    return [nums.index(dict.get(nums[i])), i]
            else:
                dict.update({target-nums[i]: nums[i]})

厉害了!不如上面的简洁。
Runtime: 40 ms, faster than 87.10% of Python3 online submissions for Two Sum.
Memory Usage: 14.2 MB, less than 53.05% of Python3 online submissions for Two Sum.

对比一下,新的分数还行,Top 5%的位置,36ms,14.2MB。

####写在最后

最重要的测试集,用例,三个有代表性的列表,以及目标值:

[2, 7, 11, 15]
9
[3, 3]
6
[3, 2, 4]
6

第二波的对比第一波:排名从前63到了前5,耗时从776ms到36ms,内存从13.8MB到14.2MB。

最后的最后,剩下的几种解法呢?

简单来说,就是暴利查找的时候,第二层循环index下标从i+1开始啊!具体示例如下:

(7) 基于index的直接切片查找法

        for i in nums:
            for j in nums[nums.index(i):]:
                # find it!
                if (i+j)==target:
                    # maybe twice?
                    if i==j:
                        # more than 1 elements!
                        if nums.count(i)>1:
                            # don't forget find the 2nd one's index
                            return [nums.index(i), nums.index(i, nums.index(i)+1)]
                    # not twice
                    else:        
                        return [nums.index(i), nums.index(j)]

成功!比原来的速度略有提升。
Runtime: 3856 ms, faster than 26.13% of Python3 online submissions for Two Sum.
Memory Usage: 13.7 MB, less than 85.58% of Python3 online submissions for Two Sum.

(8) 基于index的间接切片问询法

        for i in range(len(nums)):
            # begin from i's index + 1, hope more and faster
            if (target - nums[i]) in nums[i+1:]:
                if i==nums.index(target-nums[i]):
                    if nums.count(nums[i])>1:
                        return [i, nums.index(nums[i], i+1)]
                else:
                    return [i, nums.index(target-nums[i])]

成功!但是速度并没有跷跷板的快。
Runtime: 836 ms, faster than 33.40% of Python3 online submissions for Two Sum.
Memory Usage: 13.8 MB, less than 66.48% of Python3 online submissions for Two Sum.

有几点需要说明:

  1. 忽略从i+1开始,是因为直接被[3,3]带歪思路了,看来用例有时候也是把双刃剑。得瑟啥?可悲。
  2. 第一次遇见跷跷板的时候,惊为天人,现在没那么惊吓了,还是赞叹。天外有天,山外有山。
  3. 原本以为加了i+1开始,找的越来越快,能跟跷跷板比一比。发现还是差了档次,应是dict的硬伤。
  4. 虽然说有8个解法,其实核心思想是这几个:暴力查找、差值问询、临时存取、缩减范围。
  5. 文中引用的数据应该不精准,看个定性就好。游戏也挺好玩的。

游戏夜读 | Scikit-learn的2018自述

文/良宵听雨。授权“游戏夜读”发表。

R和Python的交谊舞

曾几何时,数据分析入门的一大讨论就是R和Python的选择。

当统计学家连上了互联网的那刻起,这种选择一直就存在,只是主演们在换。

上一代的主角,一方是R和S。大家选择R是因为它是免费的解决方案,又能用,还有一批人维护更新,而且下载即可。概括起来,就是“开源大法好”。另一方是Matlab和Python。可能会有很多的异议,不过这里也只是举个见识范围内的例子,愿意无条件接受任何的反驳。近年,Python的排名越来越高。

站在2019年,R和Python主演的选择大戏有结局了吗?

一条蟒蛇跟一个字母的故事,编剧被寄了刀片,剧情搁浅。没有结局的原因很简单,因为两个都是开源的,所以“诸事不决,选开源”的策略失效了。那该如何有理有据地抨击一款正被广泛使用的工具呢?

请务必从用户需求下手。

那就聊一聊机器学习模块,算法,模型,策略,评估,可视化……那些跟人工智能有关的需求。

Scikit-learn的初心是…

这里应该回忆一遍Scikit-learn(sklearn)是如何成长为Python的机器学习库的,哪怕是最快速的带过:2007年开始,距离2018年已经过去11年。(其他的废话准备另写一篇《Scikit-learn迎来0.21之前》。)

Python在数据科学领域的快速发展,归功于那些频繁提交commit的家伙们。

但夜以日继,不辞辛苦的,还有很多人,劲敌永远存在。翻开sklearn的文档,会发现除了主页常设的分类、回归、聚类、降维、模型选择、数据处理这六大主题之外,还有一个有关这个项目本身的Roadmap。

如果没有人关心这个项目的里程碑,会怎么样?

过去的11年里,机器学习的世界变化很多,但影响最微妙,可能也是“最致命”的,是开源贡献者的身份产生了变化。跟十年前那会儿很不同。

Statement of purpose: Scikit-learn in 2018

  • A more subtle change over the last decade is that, due to changing interests in ML, PhD students in machine learning are more likely to contribute to PyTorch, Dask, etc. than to Scikit-learn, so our contributor pool is very different to a decade ago.

在这最新一份的《Scikit-learn项目目标自述2018》里,还可以看到sklearn不变的初心:数据处理和机器学习的经典工具集合。

如今,机器学习博士生们“更乐意去为PyTorch、Dask等添砖加瓦”。sklearn也更开放,会提供更多的接口便利,也不排斥互通。

写在文档里的可能是实现不了的诺言,或者谎言。关于这一点疑虑,sklearn的开发者这样宣言:资源有限,所以列清单不等于许下承诺,而是指引我们前行的航标,也是我们急需帮助的不足之处。

争吵不是真相,真理落在实处

为什么不是Scikit了呢?又为什么是PyTorch、Dask呢?时代变迁,新的角色不断涌现,又会有一大波选择的大剧等待上演。选择不尽,争吵不休。

算法层出不穷,包或者模块的名字也在变化,甚至框架也可以有很多种选择,这个世界正在对数据科学领域开放大量的人力资源和发展机会。

scikit-learn在2007年问世时,NumPy、SciPy和matplotlib是不是在颤抖?有机会真该去看看它们那些年的项目文档,可能有精彩的故事。

选择开源,就注定不能一劳永逸。而拒绝开源,只会被潮水淹没。Scikit-learn的2018自述,讲述了开源的波折和信念,言辞恳切,不失风度。

游戏夜读 | Scikit-learn迎来0.21之前

文/良宵听雨。授权“游戏夜读”发表。

Scikit-learn(sklearn)是Python的机器学习库。它从2007年开始,距今2019年,已经服务12年。

那年Python正好18岁

如果说机器学习(ML)的研究热点变化,影响了sklearn的兴衰,那么有关Python的变化,与有存亡焉。

Python作为一门编程语言,诞生至今,一直在蓬勃发展,具有很强的生命力。其公认的是创始人是Guido,荷兰人。他在1989年圣诞夜的闲暇中,决定开发Python。有关命名也是一段趣事,这里不谈。

由于创始人独特的理念,以及开源后各地开发者的热情,随后的二十多年间,Python不断发展。Python 2于2000年10月16日发布,稳定版本是Python 2.7。Python 3于2008年12月3日发布,不完全兼容Python 2。

© 2007 - 2019, scikit-learn developers (BSD License).

Python诞生后的第18个年头,2007年,scikit-learn诞生了。故事就从这里开始。

与Python 2相知相守的12年

sklearn初期的版本由少数几位开发者维护,直到2010年后,开发者的名单慢慢变长,文档也越来越规范,更新的内容也都记录在册。那时Python 3小荷才露尖尖角,很多库都还是基于Python 2.x。

before August 26, 2010 (Earlier versions)

  • Earlier versions included contributions by Fred Mailhot, David Cooke, David Huard, Dave Morrill, Ed Schofield, Travis Oliphant, Pearu Peterson.

sklearn第一次开始支持Python3是在0.8版本,那是2011年5月。那时的sklearn正在快速补充数据科学工具箱内的物件:各种函数、模型,以及随之而来的各类bug。版本更新里,已经去掉了开发者的名单。

May 11, 2011 (Version 0.8)

开始拥抱Python 3之后,是sklearn的2与3共存时代。同时,也意味着sklearn开始了告别Python 2之旅。比如,发布于2012年1月的0.10版本,sklearn宣告Python 2.5被淘汰,支持从2.6开始。

January 11, 2012 (Version 0.10)

  • Python 2.5 compatibility was dropped; the minimum Python version needed to use scikit-learn is now 2.6.

2018年3月,创始人Guido在邮件列表上宣布Python 2.7将于2020年1月1日终止支持。2018年7月,创始人Guido发邮件表示退出决策层。作为一个发展中的Python库,sklearn也要做出一些选择。

0.20宣告决心:准备不再支持Python 2.7和3.4

在2018年9月25日发布的0.20版本中,sklearn做出了声明:将在0.21正式抛弃Python 2.7 和 Python 3.4。

作为一个从Python 2走出来的Python库,这样的反应不算迟钝。这一切要归功于辛勤的开发者们。

September 25, 2018 (Version 0.20.0)

  • Warning: Version 0.20 is the last version of scikit-learn to support Python 2.7 and Python 3.4. Scikit-learn 0.21 will require Python 3.5 or higher.

0.21正式分手,携手Python 3.5继续前行

终于,2019年5月,sklearn迎来了0.21版本,这应是一个接轨了Python未来的版本,并且从3.5开始支持。

从更新的内容来看,库没有大地震,包有众多更新,模块有新功能。并在其后陆续更新了几个小版本,修复了不少内容。有兴趣的,可以就0.21这个版本的更新内容做一个了解,也是个了解sklearn的好机会。

1赞

游戏夜读 | Scikit-learn迎来0.21版本

文/良宵听雨。授权“游戏夜读”发表。

2019年5月,Scikit-learn(sklearn)迎来了历史性的0.21版本,不再支持Python 2.7和3.4,仅支持Python 3.5及后续版本。此前,2018年9月0.20版本发布时,已对此做出了提前说明。

sklearn版本更新内容的六大分类

在了解这一次的版本更新内容前,先熟悉一下sklearn对更新内容的分类习惯。

sklearn将更新内容划分成六个大类,由四种颜色标识。分别是:

  1. 绿色,重大新功能 Major Feature;
  2. 绿色,新功能 Feature;
  3. 蓝色,效率提高 Efficiency;
  4. 蓝色,性能增强 Enhancement;
  5. 红色,缺陷修复 Fix;
  6. 橙色,接口改动 API Change。

在0.21版本发布后,陆续更新了几个以缺陷修复为主的小版本。考虑到0.21版本的更新内容不算少,所以,挑选绿色标识的内容,主要关注一下新增的功能。

0.21的绿色功能更新内容摘要

一共有24个绿色标签的功能性改动,涉及到了14个类别。其中,13类是具体模块,剩下的1类,是牵涉多个模块的基础性改动。

sklearn.cluster 新增了1项
  • 一个聚类算法 cluster.OPTICS,比cluster.DBSCAN更方便调参。
sklearn.ensemble 新增了2项
  • 两个实验性质的梯度下降树GBT,分别是ensemble.HistGradientBoostingClassifier 和 ensemble.HistGradientBoostingRegressor,据说是受到了LightGBM的启发。当样本数量大于数万个时,会比ensemble.GradientBoostingRegressor 和 ensemble.GradientBoostingClassifier要快。但因为是实验性质的,功能还不健全,sklearn也可能随时修改这一项更新的内容,对结果不做一致性的保证。
  • 添加了ensemble.VotingRegressor,它为回归问题提供了等效的ensemble.VotingClassifier。
sklearn.impute 新增了2项
  • 添加了缺失值处理的新方法 impute.IterativeImputer,实验性质。
  • impute.SimpleImputer 和 impute.IterativeImputer 新增了一个参数 “add_indicator”,实现了impute.MissingIndicator的转换输出。这样一来,预测模型也可以解释缺失值了。
sklearn.inspection 新增了1项
  • 号外!号外!现在凡是有 “predict_proba”方法的回归或者分类器都支持部分依赖图(inspection.plot_partial_dependence)啦!
sklearn.isotonic 新增了1项
  • 允许在 isotonic.IsotonicRegression 处理不同的数据类型了,比如:float32。
sklearn.linear_model 新增了2项
  • 通过选择“saga”解算器,linear_model.LogisticRegression 和 linear_model.LogisticRegressionCV 现在支持Elastic-Net惩罚约束了。
  • 添加了 linear_model.lars_path 的加强版 linear_model.lars_path_gram,可以直接不提供 X 和 y 就开搞。
sklearn.metrics 新增了4项
  • 为单输出回归提供了 metrics.max_error 指标,以及相应的 “max_error”得分参数。
  • 可以计算每个类别的混淆矩阵了!新增的 metrics.multilabel_confusion_matrix 有助于调参。
  • 新增的 metrics.jaccard_score 可以用来计算 Jaccard系数,操作方式跟 metrics.f1_score 差不多。
  • 之前“Haversine距离”可以通过最近邻计算得到,现在新增了metrics.pairwise.haversine_distances ,可以通过 metrics.pairwise_distances 设置“metric=‘pairwise’”实现。
sklearn.model_selection 新增了1项
  • 新增了两个类,分别是:GridSearchCV, RandomizedSearchCV。现在允许“refit=callable”来加强查找的可伸缩性,具体可以参考《模型复杂度和交叉验证分数的平衡之道》。
sklearn.neighbors 新增了1项
  • 添加了 neighbors.NeighborhoodComponentsAnalysis,它实现了近领成分分析算法。
sklearn.pipeline 新增了2项
  • pipeline.Pipeline 现在可以使用索引切片了!比如:my_pipleline[0:-1]。提取的子序列可以作为另一个Pipeline实例。还可以直接索引管道的特定步骤,跟通过“named_steps”一样的效果,但更方便。比如:my_pipeline[‘svc’]。
  • 为pipeline.Pipeline,compose.ColumnTransformer 和 pipeline.FeatureUnion以及相应的“make_” 添加了可选参数“verbose”,用来显示每个步骤的进度和时间。
sklearn.preprocessing 新增了1项
  • preprocessing.OneHotEncoder 现在支持通过“drop”删除某个类别的特征。这在存在共线性的时候比较实用,例如:将结果数据输入神经网络或非规则化回归时。
sklearn.tree 新增了3项
  • 决策树更容易画出来了!现在可以基于“matplotlib”,通过 tree.plot_tree作图,不再依赖难安装的“dot”库了。
  • 现在可以通过 tree.export_text 导出阅读性良好的“文本格式”决策树了。
  • tree.BaseDecisionTree 新增了 get_n_leaves() 和 get_depth() 两个方法。重点是:基于这个基础算法的那些模型都同步更新了这两个方法。比如:tree.DecisionTreeClassifier,tree.DecisionTreeRegressor,tree.ExtraTreeClassifier,tree.ExtraTreeRegressor。
sklearn.utils 新增了1项
  • utils.resample 现在可以通过新增的“stratify”参数,设置根据分布分层取样。
涉及多个模块的基础更新,新增有2项
  • 完全重写了“_repr_()”方法,现在用的是Python标准库的打印方式,很优雅。这个方法用在调用 print(estimator) 的时候。但想改的话也可以,通过修改 sklearn.set_config 的 “print_changed_only”参数。
  • 引入了Estimator Tags 估算器标签,字典形式存储,通过调用“_get_tags()”方法获取。像sklearn.utils.estimator_checks.check_estimator 可以使用这些标签决定运行哪些测试以及输入哪些数据是合适的。标签可以依赖于估算器的参数设置,甚至系统控制,一般只在运行的时候才真正生效。标签作为注释,可以标识具体某个估算器的功能、数据要求、支持的输出类型、支持的方法等信息。

以上就是sklearn的0.21版本绿色功能性改动部分的摘要,更详细准确的内容就必须前往官方文档查阅了。

游戏夜读 | 写游戏用什么语言?

文/良宵听雨。授权“游戏夜读”发表。

写几句题记

这个标题如果用英文表达,可能更贴切,比如:Beginning game programming,What language should I use? 用简洁的中文似乎表达不出重点。

之所以用了“写游戏”,是为了照顾“语言”,更是考虑到大部分的问题需求确实是为了“写”。而“做”游戏的范围又太大。

话题范围足够小的时候,即使表述的不准确,也并不影响理解力。现在话题是较为明确的,也很常见,场景比如:入门、新手、咨询,搭配游戏名称或爱好。

如果对这个话题有兴趣,建议在中文搜索之上,再辅以英文。

一个方面:如何做选择?

先把这个问题,看成是一个悬而未决的决策。那下面就简单介绍一下策略:如何做出这个决定。最容易的选择,就是盯着评价指标勾勾叉叉。

那么选择某种语言的理由可以有哪些呢?

有三个主要的方面:知名度,热度,上手难易程度。先说前两个,其中知名度高的,一般是历史悠久的;然后热度高的,一般是当下的主流;两者有联系也有区别,两方面都占的,基本上就可以锁定价值了。

关于“上手难易程度”,也可以简单说成“门槛”。这可能是讨论最多,主观意见最容易发酵的危险地带。也是可以细分理由的。

门槛和“普适性”大体上是负相关的,越大众的门槛越低。门槛和“专业性”一般是正相关的,越专业门槛越高,即使学习曲线一开始平缓,后面肯定会陡峭,否则体现不了“专业度”。这里面内容庞杂,不建议深究。

直接对比“知名度”和“热度”,再权衡需求即可。

说到门槛本身的话,比方说:前置条件、知识储备,硬件条件,软件条件等。其中软件条件需要特别注意。大部分的讨论和建议就集中于此。

想要精打细算的,具体要考虑:对某种语言的好感度,是否能适应现有的集成环境,对编辑器的个人爱好能否实现等等。几番了解后,就大致有了数。

另一方面:用哪些语言?

要把选择落在实处,即是看中了某一个语言。如此,才算问题得到了解决。

落到“游戏”上面。子曰:“贤哉,回也!一箪食,一瓢饮,在陋巷,人不堪其忧,回也不改其乐。”那么做游戏的也有类似。

自然语言。一支笔、一页纸、一粒骰子,做个简单的桌游应该不成问题了。

计算机语言。命令行式的,通过一个黑色或者蓝色的终端,跟电脑进行互动,进行文字、图片的交流,比如:文字游戏,冒险类的,选择类的。

不同的编程形式。大多数的电子游戏都是这样诞生的,大多数的问题正是问这些游戏背后的语言。比如:面向对象的,结构式的,过程式的,元素式的。

游戏引擎,准现成的解决方案。直接去看专门描述引擎效果的广告文案吧。

66666,Mark

1赞

(^▽^)很开心得到关注哦!

游戏夜读 | 工具游戏的辉煌

有网络之前,故事很精彩。

单机游戏成就了一个人的狂欢,街机更是让人战斗力十足,只是这些还不是普通人玩得起。

网络的普及可能从有线电话开始,随后是智能手机爆发,再后来是无线网络的全覆盖……

然而,通网只是开始。

因为一开始的网络并不快,于是,局域网联机成就了你我他的恩怨情仇,网吧成就了逃课。

等到全民、天天这些系列游戏流行的时候,中国的游戏行业迎来了属于自己的高光时刻:移动端游戏的市场一片热闹!

都说外行看热闹,内行看门道。千禧年一代所经历的正是人类历史上的移动游戏第一次大爆发!

大量的手机使用者接入了网络,每个人都有属于自己的空闲时刻,不论是按天算的,还是按分钟算的,大量的时间!

大把时光除了学习、工作、发呆之外,还需要娱乐!他们需要娱乐!娱乐!谁会排斥“单纯的快乐和幸福感”呢?电子游戏可谓是一剂猛药。

这一时期的游戏内容不如游戏渠道重要,因为大把的人从来都没有玩过游戏,能玩上就很好!要是能玩上全民都在玩的,大家天天玩的,更好!

不是说这一时期没有重内容的游戏。商业游戏的制作历来都是设计驱动和商业数据驱动并行。只是,21世纪初的这二十年,有大量的游戏是作为流量的变现工具而存在。

流量、眼球,自然是这一时期的宝贵财富,作为变现工具之一的游戏,也可以说是“工具游戏”!但这并非是游戏唯一应有的角色和立场。

商场变化多端,时间来到2020年,已经能明显感觉到电子游戏产品内容创造上的迸发了!

从游戏行业的发展来看也应是如此。

回想一下,从街机,到家用游戏机,再到掌机、移动手机,再到触屏操作的各类电子产品,游戏机制的创新并不容易,但随着形式的变化,游戏规则可以快速复制和微创新。至于游戏内容,则是要跟着大家的认知和生活水平一起发展。

所谓一方水土,养一方人。游戏也是要耕耘。

文/良宵听雨。授权“游戏夜读”发表。

游戏夜读 | 关于构图的困难

构图,这个词通常频繁出现在美术工作者和摄影爱好者的口中。通常意义上,构图是《影视听语言》中的重要组成部分。那在游戏中呢?电子游戏业发端以来,视频游戏就应运而生——一种集结了众多艺术表现形式的“游戏化”现象。

一个游戏制作团队中,美术组应该是最关心“构图”的了。而上线后的视觉效果,将直接影响整个团队的工作业绩。

构图是有章法的,有标准,有范式,但要用到位却不容易。关键在于守中有变,先学会如何观察变化,再通过模仿、练习,最终懂得如何创造变化。这样的能力,不仅限于构图,在用色上也差不多,只是用色还讲究主题、统一。

倘使仅仅抄袭古人,移东搬西,不能变化,怎能创得出社会主义新风格出来?——《关于构图问题》潘天寿

构图也可以讲究统一,但容易造成视觉疲劳。这样说起来,眼睛如此,耳朵也是,值此盛夏,蛙叫、虫鸣伴着入睡。清晨的鸟叫倒是丰富多彩,令人神清气爽,婉转丰富的形式让内容更出色。这么些好处,当用,可又不生搬硬套,难。

克服困难,即是成长。构图的困难主要体现在两个方面。一方面是师徒关系,一方面是分析方法。

不用细说,由于学徒人数的大曝光,中国传统的师徒关系已经不能满足需要,随之而来的是师生关系,现在又有了同学关系的趋势,比方说视频弹幕伴着培训、写作业等等。“师父领进门,修行在个人”,这句话的后半句是越来越地道。

分析方法的确是很关键的,自我修行的一方面就是琢磨这个,并且略有小成也是因为有所悟道。容易卡壳的地方通常是看得到画面中的器物,却看不见画面中的气势。而所谓构图,就是依着气势构建。气势用白话讲,就是组织规律。

都说一图胜千言,关于构图的研究,这方面的知识还很浅薄。关于构图的困难,几句粗语感悟,仅一家之言,见笑。

文/良宵听雨。授权“游戏夜读”发表。


突然发现论坛里面讲“自己研发的第一款小游戏”、“软著申请注意事项”这一类东东,还是很实用的……希望自己在不久的将来也可以加入到大家的奋斗当中!!!

游戏夜读 | 跟风说一说爬虫

爬虫,原本是一类动物的指代。但对熟悉计算机网络的人来说,说起爬虫,第一个想到的就是网络数据的采集行为。

计算机网络不是直观的事物,它不像自行车一样一目了然。对于自行车,我们不仅熟悉车把、链条、坐垫、脚踏板、轮胎、轴承等配件,也能亲身体验速度、惯性、平衡的物理奥妙。但计算机网络不同,除了电缆、光纤,其他的都神秘。

想要化身电流的一份子:电子。体验一趟趟云霄飞车、电击、拥挤、千锤百炼……不妨想象一下超大型过山车的感受。

网络不仅是一种技术,更是我们用来存储、获取、交流信息的工具。其中跟我们关心的信息,关系最紧密的一个概念,可能非“网络协议”莫属了。网络协议本身的内容挺复杂,也有不少的标准,实际操作中一般都会提到:网络协议三要素。

是哪三要素呢?常见的说法是,语法,语义,时序。语法会定义计算机网络语言,基本上是一些数据符号的事情,通常被解释为“怎么讲”。语义,就跟我们所理解的信息内容非常接近了,基本上是讲怎么把那些干涩的数据符号吃透:弄明白今天的一个字母代表的是苹果,到了明天这个字母就是代表香蕉了,诸如此类,通常被解释成“讲什么”。时序,有时也全称为时序规则,主要是时间上的考量和分析,一般不直接挂钩被传递的信息内容。

说到这里,我们日常在计算机网络上搜索、讨论、发文件等等,除了网速快慢,主要涉及语法、语义。话说回来,爬虫就是模仿人类上网冲浪的行为,可以把一个个爬虫程序理解成是一个个网络机器人,由此,爬虫工程师也就不那么神秘了。

文/良宵听雨。授权“游戏夜读”发表。

游戏夜读 | 数据整理的难题?

文/良宵听雨。授权“游戏夜读”发表。

数据处理涉及面比较广,数据清理是一些手段和步骤,整理范围相对更小。基于这个认识,开始聊下面的。

一个模糊的提问
整理数据的时候遇到困难,往往是针对现有的数据结构不满。比如常见的三种期望:每种统计量是一列,每次观测值是一行,每一类实验数据单独一个表。

实际遇到的数据,往往不够理想。

这个时候能力不足无法解决,或者虽然有了笨办法,但又想知道更高效、实用的,怎么办呢?

肯定是搜索和提问。

难就难在不知道怎么描述。可能七七八八说了个大概,总体上还是一个模糊的提问。

行列变换,reshape(重塑)
常见的用词是“行列变换”。

说起行列变换,可能说中了大部分的数据整理问题!只是因为行列变换这四个字,模模糊糊地描述出了可能的解决办法。

但实际上,这个数据整理的难题,跟线性方程组、矩阵、行列式的初等变换不太一样。

另一个说到点子上的词是 reshape 重组。

说起reshape,可能第一个反应是 numpy.reshape ,其常见的应用如下所示了。但这里要说的不是这个。而是pandas官方文档里的图例。对应的操作,在R语言也比较成熟。

a = np.arange(6).reshape((3, 2))
a
array([[0, 1],
[2, 3],
[4, 5]])
数据整理的难题:reshape 重组
数据重组(reshape)就是对数据的统计结构进行变换,枚举的变成计数的,分类的改成变量。

部分效果跟Excel透视表是差不多的。这类问题在pandas的官方文档里也有专题,还有有一个统称,叫“数据重塑和透视表”。

英文是 Reshaping and Pivot Tables。一共介绍了重塑数据框的三大类方法:透视pivot,堆叠stack和平铺unstack,熔化melt。

首先是透视(pivot)。透视是指小而美的个性化重组。需要提前设定好需要的横向标签index、纵向标签column、被观察的数据value。

Reshaping by pivoting DataFrame objects
然后是堆叠(stack)和平铺(unstack)。堆叠是“横向变成纵向标签”,往垂直方向堆叠。平铺是“纵向标签变成横向”,往水平方向平铺。

Reshaping by stacking and unstacking -1
堆叠和平铺都是指简单粗暴的索引重组。只需要执行命令即可,优点是“矫揉造作”:伸缩自如,循环往复。

Reshaping by stacking and unstacking -2.1
其中,平铺unstack可以指定把现有的哪一个层级拉出来溜溜,只需要通过一个参数确定。默认情况下,就是对最末尾的那个索引下手。

Reshaping by stacking and unstacking -2.2
Reshaping by stacking and unstacking -2.3
最后是熔化(melt)。先熔化(melt)已待利用。操作也非常简单粗暴,就是完全打散,退化成“键值对”形式的重组。

兼具解释性强和便利性的优点。解释性强指的是能直白感受到信息的完全保留。便利性体现在保留了拒绝打散的权力。

Reshaping by Melt
数据整理的经典论文《Tidy Data》。
绝大部分的R使用者,大部分的数据处理工作者,应该都有机会接触到这篇论文。可能是直接看论文中的例子,也可能是通过转了几手的笔记间接习得。如果早些年阅读过这篇论文,那在提问的时候,可能带上一些模糊的印象。

但如果没有这些储备的知识呢?当遇到此类数据整理的问题时,该如何表达自我?该如何描述问题?一个实用的提问方法是:找到一个相对活跃的论坛,然后把具体的现状、期待的状态摆出来。

有不少的教材、笔记,是翻译过来的。早前还出现过“数据整容”这样词,现在几乎搜不到了。

这篇论文现在是开放下载的。

Authors: Hadley Wickham
Title: Tidy Data
Abstract: A huge amount of effort is spent cleaning data to get it ready for analysis, but there has been little research on how to make data cleaning as easy and effective as possible. This paper tackles a small, but important, component of data cleaning: data tidying. Tidy datasets are easy to manipulate, model and visualize, and have a specific structure: each variable is a column, each observation is a row, and each type of observational unit is a table. This framework makes it easy to tidy messy datasets because only a small set of tools are needed to deal with a wide range of un-tidy datasets. This structure also makes it easier to develop tidy tools for data analysis, tools that both input and output tidy datasets. The advantages of a consistent data structure and matching tools are demonstrated with a case study free from mundane data manipulation chores.
Submitted: 2013-02-20. Published: 2014-09-12.
https://www.jstatsoft.org/article/view/v059i10

游戏夜读 | 怎么让游戏跑起来?

文/良宵听雨。授权“游戏夜读”发表。

让游戏跑起来,最直观的就是,画面不卡顿,不卡帧数,运行流畅。

但细究起来,游戏元素怎么动起来的?规则是怎么实现的?游戏机制怎么运作的?画皮之下,游戏的骨骼是怎么样的?脉络是什么分布?

一万个为什么,一万个怎么样……最后,呈现出来的,是电子游戏程序的运行框架。大部分的基本框架,本质上是一个循环,是一个套娃的策略。一个游戏研发团队,除去项目经理之外,常设的策划、美术、音效、程序、测试等五大职能,所付出的心血,都会被注入这个“运行框架”。

电子游戏的本质是计算机程序。

一个完整的游戏运行框架
可以理解为就是一个循环绘制图像的程序。虽然是最基本的运行框架,也有一个基础结构。整体上是一个“死循环”,在循环里面是需要重复做的事情,分为三大类:更新游戏内容、准备画面、屏幕展示效果。

// 一个完整的游戏运行框架(示意)
gameLoop(){
    while(True){
        gameUpdate(){ // 更新游戏逻辑
            pass
        }
        gameRender(){ // 离屏绘制
            pass
        }
        gamePaint(){  // 前屏绘制
            pass
        }
    }
}

上面示意的这个“框架”取材并改编自《游戏程序设计教程》,该教材由对Greenfoot颇有钻研的何青编著,近年又有了新书2.0,对新手更加友好了。说回这个简洁的“框架”,而且明显可以再简洁,比如只放一个“图像绘制”的函数。可是,为什么不呢?

双缓冲机制
这是一种绘制手法,叫缓冲机制,常见是双缓冲机制。跟计算机图形学、影像成形等领域有关。之所以要采用缓冲机制,是因为只放一个图像绘制的函数,那势必就是直接在屏幕上绘制。但游戏元素多了以后,绘画的速度跟不上肉眼的识别。

一个很简单的例子:翻书画。翻的慢了,画面就卡顿了。因为种种原因,直接在屏幕上作画的步骤,跟在画板上作画差不多,擦除、一笔一笔画上,速度慢了,效果就不好了。缓冲机制的做法就是“蒸好馒头再卖”,先在蒸馒头的笼屉里蒸好馒头,然后再转移到卖馒头的笼屉里。对应的,就是离屏、前屏。离屏一般就是在内存里。

程序设计思路
软件程序有设计方法,电子游戏也不例外。有了运行框架的先入为主,可能会让大部分人都陷入“从上而下”的设计思路。其实,并非如此。更常见的是,原型设计法。先让游戏的一小部分跑起来,然后再去开发游戏的其他部分。

但话说回来,不管是哪种设计法,都离不开运行框架。

游戏夜读 | 刀塔选手比较老吗?

文/良宵听雨。授权“游戏夜读”发表。

前几天回答了一个问题,题目是“为什么感觉刀塔2的选手比LOL的职业选手要成熟”?当时,不假思索,就答了一通……

关于成熟的理解
所谓成熟,可能是心理上的。因为题主也是用的“感觉”这个词,所以很可能探讨的不是生理年龄的问题。于是从年龄角度的回答就有点片面。

成熟也可能是认知上的。比方说,职业选手的说法,也会有电竞选手的说法,其实指称的同一批人,但由于熟悉度、知识领域、语言习惯,会产生偏差。

但生理年龄确实是一个比较容易获取的统计指标,所以抛开题主的问题。准备收集一下职业选手的年龄数据,稍微对比分析一下,就有了年龄层面的认知。

职业选手的年龄,哪里有?
谁会没事公布自己的年龄?还是贴的网络上一搜就能搜到的那种程度呢?还真的能查到不少电竞选手的出生日期信息啊!电子竞技真在崛起。当然,这些状况可能是由于当年玩游戏的孩子们都步入中青年的自然现象。

只是,按图索骥般搜索信息,效率太低。既然电子竞技有点小热,肯定是要有平台或者团队进行电子竞技选手信息的专业管理的。比如战队、姓名、游戏ID、赛事相关、直播间、梗、个人社交主页等等,甚至于恋爱、癖好。

如果能找到上述的这种平台,大概率会有职业选手的出生日期,就能对电竞选手的年龄进行基础的数据分析了。果然,姜还是老的辣,游久网。

五款热门游戏的职业选手数据
经过一番折腾,拿到了《DOTA2》,《英雄联盟》,《绝地求生》,《王者荣耀》,《穿越火线》这五款游戏关注度较高的职业选手信息,其中个人信息部分就有包括“出生日期”这个关键数据。激动。

文/良宵听雨。授权“游戏夜读”发表。

因为这里只关注选手的出生日期,对其他信息不关注,所以需要简单说明一下拿到的有效样本。也就是那些有比较明确的出生时间信息的选手。

《DOTA2》拿到了39位选手的信息,其中23份有效。
《英雄联盟》拿到了51份,其中44份有效。
《绝地求生》拿到了41份,其中17份有效。
《王者荣耀》拿到了47份,其中38份有效。
《穿越火线》拿到了37份,其中22份有效。
合计,一共拿到了215位选手的信息,其中144份是有效样本。

5款游戏的职业选手有效数据量对比(来自:游戏夜读)
应该是一帮有偏样本,但偏在哪里不明确。无效样本提供的大多数是:未知、暂无。是什么原因拿不到这些数据呢?可能是低调,不喜欢曝光。而年纪的大小会不会影响曝光心理,这个可能是另外一个研究课题,不可以轻应作结论的。

另外需要注意的是:数据的错误在所难免。错报、纂改、记录错误、获取失败等等,都会影响数据的准确度,这里只能保证从网络上获取后没有纰漏。

职业选手的年龄数据分析
虽然数据有很多的不确定性,但分析样本总是会有乐趣的。

最大和最小的比较
通过一系列看似简单,实则繁琐的数据处理,终于可以对144位职业选手的出生日期有所认识了!先说其中最早的年份,1989年,一共有2位,均玩着《DOTA2》。其说最晚的2002年,同样也是一共有2位,均玩着《王者荣耀》。其余的140位选手主要分布在90年代,尤其是1995年到2000年这5年间。

144位职业选手的出生年份概况 (来自:游戏夜读)
其中,五分之一的选手,即有29位职业选手都出生于1998年。在今2019年正值法定结婚年龄附近的21岁。其次是1999年21位,1997年19位,1996年18位。

年龄最大的跟最小的,相差13岁。整体分布上,属相、星座都包圆了。

具体是谁我没有看。

平均年龄的比较
144位职业选手的出生年份-箱线图对比 (来自:游戏夜读)
下面计算一些统计量,看一下具体游戏的年龄分布情况。四舍五入。

《DOTA2》跨度11年(1989~1999),涉及10个年份,平均年份值1994.7。
《英雄联盟》跨度9年(1993~2001),涉及9个年份,平均年份值1997.0。
《绝地求生》跨度11年(1990~2000),涉及个8年份,平均年份值1997.1。
《王者荣耀》跨度13年(1990~2002),涉及个10年份,平均年份值1998.4。
《穿越火线》跨度10年(1990~1999),涉及个9年份,平均年份值1994.6。
合计,144位选手跨度14年(1989~2002),平均年份值1996.4。

144位职业选手的出生年份-密度图对比 (来自:游戏夜读)
从拿到的这份数据看,《DOTA2》和《穿越火线》的职业选手们年纪相对大一些。

经典问题:生日在同一天的概率
因为手握144个样本,又是在做出生日期相关的数据分析,那就自然很可能会发现有职业选手是在同一天生日这个现象。

依据经典概率,144份样本中至少有两个人生日在同一天的概率是高达14个9。

那些生日在同一天的职业选手
是时候发现同年同月同日生的职业选手了。一度怀疑是不是数据被记录的时候弄错了。这样有趣的日子一共有3个,每个日子都恰好有2个选手出生。

首先是1996年4月24日,两位同在《穿越火线》的小伙伴都在这一天出生:宠儿(张签)和k(许宏宇)。前者在AG战队,后者在情久战队。

然后是1998年10月24日,两位小伙伴在这一天出生:Lwx(林炜翔)和凉晨(张奇)。前者在《英雄联盟》FPX战队,后者在《王者荣耀》RNG.M战队。

最后是1999年6月7日,两位同在《王者荣耀》Hero战队的小伙伴在这一天出生:久诚(曹志顺)和最初(龙志彪)。

不知道说啥,恭喜,祝大家幸福吧!

游戏夜读 | 世界两大游戏评论!

文/良宵听雨。授权“游戏夜读”发表。

OpenCritic和Metacritic是两个在世界范围内影响较深远的娱乐作品类评论网站,尤其是电子游戏。

其影响力主要在两个方面。一方面向全球地区的玩家和评测人员。另一方面则是面向全球的游戏发布、评测发布等游戏平台。尤其是后者。例如:游民星空作为中国单机游戏门户网站,于2018年1月发表一篇题为《游民星空的游戏评测已被OpenCritic正式收录》的新闻。再比如:《每日星报(Daily Star)》是英国的一份著名报纸,也有其同名网站和游戏版面,于2019年4月发表一篇题为《每日星报的游戏评测已被OpenCritic和Metacritic正是收录(Daily Star Gaming joins OpenCritic and Metacritic)》的新闻。足可见这两大世界游戏评论阵地的影响力之大了。

image
OpenCritic的公益和开放
OpenCritic有四位创始人,分别是马修·恩托温,查理斯·格林,亚伦·拉特利奇,理查德·特里格斯(Matthew Enthoven, Charles Green, Aaron Rutledge, and Richard Triggs)。他们一直保持着网站非营利的状态,日常的服务器开销、运营成本主要靠众筹、捐赠来维持,所以官网最底下有个专门致谢的传送门。网站地址是www.opencritic.com,整体风格简洁、高效,分类检索最早能查到2013年。

关于网站的初衷,四位创始人表示想建立一个真正庆祝游戏的阵地,以此推动游戏行业积极的变化。他们认为自己富有“幼稚”的乐观主义精神,希望通过这个网站,汇聚开发者、评论家、游戏玩家。在OpenCritic的众筹页面还有其他的介绍,包括他们自身的背景、网站的规划、收入的用途等。

OpenCritic的创始人是游戏玩家和开发者。顺便还提到了《魔兽世界》最经典的BOSS战之一“巫妖王之冰封王座(The Lich King)”,“召唤师峡谷(Summoner’s Rift)”,《命运》的主线结尾任务Raid之一“玻璃宝藏(Vault of Glass)”,《辐射4》的那块“波士顿荒地(Boston wasteland)”,上古卷轴,《星际争霸2:虚空之遗》中的艾尔母星(fields of Aiur),还把《沙漠2(Dust2)》称为“海市蜃楼”。他们还一起建设WoW公会的网站、自动招募,用作娱乐的大菠萝3机器人(Diablo 3 bots),还有英雄联盟(League of Legends)相关的。

Metacritic的红黄绿和被收购
Metacritic有三位创始人,此前都是律师职业。主要涉及电影、电子游戏。网站网址是www.metacritic.com,整体风格明快、丰富。分类检索最早能查到1995年。不过,该年只查到一个作品。

关于网站的初衷,三位创始人的想法形成于1999年,他们希望能给众多的娱乐产品进行一个综合打分,这样用户就能更合理的消费,并更好地提前安排自己的娱乐时间,网站于2001年1月正式推出,快速发展几年后,2005年被CNET收购。

Metacritic的特色是它特有的加权平均打分系统得出的综合评分:metascore。好的评价显示为绿色,中等的是黄色,差劲显示的是红色。综合评分主要来自两个方面的考量,一方面是用户的反馈,另一方面是经过挑选的评论员和评测网站。

游戏夜读 | 预测问题的硬核是?

知识储备少的一个可能的好处是“不落窠臼”,大白话就是:套路少。

为什么能套路少?主要是因为懂得套路少。换句话说:大部分的知识都基于范式。学的多了,会发现教书先生的观点各有不同,然而教材里的内容是相似的。那还要继续学习吗?不耽误。想学就继续,套路虽然俗气,但认识的过程里也会有些乐趣。不想学也不错,守着有限的认识,过日子或者哲思。都很美好。

这些跟预测有什么关系呢?预测是有方法的,熟练掌握某种或某些方法后,就容易丧降低“空想”的意愿,养成一些依着套路走的习惯。这样对预测并不利。

太阳底下没有新鲜事。目之所及,预测问题都是常见场景。非典型的预测,则被称为冒险。尤其是量化预测领域。统计学家也费尽苦心,建立假设和约束条件,又寻求条件的放宽、转换,甚至废弃一组方法,重装出另一套方法,生生不息。

正统的方法自然有一大堆理论证明,还是聊一场朴素自然地随心畅想。

测一测玩哪个游戏

之前搜集过一份电竞职业选手的年龄样本,具体涉及到144位电竞职业选手的出生日期。基于这份数据,是不是能解决一些个相关的预测问题呢?比如:根据某人的出生日期,预测该人玩的哪个游戏。这个预测问题一抛出来,即使是一个对预测方法完全不懂的人,可以想的方面和方向就不少。这的确是一个很有意思的问题。

出生日期跟玩哪个游戏,有关系吗?怎么看有没有关系?如果有,是不是就承认了属相、星座哪一套说法?如果没有,是不是就是尊重客观事实?这样一想,两者应该是没有关系的。但还是可以主观上假设有,然后继续讨论。

如果有关系,那是前者影响了后者,还是后者影响了前者?是有因果关系,还是其他什么复杂的关系?因为本来就是假设的,所以不好具体讨论下去,于是就再假设一番。比方说,两者可能是一种同时出现或者不出现的关系,不一定是线性的,应该是一种概率问题,接着故事从啤酒和尿布开始了。再比分说,两者可能是一种类规则的关系,就是能设计一个机器猫,能准确预测出答案来的那种。

同一天生日的那些家伙,在预测问题里可能是个麻烦了。同年同月同日生,但玩着不一样的游戏,这种情况该怎么处理?简单粗暴的剔除即可。于心不忍的话,那就放到测试集里。实际上,有些同一天出生的职业选手玩的是一款游戏,有些个是玩着不同的游戏,所以等预测方法想出来了,拿那几天测试一下,应该会很好玩。

异常值不仅仅是表面上的异常,可能是数据处理过程带来的。比方说,144个样本中,其中有一份显示是1994年1月1日出生的职业选手,但是实际上,当初只是拿到了1994年这个年份数据,在处理过程中自动补全成了1月1日。不知道影响大不大?如果有影响的话,对最后的预测结果到底有多大的影响?

就算预测结果出来了,还是放心不下。是只有一个结果,还是有多个呢?每个结果可靠吗?可不可靠怎么比较呢?可不能像人民公园里面相亲的那样走马观花了。

预测NBA球员的第一次伤情

还有一种预测问题也很有意思,就是成功预言第一次出现。这类问题跟冒险的区别在于,冒险问题是没有类似的历史信息可以参考,包括自身时间序列、普世的横截面等,但NBA球员的伤情不是一个陌生的话题。

虽然,NBA球员的伤情很常见,但是,针对某个具体的球员,尤其是他/她还从来没有被报道过伤停,那怎么预测该名球员第一次受伤事件在什么时候发生呢?

文/良宵听雨。授权“游戏夜读”发表。

完整的看了下楼主的文章,感觉挺乱的,什么题材都有,我觉得最好能系统一点,游戏就说游戏或者更细化 策划(关卡,世界,数值,系统),程序(前端/后端/算法等),美术之类的 如果是游戏史就说游戏史相关的一系列,这样比较有条理,看起来也会有意思一点 推荐你看下B站UP主 芒果冰的中国网游史

游戏夜读 | 关卡设计为什么难?

设计需要灵感,持久的设计产出则需要持续的灵感。灵感的源源不断,得益于精神家园的郁郁葱葱。思想的贫瘠,促使灵感的枯竭。

与此同时,关卡设计需要高质量的产出。高质量主要体现在有限的游戏规则下创作,以及需要对玩家的体验负责。带着镣铐的跳舞,又必须跳得满堂喝彩。

这样的一个岗位能不难吗?

要保持产出,就要保持灵感。灵感可以分享,进而出现了许多的借鉴,甚至抄袭行为。分析起来,这一切是灵感与产出的供求不平衡,在设计界引起的经济学现象。

追根溯源,灵感,或者说原创性的灵感来自哪里呢?这可是个很大很深的话题。长话短说,艺术来源于生活嘛。

想明白了灵感,便要好好理解游戏规则,熟记于心,才能设计得心应手,不至于闹出笑话,或不可运行的缺陷来。

最难莫过于取悦人心。

奈何现在的游戏都是设计给人玩的,能不难吗?所以,不光是要当客服,为一个个玩家提供全方位的服务,还要急人所急、想人未想、说人未说……可行的办法是边看心理学边实践出真知。

文/良宵听雨。授权“游戏夜读”发表。

恩恩 非常感谢你的反馈!确实是‘杂文’了 ,,,已经立刻关注了你推荐的这位up主

游戏夜读 | 游戏设计需要天赋?

有句话叫,“以大多数人的努力,还远没有到拼天赋的程度”。这句话经常被用来回答诸如“要不要天赋”这类问题。这里也无意去讨论天赋与努力的关系。

设计所需要的天赋其实很简单,态度、积累。

先说积累。

同样的年龄,却有不同的才华。同样的才华,也会有不同的光芒。有人积累的多,有人积累的少。没积累的往往会质疑挡在崎岖前途上黑压压的一片:他们是不是空降的?

积累的速度有快慢之分,当然是越快越好。可速度是个综合成绩,包括了残废的程度、可用的时间和空间、心情等。不过,谁家都有一本难念的经,谁不是如此?

积累的目标有高低远近,当然是如此甚好:远的越清晰,近的越容易。可容易的可能是陷阱,清晰的可能是大饼,有接触的免不了利益关系。不过,世界上还是好人多,你是信还是不信?

这一切干天赋何事?除非,是有人硬要与门第世家的孩子比家庭教育罢了。那是没法比的。那不是“天赋”,那是在比出身。种一棵树,最好的时机是十年前,另外就是现在。那么同理,成为设计师最好的时机是二十年前,另外就是现在。

再说态度。尤为关键。

态度可能比积累更为致命,或在很大程度上影响积累。态度可以指对游戏这件事的看法。一个对游戏行为持反对观点的家伙,能成为游戏设计师吗?能。是那种真的游戏设计师吗?是。Why?为什么呢?因为这个家伙肯定是对游戏又爱又恨,是个矛盾综合体。

态度也可以指对默默无闻搞创作的看法。想成为一个游戏设计师,只需要在自我介绍的时候做个头衔的强调。想成为一个真正的游戏设计师,只需要不辞辛苦地坚持创作。但想要名和利,就没了答案。

没有人证明过积累一定会量变引起质变,也没有人在前途上呐喊:已经看见了最美的风景。

设计师往往是追求完美的,对大多数人来说,这样的态度会加速放弃。而所谓信仰,是全场唯一可能可以纳入天赋范畴的一种东西了。

文/良宵听雨。授权“游戏夜读”发表。

游戏夜读 | 设计师的数据模型

设计师需要自信、画布、画笔、环境、团队、高配的工具集,还需要什么?好看的,吃的,喝的,玩的,听的,好折磨的……还有数据模型。

这是个全民数据分析的时代,而最有数据使用权的正是各位设计师傅。话说回来,数据模型驱动的设计与个性化的风格创作并不协调,所以不使用数据模型并不会有很大的损失。

数据模型可以从三个层次理解:跨行业标准,领域理论基础,实用方法论的举例。

当业内的标准并不成熟的时候,往往就需要看相似、相关的行业标准。幸运的是,数据作为信息的载体,还有一伙人专门为这个领域制定标准,这样形成的标准,是纯天然跨行业考量的。主要有知识发现领域的数据挖掘的标准,项目管理领域的需求分析标准等。

接下来就是特定领域的理论基础。比如:用户行为理论,动机成就理论,需求理论等。

如果没有时间了解以上两个层次,又足够幸运获得了具体的方法论,那就是妥妥“有人带,进步快”的写照了!具体来说有:增长黑客领域的AARRR以及根据不同优先级调整字母顺序后的种种变形,谷歌的用户行为量化框架HEART及类似的认知、兴趣、行动模型,比较纯粹的用户体验指数CX-Index及各种评分卡模型等。

文/良宵听雨。授权“游戏夜读”发表。