返錢源碼
1. 朋友們,大家好!我是一個java語言的初學者.
學習一門新的知識,不可能指望只看一本,或者兩本書就能夠完全掌握。需要有一個循序漸進的閱讀過程。我推薦Oreilly出版的Java系列書籍。
在這里我只想補充一點看法,很多人學習Java是從《Thinking in Java》這本書入手的,但是我認為這本書是不適合初學者的。我認為正確的使用這本書的方法應該是作為輔助的讀物。《Thinking in Java》並不是在完整的介紹Java的整個體系,而是一種跳躍式的寫作方法,是一種類似tips的方法來對Java很多知識點進行了深入的分析和解釋。
對於初學者來說,最好是找一本Java入門的書籍,但是比較完整的循序的介紹Java的語法,面向對象的特性,核心類庫等等,在看這本書的同時,可以同步來看《Thinking in Java》,來加深對Java的理解和原理的運用,同時又可以完整的了解Java的整個體系。
對於Java的入門書籍,蔡學鏞推薦的是Oreilly的《Exploring Java, 2nd Edition》 或者《Java in a Nutshell,2nd Edition(針對C++背景)》,我並沒有看過這兩本書。其實我覺得電子工業出版社的《Java 2編程詳解》或者《Java 2從入門到精通》就很不錯。
在所有的Java書籍當中,其實最最有用的,並不是O'reilly的 Java Serials,真正最最有用處是JDK的Documentation!幾乎你想獲得的所有的知識在Documentation裡面全部都有,其中最主要的部分當然是Java基礎類庫的API文檔,是按照package來組織的,對於每一個class都有詳細的解釋,它的繼承關系,是否實現了某個介面,通常用在哪些場合,還可以查到它所有的public的屬性和方法,每個屬性的解釋,意義,每個方法的用途,調用的參數,參數的意義,返回值的類型,以及方法可能拋出的異常等等。可以這樣來說,所有關於Java編程方面的書籍其實都不過是在用比較通俗易懂的語言,和良好的組織方式來介紹 Documentation裡面的某個package裡麵包含的一些類的用法而已。所以萬變不離其宗,如果你有足夠的能力來直接通過 Documentation來學習Java的類庫,那麼基本上就不需要看其他的書籍了。除此之外,Documentation也是編程必備的手冊,我的桌面上有三個Documentation的快捷方式,分別是J2SDK1.4.1的Documentation,Servlet2.3的 Documentation和J2SDKEE1.3.1的Documentation。有了這個三個Documentation,什麼其他的書籍都不需要了。
對於Java Web 編程來說,最核心的是要熟悉和掌握HTTP協議,這個就和Java無關了,在熟悉HTTP協議之後,就需要熟悉Java的實現HTTP協議的類庫,也就是 Servlet API,所以最重要的東西就是Servlet API。當然對於初學者而言,直接通過Servlet API來學習Web編程有很大的難度,我推薦O'reilly的《Java Server Pages 》這本書來學習Web 編程。
EJB的書籍當中,《Enterprise JavaBeans, 2nd Edition》是一本很不錯的書, EJB的學習門檻是比較高,入門很難,但是這本書完全降低了學習的難度,特別重要的一點是,EJB的學習需要結合一種App Server的具體實現,所以在學習EJB的同時,必須同步的學習某種App Server,而這本書相關的出了三本書,分別是Weblogic6.1,Websphere4.0和JBoss3.0上面部署書中例子的實做。真是既有理論,又有實踐。在學習EJB的同時,可以邊看邊做,EJB的學習會變得很輕松。
但是這本書也有一個問題,就是版本比較舊,主要講EJB1.1規范和部分EJB2.0的規范。而Ed Roman寫的《Mastering EJB 2.0》這本書完全是根據EJB2.0規范寫的,深入淺出,覆蓋了EJB編程的各個方面,並且還有很多編程經驗tips,也是學習EJB非常推薦的書籍之一。
如果是結合Weblogic來學習J2EE的話,《J2EE應用與BEA Weblogic Server》絕對是首選讀物,雖然是講述的Weblogic6.0,仍然值得購買,這本書是BEA官方推薦的教材,作者也是BEA公司的工程師。現在中文版已經隨處可見了。這本書結合Weblogic介紹了J2EE各個方面的技術在Weblogic平台上的開發和部署,實踐指導意義非常強。
在掌握了Java平台基礎知識和J2EE方面的知識以後,更進一步的是學習如何運用OO的方法進行軟體的設計,那麼就一定要學習「設計模式」。 Sun公司出版了一本《J2EE核心模式》,是每個開發Java企業平台軟體的架構師必備的書籍。這本書全面的介紹了J2EE體系架構的各種設計模式,是設計師的必讀書籍。
Java Learning Path(三)過程篇
每個人的學習方法是不同的,一個人的方法不見得適合另一個人,我只能是談自己的學習方法。因為我學習Java是完全自學的,從來沒有問過別人,所以學習的過程基本上完全是自己摸索出來的。我也不知道這種方法是否是比較好的方法,只能給大家提供一點參考了。
學習Java的第一步是安裝好JDK,寫一個Hello World,? 其實JDK的學習沒有那麼簡單,關於JDK有兩個問題是很容易一直困擾Java程序員的地方:一個是CLASSPATH的問題,其實從原理上來說,是要搞清楚JRE的ClassLoader是如何載入Class的;另一個問題是package和import問題,如何來尋找類的路徑問題。把這兩個問題摸索清楚了,就掃除了學習Java和使用JDK的最大障礙。推薦看一下王森的《Java深度歷險》,對這兩個問題進行了深入的探討。
第二步是學習Java的語法。Java的語法是類C++的,基本上主流的編程語言不是類C,就是類C++的,沒有什麼新東西,所以語法的學習,大概就是半天的時間足夠了。唯一需要注意的是有幾個不容易搞清楚的關鍵字的用法,public,protected,private,static,什麼時候用,為什麼要用,怎麼用,這可能需要有人來指點一下,我當初是完全自己琢磨出來的,花了很久的時間。不過後來我看到《Thinking in Java》這本書上面是講了這些概念的。
第三步是學習Java的面向對象的編程語言的特性的地方。比如繼承,構造器,抽象類,介面,方法的多態,重載,覆蓋,Java的異常處理機制。對於一個沒有面向對象語言背景的人來說,我覺得這個過程需要花很長很長時間,因為學習Java之前沒有C++的經驗,只有C的經驗,我是大概花了一個月左右吧,才徹底把這些概念都搞清楚,把書上面的例子反復的揣摩,修改,嘗試,把那幾章內容反復的看過來,看過去,看了不下5遍,才徹底領悟了。不過我想如果有 C++經驗的話,應該一兩天時間足夠了。那麼在這個過程中,可以多看看《Thinking in Java》這本書,對面向對象的講解非常透徹。可惜的是我學習的時候,並沒有看到這本書,所以自己花了大量的時間,通過自己的嘗試和揣摩來學會的。
第四步就是開始熟悉Java的類庫。Java的基礎類庫其實就是JDK安裝目錄下面jre\lib\rt.jar這個包。學習基礎類庫就是學習rt.jar。基礎類庫裡面的類非常非常多。據說有3000多個,我沒有統計過。但是真正對於我們來說最核心的只有4個,分別是
java.lang.*;
java.io.*;
java.util.*;
java.sql.*;
這四個包的學習,每個包的學習都可以寫成一本厚厚的教材,而O'reilly也確實是這樣做的。我覺得如果時間比較緊,是不可能通過讀四本書來學習。我覺得比較好的學習方法是這樣的:
首先要通讀整個package的框架,了解整個package的class,interface,exception的構成,最好是能夠找到介紹整個包框架的文章。這些專門介紹包的書籍的前幾章應該就是這些總體的框架內容介紹。
對包整體框架的把握並不是要熟悉每個類的用法,記住它有哪些屬性,方法。想記也記不住的。而是要知道包有哪些方面的類構成的,這些類的用途是什麼,最核心的幾個類分別是完成什麼功能的。我在給人培訓的時候一般是一次課講一個包,所以不可能詳細的介紹每個類的用法,但是我反復強調,我給你們講這些包的不是要告訴你們類的方法是怎麼調用的,也不要求你們記住類的方法調用,而是要你們了解,Java給我們提供了哪些類,每個類是用在什麼場合,當我遇到問題的時候,我知道哪個類,或者哪幾個類的組合可以解決我的問題,That'all!,當我們具體寫程序的時候,只要你知道該用哪個類來完成你的工作就足夠了。編碼的時候,具體的方法調用,是邊寫代碼,邊查Documentation,所有的東西都在Documentation裡面,不要求你一定記住,實際你也記不住3000多個類的總共將近10萬個方法調用。所以對每個包的總體框架的把握就變得極為重要。
第五步,通過上面的學習,如果學的比較扎實的話,就打好了Java的基礎了,剩下要做的工作是掃清Documentation裡面除了上面4個包之外的其他一些比較有用處的類。相信進展到這一步,Java的自學能力已經被培養出來了,可以到了直接學習Documentation的水平了。除了要做 GUI編程之外,JDK裡面其他會有用處的包是這些:
java.text.*;
java.net.*;
javax.naming.*;
這些包裡面真正用的比較多的類其實很少,只有幾個,所以不需要花很多時間。
第六步,Java Web 編程
Web編程的核心是HTTP協議,HTTP協議和Java無關,如果不熟悉HTTP協議的話,雖然也可以學好Servlet/JSP編程,但是達不到舉一反三,一通百通的境界。所以HTTP協議的學習是必備的。如果熟悉了HTTP協議的話,又有了Java編程的良好的基礎,學習 Servlet/JSP簡直易如反掌,我學習Servlet/JSP就用了不到一周的時間,然後就開始用JSP來做項目了。
在Servlet/JSP的學習中,重頭仍然是Servlet Documentation。Servlet API最常用的類很少,花比較少的時間就可以掌握了。把這些類都看一遍,多寫幾個例子試試。Servlet/JSP編程本質就是在反復調用這些類來通過 HTTP協議在Web Server和Brower之間交談。另外對JSP,還需要熟悉幾個常用JSP的標記,具體的寫法記不住的話,臨時查就是了。
此外Java Web編程學習的重點要放在Web Application的設計模式上,如何進行業務邏輯的分析,並且進行合理的設計,按照MVC設計模式的要求,運用Servlet和JSP分別完成不同的邏輯層,掌握如何在Servlet和JSP之間進行流程的控制和數據的共享,以及Web Application應該如何配置和部署。
第七步,J2EE編程
以上的學習過程如果是比較順利的話,進行到這一步,難度又陡然提高。因為上面的知識內容都是只涉及一個方面,而像EJB,JMS,JTA等核心的J2EE規范往往是幾種Java技術的綜合運用的結晶,所以掌握起來難度比較大。
首先一定要學習好JNDI,JNDI是App Server定位伺服器資源(EJB組件,Datasouce,JMS)查找方法,如果對JNDI不熟悉的話,EJB,JMS這些東西幾乎學不下去。 JNDI其實就是javax.naming.*這個包,運用起來很簡單。難點在於伺服器資源文件的配置。對於伺服器資源文件的配置,就需要看看專門的文檔規范了,比如web.xml的寫法,ejb-jar.xml的寫法等等。針對每種不同的App Server,還有自己的服務資源配置文件,也是需要熟悉的。
然後可以學習JTA,主要是要理解JTA對於事務的控制的方法,以及該在什麼場合使用JTA。這里可以簡單的舉個例子,我們知道一般情況可以對於一個資料庫連接進行事務控制(conn.setAutoCommit(false),....,conn.commit()),做為一個原子操作,但是假設我的業務需求是要把對兩個不同資料庫的操作做為一個原子操作,你能做的到嗎?這時候只能用JTA了。假設操作過程是先往A資料庫插一條記錄,然後刪除B 資料庫另一個記錄,我們自己寫代碼是控制不了把整個操作做為一個原子操作的。用JTA的話,由App Server來完成控制。
在學習EJB之前要學習對象序列化和RMI,RMI是EJB的基礎。接著學習JMS和EJB,對於EJB來說,最關鍵是要理解EJB是如何通過RMI來實現對遠端對象的調用的,以及在什麼情況下要用到EJB。
在學習完EJB,JMS這些東西之後,你可能會意識到要急不可待學習兩個領域的知識,一個是UML,另一個是Design Pattern。Java企業軟體的設計非常重視框架(Framework)的設計,一個好的軟體框架是軟體開發成功的必要條件。在這個時候,應該開始把學習的重點放在設計模式和框架的學習上,通過學習和實際的編程經驗來掌握EJB的設計模式和J2EE的核心模式。
J2EE規范裡面,除了EJB,JMS,JTA,Servlet/JSP,JDBC之外還有很多很多的企業技術,這里不一一進行介紹了。
另外還有一個最新領域Web Services。Web Services也完全沒有任何新東西,它像是一種黏合劑,可以把不同的服務統一起來提供一個統一的調用介面,作為使用者來說,我只要獲得服務提供者給我的WSDL(對服務的描述),就夠了,我完全不知道伺服器提供者提供的服務究竟是EJB組件,還是.Net組件,還是什麼CORBA組件,還是其他的什麼實現,我也不需要知道。Web Services最偉大的地方就在於通過統一的服務提供方式和調用方式,實現了整個Internet服務的共享,是一個非常令人激動的技術領域。Web Services好像目前還沒有什麼很好的書籍,但是可以通過在網路上面查資料的方式來學習。
Java Learning Path(四) 方法篇
Java作為一門編程語言,最好的學習方法就是寫代碼。當你學習一個類以後,你就可以自己寫個簡單的例子程序來運行一下,看看有什麼結果,然後再多調用幾個類的方法,看看運行結果,這樣非常直觀的把類給學會了,而且記憶非常深刻。然後不應該滿足把代碼調通,你應該想想看如果我不這樣寫,換個方式,再試試行不行。記得哪個高人說過學習編程就是個破壞的過程,把書上的例子,自己學習Documentation編寫的例子在運行通過以後,不斷的嘗試著用不同的方法實現,不斷的嘗試破壞代碼的結構,看看它會有什麼結果。通過這樣的方式,你會很徹底的很精通的掌握Java。
舉個例子,我們都編過Hello World
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
很多初學者不是很理解為什麼main方法一定要這樣來定義public static void main(String[] args),能不能不這樣寫?包括我剛學習Java的時候也有這樣的疑問。想知道答案嗎?很簡單,你把main改個名字運行一下,看看報什麼錯誤,然後根據出錯信息進行分析;把main的public取掉,在試試看,報什麼錯誤;static去掉還能不能運行;不知道main方法是否一定要傳一個 String[]數組的,把String[]改掉,改成int[],或者String試試看;不知道是否必須寫args參數名稱的,也可以把args改成別的名字,看看運行結果如何。
我當初學習Java的時候就是這樣做的,把Hello World程序反復改了七八次,不斷運行,分析運行結果,最後就徹底明白為什麼了main方法是這樣定義的了。
此外,我對於staic,public,private,Exception,try{ }catch {}finally{}等等等等一開始都不是很懂,都是把參考書上面的例子運行成功,然後就開始破壞它,不斷的根據自己心裏面的疑問來重新改寫程序,看看能不能運行,運行出來是個什麼樣子,是否可以得到預期的結果。這樣雖然比較費時間,不過一個例子程序這樣反復破壞幾次之後。我就對這個相關的知識徹底學通了。有時候甚至故意寫一些錯誤的代碼來運行,看看能否得到預期的運行錯誤。這樣對於編程的掌握是及其深刻的。
其中特別值得一提的是JDK有一個非常棒的調試功能,-verbose
java –verbose
javac –verbose 以及其它很多JDK工具都有這個選項
-verbose 可以顯示在命令執行的過程中,JVM都依次載入哪裡Class,通過這些寶貴的調試信息,可以幫助我們分析出JVM在執行的過程中都幹了些什麼。
另外,自己在學習過程中,寫的很多的這種破壞常式,應該有意識的分門別類的保存下來,在工作中積累的典型常式也應該定期整理,日積月累,自己就有了一個代碼庫了。遇到類似的問題,到代碼庫裡面 Copy & Paste ,Search & Replace,就好了,極大提高了開發速度。最理想的情況是把一些通用的常式自己再抽象一層,形成一個通用的類庫,封裝好。那麼可復用性就更強了。
所以我覺得其實不是特別需要常式的,自己寫的破壞常式就是最好的例子,如果你實在對自己寫的代碼不放心的話,我強烈推薦你看看JDK基礎類庫的 Java源代碼。在JDK安裝目錄下面會有一個src.zip,解開來就可以完整的看到整個JDK基礎類庫,也就是rt.jar的Java源代碼,你可以參考一下Sun是怎麼寫Java程序的,規范是什麼樣子的。我自己在學習Java的類庫的時候,當有些地方理解的不是很清楚的時候,或者想更加清晰的理解運作的細節的時候,往往會打開相應的類的源代碼,通過看源代碼,所有的問題都會一掃而空。
Java Learning Path(五)資源篇
1、 http://java.sun.com/ (英文)
Sun的Java網站,是一個應該經常去看的地方。不用多說。
2、http://www-900.ibm.com/developerWorks/cn/
IBM的developerWorks網站,英語好的直接去英文主站點看。這里不但是一個極好的面向對象的分析設計網站,也是Web Services,Java,linux極好的網站。強烈推薦!!!
3、http://www.javaworld.com/ (英文)
關於Java很多新技術的討論和新聞。想多了解Java的方方面面的應用,這里比較好。
4、http://dev2dev.bea.com.cn/index.jsp
BEA的開發者園地,BEA作為最重要的App Server廠商,有很多獨到的技術,在Weblogic上做開發的朋友不容錯過。
5、http://www.huihoo.com/
灰狐動力網站,一個專業的中間件網站,雖然不是專業的Java網站,但是在J2EE企業應用技術方面有深厚的造詣。
6、http://www.theserverside.com/home/ (英文)
TheServerSide是一個著名的專門面向Java Server端應用的網站。
7、http://www.javaresearch.org/
Java研究組織,有很多優秀的Java方面的文章和教程,特別是在JDO方面的文章比較豐富。
8、http://www.cnjsp.org/
JSP技術網站,有相當多的Java方面的文章和資源。
9、http://www.jdon.com/
Jdon論壇,是一個個人性質的中文J2EE專業技術論壇,在眾多的Java的中文論壇中,Jdon一個是技術含量非常高,帖子質量非常好的論壇。
10、http://sourceforge.net/
SourgeForge是一個開放源代碼軟體的大本營,其中也有非常非常豐富的Java的開放源代碼的著名的軟體。
參考資料:還有JAVA中文網站http://www.java-cn.com/book/index.html
=================================================================
=================================================================
-----------------------------------------------------------------
程序員是一種技術工作,在IT的發展中有相當重要的地位,從底層硬體通訊協議的建立, 到數據傳輸層的處理,到操作系統的建設,到資料庫平台的建設,一直到應用層上各種數 據營銷平台的搭建,程序員在裡面都扮演著舉足輕重的角色並為IT事業的發展做出了巨大 的貢獻。
中國有很多精於編碼的人,但是中國軟體行業,尤其是網路應用開發方面誤區很大,很難形成有規模的軟體開發力量和產品能力,不但比美國差距甚遠,和印度相比也是頗有不如。這些問題不是在於中國程序員的智商和工作努力狀況,也不是在於國家和民間對開發的投入程度,而是很大程度上,有一些對技術,對程序開發,對項目設計方面的思想誤區,這些誤區,導致了軟體行業的產品化能力不足,缺乏規模化和大型復用系統研發能力,可以說,改變認識誤區,是解決軟體行業小作坊模式和個體英雄模式所帶來的局限性 的重要工作。
中國有很多小朋友,他們18,9歲或21,2歲,通過自學也寫了不少代碼,他們有的代碼寫的很漂亮,一些技術細節相當出眾,也很有鑽研精神,但是他們被一些錯誤的認識和觀點左右,缺乏對系統,對程序的整體理解能力,這些人,一個網上的朋友說得很好,他們實際 上只是一些Coding fans,壓根沒有資格稱為程序員,但是據我所知,不少小網路公司的 CTO就是這樣的coding fans,拿著嚇人的工資,做著嚇人的項目,項目的結局通常也很嚇 人。
程序員基本素質:
作一個真正合格的程序員,或者說就是可以真正合格完成一些代碼工作的程序員,應該具 有的素質。
1:團隊精神和協作能力
把它作為基本素質,並不是不重要,恰恰相反,這是程序員應該具備的最基本的,也是最重要的安身立命之本。把高水平程序員說成獨行俠的都是在囈語,任何個人的力量都是有限的,即便如linus這樣的天才,也需要通過組成強大的團隊來創造奇跡,那些遍布全球的為linux寫核心的高手們,沒有協作精神是不可想像的。獨行俠可以作一些賺錢的小軟體發點小財,但是一旦進入一些大系統的研發團隊,進入商業化和產品化的開發任務,缺乏這種素質的人就完全不合格了。
2:文檔習慣
說高水平程序員從來不寫文檔的肯定是乳臭未乾的毛孩子,良好的文檔是正規研發流程中 非常重要的環節,作為代碼程序員,30%的工作時間寫技術文檔是很正常的,而作為高級 程序員和系統分析員,這個比例還要高很多。
缺乏文檔,一個軟體系統就缺乏生命力,在未來的查錯,升級以及模塊的復用時就都會遇 到極大的麻煩。
3:規范化,標准化的代碼編寫習慣
作為一些外國知名軟體公司的規矩,代碼的變數命名,代碼內注釋格式,甚至嵌套中行縮 進的長度和函數間的空行數字都有明確規定,良好的編寫習慣,不但有助於代碼的移植和 糾錯,也有助於不同技術人員之間的協作。
有些coding fans叫囂高水平程序員寫的代碼旁人從來看不懂,這種叫囂只能證明他們自 己壓根不配自稱程序員。代碼具有良好的可讀性,是程序員基本的素質需求。
再看看整個linux的搭建,沒有規范化和標准化的代碼習慣,全球的研發協作是絕對不可 想像的。
4:需求理解能力
程序員需要理解一個模塊的需求,很多小朋友寫程序往往只關注一個功能需求,他們把性能指標全部歸結到硬體,操作系統和開發環境上,而忽視了本身代碼的性能考慮,有人曾經放言說寫一個廣告交換程序很簡單,這種人從來不知道在百萬甚至千萬數量級的訪問情況下的性能指標是如何實現的,對於這樣的程序員,你給他深藍那套系統,他也做不出太極鏈的並訪能力。性能需求指標中,穩定性,並訪支撐能力以及安全性都很重要,作為程序員需要評估該模塊在系統運營中所處的環境,將要受到的負荷壓力以及各種潛在的危險和惡意攻擊的可能性。就這一點,一個成熟的程序員至少需要2到3年的項目研發和跟蹤經驗才有可能有心得。
5:復用性,模塊化思維能力
經常可以聽到一些程序員有這樣的抱怨,寫了幾年程序,變成了熟練工,每天都是重復寫 一些沒有任何新意的代碼,這其實是中國軟體人才最大浪費的地方,一些重復性工作變成 了熟練程序員的主要工作,而這些,其實是完全可以避免的。
復用性設計,模塊化思維就是要程序員在完成任何一個功能模塊或函數的時候,要多想一些,不要局限在完成當前任務的簡單思路上,想想看該模塊是否可以脫離這個系統存在,是否可以通過簡單的修改參數的方式在其他系統和應用環境下直接引用,這樣就能極大避免重復性的開發工作,如果一個軟體研發單位和工作組能夠在每一次研發過程中都考慮到這些問題,那麼程序員就不會在重復性的工作中耽誤太多時間,就會有更多時間和精力投 入到創新的代碼工作中去。
一些好的程序模塊代碼,即便是70年代寫成的,拿到現在放到一些系統裡面作為功能模塊 都能適合的很好,而現在我看到的是,很多小公司軟體一升級或改進就動輒全部代碼重 寫,大部分重復性工作無謂的浪費了時間和精力。
程序員應具備的素質中
6:測試習慣
作為一些商業化正規化的開發而言,專職的測試工程師是不可少的,但是並不是說有了專職的測試工程師程序員就可以不進行自測;軟體研發作為一項工程而言,一個很重要的特點就是問題發現的越早,解決的代價就越低,程序員在每段代碼,每個子模塊完成後進行認真的測試,就可以盡量將一些潛在的問題最早的發現和解決,這樣對整體系統建設的效 率和可靠性就有了最大的保證。
測試工作實際上需要考慮兩方面,一方面是正常調用的測試,也就是看程序是否能在正常調用下完成基本功能,這是最基本的測試職責,可惜在很多公司這成了唯一的測試任務,實際上還差的遠那;第二方面就是異常調用的測試,比如高壓力負荷下的穩定性測試,用戶潛在的異常輸入情況下的測試,整體系統局部故障情況下該模塊受影響狀況的測試,頻發的異常請求阻塞資源時的模塊穩定測試等等。當然並不是程序員要對自己的每段代碼都需要進行這種完整測試,但是程序員必須清醒認識自己的代碼任務在整體項目中的地位和各種性能需求,有針對性的進行相關測試並盡早發現和解決問題,當然這需要上面提到的 需求理解能力。
7:學習和總結的能力
程序員是人才很容易被淘汰,很容易落伍的職業,因為一種技術可能僅僅在三兩年內具有 領先性,程序員如果想安身立命,就必須不斷跟進新的技術,學習新的技能。
善於學習,對於任何職業而言,都是前進所必需的動力,對於程序員,這種要求就更加高 了。
但是學習也要找對目標,一些小coding fans們,他們也津津樂道於他們的學習能力,一會學會了asp,一會兒學會了php,一會兒學會了jsp,他們把這個作為炫耀的資本,盲目的追逐一些膚淺的,表面的東西和名詞,做網路程序不懂通訊傳輸協議,做應用程序不懂中斷向量處理,這樣的技術人員,不管掌握了多少所謂的新語言,永遠不會有質的提高。
善於總結,也是學習能力的一種體現,每次完成一個研發任務,完成一段代碼,都應當有 目的的跟蹤該程序的應用狀況和用
2. 阿里sentinel源碼解析
sentinel是阿里巴巴開源的流量整形(限流、熔斷)框架,目前在github擁有15k+的star,sentinel以流量為切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。
我們以sentinel的主流程入手,分析sentinel是怎麼搜集流量指標,完成流量整形的。
首先我們先看一個sentinel的簡單使用demo,只需要調用SphU.entry獲取到entry,然後在完成業務方法之後調用entry.exit即可。
SphU.entry會調用Env.sph.entry,將name和流量流向封裝成StringResourceWrapper,然後繼續調用entry處理。
進入CtSph的entry方法,最終來到entryWithPriority,調用InternalContextUtil.internalEnter初始化ThreadLocal的物鋒Context,然後調用lookProcessChain初始化責任鏈,最終調用chain.entry進入責任鏈進行處理。
InternalContextUtil.internalEnter會調用trueEnter方法,主要是生成DefaultNode到contextNameNodeMap,然後生成Context設置到contextHolder的過程。
lookProcessChain已經做過優化,支持spi載入自定義的責任鏈bulider,如果沒有定義則使用默認的DefaultSlotChainBuilder進行載入。默認載入的slot和順序可見鎮樓圖,不再細說。
最後來到重頭戲chain.entry進入責任鏈進行處理,下面會按照順序分別對每個處理器進行分析。
首先來到NodeSelectorSlot,主要是獲取到name對應的DefaultNode並緩存起來,設置為context的當前節點,然後通知下一個節點。
下一個節點是ClusterBuilderSlot,繼續對DefaultNode設置ClusterNode與OriginNode,然頌咐後通知下一節點。
下一個節點是LogSlot,只是單純的列印日誌,不再細說。
下一個節點是StatisticSlot,是一個後置節點,先通知下一個節點處理完後,
1.如果沒有報錯,則對node、clusterNode、originNode、ENTRY_NODE的線程數、通過請求數進行增加。
2.如果報錯是PriorityWaitException,則只對線程數進行增加。
3.如果報錯是BlockException,設置報錯到node,然後對阻擋請求數進行增加。
4.如果是其他報錯,設置報錯到node即可。
下一個節點是FlowSlot,這個節點就是重要的限流處理節點,進入此節點是調用checker.checkFlow進行限流處理。
來到FlowRuleChecker的checkFlow方法,調用ruleProvider.apply獲取到資源對應的FlowRule列表,然後遍歷FlowRule調用canPassCheck校驗限流規則。
canPassCheck會根據rule的限流模式,選擇集群限流或者本地限流,這里分別作出分析。
passLocalCheck是本地限流的入口,首先會調用選出限流的node,然後調用canPass進行校驗。罩櫻晌
會根據以下規則選中node。
1.strategy是STRATEGY_DIRECT。
1.1.limitApp不是other和default,並且等於orgin時,選擇originNode。
1.2.limitApp是other,選擇originNode。
1.3.limitApp是default,選擇clusterNode。
2.strategy是STRATEGY_RELATE,選擇clusterNode。
3.strategy是STRATEGY_CHAIN,選擇node。
選擇好對應的node後就是調用canPass校驗限流規則,目前sentinel有三種本地限流規則:普通限流、勻速限流、冷啟動限流。
普通限流的實現是DefaultController,就是統計當前的線程數或者qps加上需要通過的數量有沒有大於限定值,小於等於則直接通過,否則阻擋。
勻速限流的實現是RateLimiterController,使用了AtomicLong保證了latestPassedTime的原子增長,因此停頓的時間是根據latestPassedTime-currentTime計算出來,得到一個勻速的睡眠時間。
冷啟動限流的實現是WarmUpController,是sentinel中最難懂的限流方式,其實不太需要關注這些復雜公式的計算,也可以得出冷啟動的限流思路:
1.當qps已經達到溫熱狀態時,按照正常的添加令牌消耗令牌即可。
2.當qps處於過冷狀態時,會添加令牌使得演算法繼續降溫。
3.當qps逐漸回升,大於過冷的邊界qps值時,不再添加令牌,慢慢消耗令牌使得逐漸增大單位時間可通過的請求數,讓演算法繼續回溫。
總結出一點,可通過的請求數跟令牌桶剩餘令牌數量成反比,以達到冷啟動的作用。
接下來是集群限流,passClusterCheck是集群限流的入口,會根據flowId調用clusterSerivce獲取指定數量的token,然後根據其結果判斷是否通過、睡眠、降級到本地限流、阻擋。
接下來看一下ClusterService的處理,會根據ruleId獲取到對應的FlowRule,然後調用ClusterFlowChecker.acquireClusterToken獲取結果返回。ClusterFlowChecker.acquireClusterToken的處理方式跟普通限流是一樣的,只是會將集群的請求都集中在一個service中處理,來達到集群限流的效果,不再細說。
FlowSlot的下一個節點是DegradeSlot,是熔斷處理器,進入時會調用performChecking,進而獲取到CircuitBreaker列表,然後調用其tryPass校驗是否熔斷。
來到AbstractCircuitBreaker的tryPass方法,主要是判斷熔斷器狀態,如果是close直接放行,如果是open則會校驗是否到達開啟halfopen的時間,如果成功將狀態cas成halfopen則繼續放行,其他情況都是阻攔。
那怎麼將熔斷器的狀態從close變成open呢?怎麼將halfopen變成close或者open呢?sentinel由兩種熔斷器:錯誤數熔斷器ExceptionCircuitBreaker、響應時間熔斷器ResponseTimeCircuitBreaker,都分析一遍。
當業務方法報錯時會調用Tracer.traceEntry將報錯設置到entry上。
當調用entry.exit時,會隨著責任鏈來到DegradeSlot的exit方法,會遍歷熔斷器列表調用其onRequestComplete方法。
ExceptionCircuitBreaker的onRequestComplete會記錄錯誤數和總請求數,然後調用繼續處理。
1.當前狀態是open時,不應該由熔斷器底層去轉換狀態,直接退出。
2.當前狀態是halfopen時,如果沒有報錯,則將halfopen變成close,否則將halfopen變成open。
3.當前狀態時close時,則根據是否總請求達到了最低請求數,如果達到了話再比較錯誤數/錯誤比例是否大於限定值,如果大於則直接轉換成open。
ExceptionCircuitBreaker的onRequestComplete會記錄慢響應數和總請求數,然後調用繼續處理。
1.當前狀態是open時,不應該由熔斷器底層去轉換狀態,直接退出。
2.當前狀態是halfopen時,如果當前響應時間小於限定值,則將halfopen變成close,否則將halfopen變成open。
3.當前狀態時close時,則根據是否總請求達到了最低請求數,如果達到了話再比較慢請求數/慢請求比例是否大於限定值,如果大於則直接轉換成open。
下一個節點是AuthoritySlot,許可權控制器,這個控制器就是看當前origin是否被允許進入請求,不允許則報錯,不再細說。
終於來到最後一個節點SystemSlot了,此節點是自適應處理器,主要是根據系統自身負載(qps、最大線程數、最高響應時間、cpu使用率、系統bbr)來判斷請求是否能夠通過,保證系統處於一個能穩定處理請求的安全狀態。
尤其值得一提的是bbr演算法,作者參考了tcp bbr的設計,通過最大的qps和最小的響應時間動態計算出可進入的線程數,而不是一個粗暴的固定可進入的線程數,為什麼能通過這兩個值就能計算出可進入的線程數?可以網上搜索一下tcp bbr演算法的解析,十分巧妙,不再細說。
3. 股票公式源碼 誰能幫我翻譯一下,跪謝了 我實在是看不懂啊
V1賦值:是否最後一個周期
V2賦值:N1*VARTIME日前的最高價=2*N1+1*VARTIME日內最高價的最高值
V3賦值:V2的N1日過濾
V4賦值:若V3則將最近N1+1周期置為1
V5賦值:V4的N1日過濾
V6賦值:V5 OR V1
V7賦值:N1日前的最低價=2*N1+1日內最低價的最低值
V8賦值:V7的N1日過濾
V9賦值:若V8則將最近N1+1周期置為1
VA賦值:V9的N1日過濾
VB賦值:VA AND 取反
VC賦值:若V6則將最近昨日上次VB距今天數+1周期置為1
VD賦值:VC>昨日VC
VE賦值:若VD則將最近2周期置為1
VF賦值:VE>昨日VE
V10賦值:若VFANDCOUNT(V6,昨日上次VB距今天數+2)=0則將最近昨日上次VB距今天數+2周期置為1
V11賦值:V10>昨日V10
V12賦值:若V11ANDCOUNT(V6,昨日上次VB距今天數+2)=0則將最近昨日上次VB距今天數+2周期置為1
V13賦值:V12>昨日V12
V14賦值:如果V6,返回統計昨日上次V6距今天數+1日中滿足VB的天數,否則返回0
V15賦值:如果V14=1ANDV6,返回上次VF距今天數,否則返回0
V16賦值:如果V6ANDREF(最低價,上次VF距今天數)>=上次V11距今天數日前的最低價,返回上次V11距今天數,否則返回上次VF距今天數
V17賦值:如果V14=2ANDV6,返回V16,否則返回0
V18賦值:如果V14>=3ANDV6,返回如果V6ANDREF(最低價,V16)>=上次V13距今天數日前的最低價,返回上次V13距今天數,否則返回V16,否則返回0
V19賦值:V15+V17+V18
V1A賦值:若V6則將最近V19周期置為1
V1B賦值:V1A>昨日V1A
V1C賦值:若V1B則將最近2周期置為1
V1D賦值:V1C>昨日V1C
V1E賦值:V1D OR V1
V1F賦值:若V1E則將最近昨日上次V6距今天數+1周期置為1
V20賦值:V1F>昨日V1F
V21賦值:若V20則將最近2周期置為1
V22賦值:V21>昨日V21
V23賦值:若V22ANDCOUNT(V1E,昨日上次V6距今天數+2)=0則將最近昨日上次V6距今天數+2周期置為1
V24賦值:V23>昨日V23
V25賦值:若V24ANDCOUNT(V1E,昨日上次V6距今天數+2)=0則將最近昨日上次V6距今天數+2周期置為1
V26賦值:V25>昨日V25
V27賦值:如果V1E,返回統計昨日上次V1E距今天數+1日中滿足V5的天數,否則返回0
V28賦值:如果V27=1ANDV1E,返回上次V22距今天數,否則返回0
V29賦值:如果V1EANDREF(最高價,上次V22距今天數)<=上次V24距今天數日前的最高價,返回上次V24距今天數,否則返回上次V22距今天數
V2A賦值:如果V27=2ANDV1E,返回V29,否則返回0
V2B賦值:如果V27>=3ANDV1E,返回如果V1EANDREF(最高價,V29)<=上次V26距今天數日前的最高價,返回上次V26距今天數,否則返回V29,否則返回0
V2C賦值:V28+V2A+V2B
V2D賦值:若V1E則將最近V2C周期置為1
V2E賦值:V2D>昨日V2D
V2F賦值:若V2E則將最近2周期置為1
V30賦值:V2F>昨日V2F
V31賦值:若V1則將最近上次V1D距今天數+1周期置為1
V32賦值:V31>昨日V31
V33賦值:若V1則將最近上次V30距今天數+1周期置為1
V34賦值:V33>昨日V33
V35賦值:如果上次V32距今天數<上次V34距今天數,返回V32,否則返回V34
V36賦值:如果上次V32距今天數<上次V34距今天數,返回最低價,否則返回最高價
V37賦值:若V1則將最近上次V1D距今天數+1周期置為1
V38賦值:V37>昨日V37
V39賦值:若V38則將最近昨日上次V1D距今天數+2周期置為1
V3A賦值:V39>昨日V39
當滿足條件V3A*VARTIME時,在最低價位置畫直線起點,當滿足條件V38*VARTIME時,在最低價位置畫直線終點,1表示是否延長.,LINETHICK1,畫黃色,LINEDOT
V3B賦值:若V1則將最近上次V30距今天數+1周期置為1
V3C賦值:V3B>昨日V3B
V3D賦值:若V3C則將最近昨日上次V30距今天數+2周期置為1
V3E賦值:V3D>昨日V3D
當滿足條件V3E*VARTIME時,在最高價位置畫直線起點,當滿足條件V3C*VARTIME時,在最高價位置畫直線終點,1表示是否延長.,LINETHICK1,畫黃色,LINEDOT
輸出 XX1: 上次V38距今天數*VARTIME日前的最低價,COLORCCFF99,LINETHICK2
輸出 前二低: 上次V3A距今天數*VARTIME日前的最低價,畫洋紅色,LINETHICK2
輸出 YY1: 上次V3C距今天數*VARTIME日前的最高價,COLORCCFF99,LINETHICK2
輸出 前二高: 上次V3E距今天數*VARTIME日前的最高價,畫洋紅色,LINETHICK2
當滿足條件是否最後一個周期*VARTIME時,在YY1位置書寫數字
當滿足條件是否最後一個周期*VARTIME時,在XX1位置書寫數字
當滿足條件是否最後一個周期*VARTIME時,在前二低位置書寫數字
當滿足條件是否最後一個周期*VARTIME時,在前二高位置書寫數字
含義:對應代碼的每一行
4. 跪求C++大神,只需要寫一個小游戲源代碼,事成有現金酬謝。
#include <iostream>
using namespace std;
double shengmingli=2000;//定義主角初始生命力
int gongjili=150;//定義主角初始攻擊力
int fangyuli=200;//定義主角初始防禦力
int money=20;//定義主角初始金錢數量
bool guoguan;//定義是否通關判定
void wuqidian();//定義武器店函數
void yaodian();//定義葯店函數
void guaiwu1();//定義小怪物函數
void guaiwu2();//定義大怪物函數
int main()
{
cout<<"歡迎你開始玩打怪物小游戲!\n";
cout<<"小鎮\n";
cout<<"一個1000年的小鎮。周圍有一條河,有一片樹林,很多房子和很多人。\n有一家葯店"<<endl;
cout<<"和一家武器店。\n";
int xiaozhen;//定義選擇項目
cout<<"1.去武器店"<<endl;
cout<<"2.去葯品店"<<endl;
cout<<"3.去打小怪物"<<endl;
cout<<"4.去打大怪物"<<endl;
cout<<"5.退出遊戲"<<endl;
cout<<"6.顯示你的狀態"<<endl;
cin>>xiaozhen;
while(xiaozhen!=5)//輸入5時退出遊戲
{
if(shengmingli<=0)//主角生命力小於等於0時游戲結束
{
cout<<"你死啦!"<<endl;
break;
}
if(guoguan)
{
cout<<"恭喜通關!"<<endl;
break;
}
if(xiaozhen==6)//輸入6可檢測自己的狀態
{
cout<<"你的生命力:"<<shengmingli<<endl;
cout<<"你的攻擊力:"<<gongjili<<endl;
cout<<"你的防禦力:"<<fangyuli<<endl;
cout<<"你擁有的錢:"<<money<<endl;
}
else
switch(xiaozhen)
{
case 1 : wuqidian();break;
case 2 : yaodian();break;
case 3 : guaiwu1();break;
case 4 : guaiwu2();break;
default : cout<<"請不要亂選!"<<endl;break;
}
cin>>xiaozhen;
}
if(xiaozhen==5)
{
cout<<"正在退出遊戲……"<<endl;
}
cin.get();
cin.get();
return 0;
}
void wuqidian()
{
cout<<"歡迎來到武器店!"<<endl;
cout<<"1、買小刀(1M加2攻擊力)"<<endl;
cout<<"2、買短劍(2M加20攻擊力)"<<endl;
cout<<"3、買大砍刀(5M加40攻擊力)"<<endl;
cout<<"4、買雙節棍(7M加60攻擊力)"<<endl;
cout<<"5、買盾牌(2M加30防禦力)"<<endl;
cout<<"6、買鎧甲(5M加60防禦力)"<<endl;
cout<<"7、離開武器店"<<endl;
int wuqidian;
cin>>wuqidian;
while(wuqidian!=7)//輸入7時結束函數
{
switch(wuqidian)
{
case 1 : if(money<10)
cout<<"你的錢不夠"<<endl;//錢不夠時返回Flase
else
cout<<"購買成功!"<<endl;//錢足夠時返回True
gongjili+=2;
money-=1;
break;
case 2 : if(money<80)
cout<<"你的錢不夠"<<endl;
else
cout<<"購買成功!"<<endl;
gongjili+=20;
money-=80;
break;
case 3 : if(money<140)
cout<<"你的錢不夠"<<endl;
else
cout<<"購買成功!"<<endl;
gongjili+=40;
money-=140;
break;
case 4 : if(money<200)
cout<<"你的錢不夠"<<endl;
else
cout<<"購買成功!"<<endl;
gongjili+=60;
money-=200;
break;
case 5 : if(money<60)
cout<<"你的錢不夠"<<endl;
else
cout<<"購買成功!"<<endl;
fangyuli+=30;
money-=60;
break;
fangyuli+=60;
money-=100;
break;
default : cout<<"無"<<endl;
break;
}
cin>>wuqidian;
}
if(wuqidian==7)
{ //返回main()主函數
cout<<"歡迎下次再來!"<<endl;
cout<<"歡迎你開始玩打怪物小游戲!\n";
cout<<"小鎮\n";
cout<<"一個1000年的小鎮。周圍有一條河,有一片樹林,很多房子和很多人。\n有一家葯店"<<endl;
cout<<"和一家武器店。\n";
cout<<"1.去武器店"<<endl;
cout<<"2.去葯品店"<<endl;
cout<<"3.去打小怪物"<<endl;
cout<<"4.去打大怪物"<<endl;
cout<<"5.退出遊戲"<<endl;
cout<<"6.顯示你的狀態"<<endl;
}
}
/*
yaodian()的設置與wuqidian()相同,可參照閱讀.
*/
void yaodian()
{
cout<<"歡迎來到葯品店!"<<endl;
cout<<"1、買1號補血葯(10M加200生命)"<<endl;
cout<<"2、買2號補血葯(50M加1000生命力)"<<endl;
cout<<"3、買3號補血葯(100M加2200生命力)"<<endl;
cout<<"4、離開葯品店"<<endl;
int yaodian;
cin>>yaodian;
while(yaodian!=4)
{
switch(yaodian)
{
case 1 : if(money<10)
cout<<"你的錢不夠"<<endl;
else
cout<<"購買成功!"<<endl;
shengmingli+=200;
money-=10;
break;
case 2 : if(money<50)
cout<<"你的錢不夠"<<endl;
else
cout<<"購買成功!"<<endl;
shengmingli+=1000;
money-=50;
break;
case 3 : if(money<100)
cout<<"你的錢不夠"<<endl;
else
cout<<"購買成功!"<<endl;
shengmingli+=2200;
money-=100;
break;
default : cout<<"無"<<endl;
break;
}
cin>>yaodian;
}
if(yaodian==4)
{
cout<<"歡迎下次再來!"<<endl;
cout<<"歡迎你開始玩打怪物小游戲!\n";
cout<<"小鎮\n";
cout<<"一個1000年的小鎮。周圍有一條河,有一片樹林,很多房子和很多人。\n有一家葯店"<<endl;
cout<<"和一家武器店。\n";
cout<<"1.去武器店"<<endl;
cout<<"2.去葯品店"<<endl;
cout<<"3.去打小怪物"<<endl;
cout<<"4.去打大怪物"<<endl;
cout<<"5.退出遊戲"<<endl;
cout<<"6.顯示你的狀態"<<endl;
}
}
/*這里是兩個戰斗函數,使用指針來處理.避免造成內存崩潰.*/
void guaiwu1()
{
cout<<"開始與小怪物戰斗!!!"<<endl;
double* g_shengmingli=new double;//定義怪物生命
int* g_gongjili=new int;//定義怪物攻擊力
int* g_fangyuli=new int;//定義怪物防禦力
int* g_money=new int;//定義怪物金錢
*g_shengmingli=100;
*g_gongjili=5;
*g_fangyuli=3;
*g_money=5;
double* tongji1=new double;//用來計算主角對怪物的殺傷
double* tongji2=new double;//用來計算怪物對主角的殺傷
*tongji1=0;
*tongji2=0;
int* huihe=new int;//定義回合數
*huihe=1;
cout<<"你開始對小怪物進行攻擊!"<<endl;
int* xuanze=new int;
/*
攻擊計算公式
殺傷=攻擊力*2-防禦力
玩家每回合可以選擇攻擊與逃跑
*/
while((*g_shengmingli)>0 && shengmingli>0 && (*xuanze)!=2)
{
cout<<"現在是"<<"第"<<*huihe<<"回合!"<<endl;
cout<<"請選擇你的動作:\n";
cout<<"1、攻擊\n2、逃跑\n";
cin>>*xuanze;
switch((*xuanze))
{
case 1 : cout<<"你對小怪物發動了攻擊!"<<endl;
*g_shengmingli-=gongjili*2-(*g_fangyuli);
*tongji1=gongjili*2-(*g_fangyuli);
cout<<"你打掉了小怪物"<<*tongji1<<"的生命!"<<endl;
cout<<"小怪物還剩"<<(*g_shengmingli)-(*tongji1)<<"點生命"<<endl;
shengmingli-=(*g_gongjili)*2-fangyuli;
*tongji2=(*g_gongjili)*2-fangyuli;
cout<<"小怪物對你發動了攻擊!"<<endl;
cout<<"小怪物打掉了你"<<*tongji2<<"的生命!"<<endl;
cout<<"你還剩"<<shengmingli-(*tongji2)<<"點生命"<<endl;break;
case 2 : cout<<"你決定逃跑!"<<endl;
cout<<"逃跑成功!"<<endl;continue;
default : cout<<"請不要亂選!"<<endl;
}
(*huihe)++;
}
if((*g_shengmingli)<=0)
{//殺死怪物後的返回
cout<<"小怪物被你殺死了!你真厲害!!!"<<endl;
money+=(*g_money);
cout<<"歡迎你開始玩打怪物小游戲!\n";
cout<<"小鎮\n";
cout<<"一個1000年的小鎮。周圍有一條河,有一片樹林,很多房子和很多人。\n有一家葯店"<<endl;
cout<<"和一家武器店。\n";
cout<<"1.去武器店"<<endl;
cout<<"2.去葯品店"<<endl;
cout<<"3.去打小怪物"<<endl;
cout<<"4.去打大怪物"<<endl;
cout<<"5.退出遊戲"<<endl;
cout<<"6.顯示你的狀態"<<endl;
}
else
if(shengmingli<=0)
{//被怪物殺死後的返回
cout<<"你被小怪物殺死了!游戲結束!!!"<<endl;
}
else
if((*xuanze)==2)
{//逃跑的返回
cout<<"你逃回了小鎮!"<<endl;
cout<<"歡迎你開始玩打怪物小游戲!\n";
cout<<"小鎮\n";
cout<<"一個1000年的小鎮。周圍有一條河,有一片樹林,很多房子和很多人。\n有一家葯店"<<endl;
cout<<"和一家武器店。\n";
cout<<"1.去武器店"<<endl;
cout<<"2.去葯品店"<<endl;
cout<<"3.去打小怪物"<<endl;
cout<<"4.去打大怪物"<<endl;
cout<<"5.退出遊戲"<<endl;
cout<<"6.顯示你的狀態"<<endl;
}
delete g_shengmingli;
delete g_gongjili;
delete g_fangyuli;
delete g_money;
delete tongji1;
delete tongji2;
}
/*
設置均與void函數guaiwu1()相同,可參照上例閱讀.
*/
void guaiwu2()
{
cout<<"開始與大怪物戰斗!!!"<<endl;
double* g_shengmingli=new double;
int* g_gongjili=new int;
int* g_fangyuli=new int;
*g_shengmingli=3600;
*g_gongjili=500;
*g_fangyuli=500;
double* tongji1=new double;
double* tongji2=new double;
*tongji1=0;
*tongji2=0;
int* huihe=new int;
*huihe=1;
cout<<"你開始對大怪物進行攻擊!"<<endl;
int* xuanze=new int;
while((*g_shengmingli)>0 && shengmingli>0 && (*xuanze)!=2)
{
cout<<"現在是"<<"第"<<*huihe<<"回合!"<<endl;
cout<<"請選擇你的動作:\n";
cout<<"1、攻擊\n2、逃跑\n";
cin>>*xuanze;
switch((*xuanze))
{
case 1 : cout<<"你對大怪物發動了攻擊!"<<endl;
*g_shengmingli-=gongjili*2-(*g_fangyuli);
*tongji1=gongjili*2-(*g_fangyuli);
cout<<"你打掉了大怪物"<<*tongji1<<"的生命!"<<endl;
cout<<"大怪物還剩"<<(*g_shengmingli)-(*tongji1)<<"點生命"<<endl;
shengmingli-=(*g_gongjili)*2-fangyuli;
*tongji2=(*g_gongjili)*2-fangyuli;
cout<<"大怪物對你發動了攻擊!"<<endl;
cout<<"大怪物打掉了你"<<*tongji2<<"的生命!"<<endl;
cout<<"你還剩"<<shengmingli-(*tongji2)<<"點生命"<<endl;break;
case 2 : cout<<"你決定逃跑!"<<endl;
cout<<"逃跑成功!"<<endl;continue;
default : cout<<"請不要亂選!"<<endl;
}
(*huihe)++;
}
if((*g_shengmingli)<=0)
{
cout<<"大怪物被你殺死了!你真厲害!!!"<<endl;
guoguan=true;
cout<<"歡迎你開始玩打怪物小游戲!\n";
cout<<"小鎮\n";
cout<<"一個1000年的小鎮。周圍有一條河,有一片樹林,很多房子和很多人。\n有一家葯店"<<endl;
cout<<"和一家武器店。\n";
cout<<"1.去武器店"<<endl;
cout<<"2.去葯品店"<<endl;
cout<<"3.去打小怪物"<<endl;
cout<<"4.去打大怪物"<<endl;
cout<<"5.退出遊戲"<<endl;
cout<<"6.顯示你的狀態"<<endl;
}
else
if(shengmingli<=0)
{
cout<<"你被大怪物殺死了!游戲結束!!!"<<endl;
}
else
if((*xuanze)==2)
{
cout<<"你逃回了小鎮!"<<endl;
cout<<"歡迎你開始玩打怪物小游戲!\n";
cout<<"小鎮\n";
cout<<"一個1000年的小鎮。周圍有一條河,有一片樹林,很多房子和很多人。\n有一家葯店"<<endl;
cout<<"和一家武器店。\n";
cout<<"1.去武器店"<<endl;
cout<<"2.去葯品店"<<endl;
cout<<"3.去打小怪物"<<endl;
cout<<"4.去打大怪物"<<endl;
cout<<"5.退出遊戲"<<endl;
cout<<"6.顯示你的狀態"<<en;
}
delete g_shengmingli;
delete g_gongjili;
delete g_fangyuli;
delete tongji1;
delete tongji2;
}
5. Shark(鯊魚記賬系統)–附源碼
Shark(鯊魚記賬系統)–附源碼
package com.shayu.note;
import java.util.Scanner;
public class SharkSystem {
// //下面開始循環
while (flag) {
//或蔽開機界面
System.out.println("-----歡迎使用鯊魚記賬系統-----");
System.out.println("1,收支明細");
System.out.println("2,登記收入");
System.out.println("3,登記支出");
System.out.println("4,退出系統");
System.out.println("請按照提衫鄭州示選擇你要使叢孝用的的功能--");
Scanner scanner = new Scanner(System.in);//判斷用戶輸入是否符合要求
int choice = scanner.nextInt();//選擇
//檢測用戶輸入的數據並返回相應的請求結果
while (choice != 1 & choice != 2 & choice != 3 & choice != 4) {
System.out.println("請重新輸入--");
int newchoice = scanner.nextInt();
choice = newchoice;
}
}
package com.shayu.note;
import java.util.Scanner;
//鯊魚記賬系統
public class Shark {
public static void main(String[] args) {
SharkSystem shark=new SharkSystem();
shark.StartSystem();
}
}
6. 通過手機點了這個鏈接之後可以跳轉到微信支付,這個源碼怎麼寫
微信公司平台帳號注冊後官方首頁很簡單,沒有導航欄目頁面新建等功能。需要通過三方軟體與微信介面做二次開發。首先要在現在微信開個介面,這是要工商局認證的。
7. 國雲商城app開發消費全返模式系統源碼定製哪家好
商城APP的全返模式系統定製服務有很多公司都在做;
簡單羅列一下有ecshop,好商城,shopnc,niushop,人人商城,一門APP等等,你這個消費全返模式這些都有提供,無論是現成功能,還是插件市場購買,還是定製開發,這都是鉛伏可以提供的。價格一般在1-5萬左右。
如果你想低信激鉛成本做這個APP的二次開發,滑好可以使用H5混合開發技術,用appcan,安卓益,奇門應用這些第三方的H5混合開發平台進行操作,可以大大降低開發成本,H5混編一鍵生成APP可以參考一下。