• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            教父的告白
            一切都是紙老虎
            posts - 82,  comments - 7,  trackbacks - 0
                 摘要: Phing是什么?Phing是一個基于Apache Ant的項目代碼構建系統.你可以用她做傳統的構建系統能做的任何事情,比如GNU make,并且Phing使用簡單的XML構建文件和可擴展的”任務”使之成為易于使用和極具可擴展性的框架.因為Phing是基于Ant的,所以本手冊部分內容是摘自Ant手冊.Phing & Binarycloud :歷史Phing源自Bin...  閱讀全文
            posted @ 2010-04-08 15:08 暗夜教父 閱讀(4659) | 評論 (0)編輯 收藏
            數據庫備份是很重要的。如果定期做好備份,這樣就可以在發生系統崩潰時恢復數據到最后一次正常的狀態,把損失減小到最少。
            以前在FREEBSD系統里面都先把MYSQL停掉,然后直接用tar命令直接把數據庫文件打包,下載到本地。如果要恢復數據庫,也是直接上傳,用tar解壓,然后設置下權限就可以用了。

            現在在windows下,本來用PHPmyadmin管理數據庫是很好,但是本地的服務器,死活連不上數據庫,新版的2.11的我都不知道怎么配置,汗死!用MySQL Control Center 等客戶端軟件也不行,暈死了! 無奈,只好用mysqldump 來備份了!

            因為沒有好好的準備 ,以為mysqldump 是 MYSQL解析器里面的命令-_-!! 死活運行不起來。
            使用了之后,才發現。。原來,MYSQL的備份可以這么美的。哈哈。。(漸遠!)

            好了,收集了一些mysqldump命令的語法,先學學!
            用mysqldump對MySQL數據庫進行數據備份與恢復

            MySQLl提供了一個mysqldump命令,我們可以用它進行數據備份,下面假設要備份yejihao_agent這個數據庫:

            #mysqldump -u root -p yejihao_agent > yejihao_agent.sql

            按提示輸入密碼,這就把yejihao_agent數據庫所有的表結構和數據備份到yejihao_agent.sql了,因為要總進行備份工作,如果數據量大會占用很大空間,這時可以利用gzip壓縮數據,命令如下:

            #mysqldump -u root -p yejihao_agent | gzip > yejihao_agent.sql.gz

            系統崩潰,重建系統時,可以這樣恢復數據:

            #mysql -u root -p yejihao_agent < yejihao_agent.sql

            從壓縮文件直接恢復:

            #gzip < yejihao_agent.sql.gz | mysql -u root -p yejihao_agent

            /*************************************/
            命令解釋 
            /************************************/

            導出要用到MySQL的mysqldump工具,基本用法是:   

            shell> mysqldump [OPTIONS] database [tables]   

            如果你不給定任何表,整個數據庫將被導出。   

            通過執行mysqldump --help,你能得到你mysqldump的版本支持的選項表。   

            注意,如果你運行mysqldump沒有--quick或--opt選項,mysqldump將在導出結果前裝載整個結果集到內存中,如果你正在導出一個大的數據庫,這將可能是一個問題。   

            mysqldump支持下列選項:   

            --add-locks   
            在每個表導出之前增加LOCK TABLES并且之后UNLOCK TABLE。(為了使得更快地插入到MySQL)。   
            --add-drop-table   
            在每個create語句之前增加一個drop table。   
            --allow-keywords   
            允許創建是關鍵詞的列名字。這由表名前綴于每個列名做到。   
            -c, --complete-insert   
            使用完整的insert語句(用列名字)。   
            -C, --compress   
            如果客戶和服務器均支持壓縮,壓縮兩者間所有的信息。   
            --delayed   
            用INSERT DELAYED命令插入行。   
            -e, --extended-insert   
            使用全新多行INSERT語法。(給出更緊縮并且更快的插入語句)   
            -#, --debug[=option_string]   
            跟蹤程序的使用(為了調試)。   
            --help   
            顯示一條幫助消息并且退出。   
            --fields-terminated-by=...   
                
            --fields-enclosed-by=...   
                
            --fields-optionally-enclosed-by=...   
                
            --fields-escaped-by=...   
                
            --fields-terminated-by=...   
            這些選擇與-T選擇一起使用,并且有相應的LOAD DATA INFILE子句相同的含義。   
            LOAD DATA INFILE語法。   
            -F, --flush-logs   
            在開始導出前,洗掉在MySQL服務器中的日志文件。   
            -f, --force,   
            即使我們在一個表導出期間得到一個SQL錯誤,繼續。   
            -h, --host=..   
            從命名的主機上的MySQL服務器導出數據。缺省主機是localhost。   
            -l, --lock-tables.   
            為開始導出鎖定所有表。   
            -t, --no-create-info   
            不寫入表創建信息(CREATE TABLE語句)   
            -d, --no-data   
            不寫入表的任何行信息。如果你只想得到一個表的結構的導出,這是很有用的!   
            --opt   
            同--quick --add-drop-table --add-locks --extended-insert --lock-tables。   
            應該給你為讀入一個MySQL服務器的盡可能最快的導出。   
            -pyour_pass, --password[=your_pass]   
            與服務器連接時使用的口令。如果你不指定“=your_pass”部分,mysqldump需要來自終端的口令。   
            -P port_num, --port=port_num   
            與一臺主機連接時使用的TCP/IP端口號。(這用于連接到localhost以外的主機,因為它使用 Unix套接字。)   
            -q, --quick   
            不緩沖查詢,直接導出至stdout;使用mysql_use_result()做它。   
            -S /path/to/socket, --socket=/path/to/socket   
            與localhost連接時(它是缺省主機)使用的套接字文件。   
            -T, --tab=path-to-some-directory   
            對于每個給定的表,創建一個table_name.sql文件,它包含SQL CREATE 命令,和一個table_name.txt文件,它包含數據。 注意:這只有在mysqldump運行在mysqld守護進程運行的同一臺機器上的時候才工作。.txt文件的格式根據--fields-xxx和--lines--xxx選項來定。   
            -u user_name, --user=user_name   
            與服務器連接時,MySQL使用的用戶名。缺省值是你的Unix登錄名。   
            -O var=option, --set-variable var=option設置一個變量的值。可能的變量被列在下面。   
            -v, --verbose   
            冗長模式。打印出程序所做的更多的信息。   
            -V, --version   
            打印版本信息并且退出。   
            -w, --where='where-condition'   
            只導出被選擇了的記錄;注意引號是強制的!   
            "--where=user='jimf'" "-wuserid>1" "-wuserid<1"  

            最常見的mysqldump使用可能制作整個數據庫的一個備份:  

            mysqldump --opt database > backup-file.sql   

            但是它對用來自于一個數據庫的信息充實另外一個MySQL數據庫也是有用的:   

            mysqldump --opt database | mysql --host=remote-host -C database   

            由于mysqldump導出的是完整的SQL語句,所以用mysql客戶程序很容易就能把數據導入了:   

            shell> mysqladmin create target_db_name   
            shell> mysql target_db_name < backup-file.sql  
            就是  
            shell> mysql 庫名 < 文件名  

            posted @ 2010-03-31 22:15 暗夜教父 閱讀(417) | 評論 (0)編輯 收藏

            轉至游戲大觀 http://www.gamelook.com/?p=1616


            簡介
            Boomzap是一個完全虛擬的工作室。我們沒有辦公室,每個人都使用彈性工作時間在家工作。我們的團隊包括了十多個全職員工,以及來自世界各地的兼職員工,如美國,日本,馬來西亞,新加坡,俄羅斯,菲律賓。他們其中的大多數人一年只見過一次面,甚至很多核心的團隊成員都從未彼此見過面。更不可想象的是,我們當中的很多成員都過著具有移動性的生活:例如我本人經常在西雅圖,新加坡和橫濱之間穿梭。我們從2005年開始就一直用這種方式工作,并取得了令人滿意的成效。

             

            我曾經多次被問起我們是怎么成功的使用這種工作方式的,我很樂意分享這其中的經驗。雖然本文可能更適合于想我們這樣的小型的偏外包行的工作室,但是傳統大型工作室的管理者們應該也能從中獲得一些有用的信息。首先我想說明一下為什么我們會采用目前這種工作方式,這種在家工作的分布式辦公模式有什么優勢:

             

            接觸到世界各地最好的開發者:我們能雇傭全球任何地方的任何人,而不用擔心辦公地點和護照等問題。我們的員工不必遠離他們的居住地,遠離他們的交際圈,來和我們一起工作。事實上,我們有些員工正是居住在十分偏遠的地方,為我們工作,他們的家距離最近的游戲公司也有上百英里。

             

            更低的勞動力成本+更低的生活成本=快樂的開發者(Lower Labor Costs + Cost of Living Adjustments = Happy Developers):因為亞洲的薪籌水平比北美要低,所以我們的人力成本很有競爭力。但是我們并沒有把這當成是雇傭廉價勞動力的機會,我們沒有根據當地的收入水平而降低員工的薪水,而是統一按照新加坡的薪籌水平來支付員工工資,不管員工在哪個國家。可能對于美國和英國的開發者來說這不是最好的策略,但是對于俄羅斯,馬來西亞,菲律賓這些地方的員工來說,他們得到的薪籌在當地應該算是最好的。這樣我們就能夠聘用到這些地區最好的開發者,并讓他們覺得非常開心。

             

            更低的日常開銷:我們不用為辦公地點,電腦,用電,咖啡機甚至是便箋紙而花錢。當然我們的確會花一些錢來幫助員工們購置開發設備,但是要知道他們是游戲開發者,即使我們不幫他們購買,他們自己家里通常會擁有他們所能買得起的最好計算機。我們只是避免了傳統辦公室里的重復開銷,并用這些省下來的錢來更好的補償我們的員工罷了。

             

            自由高效地安排工作和生活:我們的工作方式允許團隊中的每個人自己安排工作時間,將工作效率最大化。這不僅節省了很多通常會被浪費掉的時間,例如成員之間的交流時間等,也讓員工們能夠有更多的時間去做一些在傳統公司中不可能做到的事,例如上函授學校,在學校教等等。這種自由度所能為員工帶來的好處和快樂是其它任何傳統工作方式都無法比擬的,是無法簡單用時間和金錢來衡量的。

             

            工作與生活的平衡+金錢=忠誠無私的員工:簡單來說,這種工作方式最終的結果就是我們的員工非常樂意為Boomzap工作。任何管理者都知道留住優秀的員工是公司成長的關鍵因素之一,我們的這種工作方式就是不僅讓我們能從世界各地招聘到最好的員工,而且能留住他們。事實上,從2005年至今,我們還沒有一個員工主動離職。

             

            這些聽起來很不錯,不是嗎?是的,確實很不錯。但是其中的奧秘在于你能像管理一個傳統工作室那樣去管理一個虛擬的分布式的工作室。我們的具體管理策略很難在這里詳細表述,所以在此我僅僅列出我們管理一個虛擬開發工作室的最重要的10條策略。簡單來說,這些策略雖然對于我們來說很適用,但是你需要根據你的團隊具體情況,你們的工作流程,團隊結構來綜合考慮這些是否適用于你們。

             

            10條戒律
            #1: 我們從不記錄工作時間
            我管理Boomzap所遇到的第一個問題就是:“你怎么知道他們是否在工作?”回答很簡單:“無所謂。”我知道一個專業的開發者在40個小時一周的工作時間中能夠完成多少工作。每周一我將這些工作分配下去,期望它在周末的時候能被完成。如果完成了,我不在乎他們花了多少時間去完成它。如果沒完成,他們就得周末繼續工作來確保它的完成。事實上,我非常希望他們能在40小時內完成我分配的任務,然后用剩余時間去做自己高興做的任何事。

            關于這個問題的經濟帳很簡單:如果你想鼓勵你的員工更高效的工作,你就不能把“工作時間”固定下來,因為如果工作時間成為了常量,工作質量和數量就會反而成為變量。在傳統工作室中,“工作時間”是固定不變的常量,對于高效完成工作的最好獎勵就是你會獲得更多的工作安排。更糟糕的情況是,在傳統模式下,較差的員工所遺留下來的工作要交給較好的員工來做,因為較好的員工在相同時間內能完成更多的事情。這樣你在不經意間就給了較差的員工一個獎勵:少做些事,剩下的讓較好的員工去做吧。這真的很糟糕。

            相反在Boomzap,我們把工作質量和數量當作常量,然后允許員工自己用時間來衡量自己的工作效率:他們有一個任務列表和一個最低標準,然后自己安排時間去完成這些任務。如果他們能更快更好地完成任務,他們所獲得的獎勵就是有更多的剩余時間用來休息。如果他們不能完成任務,很快他們就會發現自己周末經常需要加班。在這種模式中,不具備效率的員工自然會被淘汰,因為他們有太多的工作需要加班去完成。同時,效率高的員工會發現自己擁有了更多的自由支配時間——自由支配時間就是對員工的一種很好的獎勵。每天都能讓你的好員工獲得獎勵,這可是很不錯的魔咒哦。

             

            #2: 我們會做Daily Build(每日構建)
            在一個你不能在大廳里游走,查看每個人都在做什么,并給他們分配任務的虛擬工作室中,你需要一種至關重要的機制,來檢查人們每天都在做什么,并對他們的工作給予反饋。為了解決這個問題,我們有一套非常嚴格的Daily Build策略。每一天結束的時候,我們會構建一個包含了所有最新美術資源和設計要素的游戲版本。我們根據這個最新的游戲版本來評價這一天的工作。這也是我們用來評價工作的唯一標準。我對員工的工作反饋當中有90%都是直接來自于這個daily build。我確保員工每天能拿到這份反饋意見,這樣他們就能知道他們十分在朝著正確的方向前進。這樣的daily build以及反饋過程是我們這個公司的生命血液。如果我們的daily build走向失敗,那么整個項目也就走向失敗了。

             

            #3: 我們將全職員工和基于項目的特別員工混合編制在一起
            有些工作只要有足夠多的初級員工就能做得很好,有些工作交給擅長這方面的人來做,能做得更快更好,沒必要使用你最好的資源來做所有的工作。問題是你很難用固定不變的薪水來長時間留住初級員工和專才。所以我們的策略是留住那些高級的通才,并讓他們來做游戲中的核心設計和架構工作,然后將大量的內容制作外包給那些專門做這方面的人,以及我們雇傭的一些工作室。因為在任何時候我們的項目當中都有超過一半的成員是來自于我們雇傭的一次性合同工,這些人員是我們能夠根據需要隨時變更的,或者是根據需要縮減項目組成員,而不必裁減任何我們的員工。這對于現金流的控制及其有用。

            關鍵在于我們外包的目的不是在于減少成本——事實上我們的很多合同工的成本比正式員工還要高——我們外包的目的是將我們工作室的空閑時間風險轉移出去。舉例來說,我們會將所有的網頁,聲音,大量的手繪背景,人物肖像等工作外包出去。這些工作都是熟練工們可以高效高質量完成的工作,并且都是只在項目開發中的某些特定階段才需要的。當我們需呀他們的時候,我們支付比正常水平高的報酬給他們,而當我們不需要他們的時候,不用為了“解雇他們”而付出任何開銷。

             

            #4: 我們是否雇傭他為全職員工主要取決于他的性格
            我們的工作方式對于成熟的,主動的,富于自律精神的人來說是最好不過的。但可惜的是很多優秀的程序員,美術和策劃并不適合在家里依照自己的作息時間表來工作。你必須及其小心地進行測試,不要雇傭那些不適合這種方式的人。

            我們的做法是對于每一個要加入我們工作室的成員,先進行一個月的考核,然后給他3個月的試用期。即使是我們很熟悉的開發者也是如此。第一個月的考核主要是考核對方的專業能力,判斷他是否有能力完成這個工作。3個月的試用期里則是對他性格和自我管理能力的綜合考察。有幾次我們縮短了對一些人的3個月的試用期,隨后我們便后悔了。此后我們再也不隨便縮短試用期,對于不是很熟悉的人,我們甚至會延長3試用期。

            這里的底線是,如果你將要讓你的員工以這種方式工作,你必須要認識到有一些人——甚至包括一些十分優秀的程序員——就是無論如何也無法適應這種工作方式的。但是對于那些獨立自主,善于自我激勵的人,這種工作方式能起到很好的作用。

            一些人將這種現象解釋為“虛擬工作室不能雇傭那些年輕的沒有經驗的開發者”,我們不同意這個看法。我們的一些最好的員工恰恰是那些年輕的,很有動力的實習者。而那些無法適應這種方式的人往往是一些接受過專業訓練的,有長期的傳統游戲工作室經驗的人。這里最重要的不是經驗而是工作動力和個人品質。

             

            #5: 我們用“基于項目的聯盟結構”來取代權威
            另一個我經常被問起的關于Boomzap結構的問題是:“你不能跟他們會面和交談,那你到底怎么管理這些人呢?”用一個制作人的說法來問就是:“你怎么保證團隊中的人所做出來的東西就是你想要的呢?”回答很簡單,我們不保證。公司中的每個員工都被分配在一個特定的項目中。他們知道他們所在的項目是什么,在項目里他們有很大的自由和權利。我們的策劃所做的是高度抽象化的設計,就像我們的任務一樣。我們不對我們的員工做細致的管理,并不是因為我們討厭細致的管理,僅僅是因為要做到細致管理,光是大量的郵件就夠你受的了。相反的,我們建立3到4個人的小組,我們允許他們按照自己的意愿去做游戲。我們對他們的管理非常松散,給了他們足夠的自由度,讓他們能夠自己做決定。

            這種方法相對于傳統的集中管理式的工作室來說,更像是一堆獨立項目所組成的聯盟。每個小組都有獨立的權利可以對設計做出很大的改動,而不必去問總部這樣做是否合適,由此而減少了大量的溝通成本。這種方法對于一個項目能力很強的團隊來說,可以收到很好的效果,而對于項目能力較弱的團隊來說,由于缺少了整體把握,可能會導致項目失敗。所以了解你的員工的能力很重要。

            有一句話是這么說的,接受那些并不是你所期望的,但是被完成得很好的工作,是成功的關鍵。在傳統游戲工作室里,最常見的情況是整個項目組耗費了大量的時間,僅僅是為了實現其中某一個人的夢想,然后他們就在這無止盡的追求中反復修改,返工,試圖讓游戲更接近他的想法。請將項目托付和授權給你的項目組成員,客觀地去取舍那些不是你想要的但是做得很好的東西。這樣做有兩大好處:1)你的組員們會由衷地感到高興,因為他們自己做的東西能被最終放在游戲里面,而不必為了別人的想法去改變什么;2)有些時候那些你不想要的東西的確會比你腦子里的想法要更好一些。

            記住,將項目托付給組員的同時,要將責任也托付給他們。如果你想要你的組員們真正地對自己的工作負起責任來,你就不能老是低估他們的工作,總是強迫他們按照你的意愿去返工。“這是不是我想要的?”這個并不是問題。你最好這樣問自己:“這是不是玩家所喜歡的東西?”

             

            #6: 我們雇傭那些會做實事的管理者
            我們這種工作方式的一大優點是你無法隱藏那些對項目沒有貢獻的成員。那些潛伏傳統大型工作室里,老是做一些“過程優化”和“促進會議”工作的中層管理者們在一個虛擬的工作室里就找不到這樣的事可做。我們也一點兒也不因此而想念他們。團隊中的每個人,甚至包括公司組建者,都會在項目里承擔一定的工作,例如腳本編輯,測試,關卡設計等。因為我們評價一個員工的唯一標準就是他的工作有多少被包含在了我們的游戲中。正因為我們的管理者被迫要與項目的技術層面打交道,他們會對團隊中的每一個成員在做什么都了如指掌,對某項工作到底要花多少人力來完成也會更加清楚。這樣對項目所帶來的好處是不言而喻的。

             

            #7: 我們依賴于3P:PowerPoint, Prototypes(游戲原型), Photoshop
            我希望我不是第一個告訴你這話的人,但是的的確確是沒有人會閱讀設計文檔。事實上,當我以前在一個比較大型的工作室上班的時候,我就養成了一個習慣,我會在那些超過50頁的設計文檔中的某處插入一句話:“誰看到這句話我就給他5美元。”然而10年來從沒有一個人來找我要過這5美元。這是個真實的故事。有問題的是,業界找到了一種方法來改變這種狀況,開會,開大量的會議。然而作為一個虛擬工作室,我們不能像他們那樣大量開會,我們甚至都不能彼此見面,因此我們只能想出另一種解決方法。

            首先,我們用一個很短的PowerPoint演示稿來作為游戲的最初設計。這個PowerPoint文檔中全是圖片,掃描的手繪圖,從其他游戲中引用的截圖,google中搜索到的各種圖片。是的,一個沒有文字的文檔。這個文檔基本上是游戲中所有狀態畫面的設計草案,描繪出這個游戲大致的樣子以及它的玩法。接下來,我們讓程序員基于這份文檔做出一個粗糙的游戲原型,原型中的圖片就用PowerPoint文檔中的圖片,沒有合適圖片的就用灰色方塊來替代。這個游戲原型,加上我們每天對于它的反饋和改進記錄,就構成了我們的“策劃案”。過了一段時間之后,當這個游戲原型變得真正好玩起來了,我們的美術就從這個原型游戲的截圖開始,在Photoshop中設計它的畫面,然后給出游戲mockup版本所需的所有圖形資源。

            當這些都完成之后,我們就進入完整開發階段。通常會有一個人坐下來,利用現有的PowerPoint文檔和游戲原型,列出一些列簡單的任務列表,表明要讓這個原型變成最終產品,還有哪些工作是需要去做的,這樣的一些列表加上PowerPoint文檔和與游戲原型,3者就構成了一個更接近于策劃案的“策劃案”。我們的大多數游戲都只有不超過20頁的文檔,而且我們還在考慮這20頁是否太多了點。

             

            #8: 我們使用“制作人兼程序(Producer-Programmers)”
            我們開發中的另一個強大的秘密就是,我們的每一個項目都由一個制作人兼程序來負責。他是一個具備較高專業技能的程序員,不僅要完成游戲的核心代碼,而且要從整體上來把握這個產品,把握這個游戲里面的所有方方面面。我們以這樣的結構來搭建項目組有幾個原因,最重要的一個原因就是:這樣一來,與美術和音樂制作者打交道的人就是那個要把這些資源加入到游戲中的人。這樣就減少了很多溝通環節,減少了很多由于溝通而帶來的誤差。而且這樣一來制作人就可以直接去實現和測試自己的新想法,而不是當制作人有了新的想法后,要先去給程序員解釋,然后再由程序員來實現。

             

            #9: 我們創建了一套“簡明可靠(Idiot-proof)”的工作流程
            傳統開發工作室經常需要消耗大量的“溝通時間”來幫助美術,策劃和音樂制作者將他們的工作內容集成到游戲中去。因為我們沒法讓兩三個人圍坐在一張桌子周圍來解決這類問題,也因為讓我們的程序員來撰寫詳細的資源集成文檔是一種浪費和幼稚,我們會花很長的時間來開發相應的自動化工具,確保所有這些資源能很簡單地被加入到游戲中。

            我們最大的工具就是Excel,我們用它來編寫各種資源腳本,例如精靈列表,聲音文件列表,關卡設計變量,物體變量,國際化字符串等等。每個Excel表格中會有一個很大的“導出”按鈕,用來導出資源腳本,任何人都不能隨意修改其中的內容。請記住,自動化意味著所有的錯誤都是系統錯誤,都是可以快速定位和解決的。同時因為所有的人都能很容易地閱讀Excel表格,并填充里面的變量,大多數人都能清楚地知道如何將他們手頭的資源集成到游戲中,這些過程都不需要程序員來干預。

            我們的關卡設計工具也是很簡單的。它們都是符合“所見即所得”思路的編輯器,可以直接從游戲中開啟,僅用鼠標即可完成大多數操作。這讓我們的設計人員能高效地設計和測試游戲中的關卡。因為決定哪些Excel表格會被游戲引擎處理的人同時也是導出Excel表單和關卡編輯器數據的人,這個過程保證了絕對的簡明可靠。

             

            #10: 我們只雇傭技術型的美工
            最后需要說明的是,事實上我們沒有多少全職的美術人員。我們會將大量的美術工作外包出去,尤其是各種花紋,背景,肖像,故事插圖等等。所有這些都能迅速地被那些外包團隊完成,然后返給我們,我們僅需要少量的工作將這些資源整合到游戲中即可。我們團隊中的美術都是技術型的,他們對于我們的開發工具和相關技術比較了解,例如字體,動畫物體,粒子,用戶界面等。這樣我們不僅可以不用在團隊中維持那些概念美術,而且也避免了讓我們去交那些臨時合同工使用我們的工具。

            虛擬工作室的9個關鍵工具
            下面這些是我們的虛擬工作室中實際使用的用以幫助我們開發的工具。這個部分不是幫下面這些工具打廣告,只是這些工具跟我們的所有人都合作愉快。你可能知道更好的選擇,但我只是告訴你我們的選擇:

            1. CVS: 如果你在開發中還沒有使用任何版本控制系統,那么遲早你會發現自己將大量的人力浪費在了解決無休止的文件錯亂,版本錯亂的問題中。在傳統工作室中是如此,在虛擬工作室中這顯得更加重要。你使用何種工具并不重要,但你一定要至少使用一種。我們用的是CVS,但這只是我們的選擇。任何你覺得方便的工具都可以。

            2. Basecamp: 我們項目中使用的一個小巧的在線團隊合作工具。每月只需25美元,就能讓我們創建無限量的工程,讓發行商合作伙伴能直接看到我們的日常項目管理情況,創建項目進度的簡單報表。方便地發布每天的新版本和項目日志。每當有新消息發布時還能自動發送通知郵件,你能通過回復郵件來自動將你的反饋發布到網站上。很酷。

            3. MSN Messenger: 我們的工作室與MSN息息相關。我們要求所有員工在工作時保持MSN在線。他們還必須設置“如果我在xx分鐘內不活動,則自動顯示成離開”,這樣我們就能知道我們是否能跟他們交談。我們還要求他們在MSN中設置個性簽名來表明他們目前正在做什么。因此如果他們要去看醫生,就寫上“看醫生,3點回來”,或者當他們在做項目中的任務中時,就會寫上“繪制背景圖片”之類的。這樣每個人都知道其他人都在做什么,而不必總去打擾別人。如果有人需要安靜思考,那他就把自己的狀態設置為“忙碌”。我們有條嚴格的規定“不要輕易去打擾正在忙碌中的人,除非有特別緊急的事”。所以如果有人想集中精力思考代碼,或者解決難題,他們就可以避免被打擾而分散精力。但如果真的有緊急情況會影響到其他人的工作進度,我們依然能夠及時聯系到他。

            4. SkypeIn 和 SkypeOut: 除了經常使用免費的Skype語音電話之外,我們還是用SkypeOut來呼叫真實電話。戴著耳麥來使用的話就比用手機要方便,能解放雙手,而且價格很便宜,打到全世界各地都是2美分一分鐘,接近于免費。更方便的是你能設定一個真實電話號碼作為你的SkypeIn號碼,讓別人通過真實電話來呼叫你的Skype賬號,對方會感覺就像在打本地電話一樣。我們的工作室SkypeIn號碼設在西雅圖,因為我們的大多數雇員生活在那里,撥打本地號碼會讓他們感到無比親切。你還能設定SkypeIn號碼的轉呼,這樣當你指定的號碼無人接聽的時候還能轉呼到任何其它電話上,包括你的手機。它還帶有一個語音郵箱!最終的效果是,無論你身在何處,身在美國的人能免費呼叫你,你也能以兩美分一分鐘的價格呼叫任何人。這樣,你的電子通訊交流問題就解決了。

            5. Earth Class Mail: 怎樣才能方式你的合作伙伴將支票和合同寄錯地址?首先,強迫他們采用電子文檔進行往來。Automated Clearing House(美國的一種基于電子自動清算系統)是免費使用的,大多數合同都能被掃描并轉換成pdf格式。對于那些覺得有必要親自去寫支票和傳統信件的Luddites(惟恐失業而反對用機器生產者),你可以在Earth Class Mail里建立一個郵箱,他們會將郵寄給你的真實信件的信封掃描,然后給你發送一封電子郵件通知。然后你對這封信下達指令,你可以轉發這封信,粉碎它,或者打開它并掃描信件內容。這并不是免費服務,但是對于那些少量的你必須去接收的紙質信件來說,這種服務是很便宜的。他們在全美都有服務點。要小心:當你設置這個郵箱的時候,一定要選擇non-PO-box類型,因為有時候郵遞員不會投遞PO郵箱。

            6. MyFax: 在地球上,如果你擁有一臺打印機,那你就沒有理由去購買一臺傳真機。只要在MyFax設置一個賬號,就能讓所有發送給你的傳真變成電子郵件發送給你。它不僅簡單干凈又便宜,更能重要的是,它能讓你不管身在何處,都能擁有一個固定不變的,在美國的,完全免費的傳真號碼。

            7. PayPal: 我想我沒必要再告訴你如果你需要付款給全球各地的人,PayPal是你唯一的選擇。我們使用它支付薪水給所有的美國和歐洲員工,這樣不僅能立刻到賬,還能生成一個很棒的支付記錄。而且因為你能以多種形式為PayPal賬戶充值,你可以利用這點來形成一個短期的信用卡效果,用以緩解一定的資金短缺問題。

            注:因為PayPal在某些國家的手續費過高,我們已經決定放棄使用它了。我們正在尋找一種替代方案,但是目前我們還在繼續使用它。請根據您的具體情況考慮。

            8. Your Mailing List Provider: 如果你在管理者一個休閑游戲工作室,你會有大量的電子郵件往來。有很多解決方案,但是最超值的是YMLP.com。它有一個很好的工具用于從各種來源中導入地址簿,還能直接從我們的網站中收集新的聯系人地址。最重要的是即使你不能使用自己的筆記本電腦,也能從任何地方獲取完整的郵件列表。你也能方便地分配郵件列表職責,從而讓不同的人同時維護這個郵件列表,每個人都能擁有對問題的詳細討論記錄。

            9. 移動性的裝備: 最后但也是很重要的一點,每次在購買新設備的時候,考慮它的移動性。我的家用工作站是一臺Acer筆記本,自帶內置攝像頭和一塊小型可折疊的第二屏幕。我還擁有一臺USB供電的便攜式袖珍掃描儀,一個迷你打印機和一個耳麥用于Skype。所有這些都能塞進一個小手提箱里(雖然我不是機場安全崗里的時髦青年)。我能在3分鐘內打包我的所有設備然后帶著他們前往任何地方。任何擁有一臺桌子和Internet連接的地方都能作為我的辦公室。提示:只有對于不太常用的東西才選擇非USB供電的款式。這在跨洋履行中很有用,能讓你的筆記本變成一個電源轉換器,為所有周邊設備提供電力。
            總結
            我并不期望我們的運作方式能適合所有其他人,但是我可以向你保證:這種方式對我們很有效。我希望你能從這里找到有用的東西,更希望你能聯系我,告訴我你的想法,以及你們是怎么解決跟我們類似的問題的。
            下面是關于這篇文章的討論:
            問:你們從這多多不同國家雇傭人員,怎么處理各地的法律問題呢?你們的公司需要在所有這些國家都注冊嗎?

            答:不是,我們在美國和新加坡有注冊,所以在這兩個地方我們雇傭正式員工,而在其他地方我們只雇傭合同工(采用的合同只覆蓋到了商業游戲開發的相關條款)。
            問:你們怎么處理員工將開發完成的游戲泄露給盜版者這樣的威脅?

            答:就跟常規公司一樣處理。如果是無意的,我們就嚴厲責備并警告他。如果是故意的,就解雇他。不知道美國或者英國公司還有什么不同的解決方式,除了訴訟他(浪費時間)或者報告警察。
            問:我還注意到了Boomzap所開發的是一些“微型”游戲。

            答:更準確的說法是“休閑”游戲。我們的團隊的確也能大到包含10-12個人,但是我不會用這樣的團隊去開發像戰爭機器,刺客信條這樣的游戲。并不僅僅是因為你會面臨眾多管理和控制問題,單單是將10-12GB的海量數據在Internet上頻繁傳輸,就會對項目造成巨大的延誤作用。我們的團隊一般是3-7個人,包括處理圖像和聲音外包的人。
            問:你們說你們會做Daily Build,但是你們怎么定義“一天的結束”呢,因為你們的團隊成員可能遍布在各個時區。

            答:每個項目里我們都會指派一個程序員作為構建管理員(Build-master),團隊中的所有其他人都要在他指定的最后期限內提交自己的工作成果,然后他就會在每天自己工作完成之后構建一個當天的版本。實際的構建時間可以根據項目組各成員的工作時間,大家一起商量指定一個時間。
            問:這方法只能在你有很強的管理能力的情況下才能起作用,這也是為什么團隊規模不能很大的原因,如果你的管理層次變得更為復雜,而傳統面對面的管理方法又用不上的話,這種方法就肯定不行了。當每個成員都具有責任心的時候,這樣的團隊行為才更像是一個商業行為。總之這種方法有好有壞。

            答:有個方法可以緩解這種情況,就像我剛剛提到的,相對于一般游戲公司,我們傾向于雇傭更專業一些的人,這很有用。我們當中有很多人都有妻子和兒女,在虛擬工作室里工作讓我們能更容易地照顧我們的孩子。你也能通過組建更小的團隊來解決這個問題,10-12個人的組織會在虛擬環境中變得有些模糊,同時擁有3個5-8人的團隊,每個團隊擁有自己的確定權,這樣會更好一些。最后,你必須雇傭優秀的制作人,他會花費大量時間去玩這個游戲,跟團隊成員討論這個游戲,并且直接參與游戲開發過程(是的,這意味著他們要制作關卡,測試,優化等。所有我們的制作人都會身兼策劃的角色)。
            問:從我個人觀點來看,這種商業模式其實是“坐享游戲業界的成功果實”,因為你們沒有培訓,不能幫助員工提升自己的水平。

            答:從某種程度上來說是對的。但事實上我們擁有一個非常強大的實習計劃,并且我本人也是一直教授游戲開發課程的。我本人還是新加坡一些大學和研究機構的顧問,所有有機會能接觸到一些非常有潛力的對游戲開發感興趣的學生。沒能讓他們加入進來真是可惜。

            對于我的學生,我們提供他們每周20小時的兼職打工機會,直到他們畢業。事實上在過去的兩年中我們有兩個游戲的策劃是由這樣的內部實習生來完成的。

            posted @ 2010-03-31 15:47 暗夜教父 閱讀(510) | 評論 (0)編輯 收藏
            轉至游戲大觀 http://www.gamelook.com/?p=9322#_

            項目要能順利執行其實并不簡單,如果又渉及多個單位合作,困難程度又大增。取得PMP或IPMP認證,只是證明個人具備了項目管理的基本功夫,距離實際運用其實還有很大的一段距離。
             

                以下是一位項目經理的工作日志片段,我們從他的工作日志來看項目經理的工作:

                //編者注:(不知啥原因,這段缺少,百度也沒找到)

                以上只是項目經理工作的片段,相信每個項目經理應該都有自已悲慘的故事,程度恐怕只有過之而無不及。項目經理到底應該有那些看家本領呢?

            一個稱職的項目經理應該要其備以下的能力:

            1. 要易于溝通

                筆者在2002年時曾經親自問過美國的一位項目管理專家-Dr. William Wells(曾任美國阿波羅登月計劃的計劃主持人),問他一位項目經理最需要具備的功夫是什幺。那時他的回答是「一位項目管理最需具備的有三件事,第一是溝通,第二是溝通,第三還是溝通」。

                請您回想一下,在執行項目時,你花費最多時間在什么部份?跟領導報告工作進度、跟客戶介紹產品及說明工作成果、跟項目成員交待工作、跟單位內的其它人員爭取支持、跟合作廠商協調配合事項...對項目經理來說,一天內大部份的時間幾乎都是在跟人溝通。

                溝通,可以很簡單,也可以很復雜。對于部份人來說,反正溝通就是把我的意見表達出來嗎,有什么難的。可是在項目過程中有那幺多的人與項目有關,因此要考量的,不僅是把意見表達出來而已,而在于「在什么樣的時間,運用什么樣的方式,將什么樣的信息,傳達給什么樣的人」。

                很多項目經理都是屬于「被動式的項目經理」。就是「你先說你要什么項目信息,我想辦法去弄這些信息出來給你」。因此,信息整理的工作基本上是沒有列入工作管制的,只能夠見招拆招,抱著應付的心態來面對信息的供應。

                如果換個比較主動的角度來看,項目經理先了解每個與項目有關的人想要知道什么,這些信息一定有重復的地方,然后將這些信息做個整理歸類,不等你開口要,我就先提供給你,讓你對項目沒有疑惑,化被動為主動。這些信息整理歸類的動作,直接就納入在項目經理的工作管制之中,這樣對項目經理而言,也沒有任何的「意外」。

                講起來簡單,做起來其實也不難,二個小時就可以做好溝通計劃,幾個步驟掌握住就好:

            (1) 認識項目干系人
            (2) 分析項目干系人的信息需求
            (3) 依照信息需求找出信息種類
            (4) 將信息種類歸類
            (5) 決定信息傳遞的周期
            (6) 決定信息傳遞方式
            (7) 搜集信息
            (8) 傳遞信息
            (9) 檢討信息傳遞成效

            2. 要想的周全

                項目經理有點像魔術師。事前先考慮要表演那些魔術,然后將道具準備好,跟助手、燈光及舞臺配合,先仿真演練幾遍,指示每個人互動方法,并且事先想到如果發生問題時如何處置;確認都沒有問題后,開始表演;表演時要掌控會場氣氛,使整個場子有高潮迭起的感覺;如果環節出了問題,要馬上能夠應變,使節目能夠繼續下去,而不是就此停頓;節目結束后,感謝每個人的合作,同時檢討整個表演的過程需要改進的地方,如此一段表演才算正式收尾。

                項目經理的責任就是掌控全場,把這段表演完美無缺的呈現出來。不過太難了,執行過的項目的人都知道,首先客戶的需求不容易了解,其次計劃時間不夠,再來執行時問題重重,等到收尾時只能草草了事。

                表演魔術可以事先演練,找出問題先解決,執行項目可沒辦法先來一遍。因此項目經理能不能夠將未來半年、一年或二年如何執行及因應先「演」過一遍,就對項目的成功有很大影響了。而這就靠項目經理做「計劃」的功夫。做計劃其實是很煩人的事,相信每個人都有經驗。必須考量有多少時間、要怎幺做、有誰可以做、技術上是否可以支持、關鍵技術是否可以掌握等,做到這個地步,恐怕早已是滿身大汗。

                //編者注:很不錯的小方法

                做個小練習:取一張白紙,在紙的上緣首先將要交給客戶的產品以樹狀方式畫出來。然后在紙的中間,將如何做出這項產品的主要工作步驟(5-6個即可),以流程圖的方式由左至右用箭頭連起來;需要供貨商供貨或其它單位配合的部份,以分支的方式指向各主要步驟。

                上述步驟,就是整個計劃的基礎了。由上圖,可以發展出細部的工作步驟及時間、所需的人力資源及預算需求、采購品項及合同商要求等。如何發展出這些細節,限于篇幅,爾后再論。

                這樣還不夠的。再取一張白紙,將執行這些工作步驟所可能產生的問題列出來。這個是很關鍵的步驟,列的愈多,將來臨機處理的狀況愈少(試想如果項目執行過程中可能發生100個問題,你能事先考量到99個,你只要去擔心那突然出現的1個;但如果你只事先考量到1個,那結果可就不得了了)。這些問題,就是你要先期處理,以減少處理意外狀況的時間。

                二張紙,一個計劃的框架就成形了。這樣其實還不足以執行項目,但是最起碼項目經理先將整個項目執行過程大概想了一遍(就有如魔術師先行彩排一樣),同時也建立一個以后細部計劃的基礎。由以上的練習來看,做計劃并不難,重點在于去不去想,去不去做。

            3. 要能夠預測結果

                日前一個朋友赴美,飛機誤點,航空公司沒有宣布會擔誤多久時間,因此在機場枯坐了三個鐘頭。搭乘那班班機的乘客,有的人需要轉機,有的人有親友在目的地機場接機,有的人初次訪美。此時在機場看到每個人都是焦慮的眼神,焦慮的原因在于他們無法知道誤點多少時間,所以沒有辦法控制之后的行程。你的項目是不是也是如此?

                計劃是「想」,執行是「做」。真的去做的時候,碰到需求、能力、技術、管理、人力等問題,都會影響到執行效果。雖然最后都可以完成,但是如果無法推測完成的時間、成本及產出,項目經理就像是那些旅客一樣──彷徨無助。所以項目經理除了要會做計劃之外,還要能綜合研判情勢,預測項目時間、成本及產出的結果。

                以一個一年的項目來說,開始之后,項目經理就負了成敗責任,所有的壓力都落在項目經理肩上。每天項目經理要想的,不應該只是誰的問題要怎幺解決,今天的日子要怎么過,而是一年后的今天,我是否可以將客戶要的東西按時交付、公司的項目盈余目標可以達成、今天無法達成的,剩下的時間里我應該怎么處理才能達成。所以總的來看,項目經理不僅要做Micro Management(細節管理),同時還要做到Macro Management(總體管理)。而要做到Macro Management最基本的作法就是從全面預測項目結果,并且采取各種因應作法。

                要如何預測結果?今天工作延誤,明天也會延誤,后天也照樣會延誤,以后到底要如何補回來呢?傳統的項目經理在現在這個時點是沒有概念的,結果是到項目要結束前才在趕工,到那時候才發現所要花的錢早就把利潤吃光了。

                比較好的作法是今天發生問題了,找出原因,評估這個問題如何解決。如果一定得增加時間及人力,那幺假設今天這個工作得延長二周,照著時程表推下去,所有相關工作,包含對人力資源、合同商、成本的影響為何都要找出來;再往下看,推到項目完成期限,是否會延誤(不是所有工作的延誤都對項目完成時間有影響的!);如果有影響,就要思考后續的工作要如何先期調整,以適度的調配資源。要做這些評估,較簡單的方式,可能仍得借助項目管理軟件。目前項目管理軟件,不論是國內或國外的,都能做到計劃功能,也能夠經由計劃的調整,去分析對整體的影響。

                項目經理的工作其實是很復雜。對于一個不愿意看全局的項目經理,這些步驟全部在不知不覺中被省去。但是對于一個企業來說,由一位沒有看家本領的項目經理來執行重要的項目,公司的時間、名譽、獲利及質量保證,不僅僅是兒戲。您的項目經理有沒有這些看家本領呢?

            posted @ 2010-03-31 15:25 暗夜教父 閱讀(140) | 評論 (0)編輯 收藏

            大家好,今天亦樂首次為大家帶來flash actionscript轉載教程。首先聲明出處(我自己是沒時間寫教程啦,要直接找我討論還好)

             版權聲明:轉載時請以超鏈接形式標明文章原始出處和作者信息及本聲明
            http://goday.blogbus.com/logs/14062836.html

             

            今天,我也正式宣布,開始成為閃客,以往對macromedia flash的許多頭疼問題都被adobe解決了,以往一直否認我喜歡做flash,現在總算可以為adobe flash 自豪。非常有系統的developing方式。RIA 平臺, on screen project就不這里說了。

             

            這期帶來的是flash極重要元素之一,event事件。在游戲里就是所謂的Trigger. Adobe改良后的,大家謂稱的“冒泡機制”。有問題歡迎發問指教。

             

            =思路大綱=

            1. ActionScript 2的問題
            2. AS3解決問題
            3. 結合問題,說明“冒泡”
            4. 冒泡的問題所在以及解決方法


            1 - ActionScript 2的問題

            stage里有一個mc,mc里有一個btn
            點選mc實現拖動mc,鼠標松開停止拖動
            點選mc實現mc隱藏。
            最容易想到的方法,代碼如下:

            mc.onPress = function() {
                    this.startDrag();
            };
            mc.onRelease = function() {
                    this.stopDrag();
            };
            mc.btn.onPress = function() {
                    mc._visible=false
            };

            表面來看,這個思路是正確的。(實際上沒什么思路可言,很簡單的方法。)
            實際怎么樣?當然是不能實現。
            問題:點擊btn,不能觸發btn的動作!!!!
            解釋:  因為btn處于mc內部,mc被加上了事件以后,按照as2的事件機制,mc內部的btn甚至是其他的元件都不能接受事件。或者可以認為mc的事件覆蓋了mc中其他元件的事件。
            從非冒泡機制來說,在btn上點擊鼠標,首先接受到點擊事件的自然是btn的上一層(也就是mc),然后才是btn元件。Mc先接受到點擊事件,觸發相關的函數。然后呢?我們要實現的點擊btn的效果沒了。我們可以認為mc把我們的鼠標點擊事件據為私有了,不再往下傳遞。(如果是冒泡機制的話,這個動作就回繼續往下傳遞到btn,然后btn會執行。)那么這種效果在as2中還能實現么?答案自然是肯定的,不過方法就復雜了。
            這里就不討論了。As3已經成為主流。
            但是as3中的冒泡機制,讓我們可以簡單的解決這樣的難題。

            2 - AS3解決問題

            下面來看as3中怎么實現。
            代碼如下:

            import flash.events.*;
            mc.addEventListener(MouseEvent.CLICK,mcfunction);
            mc.btn.addEventListener(MouseEvent.CLICK,btnfucntion);

            function mcfunction(event:MouseEvent) {
                    trace("mc click");
            }
            function btnfucntion(event:MouseEvent) {
                    trace("btn click");
            }

             

            看看代碼就覺得,好像沒用什么特別的解決方法,就加兩個偵聽函數,就搞定了。
            這個代碼自然的不能再自然了,就好像做flash 先的安裝軟件一樣。
            但是如此自然的代碼下面,使AS3的冒泡機制在提供支持。 

            3 - 結合問題,說明冒泡機制:
            Help中有一個冒泡機制的圖,相信大家都已經看過了
            這里我聯系實例,另外做一個圖,幫助各位理解。

            2D2D13C9009ACC1FF3AADD80E5C4FB85 

            上圖為as2中的執行原理
            下圖為as3中的執行原理
             2D8D966808DAEEA2C9701B5E09B334FE 
            上圖也就是在as3中實現我們文章開始提出的例子的工作原理。
            下面詳細描述一下

            捕獲階段:
            鼠標在btn上發出點擊事件,首先捕捉到該事件的事stage.,然后事件往下傳遞到mc,再到btn..(如果鼠標事件發生在btn按鈕中的一個label上,那么該事件還會繼續向下傳遞,直到找到label元件。)AS2中,一旦找到了可以相應事件的函數,就停止了,不會往下傳遞。這個道理應該說明白了
            目標階段
            找到我們的鼠標最底層的目標,也就是btn以后,那么就開始執行btn的偵聽函數了。
                如果鼠標事件發生的所在位置,是mc中的btn中的一個label。那么將先執行label的偵聽函數。(當然我們的例子中沒有label)
            冒泡階段:
            執行了目標階段的偵聽函數以后,開始冒泡。
            換一個說法是,返回btn的父級元件mc,如果能找到相關的偵聽函數,那么就執行,如果沒有,就繼續往上冒泡到btn的父級元件mc的父級元件stage。看能不能找到相關的偵聽函數。

            注意一個:首先執行的函數一定是目標對象的偵聽函數。就像我們上面的例子一樣,點擊btn會先trace(“btn click”),然后冒泡到mc,執行trace(“mc click”)..然后繼續往上,如果stage我們也加一個偵聽函數,執行語句,那么還會繼續執行 trace(“stage click”).
            到達stage頂層了,冒泡結束。
            說到這里,各位看官也應該明白了as3的冒泡究竟是干什么用的了

            4 - 冒泡的問題所在以及解決方法
              冒泡也有問題,并不是說它有缺陷,因為出現問題無法避免。
              問題在于,
              假如在上面的例子中,我們不想在點擊btn冒泡階段中執行mc的偵聽函數,我們只想執行btn的偵聽函數。怎么解決?
            同樣的問題延伸出去,可以得到很多擴展和應用。
            那么我們需要阻止他的冒泡的時候執行相關的偵聽函數。
            Chm中的方法有

            stopImmediatePropagation():void
            防止對事件流中當前節點中和所有后續節點中的事件偵聽器進行處理。
            stopPropagation():void
            防止對事件流中當前節點的后續節點中的所有事件偵聽器進行處理。

            用來修改我們上面的例子
            代碼如下:

            import flash.events.*;
            mc.addEventListener(MouseEvent.CLICK,mcfunction);
            mc.btn.addEventListener(MouseEvent.CLICK,btnfucntion);
            function mcfunction(event:MouseEvent) {
                    trace("mc click");
            }
            function btnfucntion(event:MouseEvent) {
                    trace("btn click");
                    event.stopPropagation();//修改在此處。簡單一句,解決問題
            }

            現在可以試試,點擊btn運行得到的結果就是

            代碼:
            btn click

            說明,已經防止了冒泡階段中對mc偵聽函數的處理。也就沒有trace(“mc click”)了
            As3事件機制遠遠不像這里寫的那么簡單,還有很多東西需要研究。
            本文只為拋磚引玉,讓各位能先了解一下冒泡機制。
            希望能多的朋友能提供相關的學習資料

            posted @ 2010-03-15 15:03 暗夜教父 閱讀(450) | 評論 (0)編輯 收藏
                 摘要: 什么是反射反射 (Reflection) 是指在程序在運行時 (run-time) 獲取類信息的方式. 諸如實現動態創建類實例, 方法等. 在很語言中都有相關的的實現, 如 Java 和 c# 等反射有什么用在 as3 與 as2 不同, 類實例中任何元素, 如變量 (variable), 訪問器 (accessor, 即 getter / setter), 方法 (method) 都是不可被 f...  閱讀全文
            posted @ 2010-03-08 22:00 暗夜教父 閱讀(1790) | 評論 (0)編輯 收藏

            打麻將必勝絕技(珍藏版,逢賭必贏)(上)

                    1.147,258規則:下家丟1萬,3、4、7萬基本不吃,2、5萬可能要吃;

              2.牌過半旬,上家開始落風子,不要碰(碰聽張除外);

              3.牌局一直不胡,最好不要動牌,要打熟張,牌一動就有吃大牌的可能;

              4.下家丟3、8萬,有可能手握3、5、6、8萬,打4、7萬要小心一點;

              5.下家丟8、9萬,有可能手中還有4、7萬,打4、7萬要小心一點;

              6.開始幾圈,除嵌張、邊張外,兩頭張最好不吃,先上別的張,等上家再拿到這種牌時,他還會打下來;

              7.手中有1萬一張,2萬一對這種牌型,別人丟3萬,如有混(百搭)不要吃(吃聽張除外);

              8.外面風子除東風外全都見了,不能打,有可能要杠開,至少看二圈再打;

              9.外面有7萬碰掉,8萬見二張,9萬基本上有人碰;

              10.牌開始時先丟蕩張,再丟風子,但是手中風子不可超過二張;

              11.自己無混(百搭)聽張,比如2、5萬,上家丟2、5萬,如果你吃了可聽2、5、8,沒有必要吃;

              12.單吊不要吊一張都沒有見過的張,最好吊兩頭都碰掉,外面見一張的張子或風子;

              13.開始幾圈,有人丟東風,手中有東西風,要先丟西風,因有可能有人拿西風對,別人丟你將被輪出一圈,東風你還可能拿對。

              知已知彼戰術①怎樣猜牌

              猜牌有兩個內容:

              (一) 進攻時:自己所想要上的張,上家有沒有?肯不肯打?已經聽張了,人家會不會打?是否就打?

              (二) 守勢時:人家要什么牌?人家聽什么牌?

              取攻勢是求自己從速上張,盡早和出,以免人家和出,雖攻亦寓守意。

              取守勢時則力求猜測準確,以縮小克牌的范圍,而給自己出路,雖守亦含攻崐。

              猜牌有兩種情況:

              (一) 初步的:下家大概有哪一路牌。這張牌打出去,大概有人要碰,要吃,或要和。

              (二) 鐵定的:這一張牌打出去,一定有人和出,而且一定是某一家和出。

              前者是籠統的,可以根據統計、觀測而得到答案;后者則是確定的,決非單憑估計而可得到答案。

              猜牌的根據是什么呢?

              猜牌總是根據種種現象做出判斷的。在未列舉及分析這些現象之前,得先說明一點:下列的現象雖然是分別舉出,看來是個別的,然而這種種現象實際上又是互崐相聯貫的。

              下面是據以猜牌的現象:

              (一) 河里的牌

              就是四家所打的牌。譬如:白板見了兩張,倘若你手里還有一張白板,決計沒有人要,也沒有人再會打給你。這個例子似乎太幼稚了,然而你正可以從這個例子來加以推論。如八筒已見三張,九筒見一張,而你手里有七、八筒的六、九筒的搭子,必然極容易吃進或和出(倘若已經聽張的話)。換一個例子來說,河里絕少五、六萬,則四、七萬便是人家容易吃進或和出的牌。

              不要以為這種現象是顯而易見的,不少入局者正是忽略了這種現象而鑄成錯誤的,如以為八筒(以八筒見三為例)是熟張而打八筒,這樣在不覺中把本人的上好機會丟掉了;或是以為一萬已見三、四次(以五、六萬甚少為例),四萬亦屬可打。這是猜牌的初步概念;而成熟的準確猜牌大多建筑在初步概念上面。

              (二) 別家打牌的次序

              這一點我們在“控制下家”一節內已經講過,應該隨時記牢別家所打的牌的先后,同時可以猜想——他為什么先打那一張,后打這一張呢?其中必有道理。

              譬如:上家先打二筒,后打四筒。他也許是拆搭子;也許是打二筒時抓進一張五筒,而打四筒時已抓進六筒(因為有四筒一對),或者仍舊留有三、六筒搭子;也許是打二筒時抓進一張六筒,而打四筒時抓進一張七筒。

              倘若上家先打四筒,后打二筒。他也許是拆搭子;也許是本來有一筒一對,所以先打四筒,并不蝕搭,而打二筒時則希望一筒來碰,或把一筒一對做麻將。

              任何一張牌都可以研究,任何一張牌都會提供一種信息,因為誰都不會無緣無故打牌的。

              也許有人會說:我就是常常無緣無故打牌。不對,你有時所以隨便打牌,是因為手里的牌閑張甚多,而這也是一種信息,也是一個緣故。

              下面再做進一步的解釋。

              先打二筒,后打四筒是常例:先打四筒,后打二筒是反常。因為二筒較近幺、九。凡是反常的打法,常常含有明顯的道理。

              倘若上家先打四筒,后打二筒,而河里并未見過一筒,他手里有一筒一對,便更有把握了。倘若能再有其他的現象來旁證這一點,那上家手里有一筒一對或一坎,便可準確地加以證實了。

              據以猜牌的現象彼此都有聯系,這便是一個例子。當然這還是最簡單的。

              (三) 打牌的姿勢

              如手里是一副大牌,現出一種特殊緊張或過分仔細的精神狀態,,象把十三張牌數一數,每打一張牌都可以考慮;在聽張之前一張,故意把牌打得重一些,向桌上拼命一拍;正想吃進某一張牌,突被對家碰去,把拿出一半的牌重新縮回;想碰而不碰……。

              這種種動作都無形中告訴你:他手里有幾張什么牌,并且一般都是不會錯的。一個麻將技巧不熟練的人,幾乎每一副牌都有這一類的表示;而熟練者有時也難免,你總可從中知道他手里的幾張牌,再從旁證來加以證明,便可進一步知道他手中有什么牌要打,要吃,要和了。

              (四) 口中的驚嘆語“啊呀!”或是類似的感嘆詞

              這大多是表現出某一張牌給人家碰去了,或抓去了;牌的變化時常會使人無意中說出許多話來,而從這些話中可以找到某些線索。 言語及姿態有時是故意制造出來的,然而只要能記牢他所說的話和動作,與牌和出后他所攤出的牌來加以對照,便可知道他的脾氣——是真情的流露還是裝模作崐樣。

              打麻將需要應用心理學。倘能看透牌的路數,再加上心理推測,那猜牌的功夫便水到渠成了。

              (五) 最后的幾張牌

              當一家的牌手中有四張的時候(或者時間已遲,手中剩七張牌時),他在抓進一張之后,換出一張來,你便可猜到他手中所有的牌。不過這種猜測,應該隨時把他以往打牌的次序,和他的上家所打的牌加以驗證,方可得到正確的答案。否則未必是準確的。

              在各種各樣的牌都打過之后,所剩余的牌便可一目了然,別人聽張的可能配合便有了限制,在這種時候,你便能尋到一種“有去無來”的答案(當然也應該有旁崐的佐證來確定)。

              上面舉的五種現象,可以作為猜牌的根據,然而最根本的還是在掌握牌的路數。

              (1)很早打中、發、白,當有做平和的企圖。

              (2)在打過二、三、四、五、六、七、八之后,打幺、九,非拆搭,即去衍張。

              (3)拆兩頭搭子,不是有做一色的嫌疑,就是大幺對子很多。

              (4)先打一,后打二,緊防三、六。

              (5)先打九,后打八,緊防四、七。

              (6)開大幺對,有好搭。

              (7)想吃不吃,必有同樣的牌多張。

              (8)想碰不碰,不必防其碰大幺。

              (9)麻將頭,不要三、四、六、七。

              (10)嵌二、八是上好搭子。

              (11)牌將完,需防半熟牌張。

              (12)幺、九少見,必有對子。

              (13)臨危(指有大牌或將抓完時)而打生張,手中必有大牌。

              (14)打牌不顧一色,居心不良。

              上面所舉的不過是最容易理解的,如能根據這些例子再加以融匯貫通,便能摸到猜牌的途徑了。

              比如:在打過中心張子之后,突然又從里面打一張幺九(從原來的牌打出來,與抓來就打,分別甚大,打牌時非注意到此點不可),說明“非拆搭,即去衍張”,然而這二者又從何分別呢?

              倘若你有五、八索搭子,上家打了一張九索,當然可以希望他打一張八索給你,然而他在第二張抓進時,換出一張五索來,你便可不必再等候他的八索了,因他決不是拆邊七索或嵌八索的搭子。倘若你能從另外的現象中看出,例如河里不見八索,而七、九索已各見三張,便可認定他有八索一對或一坎;否則他是抓進一張六索,換出一張九索的。

              又如先打一,后打二,固然要提防他有三、六的搭子;然而也許他是簡單地拆一個邊三的搭子,你緊防三、六豈非徒勞了嗎!所以,在應用這種路數時,也得瞻前顧后,才可有比較可靠的答案。

              現在,我們要進一步來考慮一個更難以斷定的因素,以作為猜牌的根據。

              “他是怎樣打牌的?”這實是一個最緊要的因素,更透徹一些來說,他打牌的路數是怎樣的?他的麻將技巧水準如何?他有無特殊的牌氣?

              孫子兵法所謂:“知己知彼,方能克敵”。叉麻將亦應應用這個原則。根據我們的經驗,可把麻將技巧分為上中下三級。而這三級是根據下列現象來區分的:

              (一)抓進六筒不會換出九筒的 譬如有七、八、九筒一順,抓進一張六筒仍打六筒——這類人的麻將技巧僅能管理現成的牌,而換一張打的念頭還不能產生。當然,聽三交而不聽,生熟張不甚明了之類的毛病也包括在內。 這是下級。

              (二)抓進六筒會打九筒的 同前例,能換打九筒,說明已看清九筒是大幺,比較地不易給人家便宜。他已經了解生熟張之別,在全副牌的過程中,可不至于蝕搭。 這是中級。

              (三)抓進九筒而換打六筒的 同前例,能這樣打,說明水準更高了,因為他抓進一張九筒,而知九筒是生張,六筒的危險倒少,已能解除幺、九熟于中心張子的死限制,這顯然是更進一級的技巧了。他不但能看透生張的分別、而且還會因時制宜,隨機應變,已到出神入化的地步了。 這是上級。

              也有人用另外一種現象來區分的,即:

              下級——不知聽一、四、七而聽四、七,比如有二、三、三、四五,抓進一張六,不知打三而打六。

              中級——聽一、四、七。

              上級——情愿不聽一、四、七,而聽嵌七。

              其理由與前述之例相同。下家者顧自己還顧不周全,中級者已能顧全自己而尚未臻化境,上級者則張張見血,知己知彼,能攻能守,靈活應用。

              在猜牌的因素中,這個估計是最根本的;因為你倘若對每個入局者的水準沒有正確的估計,便會時常懷疑自己的猜測是錯誤的,以為他所打的牌出乎意料之外。其實是你自己想得不夠周到。

              譬如:一家有八、九萬兩張,抓進一張六萬時,在中、下級技巧必打九萬,而上級技巧就未必如此,明乎此理,猜牌之術便屬上乘了。

              階段舍牌的策略

              在麻將中,舍牌十分重要。摸、吃、碰、杠屬于進張,舍牌則是出張,故麻將技巧之高低、競技之勝負,舍牌系于一半,甚至不止一半。麻將高手打得“精明”,主要是精在“舍牌”上。

              舍牌之重要性在于:

              第一、舍牌的安危可以打亂摸牌的順序;

              第二、舍牌可決定各家戰術的運用;

              第三、舍牌可促進他人入聽的升級;

              第四、舍牌可破壞他人的戰略部署;

              第五、舍牌又能牽制他人的牌勢;

              第六、舍牌可放銃成全他人食用;

              第七、舍牌可迷惑他人,使自己食和;

              尤其是打新潮麻將,你舍牌精明,不點炮,既使別人和了88分值的大四喜、大三元,而你也只丟了8分。所以只要舍得精,不點炮或少點炮,再和上幾把高番牌,大概就能穩操勝券。

              1.初期舍牌走單張

              初期舍牌大體上為一至四五巡。起手13張配牌,各家都不同程度地起幾個長單張的風箭牌、么九牌和中張的蕩張。這個階段的舍牌順序,一般是:風箭牌、么九牌和中張的蕩張牌。

              牌戰初期,一般是先舍單張的風、箭牌。打字牌的技巧是:先打風,后打箭。打風的次序是:先打客風,后打圈風和本門風,最后打中、發、白,也可以把本門風放在箭牌的后面打。

              如果起手配牌時,風箭牌就有八九張之多,且又有三對,就要留下,而奔“字一色”或“大小三元”、“大小四喜”或“全不靠”、“七星不靠”或“混一色”高、中番種去努力。

              2.么九牌的去與留

              行張時,如無風箭閑張,或已把風箭閑張打完情況下,萬子、條子和筒子的中張(2至8色點)容易抓入靠張,不便先打(但設計牌局時,考慮到“清缺”、“混缺”及“缺一門”者除外),一般先把手中的么與九閑張打掉,因為么、九閑張各據首尾,抓靠張的機會比中張少一倍,所以在牌桌上,緊接風、箭之后,各家多都打么、九閑張。

              大凡起牌后,出牌不是風箭,也沒有么九,出手就見中張或邊張,說明這家牌局較佳或設計十三不靠,其余三家行張時,須多加提防。對于么九閑張的打法,也并非沒有先后,常有以下幾種情況:

              (l)對設計“清缺”、“混缺”、及“缺一門”的牌家來說,應首先打掉不需要的門類中的么與九;

              (2)在牌局中,現有的牌副、搭子或對子都以中張組成的,那么設計牌局時,必順考慮“斷么”的可能性,無論哪門的么、九牌,均可打掉;如果牌局中搭子和對子較多,準備依靠吃、碰、抓來組副,考慮留下一張尚未見面的么或九的蕩張作單釣叫牌,成和希望就較大。所以,此種情況的么、九取舍,就要視牌局發展而定了;

              (3)如果牌副里已有l、2、3或者7、8、9的順子副,那么,再打么、九閑張時,應與設計的“一般高”、“姐妹花”作一權衡,是打是留?先后次序都要統籌考慮;

              (4)對于牌局組成的后期,在原有邊張搭子8、9的基礎上,抓進同類牌6時,即應打9留6,成6、8嵌搭。小頭也一樣,如在原有邊張搭子l、2基礎上,抓進同類牌4時,也應打‘么”留個成2、4嵌搭。

              (5)凡屬設計十三不靠牌局,除留箭風外,對于萬子、條子和筒子,誠然保留么、九最佳,中間不靠牌張可擴展到4、5或6,進張副度拓寬,利于上張成和,誠然,這時的么九閑張,非但不能打掉,仍應視為牌張中的上乘了。中張,一旦上張成對,即好牌局中上乘的麻將頭。類似這樣的中張,閑而有用,當然在行張中是不會輕易舍出的。

              3.中盤舍牌觀三家

              中盤階段是作戰激烈、緊張的階段,一取一舍都關系到勝敗,所以每舍一張牌都必須真正地把握住安全關,盡量做到所舍的牌讓下家沒有吃的、讓別家沒有碰的機會,更不能讓別家有成和的可能。

              麻將實戰中,牌勢只要進入中盤階段,各家的手牌無時不在起變化,摸打一至二巡牌后,以前的熟張在這個時候可能已經成為生張了,以前認為是安全牌,現在很有可能成為危險牌,此時若舍出不是被下家吃起,就是被其余的家成和,真是隔巡如生張,舊安變新危。

              麻將的舍牌要根據牌面和牌桌上的變化來制定對策及戰略戰術,做到看上家、默下家、盯對家。

              看上家。也就是應看明白上家打出什么樣的花色牌,吃起、碰起什么花色的牌。因為他所吃、所碰之牌,即是他手中需要的花色;打出的牌,也是你可以吃起、碰起的花色。這樣,你可判斷出你自己應保留什么樣的花色,才有迅速吃、碰牌的機會。如果你手中的花色,也是上家想留存、沒有舍出來的,自然你就沒有辦法靠吃碰牌來迅速組合手中牌陣了。

              默下家。與看上家相反,下家正想靠你手中打出的牌來判斷自己手牌中的去留。若你會出的牌,多是下家正想吃起的,那他當然就會很快地吃成一副一副的牌攤開亮出,并且叫聽。故在打牌時,盡量不使下家能吃上自己舍出去的牌,就成了十分重要的思考內容。

              盯對家。既看上家、默下家,也必須盯住對家,這樣三家人需要什么花色的牌,甚至可能需要什么牌點也在你預料之中,知己知彼,方能百戰百勝。對于自己,要做什么花色的牌,成什么樣的和對自己有利,必須考慮周密,這樣才能一舉成功。

              4.終盤舍牌防點炮

              終盤階段是大家短兵相接、交鋒決斗定勝負的階段,絲毫不能疏忽大意。進人終盤階段,有以下兩種情況:

              一是四人中的兩人或一人,依然保持著聽牌,窺機食和。但因牌勢的發展趨平,只好強行打牌,應酬戰局。其他的各家均以防御為主,最后以少失分而收場。

              二是四人繼續互相牽制,打出安全牌。事實上,其中一人或兩人,早已放棄聽牌,采取少失分的作戰方案。

              凡是牌壇高手的對陣,這種局勢并不是少見的,與初手者聚桌娛樂,推倒食和大不相同。設想,牌桌上有一或兩名低手,欲使戰局發展到終盤階段,似乎是不可能的。

              下面談談幾種牌的情況處理:

              ①放炮危險牌

              這里說的危險牌,是指將其放出后使他家成和的絕對危險牌。當牌局進入中盤階段后期,對于任何舍牌,都充滿著重重危險。

              實際上,有些牌在眾多場合下,并非危險牌,但是感覺上又認為不是安全牌,這就是被放炮的KB觀念影響所致。

              所以在這期間,每舍一張牌對旁家來說都不可能是安全牌,那么如何處理這些危險牌,需要進一步地探討。除了絕對安全牌以外(如字牌東碰出,又摸入第四張),其他牌多少總帶點危險性。現在就以放炮的危險牌為焦點,觀察該點的變化。

              第一:放炮危險牌是指對方已經聽張后所要的牌,一旦出現,即可成和。假如現在手中有某張牌,并非直接放炮的危險牌,但由于這張牌被對方碰而導致他完成大番的聽

              張狀態,那么這張牌應視為放炮危險牌。

              第二:如能看準對方在中盤戰后期的番臺狀況,那么凡與其番臺無關的種類牌,一大體上可算作安全牌。

              第三:放炮危險有時可從各家舍牌相的途徑來推測,切舍種類少的牌,危險性大,尤其是生張牌,放炮危險性更大。

              第四:自己手牌中的暗坎和該同一線上的牌,是放炮的危險牌。例如手牌中有暗坎3條3張和6條1張,當桌面上一直沒有出現這樣的牌時,就可能有人聽張的叫牌是3、6條,而他和牌的叫牌張數有二分之一把握在你的手中,這樣就能極大程度地阻止他獲勝。

              ②高度危險牌的舍法

              知道是放炮牌,誰也不會往外打。但是,如遇懷疑性的高度危險牌,就要看舍牌者的膽量和到底對該局牌的勝負抱什么樣的期望而定了。自中盤階段后期到終盤階段,如自己的手牌沒有可能構成多番牌姿,而對方的手牌頗有多番形態的預兆時,最好死了心不和,不打危險牌,甚至拆掉面子安全牌,以度過最后一兩巡的摸牌難關,直到黃牌。

              ③放炮牌的處理方法

              第一:編入組合面子。牌局到了終盤期,既然放炮牌不能打,也不能孤單單地留在手牌里,妨礙自己和牌。這樣,最好將放炮危險牌編到手牌牌面中去,這是最安全而且是最有利的戰法。因為這樣一來,這張放炮危險牌的左右聯絡牌也都打上了保險系數,均不會輕易舍出,使危險性大大減少。

              第二:立即退出勝負圈。麻將牌競技中,能當機立斷地退出勝負圈的做法,是極為明智的。尤其是多門聽牌的牌姿,明知摸入危險牌,但惟恐擾亂了成形的牌勢,卻執意舍出,奢望僥幸過關。殊不知這樣戰法將會勝敗立見,決無放炮與過關的五五開之說。

              第三:沒有安全牌的困惑。在形形色色的牌姿中,常出現有人覺得手牌中沒有安全牌可打的窘迫感。誠然,這是人為造成的,大體上可分為兩種類型:其一,手牌中顯露的朋組過多,饑不擇食地見吃就吃、得碰便碰,既無算計,又不顧及戰略,結果手牌相對減少,周旋余地縮小了,調整面也窄了。手頭僅有幾張牌,即出現沒有安全牌可打的情況,以致給自己帶來很大的困惑,甚至有放炮的危險。其二,雖然呈現未吃未碰的門前清狀況,但一手13張牌仍覺得沒有安全牌可打,這其實是恐懼心理。

              照常規戰法,手牌中沒有安全牌的說法是不切實際的。以三家對手均已聽牌而言,每家通常是兩門聽,也就是說三家合計叫聽六種待牌而已。這對門前清的13張手牌來說,至少手頭上還有一半以上的牌是安全牌。即使手牌少的人,也不見得張張與他人叫聽的待牌分毫不差。問題在于是否愿意舍聽而后退一步,是否懂得計算舍牌相。所以,打出一張牌是不是安全,須憑技術高低去審定。

              打麻將必勝絕技(珍藏版,逢賭必贏)(下)      

                     麻將理牌的實例剖析

              ①沒有聽張希望的牌姿:

              例1:中、白、發、東、南,l、2、6、9筒,6、8條,8、9萬。

              顯然,這鋪牌里有5個單張字牌和3張老頭牌(么九頭),無法形成九種么九牌的倒牌。這種牌,可說是相當惡劣的手牌了。盡管其中尚有3組可構成面子牌張,但畢竟是機遇不佳的邊搭l、2筒和8、9萬與嵌搭6、8條。根據牌譜中所謂“起首三張單風箭,兵牌必難求聽和”之訓,這種牌即使每巡進張,也是距聽張食和相當遙遠的,大可不必認真組牌,勢必作好不和的思想準備。

              所以在舍牌時,應視海牌而定,客風輕易不能拋出,三無牌也需慎重,否則將會加大別家的番和。待到別家打出之后,再追打熟張不遲,首先舍出的當然是老頭牌了。

              在這種惡劣牌勢的情況下,除追打熟張牌外,應留神對手中的某一家,估計和牌平平,即可盡量供牌,促其早成早和,少失番分。

              例2:中、發、東、北,2、5、9、9條,4、5、9筒,2、4萬。

              這種牌勢雖勝于上例,風箭少了一張,對子、搭子加嵌搭,單張中張牌5條兩頭尚有牌張,聯絡價值更大,但是距離聽張仍然差得很遠。如強行奢望和牌,必失大誤。

              例3:發發、西、白,1、5、9筒,1、2、4、8條,4、5萬。

              四張字牌之內,只有綠發對子為一要素。雖然1、2、4條為復合面子,但待牌只有3條一種,決非有利形勢。4、5萬與中張牌5筒給整個牌鋪帶來一線希望,惟獨缺少麻將頭。

              倘若依靠模入一張將頭牌的話,至少也須換5到6次以上,這么遙遠的行程,恐怕不及來張時,早已敗北。故而戰略上與例2相同,照例1打法,多是有益無損的。

              ②接近聽牌的“未知數”:

              例4:中中、白,1、4、5、8筒,3、6條,1、2、7、9萬。

              此例的紅中對子系一要素,加上4、5筒子,1、2萬邊搭以及7、9萬嵌搭,合為面子牌的4個要素。倘若3與6條中的一張牌與摸進的任何一張中張條子再組成一個面子的話,即有了

              5個要素,從而具備了聽牌資格。

              牌譜中有句話:“副副求和,敗可立見”,說明求和心切者,往往極易他人放銃。因此,每當使用本例牌促成叫聽之后,必須居安思危,不要抱太大希望。待你手牌理順之際,殊不

              知別人已早“磨刀霍霍”,準備食和了。

              例5:東、南南、西,1、2、3、6筒,2、3條,1、7、9萬。

              這里已有現成的4個要素,即門風對子一組,123筒一副,2、3條搭子與7、9萬嵌搭,當然如能摸進一張與中張6筒相聯絡的牌,牌面即可重現生機了。

              對于上述要素,一旦吃碰形成面子牌朋組時,就須在理牌時小心斟酌了。雖說單張的東、南兩風屬客風牌,本可舍棄。但是,對于本例實戰情況來看,有時留下一張風牌(自然是“海”內尸牌未見或只見一張的),作單釣叫牌,對和牌極為有利。

              例6:白白、南,1、2條,3、4萬,1、222、6、8筒。

              乍看,這副牌比較整潔,有白板一對,1、2條邊搭,2、4萬嵌搭,6、8筒嵌搭,以及1、222筒的復合面子共5個要素。但是,這種牌的潛在性危機極大,無論邊搭、嵌搭與復合面子,可待牌全部是3與7的尖張牌,這些尖張牌對于高手而言,極難舍出,單純依靠吃進組成朋組的機會是極少,尚余的一半機會只能靠自己摸進了。假如平均每摸3手可得一張的話,起碼也需12巡摸牌才行。

              例7:東、西,1、2、3、77萬,2、5、8條,3、7、9筒

              這副牌反而比上例牌有利。盡管單張牌較多,但極易得手上張,這是老麻將們堅信不移的。字牌雖有兩張,且為客風牌,即便打出也無大礙。這里,7萬對子為將頭,123萬一副,7、9筒為嵌搭,雖說只有3個要素,但上張極快。其中萬子與筒子任意進牌,都能組成復合面子,決不成蕩張。對條子來說,首先應打掉中張5條(這是許多人所不愿的),從戰術上看,舍出5條后,尚有2與8條兩張,除摸進倒運的5條外,無論進什麼張了,都能組成一對要素,這是高手們非常明白的。

              所以說,倘若打的順的話,最快只需5手(摸5次牌)便可叫聽了。

              ③具有成和把握的牌姿:

              例8:東東,2、7、8筒,3、5、7、8條,1、3、4、6萬。

              這副牌本身已經有5組要素,除單張牌為2筒外,可將復合面子中的1、6萬視為單張牌對待。

              首先,舍牌是2筒無疑了。萬一上張牌出現嵌2萬或嵌5萬時,就可拆掉3、5條嵌搭。反之,出現嵌4條的話,首先應打出6萬。因為6萬中張的危險性大于老頭牌1萬,在旁家尚未上手之前舍掉,可避免放銃。一旦叫聽叫和時,再打1萬,也不致失誤。

              例9:南、發發,3、5、6、8筒,5、6條,11、3、4萬。

              這也是5個要素齊備的牌。除單張南風牌外,復合面子的3、8筒,也可視為可舍的單張牌。

              如果進張南風對或任意一張筒子時,舍牌就應仔細了。當然,首先上筒子牌,即將南風打出,倘若再進筒子,應考慮舍掉4萬較為合適,從而保留1、1、3萬的復合面子。

              不過,從一般玩牌者的習慣來看,不少人寧可拆筒子,說什麼也不原打4萬。這種舍近求遠的打法,仍屬下策。不難看出,這副牌的綠發對容易碰出,決不會留在手頭作將用,那麼唯一的將頭只有1萬了。只要進張筒子,拆舍3、4萬搭子就比較合理。誠然,對于5、6條搭子而言,因為純屬中心張子,一旦拆舍出去,極易被旁家吃進,所以不如不舍為妙。

              例10:西,5、6筒,2、3、666條,2、3、4、6、7萬。

              這是極佳的面子牌。無論是起手配牌或是兩三手后的面子牌,只要吃牌或上張,都不應留兩個搭子去尋求將頭。從實戰戰況看,應毫不猶豫地將刻子6條舍去一張,既能保留將頭,又構成了平和。此系上策保和無疑。相反,如果舍不得6條刻子,很可能會坐失良機,這就是牌譜的勝決所在。

              例11:南南、西西,88條,3、4筒,1、2、3、4、5萬。

              此例有3組對子,以要素而言合計6組,故此多余一組要素,在這種情況下,勢必要拆舍一組。誠然,兩對風牌較易碰出,所以當有人打出其中一張字牌時,不必急于去碰,反而就以該門風對作為拆打對象,以便牽制下家。

              對于8條來說,最佳是進張7條,打出8條,形成搭子牌面,使滿鋪牌構成較好的和平局面。如果牌桌正好遇上南風圈,自己又坐于第三家,那麼兩對風子全應碰出,而拆舍3、4筒。倘使兩個搭子均先吃牌,就應拆舍8條對子,以兩對風子作為雙風子作雙碰聽和了。

              祝大家逢賭必贏!

            posted @ 2010-03-02 09:39 暗夜教父 閱讀(409) | 評論 (0)編輯 收藏

            “開會”,在現在的商業運轉中,這兩個字的名聲非常不好,因為真正能通過會議這個形式取得什么成果的很少。我記得Dilbert(美國漫畫家)曾經有一幅漫畫這樣畫的:幾個人圍著桌子坐著,會議組織者說“今天會議沒什么特別的議程。像往常一樣,我們就就抱怨下、做些沒什么干系的發言就好了”。

            現在會議基本上就是這樣的,大部分的會議都是無序的、沒有激情的、沒有效率的。但我們的會議是可以開的更好的。

            當我決定寫一篇關于如何開展有效會議的文章,我找到了Marissa Mayer (Google搜索產品的副總裁,see BusinessWeek.com, 6/19/06, “Marissa Mayer: The Talent Scout”),在我所認知的人中,她在會議方面有著最豐富的知識,并且她領導創造了當今一些最有創新意義的產品,這也讓我為她在會議組織方面的才能上加了不少分。

            Mayer平均每周開差不多70個會議(SweetRiver譯注:會霸…囧rz…),并且作為最后一道關卡來把關Google工程師、項目經理向Google創始人Sergey Brin和Larry Page來陳述、推銷他們的想法的機會。一共有8個由directors, managers和engineers組成的團隊在產品開發的各個階段,向Mayer匯報。

            在Google這樣的公司里,大部分的工作都在會議中開展,Mayer的目標就是確保她的團隊有明確的工作指令、戰略方向以及有足夠支撐行動的信息,并且同時讓他們感覺有前進的動力并受到了尊重。Mayer她成功開展高效會議的6個秘訣就是:

            1. 有一個明確的議程

            Mayer要求每個會議都必須有明確的議程,內容包括參會者希望討論的問題的大綱以及他們將如何最有效地利用自己的時間。當然,議程需要有一定的靈活性,Mayer覺得議程更多地扮演這樣一個角色的工具:議程迫使參會者仔細思考自己希望在會議上所達到什么目標以及如何最好地去達成這樣的目的。

            2. 指定專門的note-taker(SweetRiver注:和我們一般概念上的“會議記錄員”還不一樣)

            Google的會議一大特色就是有很多的投影…..。一面墻上投影現在的presentation,旁邊會再有一個投影儀展示當前會議的記要(SweetRiver注:原文想要表達的意思應該是不僅要找一個專門的會議記錄員,還要專門的投影實時地展示當前會議的記要,以確保參會人員能在會議上達成真正的一致),可能旁邊還會有一個投影顯示著一個4英尺高的在走的計時器!!Google高管們相信,通過制作一份官方的記要,可以最大程度地馬上消除不準確性和不一致性。

            那些沒能參加會議的人會收到一份會議的記要。當有人試著回想會議的決定、團隊前進的方向、接下來需要做什么工作,他們可以有這樣的標準官方記要參考。

            3. 鉆小會(Carve out micro-meeting)

            Mayer留了大量的小塊時間段去參加那些有特定議題或者關于特定項目的小會。比如,在她與創始人兼CEO – Eric Schmidt的每周2小時的會議中,她會抽出5-10分鐘間隔(或者更長,這根據主題而定),去參加那些特定領域的會議,如關于站點表現的周例會、新產品發布等等。

            如果有什么緊急情況發生,這種方式給了Mayer足夠在會議前調整議程的靈活性。這也慢慢讓會議變得更有重點。Mayer對她的團隊成員也是采取同樣的策略,更多是5-10分鐘的短交流(她的行程安排所允許的最短時間段),而不是30分鐘的促膝長談。通過這樣地在一個大塊時間段鉆出時間參加小會,她可以收獲更多。

            Mayer有著engineering和computer science方面的背景經驗,自嘲地稱這些micro-meetings是“降低流水線上的延遲” (reducing latency in the pipeline)。這就是說,如果她的一個員工想跟她討論一個問題,這位員工可以在Mayer的某一個大的時間塊上跟她預約一個10分鐘的micro-meeting,而不是等她下一個空閑的30分鐘,——這30分鐘可能2個星期都等不到。

            4. Hold office hours.
            SweetRiver譯注:Hold office hours的意思可以看下Harvard Business Review的這篇文章。其實就是類似“答疑時間”的這樣一個概念,即某人固定時間待在office里,保證你在這段時間的時候能找到他,跟他交流。這樣的“答疑時間”可以讓你更加親近您的員工、更加了解公司內的事情、更加有機會聽取意見和新的idea、更加有效的處理來自下層的一些問題,特別讓你不會變成那種永遠看不到的untouchable的神人一樣。我沒有想出比較好的中文詞組來表達這個意思,所以下面都會保留英文。

            Mayer的這條秘訣來自她在Stanford做computer science教師的經驗,她也是在Stanford遇到了Google的兩位創始人。Mayer的office hour每天下午4點開始,每次一個半小時。

            員工將他們的名字寫在她office外面的一塊白板上,然后她按照先進先出的方式對隊列進行處理。有時候是PM需要她在一次市場活動上的認同,有時候是一些員工想向她sell(推銷)自己的一個想法或者設計 (see BusinessWeek.com, 6/30/06, “Inside Google’s New-Product Process”).

            Mayer說: “我們很多有意思的產品都是在這個office hour里搗鼓出來的,Google News, Orkut [Google's social networking site](SweetRiver譯注:這里作者居然給Orkut加了一個英文注釋,看來Orkut是比較痿,囧~~), Google Reviews, and Google Desktop這些產品的idea都是首先在這種office hour里出現的”。在這短短的一一個半小時的office hour的時間中,Mayer可以開多達15個會議,平均每個人7分鐘的時間…….

            5. 要數據,不要政治 (Discourage politics, use data)
            Mayer曾經談到的“9個關于創新的意見”(”Nine Notions of Innovation”)中的一條就是“要數據,不要政治”(see BusinessWeek.com, 6/19/06, “9 Notions of Innovation”).

            一個公司里,如果老板會根據他對人的喜好而不是他對產品和設計的客觀想法來做決定,如果參加會議的人都會覺得老板會給他所喜歡的人所作的設計開綠燈時,那這條意見就非常有必要了。

            Mayer相信這樣的價值傾向會讓員工士氣低落,所以她把審批流程(approval process)變成了科學。Google會根據一些明確的度量指標來選擇好的設計。選擇是基于價值以及事實,而不是個人關系 (Designs are chosen based on merit and evidence, not personal relationships)。

            Mayer不希望在設計會議上聽到類似“I like”這樣的句子,譬如“I like the way the screen looks”。而她會鼓勵類似“he experimentation on the site shows that his design performed 10% better”這樣的言論。Google是建立在客戶反饋數據驅動的企業文化上,而不是建立在內部政治上(現在很多的企業都是),所以對于Google來說,“要數據、不要政治” works。

            6. Stick to the clock.
            為了給會議增加點壓力以保持參會人員的注意力,Google的集會一般都會非常特色地在墻上都投影一個巨大的計時器,給特定的會議或者議題做倒計時…..。這真的真的就是一個網上可以下載的timer,跑在PC上,然后投影到4英尺大小。

            想想當從會議室外面來看里面的情況,那一定非常瘋狂:墻上同時投影著若干的影像:presentation, transcription(參第2條), 然后還有一個mega-timer!不過,在Google,it makes sense,在創造性的混亂中引入結構!!通過這個Timer給會議帶來的輕微的壓力感使會議保持on schedule。

            Mayer同時對這個timer也有一個忠告:對timer保持健康的幽默感。(同時,我對Mayer的采訪的timer也快到到時間了,但是Mayer讓timer變成了一個有趣、友善的提醒物,而不是對我們談話的粗魯打斷。)

            請記住,這些會議技巧在Google里用的很好。雖然可能并不適用你們公司,但這六個秘訣應該可以給你一點如何讓會議不浪費時間、更加有效的良好的啟示。

            posted @ 2010-03-01 12:49 暗夜教父 閱讀(245) | 評論 (0)編輯 收藏

            一、寫這個文章的起因:

                    經常遇到很多人想學習Flash,但是不知道從何學起,有的朋友甚至對于學會了Flash,能做些什么也很疑惑。

                    本人結合若干年Flash學習研究經驗,給想學習Flash的朋友一些建議,也歡迎大家訪問我的空間,http://hi.baidu.com/billypc給我留言。如轉載本文,希望多多宣傳本空間,謝謝。

                   一般來說,Flash的學習主要有兩個方向,一是專攻Flash動畫,一是專攻Flash編程,當然也有動畫和編程都學習的很到位的人,那是牛人。不過這里我主要分析一下Flash的這兩種方向如何開始學習,如何快速掌握。

            二、FAQs

            問:學習flash做動畫需不需要美術基礎啊?
            答:
                    首先,要說明的是,Flash動畫也分為幾種。

                    最重要的應用就是做動畫片,比如早期的ShowGood三國,小小,現在的小破孩系列,開心驛站系列,燕尾蝶等。這些都是動畫片制作,這一類的flash需要有很好的美術功底,需要有諸如手繪,視覺感,鏡頭感等相關的專業知識。這一類的動畫制作基本上需要美術和動畫的專業知識。而Flash只是作為一個動畫制作的工具而已,一個動畫片在從開始到結束,更多的需要的是美術及動畫方面的專業知識。

                   另一類應用是Flash廣告和Flash特效,這一類Flash大量應用于網絡,從網站主頁Flash動畫,到網站內部的一些廣告,一些吸引眼球的效果,都屬于這一類應用。一般學習Flash的人,基本上都在做這樣的東西。包括一些初學者在內,都認為這就是Flash,其實這只是Flash最簡單的應用。制作這一類的Flash一般需要一些創意,有一定的視覺感,有美術基礎的人會更加得心應手。有時候會需要掌握一些基礎的flash as,比如制作flash菜單,flash跳轉效果等。

                   Flash在動畫的制作過程中,主要扮演的是工具的角色,是目前動畫制作中效率比較高的工具之一,而一個好的動畫,并不依賴于你用什么工具,而依賴于你的專業程度。專業知識越扎實,創意越新穎,做出的動畫就越好。而工具的學習僅僅是第一步。


            問:我也不知道應該學習哪個方向,動畫和編程哪個好學啊?
            答:
                   學做動畫,和學做編程,這樣兩個方向,其實不僅僅是做什么的不同,也是思維方式的不同。

                   一般來說,做動畫受視覺因素影響,而編程主要受邏輯思維影響。從很寬泛的角度上來說,學動畫,就是學感覺,學新思維。而學編程,就是學邏輯,學思維方式。美學不僅僅是能感覺到,還是一種創意思維,是感性的。而程序邏輯則完全是一種逆向思維,是理性的。

                   一般情況下,邏輯思維可以通過培訓等,在短時間內鍛煉出來,所以編程應該來說是人人都能學會的,而且是可以通過死記硬背在短時間內速成的。

                   而感性思維,或者說創造性思維,是很難一下子就養成的,就像我們學畫畫,沒有個一年半載,根本畫不出什么好的東西,而且很多畫畫好的都是從小開始培養的。所以學動畫短時間內很難有一些突破,僅僅只能停留在一個較低的層面上,這也就是為什么很多人只會做flash廣告,而做不了大于3分鐘的動畫,或者說做不出高質量的動畫的原因了。

                    但是從入門的角度上來看,會用flash的人,一般都能從事簡單flash動畫的制作,其實這主要是依靠了FLASH這款工具的強大,并非代表著做動畫很簡單,或者你很聰明,一下子就學會了,入門也許很簡單,但是越想提高一個層次就越困難,比如學會FLASH沒多久,就會做flash主頁,flash廣告等,那是因為這個沒有什么難度,所以綜合看來,我認為,如果想在短時間內,從事flash工作的話,可以先掌握flash的應用,能制作簡單flash動畫,然后學習編程,短期內會很有效果。從長期來看,學習一些美術基礎,對做動畫會大有幫助。


            問:我最近想去學flash制作,在網上找了找,發現有很多制作軟件,如flash MX,flash MX2004和flash cs3 Pro,哪款比較好啊?
            答:
                   2000年 flash 5.0 
                   2002年 flash mx (就是flash 6.0) 
                   2004年 flash mx2004 (就是flash 7.0) 
                   2005年 flash 8.0 
                   2006年 flash cs3 (就是flash 9.0) 
                   2008年 flash cs4 (就是flash 10.0)

                   目前的最新版本是flash cs4 功能非常強大,不僅支持骨骼動畫,還支持3維等等,verycd上有視頻教程,可以去學習一下。

                  不過初學的話,個人建議你從flash cs3開始,以便今后玩flash cs4,因為他們的操作性很相似,Flash 8現在雖然還是很多人在用,但是已經漸漸被新軟件的新功能所取代。

                  FLASH CS3的好用之處::

                  1.cs3是ADOBE收購micromedia后的大作,無論從動畫設計上,還是程序語言上都有質的飛躍。比如鋼筆功能更加強大,超級強大的繪圖功能,這些都讓矢量圖制作者提高了效率,使用更方便。

                  2.FLASH CS3引入了面向對象的AS3語言,使得AS不在是一個簡簡單單的腳本語言,而搖身變成一種強大的高級程序語言。另外,FLASH CS3也全面支持AS之前的版本,從AS1到AS2均支持。

                 3.作為初學者,因為沒有基礎,不存在用慣一個版本的軟件,用新版本時要重新熟悉的問題,所以應盡量選擇最新版本的軟件進行學習,因為時代是在進步的,老版本的軟件,學完了也就淘汰了,再學新的,還得重新熟悉界面及操作習慣。

                 4.目前由于flash cs4 10月份剛剛推出,目前CS4的教材并不多也不系統,所以建議以FLASH CS3作為學習的開始,而且FLASH CS4的界面和CS3差不多,只是加了些新功能。


            問:怎樣學會flash編程,要有什么基礎,要學c語言嗎,哪里有教程啊?該怎么學啊??

            答:
                    如果你只是了解一下,網上的視頻教程很多,可以去看一看。

                    但是如果你是很想學會,那么我建議你,要學習一門知識,就必須看系統的教材。因此不推薦看視頻教程,網上的視頻教程雖然很多,但是都很難系統性的教會你代碼的結構、編程的思想。所以我的建議是買書學習。最好不要看電子書,個人覺得,看電子書的人,都喜歡跳著看,這樣看就失去了意義。這樣看下來,好像學會了,其實什么原理都沒搞懂。

                   要真正的買一本書,一頁一頁的翻著看,看一遍不夠,一本書至少3遍甚至n遍。還要多加練習。學習編程,首先從hello world開始,然后就是要每天寫,經常寫,這樣才有進步。

                   很多人也有這樣的擔心,怕自己沒有語言基礎,例如沒有學習過C等。其實大可不必擔心,語言只是一種工具而已,目前的主流語言就好象同素異形體一樣,看似有區別,其實都差不多。這就好像你會使用WIN98,升級到了WIN XP,你也不會說,連怎么打開文件都要重頭學習一樣。學習編程的關鍵是學習編程的思想,所以好的書教你怎么理解編程思想,差的書只是叫你怎么寫代碼,其中區別很大。

                   AS2的書,這里不做推薦了,我也沒看過什么好點的書,我學AS2完全就是看幫助學會的,主要是有JS基礎。 
                   這里推薦一本AS3的書:《action script3.0殿堂之路》


            問:我是老程序員了,對Javascript和Java都比較擅長,現在想學Flex,但不知道有什么經典一點的書籍?
            答:
                    1.初學者,推薦《action script3.0殿堂之路》,也有人推薦《as3權威寶典》個人覺得那書寫的不行。

                   2.flex的話,推薦《flex第一步》

                   3.as3語言掌握的7788了以后,可以去看以下一些書籍

                   4.實用書籍: 
                     Action Script3.0 Cook Book —— 類似幫助手冊的書籍 
                     Action Script3.0 設計模式 —— 一本講述程序設計思想的書籍,強烈推薦


            問:flash as2.0 與 as3.0的本質區別?

            答:
                   首先說下as2,as2實際上是as1的升級版,引入一面向對象的概念,但并不是完全面向對象的語言,只是在編譯過程中支持OOP語法。as2的面向對象雖然不全面,但是卻是首次將OOP帶到了FLASH,而AS3是一個完全基于OOP的標準化面向對象語言,最重要的就是as3不是as2的簡單升級,而完全是兩種思想的語言。可以說,as3全面采用了面向對象的思想,而as2則仍然停留在面向過程階段,舉個例子,就像VB和C#的對比。

                   所以as3絕不是as2的升級版,在as3里,可以看到java和c#的影子,確實,這三種語言大部分思想都是一致的,只有一些小的區別,比如as3引入了命名空間的概念,但是不支持比如委托,在包封裝及外部訪問上也引入了一些新概念。

                   在編譯階段,as2采用的是AVM1(actionScript vitual machine),而as3采用的是AVM2。新一代虛擬機采用了OOP思想,在執行速度上比起avm1也快了10倍。還提供了異常處理。以前我們在使用AS2時,一旦出錯,AVM1選擇的是靜默失敗,讓人根本不知道什么地方出錯了,會浪費大量的時間去查錯,而AVM2與目前主流的編譯器一樣,會有異常處理,運行出錯會輸出錯誤提示,工作效率大大提高。如果做個對比,我想說,AVM1就是大刀長矛,而AVM2就是手槍,大刀和長矛也能殺敵,但是只在面對弱智的敵人才能發揮作用,面對一個大型項目,不用點現代化工具是不行滴。

                    as2與as3的部分區別,只說一些大的區別,小的不同太多,就不談了:

                    1.運行時異常機制處理,這個剛才說過了。

                    2.事件機制,這也是很多人拿起as3就不知所措的原因,初學者會發現連一個按鈕點擊的方法都寫不出來。實際上as3的事件機制采用的是監聽的方式,和as2時代的onClipEvent不同,as3里所有的事件都是需要觸發器,監聽器,執行器三種結構的,這樣做的好處就是使得這個語言非常的堅強,非常的標準化。不像as2,奇形怪狀的代碼漫天飛,可以這樣寫,也可以那樣寫,代碼變得繁復難懂,可讀性太差,執行效率也大大降低。要特別說明的是,as3的所有事件都直接繼承event對象,而event是直接繼承自大老板Object類,結構多么完美。所以在as3中,所有的事件都繼承自相同的父親,結構相同,提高了重用性。

                    3.封裝性,這是as3與as2最大的不同,as3引入了封裝的概念,使得程序安全性大大提高,各個對象之間的關系也通過封裝,訪問控制而得以確定,避免了不可靠的訪問給程序帶來的意外產生。

                   4.XML,我覺得這是最令人激動人心的改變,現在as3程序員可以很輕松也很自豪的說,我們是使用XML人群中最快樂的人。AS2時代對XML的存取仍然需要解析,而AS3則創新的將XML也視作一個對象,存取XML就像存取普通對象的屬性一樣方便,用點語法就可以,無疑大大提高了效率。

                  5.最關鍵的一點,容器的概念,AS3采用了容器的思想,告別了as2一個MovieClip打天下的局面。對于as2程序員來說,可能不能理解,我mc用的好好的,干嘛不讓我用啊。但是當你真正的了解as3的思想的時候,當你真主的體會到OOP的好處的時候,你會覺得as3的容器的思想的完全正確的。as2時代,我們做什么都用mc,而as2時代的mc也是直接繼承自object,這給了mc極大的權限,極其多的方法屬性,而有時我們只需要放一個背景圖,并不需要它動,這樣做就造成了極大的浪費。說實在話as2和as3比起來就是浪費之神,所以as2編出的swf絕對比as3編譯出來的swf要大上幾倍。as3把所有你用到的顯示對象都分開,mc的屬性方法都被瓜分開來,舉個例子,你去水果超市買水果,就肯定比直接去大型超市買要方便,更節約時間,時間就是金錢,那就是很大的節省。

                  當然還有許許多多的不同,比如程序執行機制,設計模式,結構框架等等,這里就不在一一贅述。


            問:怎么才能成為編程高手?

            答:
                    可以說,學會編程并不難,怎么才能寫出好的程序,這是很多人所困惑的事情,我有時候也是左思右想,覺得自己寫出來的東西太在是太垃圾了。那么真正的高手他們在做些什么呢?他們到底因為什么才能成為高手呢?

                   其實,我們很多人都僅僅停留在會寫程序的階段,并沒有去研究,一個程序怎么寫才算是合理的,什么樣的結構,才是最完善的,什么樣的布局才是可擴展的。什么樣的代碼才是最高效的。而這正是高手花功夫去研究的事情,也是為什么高手能做的更好的原因。

                  我總結了一下,覺得以下才是一個程序員應該思考的路:

                 1.第一類人:會寫程序,這沒什么,人人都能辦到。(70%的程序員都在這里)

                  2.第二類人:有一定的結構思想,能做設計結構上的調整。能走到這一步,應該可以算真正入門了。(15%的程序員在這里,很不幸,本人也在這里。)

                 3.第三類人:熟練應用各種設計模式,到了這里,才算涉足高級編程領域。這樣的人才能算高手。(10%左右,我想黑羽同志應該屬于這個級別)

                 4.第四類人:有算法分析和創意思維,能做到這一步的人,寫出來的程序就不叫程序了,叫偉大發明!(5%左右,微軟和谷歌的專家們在這里)

                 5.第五類人:這一類人是我不敢想象的,已經超出我的思考范疇了。(趨向0%)

            最后,歡迎大家百度HI我,和我探討相關的技術。
            或者加入百度HI群:flash知道(1群)1051316、 flash知道(2群)1084144

            posted @ 2010-02-24 14:27 暗夜教父 閱讀(604) | 評論 (1)編輯 收藏
            #include   <winsock2.h>   
            //#include   <windows.h>   
            #include   <stdio.h>   

            #define   PORT   5150   
            #define   DATA_BUFSIZE   8192   
                
            typedef   struct   
            {   
                    OVERLAPPED   Overlapped;   
                    WSABUF   DataBuf;   
                    CHAR   Buffer[DATA_BUFSIZE];   
                    DWORD   BytesSEND;   
                    DWORD   BytesRECV;   
            }   PER_IO_OPERATION_DATA,   *   LPPER_IO_OPERATION_DATA;   
                
                
            typedef   struct     
            {   
                    SOCKET   Socket;   
            }   PER_HANDLE_DATA,   *   LPPER_HANDLE_DATA;   
                
                
            DWORD   WINAPI   ServerWorkerThread(LPVOID   CompletionPortID);   
                
            int main(void)   
            {   
                    SOCKADDR_IN   InternetAddr;   
                    SOCKET   Listen;   
                    SOCKET   Accept;   
                    HANDLE   CompletionPort;   
                    SYSTEM_INFO   SystemInfo;   
                    LPPER_HANDLE_DATA   PerHandleData;   
                    LPPER_IO_OPERATION_DATA   PerIoData;   
                    int   i;   
                    DWORD   RecvBytes;   
                    DWORD   Flags;   
                    DWORD   ThreadID;   
                    WSADATA   wsaData;   
                    DWORD   Ret;   
                
                    if   ((Ret   =   WSAStartup(0x0202,   &wsaData))   !=   0)   
                    {   
                          printf("WSAStartup失敗了,錯誤信息如下:   %d\n",   Ret);   
                          return;   
                    }   
                
                    // 設置一個I/O完成端口.   
                
                    if   ((CompletionPort   =   CreateIoCompletionPort(INVALID_HANDLE_VALUE,   NULL,   0,   0))   ==   NULL)   
                    {   
                          printf(   "CreateIoCompletionPort 失敗了,錯誤信息如下:   %d\n",   GetLastError());   
                          return;   
                    }   
                
                    // 測試系統中有多少cpu處理器 
                
                    GetSystemInfo(&SystemInfo);   
                
                    //   基于系統可用的處理器創建工作線程,為每個處理器創建連個線程   
                
                    for(i   =   0;   i   <   SystemInfo.dwNumberOfProcessors   *   2;   i++)   
                    {   
                          HANDLE   ThreadHandle;   
                
                          // 創建一個服務端線程并且傳遞一個完成端口給這個線程.   
                
                          if   ((ThreadHandle   =   CreateThread(NULL,   0,   ServerWorkerThread,   CompletionPort,   
                                0,   &ThreadID))   ==   NULL)   
                          {   
                                printf("CreateThread()發生了如下錯誤: %d\n",   GetLastError());   
                                return;   
                          }   
                          else 
                          {printf("創建了一個完成端口.\n");
                          }
                          //   關閉 thread句柄 
                          CloseHandle(ThreadHandle);   
                    }   
                
                    //   創建一個監聽套接字 
                
                    if   ((Listen   =WSASocket(AF_INET,   SOCK_STREAM,   0,   NULL,0,WSA_FLAG_OVERLAPPED))   ==   INVALID_SOCKET)   
                    {   
                          printf("WSASocket() 發生了如下錯誤: %d\n",   WSAGetLastError());   
                          return;   
                    }
                    else     
                    {printf("創建監聽套接字成功\n");}
                    InternetAddr.sin_family   =   AF_INET;   
                    InternetAddr.sin_addr.s_addr   =   htonl(INADDR_ANY);   
                    InternetAddr.sin_port   =   htons(PORT);   
                
                    if   (bind(Listen,   (PSOCKADDR)   &InternetAddr,   sizeof(InternetAddr))   ==   SOCKET_ERROR)   
                    {   
                          printf("bind()端口或IP時發生了如下錯誤: %d\n",   WSAGetLastError());   
                          return;   
                    }   
                    else
                    {printf("綁定端口%d成功\n",PORT);} 
                    // 準備socket 用來監聽   
                
                    if   (listen(Listen,   5)   ==   SOCKET_ERROR)   
                    {   
                          printf("listen() 發生了如下錯誤   %d\n",   WSAGetLastError());   
                          return;   
                    }   
                     else
                    {printf("預處理成功,開始在端口 %d 處監聽...\n",PORT);} 
                    //接受連接并且交給完成端口處理 
                
                    while(TRUE)   
                    {   
                          if   ((Accept   =   WSAAccept(Listen,   NULL,   NULL,   NULL,   0))   ==   SOCKET_ERROR)   
                          {   
                                printf("WSAAccept()   發生了如下錯誤:   %d\n",   WSAGetLastError());   
                                return;   
                          }   
                
                          // 創建一個套接字信息結構體去聯系起來socket   
                          if   ((PerHandleData   =   (LPPER_HANDLE_DATA)   GlobalAlloc(GPTR,     
                                sizeof(PER_HANDLE_DATA)))   ==   NULL)   
                          {   
                                printf("GlobalAlloc()   發生了如下錯誤:   %d\n",   GetLastError());   
                                return;   
                          }   
                
                          // 將接受到的套接字與原始的完成端口聯系起來.   
                
                          printf("號碼為   %d   的socket連接上了\n",   Accept);   
                          PerHandleData->Socket   =   Accept;   
                
                          if   (CreateIoCompletionPort((HANDLE)   Accept,   CompletionPort,   (DWORD)   PerHandleData,   
                                0)   ==   NULL)   
                          {   
                                printf("CreateIoCompletionPort   發生了如下錯誤:   %d\n",   GetLastError());   
                                return;   
                          }   
                
                          //   創建每一個I/O 套接字信息結構體去和下面被調用的 to   associate   with   the     
                          //   WSARecv 連接.   
                
                          if   ((PerIoData   =   (LPPER_IO_OPERATION_DATA)   GlobalAlloc(GPTR,                     sizeof(PER_IO_OPERATION_DATA)))   ==   NULL)   
                          {   
                                printf("GlobalAlloc() 發生了如下錯誤: %d\n",   GetLastError());   
                                return;   
                          }   
                          else{printf("接收了一個連接\n");} 
                          ZeroMemory(&(PerIoData->Overlapped),   sizeof(OVERLAPPED));   
                          PerIoData->BytesSEND   =   0;   
                          PerIoData->BytesRECV   =   0;   
                          PerIoData->DataBuf.len   =   DATA_BUFSIZE;   
                          PerIoData->DataBuf.buf   =   PerIoData->Buffer;   
                
                          Flags   =   0;   
                          if   (WSARecv(Accept,   &(PerIoData->DataBuf),   1,   &RecvBytes,   &Flags,   
                                &(PerIoData->Overlapped),   NULL)   ==   SOCKET_ERROR)   
                          {   
                                if   (WSAGetLastError()   !=   ERROR_IO_PENDING)   
                                {   
                                      printf("WSARecv() 發生了如下錯誤: %d\n",   WSAGetLastError());   
                                      return;   
                                }   
                          }   
                    }   
            }   
                
            DWORD   WINAPI   ServerWorkerThread(LPVOID   CompletionPortID)   
            {   
                    HANDLE   CompletionPort   =   (HANDLE)   CompletionPortID;   
                    DWORD   BytesTransferred;   
                    LPOVERLAPPED   Overlapped;   
                    LPPER_HANDLE_DATA   PerHandleData;   
                    LPPER_IO_OPERATION_DATA   PerIoData;   
                    DWORD   SendBytes,   RecvBytes;   
                    DWORD   Flags;   
                      
                    while(TRUE)   
                    {   
                
                          if   (GetQueuedCompletionStatus(CompletionPort,   &BytesTransferred,   
                                (LPDWORD)&PerHandleData,   (LPOVERLAPPED   *)   &PerIoData,   INFINITE)   ==   0)   
                          {   
                                printf("GetQueuedCompletionStatus   發生了如下錯誤: %d\n",   GetLastError());   
                                return   0;   
                          }   
                
                          //首先檢查一下去套接字看是否在上發生了錯誤并且如果發生了錯誤就關閉套接
                          //字并且清除與套接字連接的 SOCKET_INFORMATION結構信息體 
                          if   (BytesTransferred   ==   0)   
                          {   
                                printf("正在關閉socket   %d\n",   PerHandleData->Socket);   
                
                                if   (closesocket(PerHandleData->Socket)   ==   SOCKET_ERROR)   
                                {   
                                      printf("closesocket()   發生了如下錯誤: %d\n",   WSAGetLastError());   
                                      return   0;   
                                }   
                
                                GlobalFree(PerHandleData);   
                                GlobalFree(PerIoData);   
                                continue;   
                          }   
                //檢查如果 BytesRECV字段等于0,這就意味著一個 WSARecv調用剛剛完成了所以從完成的WSARecv()調用中
                //用BytesTransferred值更新 BytesRECV字段 
                          if   (PerIoData->BytesRECV   ==   0)   
                          {   
                                PerIoData->BytesRECV   =   BytesTransferred;   
                                PerIoData->BytesSEND   =   0;   
                          }   
                          else   
                          {   
                                PerIoData->BytesSEND   +=   BytesTransferred;   
                          }   
                
                          if   (PerIoData->BytesRECV   >   PerIoData->BytesSEND)   
                          {   
                //發布另外一個 WSASend()請求
                //既然WSASend()不是 gauranteed去發送所有字節的請求
                //繼續調用 WSASend()發送直到所有收到的字節被發送 
                                
                                ZeroMemory(&(PerIoData->Overlapped),   sizeof(OVERLAPPED));   
                
                                PerIoData->DataBuf.buf   =   PerIoData->Buffer   +   PerIoData->BytesSEND;   
                                PerIoData->DataBuf.len   =   PerIoData->BytesRECV   -   PerIoData->BytesSEND;   
                
                                if   (WSASend(PerHandleData->Socket,   &(PerIoData->DataBuf),   1,   &SendBytes,   0,   
                                      &(PerIoData->Overlapped),   NULL)   ==   SOCKET_ERROR)   
                                {   
                                      if   (WSAGetLastError()   !=   ERROR_IO_PENDING)   
                                      {   
                                            printf("WSASend() 發生了如下錯誤:   %d\n",   WSAGetLastError());   
                                            return   0;   
                                      }   
                                }   
                          }   
                          else   
                          {   
                                PerIoData->BytesRECV   =   0;   
                //現在沒有更多的字節發送過去用來post另外一個WSARecv()請求 
                                
                                Flags   =   0;   
                                ZeroMemory(&(PerIoData->Overlapped),   sizeof(OVERLAPPED));   
                
                                PerIoData->DataBuf.len   =   DATA_BUFSIZE;   
                                PerIoData->DataBuf.buf   =   PerIoData->Buffer;   
                
                                if   (WSARecv(PerHandleData->Socket,   &(PerIoData->DataBuf),   1,   &RecvBytes,   &Flags,   
                                      &(PerIoData->Overlapped),   NULL)   ==   SOCKET_ERROR)   
                                {   
                                      if   (WSAGetLastError()   !=   ERROR_IO_PENDING)   
                                      {   
                                            printf("WSARecv() 發生了如下錯誤:   %d\n",   WSAGetLastError());   
                                            return   0;   
                                      }   
                                }   
                          }   
                    }   
            }  
            posted @ 2010-02-24 13:34 暗夜教父 閱讀(925) | 評論 (0)編輯 收藏
            僅列出標題
            共9頁: 1 2 3 4 5 6 7 8 9 

            <2009年9月>
            303112345
            6789101112
            13141516171819
            20212223242526
            27282930123
            45678910

            常用鏈接

            留言簿(2)

            隨筆分類

            隨筆檔案

            文章分類

            文章檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            久久99精品久久久久久齐齐| 久久久精品国产亚洲成人满18免费网站| 精品久久久久久久久中文字幕| 久久久久se色偷偷亚洲精品av | 一本色道久久88精品综合| 国产成人精品久久综合| 成人久久综合网| 国产精品青草久久久久婷婷| 久久久久久久亚洲Av无码| 亚洲精品国产美女久久久| 国产成人精品综合久久久久| 少妇熟女久久综合网色欲| 一本大道久久香蕉成人网| 亚洲精品高清一二区久久| 久久无码国产| 久久亚洲熟女cc98cm| 久久久www免费人成精品| 久久精品亚洲AV久久久无码| 2019久久久高清456| 久久亚洲精品中文字幕| 日本强好片久久久久久AAA| 99久久免费国产精品热| 亚洲一区中文字幕久久| 久久人人爽人人爽AV片| 蜜桃麻豆WWW久久囤产精品| 蜜臀久久99精品久久久久久小说| 久久婷婷五月综合国产尤物app| 97久久超碰成人精品网站| 国产69精品久久久久9999| 久久精品国产一区二区| 精品久久久久久国产| 成人久久综合网| 亚洲国产成人久久综合碰| 亚洲精品无码久久千人斩| 久久久久久综合一区中文字幕| 日本精品久久久久影院日本| 欧美精品久久久久久久自慰| 99久久国产综合精品网成人影院 | 一本色道久久综合亚洲精品| www性久久久com| 日韩久久久久中文字幕人妻|