Java實(shí)現(xiàn)簡(jiǎ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è)施、遺跡等。
《簡(jiǎn)單迷宮》游戲是用java語(yǔ)言實(shí)現(xiàn),采用了swing技術(shù)進(jìn)行了界面化處理,設(shè)計(jì)思路用了面向?qū)ο笏枷搿?/p>
主要需求
方向鍵控制移動(dòng),角色走出迷宮,游戲勝利。
主要設(shè)計(jì)
1、構(gòu)建游戲地圖面板
2、設(shè)定迷宮地圖,包含可走的通道,不可走的墻體,還有出口位置
3、鍵盤的上下左右按鍵,來(lái)控制角色的移動(dòng)
4、角色移動(dòng)的算法,通道可走,遇到墻體不可走
5、走到終點(diǎn),有成功通關(guān)的提示。
功能截圖
游戲開(kāi)始頁(yè)面
移動(dòng)界面
通關(guān)的界面
代碼實(shí)現(xiàn)
窗口布局
public class MainApp extends JFrame { public MainApp(){ // 設(shè)置窗體名稱 setTitle("簡(jiǎn)易迷宮游戲"); // 獲取自定義的游戲地圖面板的實(shí)例對(duì)象 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è)定顯示的圖像對(duì)象 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)聽(tīng)鍵盤事件 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)前類對(duì)應(yīng)相對(duì)位置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來(lái)作為是否能移動(dòng)的根據(jù) // 1表示墻,不能移動(dòng);0表示地板,可以移動(dòng) if (x < COLUMN && y < ROW) {// 進(jìn)行參數(shù)校驗(yàn),不能超過(guò)數(shù)組的長(zhǎng)度 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)來(lái)判斷是否到達(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é)
通過(guò)此次的《簡(jiǎn)易迷宮》游戲?qū)崿F(xiàn),讓我對(duì)swing的相關(guān)知識(shí)有了進(jìn)一步的了解,對(duì)java這門語(yǔ)言也有了比以前更深刻的認(rèn)識(shí)。
java的一些基本語(yǔ)法,比如數(shù)據(jù)類型、運(yùn)算符、程序流程控制和數(shù)組等,理解更加透徹。java最核心的核心就是面向?qū)ο笏枷?,?duì)于這一個(gè)概念,終于悟到了一些。
到此這篇關(guān)于Java實(shí)現(xiàn)簡(jiǎn)單的迷宮游戲詳解的文章就介紹到這了,更多相關(guān)Java迷宮游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(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-03java比較兩個(gè)json文件的差異及說(shuō)明
這篇文章主要介紹了java比較兩個(gè)json文件的差異及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10Java讀取項(xiàng)目json文件并轉(zhuǎn)為JSON對(duì)象的操作
這篇文章主要介紹了Java讀取項(xiàng)目json文件并轉(zhuǎn)為JSON對(duì)象的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08認(rèn)識(shí)Java中的Stub與StubQueue
StubQueue是用來(lái)保存生成的本地代碼的Stub隊(duì)列,隊(duì)列每一個(gè)元素對(duì)應(yīng)一個(gè)InterpreterCodelet對(duì)象,InterpreterCodelet對(duì)象繼承自抽象基類Stub,下面我們介紹一下StubQueue類及相關(guān)類Stub、InterpreterCodelet類和CodeletMark類。需要的的下伙伴可以參考下面文字內(nèi)容2021-09-09Java實(shí)現(xiàn)發(fā)送手機(jī)短信語(yǔ)音驗(yàn)證功能代碼實(shí)例
這篇文章主要介紹了Java實(shí)現(xiàn)發(fā)送手機(jī)短信語(yǔ)音驗(yàn)證功能代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09Spring實(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