Java實(shí)現(xiàn)簡單的迷宮游戲詳解
前言
人類建造迷宮已有5000年的歷史。在世界的不同文化發(fā)展時(shí)期,這些奇特的建筑物始終吸引人們沿著彎彎曲曲、困難重重的小路吃力地行走,尋找真相。迷宮類小游戲應(yīng)運(yùn)而生。在游戲中,迷宮被表現(xiàn)為冒險(xiǎn)舞臺(tái)里,藏有各式各樣奇妙與謎題或?qū)毑氐奈kU(xiǎn)區(qū)域。型態(tài)有洞窟、人工建筑物、怪物巢穴、密林或山路等。迷宮內(nèi)有惡徒或兇猛的生物(真實(shí)存在或想像物體都有)徘徊,其中可能會(huì)有陷阱、不明設(shè)施、遺跡等。
《簡單迷宮》游戲是用java語言實(shí)現(xiàn),采用了swing技術(shù)進(jìn)行了界面化處理,設(shè)計(jì)思路用了面向?qū)ο笏枷搿?/p>
主要需求
方向鍵控制移動(dòng),角色走出迷宮,游戲勝利。
主要設(shè)計(jì)
1、構(gòu)建游戲地圖面板
2、設(shè)定迷宮地圖,包含可走的通道,不可走的墻體,還有出口位置
3、鍵盤的上下左右按鍵,來控制角色的移動(dòng)
4、角色移動(dòng)的算法,通道可走,遇到墻體不可走
5、走到終點(diǎn),有成功通關(guān)的提示。
功能截圖
游戲開始頁面

移動(dòng)界面

通關(guān)的界面

代碼實(shí)現(xiàn)
窗口布局
public class MainApp extends JFrame {
public MainApp(){
// 設(shè)置窗體名稱
setTitle("簡易迷宮游戲");
// 獲取自定義的游戲地圖面板的實(shí)例對象
MapPanel panel=new MapPanel();
Container contentPane = getContentPane();
contentPane.add(panel);
// 執(zhí)行并構(gòu)建窗體設(shè)定
pack();
}
public static void main(String[] args) {
MainApp app=new MainApp();
// 允許窗體關(guān)閉操作
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 顯示窗體
app.setVisible(true);
}
}核心算法
public class MapPanel extends JPanel implements KeyListener {
// 窗體的寬和高
private static final int WIDTH = 450;
private static final int HEIGHT = 450;
// 設(shè)定背景方格默認(rèn)行數(shù)和列數(shù)
private static final int ROW = 15;
private static final int COLUMN = 15;
// 設(shè)置窗體單個(gè)圖像,采用30x30大小的圖形,一行設(shè)置15個(gè),即450像素,即窗體默認(rèn)大小
private static final int SIZE = 30;
// 設(shè)定迷宮地圖
private static final byte FLOOR = 0;// 0表示通道地板
private static final byte WALL = 1;// 1表示墻
private static final byte END = 2;// 2表示終點(diǎn)
private byte[][] map = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1},
{1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1},
{1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1},
{1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1},
{1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1},
{1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1},
{1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1},
{1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 2, 1}
};
// 設(shè)定顯示的圖像對象
private Image floorImage;
private Image wallImage;
private Image heroImage;
private Image endImage;
// 角色坐標(biāo)
private int x, y;
// 區(qū)分上下左右按鍵的移動(dòng)
private static final byte LEFT = 0;
private static final byte RIGHT = 1;
private static final byte UP = 2;
private static final byte DOWN = 3;
public MapPanel() {
// 設(shè)定面板大小
setPreferredSize(new Dimension(WIDTH, HEIGHT));
// 加載圖片
loadImage();
// 初始化角色坐標(biāo)
this.x = 1;
this.y = 1;
// 設(shè)定焦點(diǎn)在本窗體并且監(jiān)聽鍵盤事件
setFocusable(true);
addKeyListener(this);
}
/**
* 畫地圖和角色
*
* @param g 畫筆
*/
public void paintComponent(Graphics g) {
drawMap(g);
drawRole(g);
}
/**
* 畫角色(英雄)
*
* @param g 畫筆
*/
private void drawRole(Graphics g) {
g.drawImage(heroImage, x * SIZE, y * SIZE, SIZE, SIZE, this);
}
private void loadImage() {
// 獲取當(dāng)前類對應(yīng)相對位置image文件夾下的地板圖像
ImageIcon icon = new ImageIcon(getClass().getResource("images/floor.png"));
// 將地板圖像實(shí)例賦給floorImage變量
floorImage = icon.getImage();
// 獲取墻體圖像
icon = new ImageIcon(getClass().getResource("images/wall.gif"));
wallImage = icon.getImage();
// 獲取英雄圖像
icon = new ImageIcon(getClass().getResource("images/hero.png"));
heroImage = icon.getImage();
// 獲取終點(diǎn)圖像
icon = new ImageIcon(getClass().getResource("images/end.png"));
endImage = icon.getImage();
}
/**
* 根據(jù)map[i][j]中記錄的地圖信息繪制圖案畫出地圖
* 標(biāo)記0為地板,標(biāo)記1為墻
*
* @param g
*/
private void drawMap(Graphics g) {
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COLUMN; j++) {
switch (map[i][j]) {
case 0:
// 標(biāo)記為0時(shí)畫出地板,在指定位置加載圖像
g.drawImage(floorImage, j * SIZE, i * SIZE, this);
break;
case 1:
// 標(biāo)記為1時(shí)畫出城墻
g.drawImage(wallImage, j * SIZE, i * SIZE, this);
break;
case 2:
// 標(biāo)記為2時(shí)畫出終點(diǎn)
g.drawImage(endImage, j * SIZE, i * SIZE, SIZE, SIZE, this);
default:
break;
}
}
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
// 根據(jù)按鍵進(jìn)行移動(dòng)
int keyCode = e.getKeyCode();// 獲取按鍵編碼
switch (keyCode) {
// 左方向鍵或'A'鍵,都可以左移
case KeyEvent.VK_LEFT:
move(LEFT);
break;
case KeyEvent.VK_A:
move(LEFT);
break;
// 右方向鍵或'D'鍵,都可以右移
case KeyEvent.VK_RIGHT:
move(RIGHT);
break;
case KeyEvent.VK_D:
move(RIGHT);
break;
// 上方向鍵或'W'鍵,都可以上移
case KeyEvent.VK_UP:
move(UP);
break;
case KeyEvent.VK_W:
move(UP);
break;
// 下方向鍵或'S'鍵,都可以下移
case KeyEvent.VK_DOWN:
move(DOWN);
break;
case KeyEvent.VK_S:
move(DOWN);
break;
default:
break;
}
// 重新繪制窗體圖像
repaint();
if (isFinish(x, y)) {
// 移動(dòng)到出口
JOptionPane.showMessageDialog(this, "恭喜通關(guān)!");
}
}
@Override
public void keyReleased(KeyEvent e) {
}
/**
* 判斷是否允許移動(dòng),如果傳入的坐標(biāo)不是墻則可以移動(dòng)
*
* @param x
* @param y
* @return 允許移動(dòng)則返回true,否則返回false
*/
private boolean isAllowMove(int x, int y) {
// 以判斷(x,y)是WALL還是FLOOR來作為是否能移動(dòng)的根據(jù)
// 1表示墻,不能移動(dòng);0表示地板,可以移動(dòng)
if (x < COLUMN && y < ROW) {// 進(jìn)行參數(shù)校驗(yàn),不能超過數(shù)組的長度
return map[y][x] != 1;
}
return false;
}
/**
* 移動(dòng)角色人物
*
* @param event 傳入移動(dòng)方向,分別可以是LEFT、RIGHT、UP、DOWN
*/
private void move(int event) {
switch (event) {
case LEFT:// 左移
if (isAllowMove(x - 1, y)) {// 判斷左移一步后的位置是否允許移動(dòng)(不是墻就可以移動(dòng))
x--;
}
break;
case RIGHT:// 右移
if (isAllowMove(x + 1, y)) {
x++;
}
break;
case UP:// 上移
if (isAllowMove(x, y - 1)) {
y--;
}
break;
case DOWN:// 下移
if (isAllowMove(x, y + 1)) {
y++;
}
default:
break;
}
}
/**
* 傳入人物的坐標(biāo)來判斷是否到達(dá)終點(diǎn)
*
* @param x
* @param y
* @return
*/
private boolean isFinish(int x, int y) {
// 2表示終點(diǎn)圖像
// 注意:x坐標(biāo)表示第幾列,y坐標(biāo)表示第幾行,所以是map[y][x]而不是map[x][y]
return map[y][x] == END;
}
}總結(jié)
通過此次的《簡易迷宮》游戲?qū)崿F(xiàn),讓我對swing的相關(guān)知識(shí)有了進(jìn)一步的了解,對java這門語言也有了比以前更深刻的認(rèn)識(shí)。
java的一些基本語法,比如數(shù)據(jù)類型、運(yùn)算符、程序流程控制和數(shù)組等,理解更加透徹。java最核心的核心就是面向?qū)ο笏枷?,對于這一個(gè)概念,終于悟到了一些。
到此這篇關(guān)于Java實(shí)現(xiàn)簡單的迷宮游戲詳解的文章就介紹到這了,更多相關(guān)Java迷宮游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java調(diào)用JavaScript實(shí)現(xiàn)字符串計(jì)算器代碼示例
這篇文章主要介紹了Java調(diào)用JavaScript實(shí)現(xiàn)字符串計(jì)算器代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。2017-12-12
搜索一文入門ElasticSearch(節(jié)點(diǎn) 分片 CRUD 倒排索引 分詞)
這篇文章主要為大家介紹了搜索一文入門ElasticSearch(節(jié)點(diǎn) 分片 CRUD 倒排索引 分詞)的基礎(chǔ)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Java讀取項(xiàng)目json文件并轉(zhuǎn)為JSON對象的操作
這篇文章主要介紹了Java讀取項(xiàng)目json文件并轉(zhuǎn)為JSON對象的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
認(rèn)識(shí)Java中的Stub與StubQueue
StubQueue是用來保存生成的本地代碼的Stub隊(duì)列,隊(duì)列每一個(gè)元素對應(yīng)一個(gè)InterpreterCodelet對象,InterpreterCodelet對象繼承自抽象基類Stub,下面我們介紹一下StubQueue類及相關(guān)類Stub、InterpreterCodelet類和CodeletMark類。需要的的下伙伴可以參考下面文字內(nèi)容2021-09-09
Java實(shí)現(xiàn)發(fā)送手機(jī)短信語音驗(yàn)證功能代碼實(shí)例
這篇文章主要介紹了Java實(shí)現(xiàn)發(fā)送手機(jī)短信語音驗(yàn)證功能代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
Spring實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換的方法總結(jié)
這篇文章主要為大家詳細(xì)介紹了一種Spring實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換的方法,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起了解一下2023-06-06

