欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實(shí)現(xiàn)貪吃蛇游戲

 更新時(shí)間:2020年07月27日 11:43:10   作者:菜雞上路  
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

最近JAVA和JSwing上手練習(xí)了一下貪吃蛇,供大家參考,具體內(nèi)容如下

歡迎交流和加入新的內(nèi)容

用到了JSwing,下面是一些具體的思路

實(shí)現(xiàn)

 * 蛇:

采用單鏈表記錄首尾,整個(gè)蛇被分為lattice格子,放在map里

 * 移動(dòng):

我在實(shí)現(xiàn)的過(guò)程中發(fā)現(xiàn)最難得反而是蛇的定義和實(shí)現(xiàn)。一直想著怎么樣用單獨(dú)的方法表示出蛇來(lái),但是如果將蛇單獨(dú)實(shí)現(xiàn),總有些細(xì)節(jié)實(shí)現(xiàn)起來(lái)特別麻煩

其實(shí)蛇移動(dòng)并非牽一發(fā)而動(dòng)全身,其實(shí)身子是沒(méi)有發(fā)生變化的,關(guān)鍵是兩點(diǎn):

a.頭的移動(dòng)
b.尾巴的移動(dòng)

實(shí)現(xiàn):

直接把蛇實(shí)現(xiàn)在地圖的小格子里,不再單獨(dú)設(shè)置子類或者ArrayList等,Map里加上蛇頭的坐標(biāo),從而使得Map可以根據(jù)蛇頭改變蛇的坐標(biāo)(類似于變量交換)。為頭部單獨(dú)設(shè)置x,y,作為移動(dòng)的方向(也可以作為靜態(tài)變量x和y,不過(guò)沒(méi)什么區(qū)別),為身子設(shè)置next指針,只要next.next不是尾巴,那么保持不變。如果next是尾巴,就把自己的設(shè)置為尾巴,并且改變next,使之成為普通地圖塊。(refresh方法)

 * 控制方向:

使用鍵盤事件,目前僅設(shè)置了wasd四個(gè)

 * 窗口設(shè)計(jì):

view extends JPanel,控制顯示,然后在Lattice里調(diào)用Graphics.draw(...)實(shí)現(xiàn)對(duì)每個(gè)格子的顯示

下面是核心的map部分代碼(包括自動(dòng)移動(dòng),檢測(cè)食物,增加長(zhǎng)度等等)

import codes.myGame.snake.cell.Lattice;
 
import java.util.Random;
 
public class Smap {
 private boolean getFood = false;//如果得到食物,該指針設(shè)為true,并且在隨后的autoChange里增加蛇的長(zhǎng)度
 private boolean gameOver = false;
 private boolean directionChange = false;//這里標(biāo)志的作用是保證在一次運(yùn)動(dòng)期間只會(huì)進(jìn)行一次轉(zhuǎn)向,使游戲更流暢
 private int MAP_SIZE;
 private Lattice[][] map;
 private int directionX = 0;//下一次頭在當(dāng)前位置的哪個(gè)方向上
 private int directionY = 1;//下一次頭在當(dāng)前位置的哪個(gè)方向上
 private int[] head = new int[2];//記錄當(dāng)前頭的位置
 private int[] food = new int[2];//記錄當(dāng)前食物的位置
 
 public Smap(int size) {
 MAP_SIZE = size;
 map = new Lattice[MAP_SIZE][MAP_SIZE];
 for(int i=0;i<size;i++){
 for (int j = 0 ;j<size;j++){
 map[i][j] = new Lattice();
 }
 }
 map[MAP_SIZE/2][MAP_SIZE/2].setHead(true,map[MAP_SIZE/2][MAP_SIZE/2-1]);//初始化設(shè)置一個(gè)頭結(jié)點(diǎn),以及他的尾節(jié)點(diǎn)
 head[0] = MAP_SIZE/2;
 head[1] = MAP_SIZE/2;
 map[MAP_SIZE/2][MAP_SIZE/2-1].setRear(true,null);
 this.randFood();
 }
 
 //模擬蛇的自動(dòng)移動(dòng)
 public void autoChange(){
 this.setHead();
 if(food[0]==head[0] && food[1]==head[1]){//如果新的頭部碰觸到了食物,那么尾部增長(zhǎng)
 getFood = true;
 }
 if(!gameOver)this.setRear();
 if(getFood)this.randFood();
 directionChange = false;
 }
 
 //根據(jù)鍵盤事件,改變頭的下一次移動(dòng)方向,注意 該移動(dòng)方向是僅針對(duì)頭部的
 //setDirection和setHead兩個(gè)方法需要互斥進(jìn)行,這里單線程,用synchronized即可
 //(否則,如果當(dāng)前頭部在邊界位置,連續(xù)變幻方向可能導(dǎo)致在setHead里發(fā)生溢出)
 public synchronized void setDirection(int x,int y){
 if(directionY!=y && directionX!=x &&!directionChange){
 directionX = x;
 directionY = y;
 directionChange = true;
 }
 }
 
 public boolean gameOver(){
 return gameOver;//頭碰到身子,證明gameOver
 }
 private synchronized void setHead(){
 int i = head[0];
 int j = head[1];
 head[0] = ( head[0] + directionX + MAP_SIZE)%MAP_SIZE;
 head[1] = ( head[1] + directionY + MAP_SIZE )%MAP_SIZE;
 if(map[head[0]][head[1]].isBody())gameOver = true;
 map[head[0]][head[1]].setHead(true,map[i][j]);
 map[i][j].setBody(true,null);
 map[i][j].setHead(false,null); //傳入null表示不改變當(dāng)前指向
 }
 
 //設(shè)置尾巴由于沒(méi)法像頭部那樣直接設(shè)置,這里只能采用鏈表遍歷的方式獲取尾巴
 private void setRear(){
 if(!getFood){
 Lattice temp = map[head[0]][head[1]];
 while (!temp.next.isRear())temp = temp.next;
 temp.next().setRear(false,null);
 temp.setRear(true,null);
 temp.setBody(false,null);
 }
 }
 
 private void randFood(){
 getFood = false;
 map[food[0]][food[1]].setFood(false);//先把當(dāng)前的食物取消掉
 boolean flag = false;//設(shè)置下一個(gè)食物
 Random random = new Random();
 int x = random.nextInt(MAP_SIZE);
 int y = random.nextInt(MAP_SIZE);
 while (!flag){
 x = random.nextInt(MAP_SIZE);
 y = random.nextInt(MAP_SIZE);
 if(!map[x][y].isHead() && !map[x][y].isRear() &&!map[x][y].isBody())flag = true;
 }
 map[x][y].setFood(true);
 food[0] = x;
 food[1] = y;
 }
 
 public Lattice get(int row, int col){
 return map[row][col];
 }
 
 public int getMAP_SIZE() {
 return MAP_SIZE;
 }
}

下面是顯示部分的代碼

顯示分為兩部分,一塊是利用Graphics.draw()方法實(shí)現(xiàn)單個(gè)單元格的繪制,另一塊設(shè)置view類繼承自JPanel。負(fù)責(zé)繪制圖畫顯示

public class Lattice {
 private boolean isBody = false;
 private boolean isHead = false;
 private boolean isFood = false;
 private boolean isRear = false;
 public Lattice next = null;
 
 
 public void setHead(boolean bool,Lattice next){
 isHead = bool;
 if(next!=null)this.next = next;
 }
 public void setBody(boolean bool,Lattice next){
 isBody = bool;
 if(next!=null)this.next = next; //傳入?yún)?shù)為null時(shí),不改變當(dāng)前的next
 }
 public void setRear(boolean bool,Lattice next){
 isRear = bool;
 this.next = next;
 }
 public void setFood(boolean bool){
 isFood = bool;
 }
 
 public Lattice next(){
 return next;
 }
 
 public boolean isHead(){
 return isHead;
 }
 public boolean isFood(){
 return isFood;
 }
 public boolean isRear(){
 return isRear;
 }
 public boolean isBody(){
 return isBody;
 }
 
 
 
 public void refresh(){
 if(isHead){
 isBody = true;
 isHead = false;
// 怎么設(shè)置下一個(gè)頭呢?(考慮把DirectionX,Y放到Smap里,而不是這里)
 }else if(isBody){
 if(next.isRear){
 next.isRear = false;
 isRear = true;
 isBody = false;
 }
 }
 }
// 在這里設(shè)置細(xì)胞可見(jiàn)
 public void draw(Graphics g, int x, int y, int size) {
 g.setColor(black);
 g.drawRect(x, y, size, size);
 if ( isHead ) {
 g.setColor( red);
 g.fillRect(x, y, size, size);
 }else if ( isBody || isRear) {
 g.setColor(black);
 g.fillRect(x, y, size, size);
 }else if(isFood){
 g.setColor( blue);
 g.fillRect(x, y, size, size);
 }
 }
}

view部分:

import codes.myGame.snake.cell.Lattice;
import javax.swing.*;
import java.awt.*;
 
 
public class View extends JPanel {
 private static final long serialVersionUID = -5258995676212660595L;
 private static final int GRID_SIZE = 32; //填充的像素?cái)?shù)量
 private Smap thisMap;
 
 public View(Smap map) {
 thisMap = map;
 }
 
 @Override
 public void paint(Graphics g) {
 super.paint(g);
 int size = thisMap.getMAP_SIZE();
 for (int row = 0; row< size; row++ ) {
 for (int col = 0; col< size; col++ ) {
 Lattice lattice = thisMap.get(row, col);
 if ( lattice != null ) {
 lattice.draw(g, col*GRID_SIZE, row*GRID_SIZE, GRID_SIZE);//對(duì)應(yīng)的格子的顯示
 }
 }
 }
 }
 @Override
 public Dimension getPreferredSize() {//創(chuàng)建該div大小
 return new Dimension(thisMap.getMAP_SIZE()*GRID_SIZE+1, thisMap.getMAP_SIZE()*GRID_SIZE+1);
 }
}

更多有趣的經(jīng)典小游戲?qū)崿F(xiàn)專題,分享給大家:

C++經(jīng)典小游戲匯總

python經(jīng)典小游戲匯總

python俄羅斯方塊游戲集合

JavaScript經(jīng)典游戲 玩不停

javascript經(jīng)典小游戲匯總

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • JDBC插入數(shù)據(jù)返回?cái)?shù)據(jù)主鍵代碼實(shí)例

    JDBC插入數(shù)據(jù)返回?cái)?shù)據(jù)主鍵代碼實(shí)例

    這篇文章主要介紹了JDBC插入數(shù)據(jù)返回?cái)?shù)據(jù)主鍵代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 詳解Java中的final關(guān)鍵字

    詳解Java中的final關(guān)鍵字

    子類可以在父類的基礎(chǔ)上改寫父類內(nèi)容,為了避免這種隨意改寫的情況,Java提供了final 關(guān)鍵字,用于修飾不可改變內(nèi)容。本文就來(lái)詳細(xì)說(shuō)說(shuō)final關(guān)鍵字的使用,需要的可以參考一下
    2022-10-10
  • SSM項(xiàng)目實(shí)現(xiàn)短信驗(yàn)證碼登錄功能的示例代碼

    SSM項(xiàng)目實(shí)現(xiàn)短信驗(yàn)證碼登錄功能的示例代碼

    這篇文章主要為大家分享了在SSM項(xiàng)目中實(shí)現(xiàn)短信驗(yàn)證碼登錄功能的示例代碼,文中的實(shí)現(xiàn)步驟講解詳細(xì),感興趣的小伙伴可以跟隨小編一起動(dòng)手嘗試一下
    2022-05-05
  • springboot整合Shiro的步驟

    springboot整合Shiro的步驟

    這篇文章主要介紹了springboot整合Shiro的步驟,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下
    2021-01-01
  • Java直接內(nèi)存和堆內(nèi)存的關(guān)系

    Java直接內(nèi)存和堆內(nèi)存的關(guān)系

    在Java編程中,內(nèi)存管理是一個(gè)重要的話題,本文介紹了Java中兩種主要內(nèi)存類型:堆內(nèi)存和直接內(nèi)存,堆內(nèi)存是JVM管理的主要內(nèi)存區(qū)域,感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • Mybatis環(huán)境搭建及文件配置過(guò)程解析

    Mybatis環(huán)境搭建及文件配置過(guò)程解析

    這篇文章主要介紹了Mybatis環(huán)境搭建及文件配置過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Post請(qǐng)求參數(shù)是數(shù)組或者List時(shí)的請(qǐng)求處理方式

    Post請(qǐng)求參數(shù)是數(shù)組或者List時(shí)的請(qǐng)求處理方式

    這篇文章主要介紹了Post請(qǐng)求參數(shù)是數(shù)組或者List時(shí)的請(qǐng)求處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • SpringBoot+Redis執(zhí)行l(wèi)ua腳本的5種方式總結(jié)

    SpringBoot+Redis執(zhí)行l(wèi)ua腳本的5種方式總結(jié)

    Lua是一種快速、輕量級(jí)的腳本語(yǔ)言,廣泛應(yīng)用于各種領(lǐng)域,包括數(shù)據(jù)庫(kù),Redis作為一個(gè)內(nèi)嵌Lua解釋器的NoSQL數(shù)據(jù)庫(kù),允許通過(guò)Lua腳本在服務(wù)器端執(zhí)行一些復(fù)雜的操作,本文給大家介紹了使用SpringBoot Redis執(zhí)行l(wèi)ua腳本的五種方式,需要的朋友可以參考下
    2023-11-11
  • java 線程的生命周期詳解

    java 線程的生命周期詳解

    這篇文章主要介紹了java 線程的生命周期詳解的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • Java Tree結(jié)構(gòu)數(shù)據(jù)中查找匹配節(jié)點(diǎn)方式

    Java Tree結(jié)構(gòu)數(shù)據(jù)中查找匹配節(jié)點(diǎn)方式

    這篇文章主要介紹了Java Tree結(jié)構(gòu)數(shù)據(jù)中查找匹配節(jié)點(diǎn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09

最新評(píng)論