Java實現(xiàn)數(shù)字連連消
本文實例為大家分享了Java實現(xiàn)數(shù)字連連消的具體代碼,供大家參考,具體內(nèi)容如下
游戲規(guī)則很簡單,點擊選中兩個相同的數(shù)字即可消除這兩個數(shù)字,沒有做復(fù)雜的判斷。
效果圖
下面開始代碼
首先是MapTool.java,用于產(chǎn)生數(shù)字和判斷選中的兩個數(shù)字是否相同
package com.feonix; import java.util.Random; public class MapTool { public static int[][] createMap() { int[][] map = new int[10][10]; Random rand = new Random(); for (int i = 0; i < map.length; i++) { for (int j = 0; j < map[i].length; j++) { map[i][j] = rand.nextInt(9) + 1; } } return map; } public static int[][] removed(int[][] map, int pi, int pj, int ci, int cj) { if (map[pi][pj] == map[ci][cj] && (pj != cj || pi != ci)) { System.out.println("消除:map[" + ci + "][" + cj + "],map[" + pi + "][" + pj + "]"); map[pi][pj] = 0; map[ci][cj] = 0; } return map; } }
然后是GamePanel.java,游戲布局,游戲核心邏輯代碼
package com.feonix; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.HashSet; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.Timer; public class GamePanel extends JPanel { private static final long serialVersionUID = 2L; private static final int sx = 50;// 左邊距 private static final int sy = 50;// 上邊距 private static final int w = 40; // 小方格寬高 private static final int rw = 400; // 網(wǎng)格總寬高 private int pj = 0, pi = 0; // 記錄兩個點擊選中的按鈕,第一個被點擊的按鈕坐標(biāo) private int cc = 0;// 被點擊選中的按鈕個數(shù) private int[][] map;// 存放游戲數(shù)據(jù)的二維數(shù)組 private boolean isEnd = false; // 游戲結(jié)束標(biāo)志 private JButton[][] btnMap; // 存放按鈕的二維數(shù)組,與map對應(yīng) private int score; // 記錄分?jǐn)?shù) private JButton restart; // 重新開始按鈕 private Timer timer; // 定時器 private int timestamp; // 時間戳 public GamePanel() { // 設(shè)置布局為不使用預(yù)設(shè)的布局 setLayout(null); } /** * 開始游戲 */ public void start() { // 創(chuàng)建游戲數(shù)據(jù)地圖 map = MapTool.createMap(); btnMap = new JButton[10][10]; score = 0; timestamp = 0; isEnd = false; // 創(chuàng)建按鈕,設(shè)置按鈕屬性,監(jiān)聽事件,并添加到按鈕數(shù)組和窗體中 for (int i = 0; i < map.length; i++) { for (int j = 0; j < map[i].length; j++) { JButton btn = new JButton(map[i][j] + ""); btn.setBounds(sx + (j * w) + 2, sy + (i * w) + 2, w - 2, w - 2); btn.setForeground(Color.RED); btn.setFont(new Font("Arial", 0, 30)); btn.setBackground(Color.WHITE); btn.setBorder(BorderFactory.createRaisedBevelBorder()); btn.setFocusPainted(false); btn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 如果游戲結(jié)束,返回,不執(zhí)行后面的代碼 if (isEnd) { return; } for (int i = 0; i < btnMap.length; i++) { for (int j = 0; j < btnMap[i].length; j++) { if (e.getSource().equals(btnMap[i][j])) { // 被選中的方格個數(shù)增加一個 cc++; compare(j, i); } } } } }); btnMap[i][j] = btn; this.add(btn); } } if (restart != null) { restart.setVisible(false); this.remove(restart); restart = null; } repaint(); // 定時器,用來刷新時間 timer = new Timer(1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { timestamp++; repaint(); } }); timer.start(); } /** * 判斷是否游戲結(jié)束 * 1、判斷二維數(shù)組map中的所有元素是否均為0, 全部為0返回true表示游戲結(jié)束 * 2、有不為0的,判斷二維數(shù)組map中是否還有重復(fù)值,沒有重復(fù)值返回true表示游戲結(jié)束 * 否則返回false游戲繼續(xù) * * @param map 二維數(shù)組,元素為int類型 * @return */ public boolean isEnd(int[][] map) { int count_0 = 0; int count = 0; HashSet<Integer> hashSet = new HashSet<Integer>(); for (int[] ms : map) { for (int m : ms) { count++; if (m != 0) { hashSet.add(m); } else { count_0++; } } } for (int[] ms : map) { for (int m : ms) { if (m != 0) { if (hashSet.size() + count_0 == count) { return true; } return false; } } } return true; } /** * 重載JPanel父類的paintComponent方法,用來繪制網(wǎng)格,以及Game Over等 */ @Override protected void paintComponent(Graphics g) { super.paintComponent(g); try { // 獲取分鐘 int min = timestamp / 60; // 獲取秒數(shù) int sec = timestamp % 60; // 判斷是否結(jié)束游戲 if (isEnd) { // 設(shè)置畫筆顏色為紅色 g.setColor(Color.RED); // 設(shè)置字體 微軟雅黑 加粗 62號 g.setFont(new Font("微軟雅黑", 0, 62)); // 繪制GAME OVER字樣 g.drawString("GAME OVER", 60, 150); // 設(shè)置字體 微軟雅黑 加粗 40號 g.setFont(new Font("微軟雅黑", 0, 40)); // 繪制得分 g.drawString("得分:" + score, 80, 230); // 繪制用時 g.drawString("用時:" + String.format("%02d", min) + ":" + String.format("%02d", sec), 80, 280); } else { // 設(shè)置字體 微軟雅黑 加粗 20號 g.setFont(new Font("微軟雅黑", Font.BOLD, 20)); // 設(shè)置畫筆顏色為黑色 g.setColor(Color.BLACK); // 繪制時間顯示框 g.fillRect(100, 8, 80, 30); // 繪制分?jǐn)?shù)顯示框 g.fillRect(400, 8, 50, 30); // 設(shè)置畫筆顏色為紅色 g.setColor(Color.RED); // 繪制時間提示標(biāo)簽 g.drawString("時間:", 50, 30); // 繪制時間 g.drawString(String.format("%02d", min) + ":" + String.format("%02d", sec), 110, 30); // 繪制分?jǐn)?shù)提示標(biāo)簽 g.drawString("分?jǐn)?shù):", 350, 30); // 繪制分?jǐn)?shù) g.drawString(String.format("%03d", score) + "", 405, 30); // 繪制外層矩形框 g.drawRect(sx, sy, rw, rw); // 繪制水平10個,垂直10個方格。 即水平方向9條線,垂直方向9條線, 外圍四周4條線已經(jīng)畫過了,不需要再畫。 同時內(nèi)部64個方格填寫數(shù)字。 for (int i = 1; i < 10; i++) { // 繪制第i條豎直線 g.drawLine(sx + (i * w), sy, sx + (i * w), sy + rw); // 繪制第i條水平線 g.drawLine(sx, sy + (i * w), sx + rw, sy + (i * w)); } } } catch (Exception e) { e.printStackTrace(); } } /** * 繪制按鈕顯示和隱藏 * * @param i * @param j */ private void drawButton(int i, int j) { if (map[i][j] != 0) { btnMap[i][j].setVisible(true); } else { btnMap[i][j].setVisible(false); } } /** * 比較兩次點擊的按鈕對應(yīng)的數(shù)字 * * @param cj * @param ci */ private void compare(int cj, int ci) { /** * 如果cc是1,表示當(dāng)前一共選中了一個方格,用px,py來記住這個方格的位置; 否則,表示現(xiàn)在選中的這個方格要與之前選中的方案比較,決定是否要刪除 */ if (cc == 1) { pj = cj; pi = ci; printMap(ci, cj); // 將所點擊的方格背景設(shè)置為灰色 btnMap[ci][cj].setBackground(Color.LIGHT_GRAY); drawButton(ci, cj); } else {// 此時,cc肯定是大于1的,表示要比較兩個方格的值是否相同 printMap(ci, cj); map = MapTool.removed(map, pi, pj, ci, cj);// 讓MapTool類的remove方法去判斷上一次所選的(px,py)處的方格值與本次選擇的(cx,cy)處的方格值是否可以消掉 // 處理第一個方格 btnMap[ci][cj].setBackground(Color.WHITE); drawButton(ci, cj); // 處理第二個方格 btnMap[pi][pj].setBackground(Color.WHITE); drawButton(pi, pj); cc = 0;// 將cc的值復(fù)位 if (map[pi][pj] == map[ci][cj]) { score += 10; } isEnd = isEnd(map); // 游戲結(jié)束 if (isEnd) { // 關(guān)閉定時器 timer.stop(); // 隱藏剩余的按鈕 for (int i = 0; i < map.length; i++) { for (int j = 0; j < map[i].length; j++) { if (map[i][j] != 0) { btnMap[i][j].setVisible(false); } } } // 創(chuàng)建添加重新開始按鈕 restart = new JButton("重新開始"); restart.setBackground(Color.WHITE); restart.setBounds(180, 350, 120, 40); restart.setBorder(BorderFactory.createRaisedBevelBorder()); restart.setFocusPainted(false); restart.setForeground(Color.RED); restart.setFont(new Font("微軟雅黑", 0, 20)); restart.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { start(); } }); this.add(restart); repaint(); } } repaint(); } /** * 打印網(wǎng)格數(shù)據(jù) * * @param ci * @param cj */ private void printMap(int ci, int cj) { if (ci == pi && cj == pj) { System.out.println("ci:" + ci + ", cj:" + cj); } else { System.out.println("ci:" + ci + ", cj:" + cj + ", pi:" + pi + ", pj:" + pj); } for (int i = 0; i < map.length; i++) { for (int j = 0; j < map[i].length; j++) { if (ci == pi && cj == pj) { System.out.print(((ci == i && cj == j) ? "[" + map[i][j] + "]" : " " + map[i][j] + " ") + " "); } else { System.out.print( ((ci == i && cj == j || pi == i && pj == j) ? "[" + map[i][j] + "]" : " " + map[i][j] + " ") + " "); } } System.out.println(); } } }
下面是GameFrame.java,定義游戲窗體
package com.feonix; import javax.swing.JFrame; /** * * 程序入口 * */ public class GameFrame extends JFrame { private static final long serialVersionUID = 1L; GamePanel panel; /** * DrawSee構(gòu)造方法 */ public GameFrame() { // 設(shè)置窗體標(biāo)題 setTitle("數(shù)字連連消"); // 設(shè)置窗體位置和大小 setBounds(100, 100, 515, 520); // 設(shè)置窗體不能改變大小 setResizable(false); // 設(shè)置窗體居中顯示 setLocationRelativeTo(null); // 設(shè)置窗體關(guān)閉即退出 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); panel = new GamePanel(); add(panel); // 最后顯示窗體 setVisible(true); } /** * 啟動游戲 */ public void start() { panel.start(); } }
最后是Main.java,游戲程序的入口
package com.feonix; public class Main { public static void main(String[] args) { new GameFrame().start(); } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Springboot連接數(shù)據(jù)庫及查詢數(shù)據(jù)完整流程
今天給大家?guī)淼氖顷P(guān)于Springboot的相關(guān)知識,文章圍繞著Springboot連接數(shù)據(jù)庫及查詢數(shù)據(jù)完整流程展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06Mybatis的Mapper代理對象生成及調(diào)用過程示例詳解
這篇文章主要為大家介紹了Mybatis的Mapper代理對象生成及調(diào)用過程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09spring+mybatis 通過@ResponseBody返回結(jié)果中文亂碼的解決方法
下面小編就為大家分享一篇spring+mybatis 通過@ResponseBody返回結(jié)果中文亂碼的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12使用Java接收和處理OpenTelemetry數(shù)據(jù)的完整指南
在現(xiàn)代分布式系統(tǒng)中,OpenTelemetry 成為了一種常見的標(biāo)準(zhǔn),用于跟蹤和監(jiān)控應(yīng)用程序的性能和行為,OTLP是 OpenTelemetry 社區(qū)定義的一種數(shù)據(jù)傳輸協(xié)議,文將介紹如何使用 Java 編寫代碼來接收和處理 OTLP 數(shù)據(jù),需要的朋友可以參考下2024-04-04如何讓W(xué)in10實現(xiàn)Java文件的開機(jī)自啟動
這篇文章主要介紹了如何讓W(xué)in10實現(xiàn)Java文件的開機(jī)自啟動,對于一些想要一直運行的Java文件,就會造成每次系統(tǒng)更新之后的重啟導(dǎo)致Java文件無法繼續(xù)運行。,需要的朋友可以參考下2019-06-06Spring Boot 實現(xiàn)Restful webservice服務(wù)端示例代碼
這篇文章主要介紹了Spring Boot 實現(xiàn)Restful webservice服務(wù)端示例代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-11-11