over 3 years ago

「Idea 不值錢」

不曉得早期泡沫掉的 web 時代是否如此

但對於人人都可寫 app「創業」的現在來說,這句話算是蠻容易聽到的

就我的解讀,這句話只是一個標題殺人法

它的內涵不是指 idea 跟垃圾一樣隨便生都有

而是一個行業的進入門檻如此低的情況下,擁有好的 idea 的人多如過江之鯽

幾乎人人都可以把自己的 idea 做成產品拿出來賣

但是成功的人並沒有隨著門檻降低而大量增加,取決於:

  • 誰的執行力強
    • 核心技術
    • 系統建置、即時修正、是否能做到敏捷開發..等速度要件
  • 誰比較能預期市場反應
    • 商業模式
    • 市場調查
    • 使用者經驗、反饋
  • 誰宣傳的快
    • 病毒行銷 (一句琅琅上口的燒毀、我的字典裡沒有放棄、殺很大..等等)
    • 飢餓行銷 (有好的質量之後使用限量的發行,在可控制的成本下測試,一部分達到宣傳的效果)
    • 代罪行銷 (分享或邀請朋友得到獎勵、填個資抽獎,讓使用者替你背書作宣傳) 這我隨便自創的名詞
  • 誰營運的好
    • 企劃能否不斷推出讓使用者黏著性高的活動
    • 第一線客服能否有辦法將玩家心聲實際傳達到高層

這些反而才是重點

當一個產業進入門檻低到一個程度,不需要開工廠,甚至也不需要租店面的時候

自然就會產生很多 idea 雷同的問題:

有些公司推出了很創新的服務或遊戲,但是因為某些因素導致並沒有很成功
此時若是有人覺得這 idea 可以做得更好,就會再包裝一次拿去賣


Puzzle & Dragons vs. 神魔之塔

最著名的神魔之塔便是這樣的例子:正妹加持!「抄」到年營收10億的神魔之塔

神魔之塔營收排名數據


圖片來源:http://evchk.wikia.com/wiki/神魔之塔

來看看他做了什麼

  • 執行力與市場反應:美工、音效、動畫、介面(針對繁中市場)、增強使用者經驗
  • 宣傳:配合臉書粉絲團等等代罪行銷、實體宣傳活動

神魔之塔會成功,一部分是紅的時候根本沒人知道 PAD 這款遊戲

如果 PAD 在繁中市場早就紅了,可能會有部分人抵制或改玩 PAD (畢竟抄襲這名詞給人印象比較差)

而 PAD 也本來就尚未有進軍繁中市場的準備 (或者還沒準備好)

因此執行效率、在地化、宣傳等因素加起來,就讓神魔之塔吃掉了這塊市場
(細節當然不會這麼簡單,但至少這些是我們這些外人可以觀察學習的)


TechCrunch vs. 36Kr

除了遊戲業之外, TechCrunch 與 36Kr 這類科技媒體網站也一樣有抄襲糾紛:
36Kr,请停止偷窃来自TechCrunch的文章 by TechCrunch官方


這裡無意糾結於誰對誰錯誰要負法律責任

不過有個人道出了關於他為何選擇 36Kr 而不是 TechCrunch 的看法:
[业界] 正版的「原罪」

为什么我还是会固定到 36Kr 上逛一逛而却几乎从来不关注 TC 中国和 FC 中文呢?
原因很简单:作为一个读者,这些镀着硅谷金的官方中文版们体验实在太糟糕了。

我稍微解讀了這作者提出的三大原因:

  1. Layout 從英文直接拿來給中文用,讀起來太煎熬
  2. 使用 wordpress.com,對大陸內地的速度及頻寬支援不夠,讀取緩慢
  3. 沒有本地化的營運方式,使用了會被大部分使用者屏蔽的 plugin

我並不是這兩個網站的忠實讀者,但如果在文章的質上 TechCrunch 也沒有大贏 36Kr
縱使 TechCrunch 才是有權利翻譯的官方,人潮很可能還是會往 36Kr 流去

人們不會管哪邊才有法律權利,而是選擇他們最喜歡的產品

尤其是當兩邊都免費又不會拿使用者開刀的時候

爐石戰記 vs. 臥龍傳說

雖然門檻低,但也不是所有抄襲都能在一開始就有高品質,不過仍然能威脅到正版,像是:
Blizzard 與網之易正式起訴《臥龍傳說》開發商游易侵權山寨《爐石戰記》


圖片來源

當時這兩款遊戲的精緻程度實在無法比擬,一開始根本沒人會選擇臥龍傳說

但重點是後者只有 兩個工程師,在20天內就做出來了 ,連 行動版 都比爐石領先推出。

爐石的優勢在於:
卡牌系統的平衡不是隨隨便便就能夠模仿得來,而爐石有著啃 Blizzard 老本的角色故事背景,臥龍並沒有。

但臥龍也有他的優勢:
Blizzard 開發速度一向是知名的慢,如果臥龍的製作團隊有努力做好系統平衡,一旦招兵買馬在美術及介面設計上,以中國著名的超高速山寨能力快速趕上,也是 Blizzard 不願意見到的。(從他們 20 天做出來以及行動版的產品也證實了他們的執行力)

至於故事背景..的確,臥龍基本上是不可能超越爐石
但這說穿了是 Blizzard 用來吸引爐石新玩家(暴雪舊玩家)進入的一個要素而已
而臥龍沒這個煩惱,因為 爐石已經替他們做了最好的廣告


Chain Chronic vs. project 72

台灣的代工複製經驗也是行之有年,大老闆們也都很習慣這樣的模式

以往台灣的大遊戲公司不外乎是靠著代理的模式生存

而開發網頁、手機遊戲成本越來越低的情況下

很多大陸遊戲已經深入到台灣市場,光靠代理網路遊戲賺錢的餅越來越小

因此也不少遊戲公司想要賺型、自己研發手機遊戲

最近看到唯晶科技的新聞:
《守護者之劍》系列再開發確定! 唯晶首度曝光《聖女之歌 3》前導劇情

唯晶在去年就有不少新聞版面,其號稱投資五億的參天律在 2013 年七月敲鑼打鼓的上市了
宣明智背書!唯晶砸5億推「參天律」7月上市 明年回台上櫃

不得不說,畢竟是替中韓知名遊戲公司做外包經驗老道的公司,動畫美術等技術在台灣來說還是不錯的

不過新聞最後提到 project 72 這個手機遊戲,並放了遊戲截圖



(上面兩張圖已經被移除)

對照一下 Chain Chronic 這款遊戲,實在是讓人覺得太像


這款遊戲還沒正式推出,已經引起一陣罵潮 (當然還是小眾,台灣玩 CC 的人不多)

就我的看法,介面有一定程度的致敬與模仿

玩法有可能雷同,也有可能不同 (比如改成回合制之類)

SEGA 在 3D 模組的經驗上絕對有一席之地,但是遊戲的營運以及平衡度的掌控還有進步空間

而唯晶的卡片角色有一部分會構築在自己以前的作品上 (參天律、聖女之歌),加上公司本身的美工底子
內容深度與遊戲精緻程度應該也有一定水準 (遊戲性目前只看圖片就不得而知)

只是大陸的盛大遊戲已經確定從 SEGA 手上拿到 CC 的海外代理權,預估今年就會在台港澳韓上市

到時候要較量的可就不只是遊戲本身而已了

畢竟目前看起來是很相似的遊戲,在推出順序、宣傳以及營運方式等方面都很重要,一不小心就會反過來變成幫對方宣傳


有辦法防範嗎?

舉了很多例子,有已經成功的、自認抄襲的;也有根本還沒推出,只是看起來畫面很像的

「正版」與「致敬」的戰爭重點就是兩個:

  1. 誰賺得比較多,比較多玩家願意花錢 (就算你抄襲,沒賺半毛錢人家也不會管你)
  2. 「致敬」會不會因為侵權得不償失

通常第二點要成立並不容易

首先是這類爭議以往較多來自大陸

而大陸對於這類保護法規一直都還不完善,抓不到管不著最後就只能隨他去

大陸仗著自己內需夠大,靠國內市場還是可以賺錢 (如果成功的話)

再來是遊戲、軟體的侵權判斷比起傳統的案例來得更加困難,判例也相對稀少

如果我抄了一首歌、一本書,有多少部分雷同是比較容易估計的
就像 TechCrunch 與 36Kr 大家都是寫文章,還有可能判個誰輸誰贏
(實務上舉證也有很多模糊地帶)

但是「遊戲玩法」卻很難受到保護,比如:

  • 網頁領土遊戲幾乎每個都一樣的玩法,也不知道到底是誰發明的
  • 神魔之塔的轉珠要怎樣才能判斷是抄襲自 PAD 的?
  • project 72 的陣型排法要怎樣才能證明是來自 Chain Chronic?

去看程式碼很可能根本就完全不一樣,技術架構也完全不一樣

但就算 idea 怎麼看就是同一個,這個「玩法」的 idea 卻很難受到保障
(除非遊戲玩法可以申請專利?這部分我不是專業的..)

所以回過頭來,目前這些「原創者」最簡單也最根本能夠保護自己的手段,就是創造無法抄襲的服務價值


為什麼「致敬來的」可以賺比較多錢?

十年前、二十年前的答案可能是成本低、人們不注重品質

而現在則是「致敬來的」有其可取之處,不管是行銷有力、執行力高、注重使用者體驗等

「抄襲的產品」不一定比較廉價粗製濫造,可能更好用更漂亮,甚至更花錢

所謂「idea 不值錢」絕對不是 idea 不重要

idea 是一個大方向,可能會決定你走到藍海或紅海

但是執行的好不好,才是槓桿拉不拉得起來的關鍵

就算是藍海也一樣會有人溺死;
就算掉到紅海裡面,誰也說不準下次它就變成藍海。

我隨便講講的你還當作是名言
 
over 3 years ago

前言(廢話很多)

我一直認為,就算到了現在,網路分享的媒介已經如此發達的 2014 年
網路資源還是較少著墨於「為什麼要這樣做」

通常都是告訴你,如果要做 x 你就下指令 A、要做 y 就下指令 B
這並不是說寫那些文章的人不好,他們提供了很好的筆記讓大家能夠快速查詢
但是由於多半出於自己的筆記性質,並沒有說明清楚只有在某些情況才會 work
這時候如果有一知半解的人查到了然後跟著做,可能就會弄巧成拙

Read on →
 
over 3 years ago

matlab 的強項在於矩陣運算
所以通常有個觀念是能用矩陣的思維取代(對其他語言來說)直觀的思維(e.g. loop)就盡量用

另外一個加速的方法是有很多內建的函式都很好用
但是因為太好用了(做的事情很多),在量很大的時候就有空間可以加速

有人可能會說需要速度快就別用 matlab,或者改用 C 寫 mex 取代大迴圈
的確,若要追求速度的極限那乾脆別用 matlab
但有時候實作時間有限,改個寫法就可以加速也是有它的價值在
另外一個附加價值就是能理解 matlab function 的行為(e.g. 做哪些事情是很花時間的)

以下是我遇過的兩個例子

  • 測試環境:16 core (Intel Xeon CPU E5530 2.40GHz)

unique

有些時候內建的 function 會被用到很多次,像 unique 就是很常用的 function

sort+diff 可以當做一部分 unique 的功能使用
ref: faster way to achieve unique() in matlab if assumed 1d pre-sorted vector?

vector = [4 1 3 5 2 4];
vector = sort(vector)
vector =
     1     2     3     4     4     5
uniqueVector = vector([true;diff(vector(:))>0])
uniqueVector =
     1     2     3     4     5

但是什麼情況下 sort+diff 會比 unique 快呢?

來比較一下 uniquesort+diff 所花費的時間

unique.m
for numElement = [100,10000,100000,1000000]
    tic;
    for i=1:1000
        vector = randi(100,1,numElement);
        uniqueVector = unique(vector);
    end
    toc;
end
result
Elapsed time is 0.103313 seconds.
Elapsed time is 0.987119 seconds.
Elapsed time is 6.199297 seconds.
Elapsed time is 60.371398 seconds.
sort+diff.m
for numElement = [100,10000,100000,1000000]
    tic;
    for i=1:1000
        vector = randi(100,1,numElement);
        vector = sort(vector);
        uniqueVector = vector([true;diff(vector(:))>0]);
    end
    toc;
end
result
Elapsed time is 0.031016 seconds.
Elapsed time is 0.877409 seconds.
Elapsed time is 5.852163 seconds.
Elapsed time is 61.032015 seconds.

結論

  • 如參考連結,給定已經排序好的 vector 只要使用 diff 就可以取得 unique vector,非常快速 (實際上原因是大部分時間都花在 sort,這裡就不貼出測試資料了)
  • size 很小的 vector (<100)使用 sort+diff 也會比 unique 來得快
  • 如果是 size 很大的未排序 vector,用 sort+diff 就跟 unique 相差無幾了

計算出現頻率

use unique + histc to get the relative frequency.
ref: Determining the number of occurrences of each unique element in a vector

除了 unique 之外,還有一個常見的需求是計算某個值出現了幾次
一個是直接用內建的 histc

example_histc.m
A=[1,2,3,1,2,4,2,1]; % an example vector

unqA=unique(A)
unqA =
     1     2     3     4

To get the number of occurances,

countElA=histc(A,unqA) % get the count of elements

countElA =
     3     3     1     1
relFreq=countElA/numel(A)
relFreq = 
    0.3750    0.3750    0.1250    0.1250
which is the relative frequency of the unique elements.
This will work for both integers and floating points.

但還有另一個方法是先排序之後,利用 unique 得到排序過的 index
再藉由 diff 得到每一個元素的個數
直覺上應該是會比 histc 快一些
詳細方法就直接放在原始碼裡面不多做說明,以下是測試:

histc.m
for numElement = [100,10000,100000,1000000]
    tic;
    for i=1:1000
        A = randi(100,1,numElement);
        unqA = unique(A);
        countElA = histc(A,unqA);
    end
    toc;
end
result
Elapsed time is 0.147729 seconds.
Elapsed time is 1.547588 seconds.
Elapsed time is 12.222510 seconds.
Elapsed time is 119.633619 seconds.
pre-sort+diff.m
for numElement = [100,10000,100000,1000000]
    tic;
    for i=1:1000
        A = randi(100,1,numElement);
        sortA = sort(A);
        dupA = [sortA, sortA(size(sortA,2))+1];
        [unqA, idx] = unique(dupA, 'first');
        countElA = diff([idx,idx(size(idx,2))+1]);
        countElA = countElA(1:end-1);
    end
    toc;
end
result
Elapsed time is 0.194604 seconds.
Elapsed time is 1.169871 seconds.
Elapsed time is 7.556745 seconds.
Elapsed time is 72.559933 seconds.

結果不意外的是後者比較快

雖然 pre-sort+diff 方法乍看之下好像會做兩次排序
但其實將 sorted vector 丟給 unique 不會再做額外排序,因此整體來說還是只做一次
diff 做的事情比 histc 少,所以比較快是合理的。

 
over 3 years ago

文章大綱是有一個人問「在學校裡寫程式」跟「在企業裡寫程式」的差異,下面有四個人的回答我覺得都很值得參考,雖然我本身不是在業界工作,但也算是在 "real world" 裡剛起步,心有戚戚焉,忍不住就順手翻譯了,希望不管是對還在學校修課的人或者剛出社會的人都有一些幫助,或者引發一些思考、討論。


rdasxy 問到:

儘管很多人在學校已經是個好的程式設計師,當他們畢業且拿到第一份工作的時候,仍然有不少人覺得他們並不是真的懂如何寫程式。在學術的設定下寫程式與「真實世界」寫程式有哪些差異呢?

Read on →
 
over 3 years ago

最近中華電信連外海纜出問題,導致 twitch 無法收看

一開始流傳的解法是使用 hinet proxy

全部瀏覽器都有用,但是開其他網頁會變很慢

這方法的缺點是所有網頁都會經過 proxy

因此除了 twitch 之外的網頁都會變得極度緩慢

那有沒有方法可以使用 proxy 看 twitch 又不影響其他網頁讀取呢?

當然可以,只要使用以下的瀏覽器外掛就可以選擇性掛上 proxy

Read on →
 
almost 4 years ago

複習一下為什麼需要 typename 這個關鍵字,這篇解答說的不錯,翻譯一下
原文:Why is the keyword “typename” needed before qualified dependent names, and not before qualified independent names?

C++ 的變數名稱可以屬於三種不同級別的 entities: 值(Values), 型別(types), 和樣板(templates)

struct Foo
{
    typedef int A;
    static double B;
    template <typename T> struct C;
};

上面這個例子的三個變數
Fooo::A 是型別
Foo::B 是值,而
Foo::C 則是樣板

在上面的例子中 Foo 是一個完全型別 (complete type)(註:沒有加上 template 的型別),所以 compiler 已經知道 Foo::A 這些東西所指為何。但若想像有個不完全型別的 struct 長得像以下這樣:

template <typename T> struct Bar
{
    T::A x;
};

這時候我們就遇到問題了:什麼是 T::A
如果 T = Foo 那麼 T::A 是個 int 也就是個型別,一切相安無事:
但是當 T = struct { char A; };T::A 就是一個值,這一條敘述就沒有任何意義。

因此 compiler 要求你告訴它 T::AT::BT::C 應該要是什麼。如果你什麼都不說,預設就是 value。如果你加了 typename,它就被解讀為 typename,你說他是 template 它就是 template。

template <typename T> struct Bar
{
    typename T::A x;    // 很好,就令它是個 typename 吧

    void foo()
    {
        int a = T::B;   // 假設它是 value, OK

        T::template C<int> z;  // 令他是 template
        z.gobble(a * x);
    }
};

再來才會確認 T::B 是否可以轉型成 intax 可否被相乘,以及 C<int> 是否真的有一個成員。
function gobble 會被留到你真的建立了 template 的 instance 之後才檢查。
但一個變數名稱該表示為 value、type 或 template 的規定,對於程式語法的正確性是很基本而且一定要在 template 定義時提供的。

 
almost 4 years ago

從網路上得知這間中途貓咖啡

為了支持「以領養代替購買」以及經營中途之家的辛苦,決定來消費一下

畢竟是在麟光站這裡,人潮真的很少,客人當然也少

其實人少對消費者來說或許是好處居多,可以一整個下午都安安靜靜的跟貓相處

但對店家來說很可能是賠本了,蠻擔心能夠支持多久

Read on →
 
almost 4 years ago

大約快兩年前,就有這麼一個山姆大叔的故事影片在網路上流傳

最近又看到這本《史上最大搶案》


與這個影片《人類史上的最大騙局》

其實講的都是同一件事情,也就是現行的經濟體制,根本就是一個可笑的大謊言、合法的搶劫與不可能實現的空頭支票

透過層層的包裝將龐式騙局,以各種方式將金融商品(貸款、債券等)銷售到每一個人手裡

Read on →
 
almost 4 years ago

什麼時候用 #define 什麼時候用 const?

一般來說推薦 C 用 #define,C++ 用 const

原本能盡量用 const 就用 const

但在 C 裡面,const 並不是 常數(constant) !他真正的意義是 唯讀(read only)

所以如果有一段 C 的程式:

#include <stdio.h>
const int ARRAY_SIZE = 100;
int data[ARRAY_SIZE];
int main(void){
...
}

編譯的時候就會出現
error: variably modified 'data' at file scope
這是因為 compiler 在 file scope 並不允許非常數的 array 宣告(ps. block scope 就沒這問題)

所以才有人建議在 C 就用 #define,C++ 則盡量用 const

但是 #define 也有自己的問題,像是:

  1. 不加雙括號會造成無法預期的計算(這很常見)
  2. 因為 code 已經被 pre-processor 轉換成數字了,compiler 的錯誤訊息就不會告訴你是哪個變數,在 debug 上比較不方便

除了 #define 也可以用 enum
enum { array_size = 100 };
但缺點就是只限於 int 型別

pointer reading trick

Q: int const vs. const int?


Ates Goral:

The trick is to read the declaration backwards (right-to-left):

const int a = 1; // read as "a is an integer which is constant"
int const a = 1; // read as "a is a constant integer"

Both are the same thing. Therefore:

a = 2; // Can't do because a is constant

The reading backwards trick especially comes in handy when you're dealing with more complex declarations such as:

const char *s;      // read as "s is a pointer to a char that is constant"
char c;
char *const t = &c; // read as "t is a constant pointer to a char"

*s = 'A'; // Can't do because the char is constant
s++;      // Can do because the pointer isn't constant
*t = 'A'; // Can do because the char isn't constant
t++;      // Can't do because the pointer is constant

Pat Notz:

To keep things straight, I always use the convection "put const on the outside"
where by "outside" I mean the far left or far right.
That way there is no confusion -- the const applies to the closest thing (either the type or the *).

 
almost 4 years ago

在試用了 logdown 寫了一篇文章之後,覺得這服務非常貼近技術人員的心
(至少我自己覺得 geek/hacker 都會很喜歡XD)
而且介面簡潔、排版輕鬆簡單,可能也會吸引到一些非技術人員的族群

傳統 blog 服務在編排版面上最討厭的就要面對一堆 html 語法
在預覽模式頻繁切換的結果,就是原始碼難以閱讀、排版
(空格不是空格、換行不是換行、還會塞一堆 tag 像是 div span 等等..)

logdown 以 markdown 作為撰寫的原始碼,可以從根本上避免上述問題
這是以往的 blog service 所無法提供的

雖然有一些小缺點,但要改進卻不難,可以預期之後都會有解決方法
作為一個剛起步的服務,非常期待~

接下來介紹一下這個服務

Read on →