導(dǎo)語:歡迎來到CN人才網(wǎng),下面是小編整理的基于java的貪吃蛇游戲編程類的畢業(yè)論文,歡迎大家閱讀借鑒!
編程類畢業(yè)設(shè)計(jì)(論文)-基于java的貪吃蛇游戲開發(fā)
前言
隨著3G的到來,讓人們的目光聚集到一個新興的互聯(lián)網(wǎng)終端
——手機(jī)上。手機(jī)的隨身性讓玩家有了隨時隨地完游戲的可能。據(jù)我調(diào)查行業(yè)分析師也對這一行業(yè)持普遍的樂觀態(tài)度。yramid Researcher 的最新報告顯示,手機(jī)游戲市場正在穩(wěn)步發(fā)展。用戶數(shù)從2008年的1.83億到現(xiàn)在將增長到3億。據(jù)報告分析,2014年,市場 規(guī)模有望達(dá)到180億美元。
手機(jī)游戲的發(fā)展有以下推動因素
1. 更好更快的無限網(wǎng)絡(luò)以及易于操作的手機(jī)終端改善了用戶
的體驗(yàn);
2. 觸摸屏,3D動畫處理能力以及在線互動能力讓游戲開發(fā)商把游戲做的更好;
3.蘋果應(yīng)用商店模式刺激作用。
J2ME是一種針對移動電話和PDA這樣的小型設(shè)備的Java語言。大部分的手機(jī)廠商都迫切希望Java手機(jī)推廣應(yīng)用。上千萬的手機(jī)已經(jīng)到了消費(fèi)者手中。它已經(jīng)極大的提高了移動電話支持游戲的能力。它有著比SMS或WAP 更好控制的界面。允許使用子圖形動畫。并且可以通過無限網(wǎng)絡(luò)連接到遠(yuǎn)程服務(wù)器。支持Java的手機(jī)的普及,所以目前它成為最好的移動游戲開發(fā)環(huán)境。J2ME不是手機(jī)上配置的唯一解釋語言,但是它是許多廠商支持的行業(yè)標(biāo)準(zhǔn)。一些專用的解釋語言也在某些區(qū)域有上著上佳的表現(xiàn)。如北美的Qualcomm的BREM和一些韓國運(yùn)營上支持的名為GVM的標(biāo)準(zhǔn)。
基于以上分析,Java手機(jī)游戲的開發(fā)具有重要的意義。
1.1.5健壯性
Java致力于檢查程序在編譯和運(yùn)行時的錯誤,并自動回收內(nèi)存,減 少了內(nèi)存出錯的可能性。Java取消了C語言的結(jié)構(gòu)、指針、#define語句、多重繼承、goto語句、操作符、重載等不易被掌握的特性,提供垃圾收集器自動回收不用的內(nèi)存空間。
1.2 J2ME介紹
雖然 Java 已經(jīng)被用到許多企業(yè)級軟體上,可是其實(shí)骨子里面還是非常適合用在嵌入式系統(tǒng)之中。Java平臺演進(jìn)到Java2后,Java平臺分別針對不同領(lǐng)域的需求被分成四個版本,亦即J2EE、J2SE、J2ME以及JavaCard中J2ME定位在消費(fèi)性電子產(chǎn)品的應(yīng)用上。這個版本針對資源有限的電子消費(fèi)產(chǎn)品的需求精簡核心類庫,并提供了模塊化的架構(gòu)讓不同類型產(chǎn)品能夠隨時增加支持的能力。這個版本的應(yīng)用層面相當(dāng)廣泛,會是未來Java平臺發(fā)展的重點(diǎn)項(xiàng)目。
J2ME在1999年的JavaOne開發(fā)人員大會上初次亮相,它的目標(biāo)是面向智能無線設(shè)備和小型計(jì)算機(jī)設(shè)備的開發(fā)人員。J2ME的一個關(guān)鍵優(yōu)點(diǎn)是,J2ME與所有支持Java的設(shè)備都是兼容的。支持Java的設(shè)備就是任何運(yùn)行Java虛擬機(jī)器的計(jì)算機(jī)。Motorola、Nokia等生產(chǎn)廠商都生產(chǎn)支持Java的設(shè)備。
JAVJ2ME平臺是由配置(Configuration)和簡表(Profile)構(gòu)成的。配置是提供給最大范圍設(shè)備使用的最小類庫集合,在配置中同時包含Java虛擬機(jī)。簡表是針對一系列設(shè)備提供的開發(fā)包集合。在J2ME
中還有一個重要的概念是可選包(Optional Package),它是針對特定設(shè)備提供的類庫,比如某些設(shè)備是支持藍(lán)牙的,針對此功能J2ME中制定了JSR82(Bluetooth API)提供了對藍(lán)牙的支持。 目前,J2ME中有兩個最主要的配置,分別是Connected Limited Devices Configuration(CLDC)和Connected Devices
Configuration(CDC)。
net]
1.3 關(guān)于ECLIPSE
Eclipse 是一個開放源代碼的、基于 Java 的可擴(kuò)展開發(fā)平臺。就其本身而言,它只是一個框架和一組服務(wù),用于通過插件組件構(gòu)建開發(fā)環(huán)境。幸運(yùn)的是,Eclipse 附帶了一個標(biāo)準(zhǔn)的插件集,包括 Java 開發(fā)工具(Java Development Tools,JDT)。
雖然大多數(shù)用戶很樂于將 Eclipse 當(dāng)作 Java IDE 來使用,但 Eclipse 的目標(biāo)不僅限于此。Eclipse 還包括插件開發(fā)環(huán)境(Plug-in
Development Environment,PDE),這個組件主要針對希望擴(kuò)展 Eclipse 的軟件開發(fā)人員,因?yàn)樗试S他們構(gòu)建與 Eclipse 環(huán)境無縫集成的工具。由于 Eclipse 中的每樣?xùn)|西都是插件,對于給 Eclipse 提供插件,以及給用戶提供一致和統(tǒng)一的集成開發(fā)環(huán)境而言,所有工具開發(fā)人員都具有同等的發(fā)揮場所。
這種平等和一致性并不僅限于 Java 開發(fā)工具。盡管 Eclipse 是使用 Java 語言開發(fā)的,但它的用途并不限于 Java 語言;例如,支持諸如
C/C++、COBOL 和 Eiffel 等編程語言的插件已經(jīng)可用,或預(yù)計(jì)會推出。Eclipse 框架還可用來作為與軟件開發(fā)無關(guān)的其他應(yīng)用程序類型的基礎(chǔ),比如內(nèi)容管理系統(tǒng)。Eclipse 是一個開放源代碼的、基于 Java 的可擴(kuò)展開發(fā)平臺。就其本身而言,它只是一個框架和一組服務(wù),用于通過插件組件構(gòu)建開發(fā)環(huán)境。
1.4 WTK介紹
WTK 的全稱是Sun J2ME Wireless Toolkit —— Sun的無線開發(fā)工具包。這一工具包的設(shè)計(jì)目的是為了幫助開發(fā)人員簡化j2me的開發(fā)過程。使用其中的工具可以開發(fā)與 Java Technology for the Wireless Industry (JTWI, JSR 185) 規(guī)范兼容的設(shè)備上運(yùn)行的j2me 應(yīng)用程序。 WTK是用來開發(fā)MIDP的,為了讓MIDlet可以順利編譯和執(zhí)行,WTK必須具有CLDC和MIDP的類庫,WTK可以幫助我們省去額外安裝調(diào)試這些類庫的時間
2.需求分析
2.1游戲的介紹
游戲的名稱叫“貪吃蛇”,節(jié):一條蛇可以看成有許多正方形的“小格子”拼湊成,我把它稱作節(jié)。節(jié)是蛇身上最小的單位。 段:當(dāng)許多節(jié)連成一條直線,我稱它為段。貪吃蛇只有一段,如果它拐彎就變成兩段。
鏈表:用來保存每一段的狀態(tài),鏈表的元素單位是段。且鏈
表的最后一個元素表示蛇的頭部段。
坐標(biāo)系:MIDP中的坐標(biāo)以左上角那點(diǎn)為(0,0),向右則x遞增,向下則y遞增。
2.2游戲開發(fā)的可行性
游戲開發(fā)至今已經(jīng)有30多年,在這個短暫的時期里,隨著硬件的水平的提高。游戲開發(fā)新技術(shù)層出不窮,經(jīng)典游戲比比皆是,游戲這個名稱一直存在于每個人的日常生活中。因此,游戲?qū)τ诂F(xiàn)代人的成長歷程,絕對是一個不可或缺的重要角色.而從技術(shù)方面來看,現(xiàn)在的java技術(shù)也融入了手機(jī)中。這些都為開發(fā)的這款貪吃蛇游戲提供了條件。
2.3設(shè)計(jì)目的
綜合運(yùn)用在校所學(xué)的知識和技能,設(shè)計(jì)開發(fā)貪吃蛇游戲,使自己熟悉應(yīng)用系統(tǒng)的開發(fā)的過程,培養(yǎng)獨(dú)立思考的能力,校驗(yàn)學(xué)習(xí)效果和動手能力,提高工程實(shí)踐能力。
2.4游戲需求
給出一條小蛇和隨機(jī)出現(xiàn)一個食物,當(dāng)小蛇吃到食物時就加分。
2.4.1游戲界面需求
良好的用戶界面,有分?jǐn)?shù)顯示和暫停。
3. 游戲開發(fā)
3.1游戲主界面的開發(fā)
屏幕的背景用白色,由于屏幕高比寬長,所以取以寬為邊長的矩形區(qū)域作為游戲區(qū)域,下面的部分作為分?jǐn)?shù)、信息區(qū)域。
圖一(游戲的主界面)
3.2 繪制蛇身
protected void paint(Graphics g) {
//清屏
g.setColor(0, 255, 0);
g.fillRect(0,0,width,height);
g.setColor(0);
//繪制蛇身
for(int i = 0;i < snakeNum;i++){
g.fillRect(snake[i][0],snake[i][1],SNAKEWIDTH,SNAKEWIDTH); }
//繪制食物
if(b){
g.fillRect(foodX,foodY,SNAKEWIDTH,SNAKEWIDTH); }
}
3.3創(chuàng)建初始“蛇”及“蛇”的移動
蛇的初始長度為5,邊長為10個像素(背景為黃色),蛇頭初始位于屏幕(100,30),方向向左,用向量表來記錄每個蛇的位置以及方向。
部分參考代碼如下:
private void move(int direction){
//蛇身移動
for(int i = snakeNum - 1;i > 0;i--){
snake[i][0] = snake[i - 1][0];
snake[i][1] = snake[i - 1][1];
}
}
3.4 吃掉食物,蛇身增長
當(dāng)小蛇吃掉食物后,會增長,
部分代碼:
/**
* 吃掉食物,自身增長
*/
private void eatFood(){
//判別蛇頭是否和食物重疊
if(snake[0][0] == foodX && snake[0][1] == foodY){ snakeNum++;
generateFood();
}
}
3.4隨機(jī)產(chǎn)生食物
部分代碼:
* 產(chǎn)生食物
* 說明:食物的坐標(biāo)必須位于屏幕內(nèi),且不能和蛇身重合 */
private void generateFood(){
while(true){
foodX = Math.abs(random.nextInt() % (width - SNAKEWIDTH + 1)) / SNAKEWIDTH * SNAKEWIDTH;
foodY = Math.abs(random.nextInt() % (height - SNAKEWIDTH + 1)) / SNAKEWIDTH * SNAKEWIDTH; boolean b = true;
for(int i = 0;i < snakeNum;i++){
if(foodX == snake[i][0] && snake[i][1] == foodY){
b = false;
break;
}
}
if(b){
break;
}
}
}case RIGHT:
if(direction != DIRECTION_LEFT){
direction = DIRECTION_RIGHT;
}
break;
case FIRE:
//暫停和繼續(xù)
isPaused = !isPaused;
break;
}
}
3.6 判斷游戲結(jié)束
只有一種游戲結(jié)束的方式,即蛇頭碰到蛇身游戲結(jié)束。
參考代碼:
private boolean isGameOver(){
//邊界判別
if(snake[0][0] < 0 || snake[0][0] > (width - SNAKEWIDTH) || snake[0][1] < 0 || snake[0][1] > (height - SNAKEWIDTH)){ return true;
}
//碰到自身
for(int i = 4;i < snakeNum;i++){
if(snake[0][0] == snake[i][0]
&& snake[0][1] == snake[i][1]){
return true;
}
}
return false;
}
4游戲測試與發(fā)布
4.1游戲運(yùn)行的效果圖
圖一表示小蛇正在移動
圖二表示,隨機(jī)產(chǎn)生一個食物
圖三表示小蛇吃掉食物增長后繼續(xù)移動
4.2 測試結(jié)果
程序運(yùn)行良好,未出現(xiàn)bug.
5.自我評價和總結(jié)
5.1遇到的問題及解決辦法
先是圖形化界面的設(shè)計(jì),一直想不出好的辦法,最后翻看了教程才解決了這個問題,后來在蛇的移動上也遇到了些問題。上網(wǎng)查了一下,才知道蛇身是由一連串的基本圖形組成的,每過1秒檢查前面是什么,如果是空的,就把圖畫成普通身子的樣子。再在前方在畫一個頭,并將其左標(biāo)記入數(shù)組,數(shù)組要足夠大,在把尾巴畫成背景色,如果前面是食物,尾巴就不刪除。這個里面的難點(diǎn)就是數(shù)組里面的操作
/**已經(jīng)使用的節(jié)點(diǎn)數(shù)量*/
int snakeNum;
/**貪吃蛇運(yùn)動方向,0代表向上,1代表向下,2代表向左,3代表向右*/ int direction;
/*移動方向*/
/**向上*/
private final int DIRECTION_UP = 0;
/**向下*/
private final int DIRECTION_DOWN = 1;
/**向左*/
private final int DIRECTION_LEFT = 2;
/**向右*/
private final int DIRECTION_RIGHT = 3;
/**游戲區(qū)域?qū)挾?/
int width;
/**游戲區(qū)域高度*/
int height;
/**蛇身單元寬度*/
private final byte SNAKEWIDTH = 4;
/**是否處于暫停狀態(tài),true代表暫停*/
boolean isPaused = false;
/**是否處于運(yùn)行狀態(tài),true代表運(yùn)行*/
boolean isRun = true;
/**時間間隔*/
private final int SLEEP_TIME = 300;
/**食物的X坐標(biāo)*/
int foodX;
/**食物的Y坐標(biāo)*/
int foodY;
/**食物的閃爍控制*/
boolean b = true;
/**Random對象*/
Random random = new Random();
public SnakeCanvas() {
//初始化
init();
width = this.getWidth();
height = this.getHeight();
//啟動線程
new Thread(this).start();
}
/**
* 初始化開始數(shù)據(jù)
*/
private void init(){
//初始化節(jié)點(diǎn)數(shù)量
snakeNum = 7;
//初始化節(jié)點(diǎn)數(shù)據(jù)
for(int i = 0;i < snakeNum;i++){
snake[i][0] = 100 - SNAKEWIDTH * i;
snake[i][1] = 40;
}
//初始化移動方向
direction = DIRECTION_RIGHT;
//初始化食物坐標(biāo)
foodX = 100;
foodY = 100;
}
protected void paint(Graphics g) {
//清屏
g.setColor(0, 255, 0);
g.fillRect(0,0,width,height);
g.setColor(0);
//繪制蛇身
for(int i = 0;i < snakeNum;i++){
g.fillRect(snake[i][0],snake[i][1],SNAKEWIDTH,SNAKEWIDTH); }
//繪制食物
if(b){
g.fillRect(foodX,foodY,SNAKEWIDTH,SNAKEWIDTH);
}
}
private void move(int direction){
//蛇身移動
for(int i = snakeNum - 1;i > 0;i--){
snake[i][0] = snake[i - 1][0];
snake[i][1] = snake[i - 1][1];
//第一個單元格移動
switch(direction){
case DIRECTION_UP:
snake[0][1] = snake[0][1] - SNAKEWIDTH;
break;
case DIRECTION_DOWN:
snake[0][1] = snake[0][1] + SNAKEWIDTH;
break;
case DIRECTION_LEFT:
snake[0][0] = snake[0][0] - SNAKEWIDTH;
break;
case DIRECTION_RIGHT:
snake[0][0] = snake[0][0] + SNAKEWIDTH;
break;
}
}
/**
* 吃掉食物,自身增長
*/
private void eatFood(){
//判別蛇頭是否和食物重疊
if(snake[0][0] == foodX && snake[0][1] == foodY){
snakeNum++;
generateFood();
}
}
/**
* 產(chǎn)生食物
* 說明:食物的坐標(biāo)必須位于屏幕內(nèi),且不能和蛇身重合 */
private void generateFood(){
while(true){
foodX = Math.abs(random.nextInt() % (width - SNAKEWIDTH + 1)) / SNAKEWIDTH * SNAKEWIDTH;
foodY = Math.abs(random.nextInt() % (height - SNAKEWIDTH + 1)) / SNAKEWIDTH * SNAKEWIDTH; boolean b = true;
for(int i = 0;i < snakeNum;i++){
if(foodX == snake[i][0] && snake[i][1] == foodY){
b = false;
break;
}
if(b){
break;
}
}
}
/**
* 判斷游戲是否結(jié)束
* 結(jié)束條件:
* 1、蛇頭超出邊界
* 2、蛇頭碰到自身
*/
private boolean isGameOver(){
//邊界判別
if(snake[0][0] < 0 || snake[0][0] > (width - SNAKEWIDTH) || snake[0][1] < 0 || snake[0][1] > (height - SNAKEWIDTH)){ return true;
}
//碰到自身
for(int i = 4;i < snakeNum;i++){
if(snake[0][0] == snake[i][0]
&& snake[0][1] == snake[i][1]){
return true;
}
}
return false;
}
/**
* 事件處理
*/
public void keyPressed(int keyCode){
int action = this.getGameAction(keyCode);
//改變方向
switch(action){
case UP:
if(direction != DIRECTION_DOWN){
direction = DIRECTION_UP;
}
break;
case DOWN:
if(direction != DIRECTION_UP){
}
//重新繪制
repaint();
long end = System.currentTimeMillis();
//延時
if(end - start < SLEEP_TIME){
Thread.sleep(SLEEP_TIME - (end - start)); }
}
}catch(Exception e){}
}
}