最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java實現(xiàn)2048小游戲

 更新時間:2021年04月07日 10:41:55   作者:小樣5411  
這篇文章主要為大家詳細介紹了java實現(xiàn)2048小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了java實現(xiàn)2048小游戲的具體代碼,供大家參考,具體內(nèi)容如下

一、實現(xiàn)效果

二、實現(xiàn)代碼

Check表示格子,GameView實現(xiàn)游戲視圖界面及功能,是核心。

Check.java

import java.awt.Color;
import java.awt.Font;

// 方格類
public class Check {
 public int value;

 Font font1 = new Font("宋體", Font.BOLD, 46);
 Font font2 = new Font("宋體", Font.BOLD, 40);
 Font font3 = new Font("宋體", Font.BOLD, 34);
 Font font4 = new Font("宋體", Font.BOLD, 28);
 Font font5 = new Font("宋體", Font.BOLD, 22);

 public Check() {
 value = 0; //value為方格中數(shù)字
 }
 //字體顏色
 public Color getForeground() {
 switch (value) {
 case 0:
 return new Color(0xcdc1b4);//0的顏色與背景色一致,相當于沒有數(shù)字
 case 2:
 case 4:
 return Color.BLACK;
 default:
 return Color.WHITE;
 }
 }

 //字體背景顏色,即方格顏色
 public Color getBackground() {
 switch (value) {
 case 0:
 return new Color(0xcdc1b4);
 case 2:
 return new Color(0xeee4da);
 case 4:
 return new Color(0xede0c8);
 case 8:
 return new Color(0xf2b179);
 case 16:
 return new Color(0xf59563);
 case 32:
 return new Color(0xf67c5f);
 case 64:
 return new Color(0xf65e3b);
 case 128:
 return new Color(0xedcf72);
 case 256:
 return new Color(0xedcc61);
 case 512:
 return new Color(0xedc850);
 case 1024:
 return new Color(0xedc53f);
 case 2048:
 return new Color(0xedc22e);
 case 4096:
 return new Color(0x65da92);
 case 8192:
 return new Color(0x5abc65);
 case 16384:
 return new Color(0x248c51);
 default:
 return new Color(0x248c51);
 }
 }

 public Font getCheckFont() {
 if (value < 10) {
 return font1;
 }
 if (value < 100) {
 return font2;
 }
 if (value < 1000) {
 return font3;
 }
 if (value < 10000) {
 return font4;
 }

 return font5;
 }

}

GameView.java

import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class GameView{
 private static final int jframeWidth = 405;//窗口寬高
 private static final int jframeHeight = 530;
 private static int score = 0;

 Font topicFont = new Font("微軟雅黑", Font.BOLD, 50);//主題字體
 Font scoreFont = new Font("微軟雅黑", Font.BOLD, 28);//得分字體
 Font explainFont = new Font("宋體", Font.PLAIN,20);//提示字體

 private JFrame jframeMain;
 private JLabel jlblTitle;
 private JLabel jlblScoreName;
 private JLabel jlblScore;
 private JLabel jlblTip;
 private GameBoard gameBoard;

 public GameView() {
 init();
 }

 public void init() {
 //1、創(chuàng)建窗口
 jframeMain = new JFrame("2048小游戲");
 jframeMain.setSize(jframeWidth, jframeHeight);
 jframeMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 jframeMain.setLocationRelativeTo(null);//窗口顯示位置居中
 jframeMain.setResizable(false);
 jframeMain.setLayout(null);//設(shè)置絕對布局,以便后面可以用setBounds設(shè)置位置

 jlblTitle = new JLabel("2048", JLabel.CENTER);
 jlblTitle.setFont(topicFont);
 jlblTitle.setForeground(Color.BLACK);
 jlblTitle.setBounds(50, 0, 150, 60);
 jframeMain.add(jlblTitle);


 //2、框架窗口搭建好,則需向里面開始添加內(nèi)容
 //設(shè)置字體及其顏色、位置
 jlblScoreName = new JLabel("得 分", JLabel.CENTER);
 jlblScoreName.setFont(scoreFont);
 jlblScoreName.setForeground(Color.WHITE);
 jlblScoreName.setOpaque(true);
 jlblScoreName.setBackground(Color.GRAY);
 jlblScoreName.setBounds(250, 0, 120, 30);
 jframeMain.add(jlblScoreName);

 //3、得分區(qū)(得分名+分數(shù))
 jlblScore = new JLabel("0", JLabel.CENTER);
 jlblScore.setFont(scoreFont);
 jlblScore.setForeground(Color.WHITE);
 jlblScore.setOpaque(true);
 jlblScore.setBackground(Color.GRAY);
 jlblScore.setBounds(250, 30, 120, 30);
 jframeMain.add(jlblScore);

 //4、提示說明區(qū)
 jlblTip = new JLabel("操作: ↑ ↓ ← →, 按esc鍵重新開始 ",
 JLabel.CENTER);
 jlblTip.setFont(explainFont);
 jlblTip.setForeground(Color.DARK_GRAY);
 jlblTip.setBounds(0, 60, 400, 40);
 jframeMain.add(jlblTip);

 //5、主游戲面板區(qū)
 gameBoard = new GameBoard();
 gameBoard.setBounds(0, 100, 400, 400);
 gameBoard.setBackground(Color.GRAY);
 gameBoard.setFocusable(true);//焦點即當前正在操作的組件,也就是移動的數(shù)字
 gameBoard.setLayout(new FlowLayout());
 jframeMain.add(gameBoard);
 }

 // 游戲面板
 class GameBoard extends JPanel implements KeyListener {
 private static final int CHECK_GAP = 10;//方格之間的間隙
 private static final int CHECK_SIZE = 85;//方格大小
 private static final int CHECK_ARC = 20;//方格弧度

 private Check[][] checks = new Check[4][4];
 private boolean isadd = true;

 public GameBoard() {
 initGame();
 addKeyListener(this);
 }

 private void initGame() {
 score = 0;
 for (int indexRow = 0; indexRow < 4; indexRow++) {
 for (int indexCol = 0; indexCol < 4; indexCol++) {
 checks[indexRow][indexCol] = new Check();
 }
 }
 // 最開始時生成兩個數(shù)
 isadd = true;
 createCheck();
 isadd = true;
 createCheck();
 }

 @Override
 public void keyPressed(KeyEvent e) {
 switch (e.getKeyCode()) {
 case KeyEvent.VK_ESCAPE:
 initGame();//重新開始游戲(初始化游戲)
 break;
 case KeyEvent.VK_LEFT:
 moveLeft();
 createCheck();//調(diào)用一次方法創(chuàng)建一個方格數(shù)字
 judgeGameOver();//創(chuàng)建后判斷是否GameOver,若所有格子均滿即跳出GameOver
 break;
 case KeyEvent.VK_RIGHT:
 moveRight();
 createCheck();
 judgeGameOver();
 break;
 case KeyEvent.VK_UP:
 moveUp();
 createCheck();
 judgeGameOver();
 break;
 case KeyEvent.VK_DOWN:
 moveDown();
 createCheck();
 judgeGameOver();
 break;
 default:
 break;//按其他鍵沒有反應(yīng)
 }
 repaint();//刷新,會自動調(diào)用paint()方法,重新繪制移動后的圖
 }


 private void createCheck() {
 List<Check> list = getEmptyChecks();

 if (!list.isEmpty() && isadd) {
 Random random = new Random();
 int index = random.nextInt(list.size());
 Check check = list.get(index);
 // 2, 4出現(xiàn)概率3:1
 int randomValue = random.nextInt(4);
 check.value = ( randomValue % 3 == 0 || randomValue % 3 == 1) ? 2 : 4;//只有[0,4)中的2才能生成4
 isadd = false;
 }
 }

 // 獲取空白方格
 private List<Check> getEmptyChecks() {
 List<Check> checkList = new ArrayList<>();
 for (int i = 0; i < 4; i++) {
 for (int j = 0; j < 4; j++) {
 if (checks[i][j].value == 0) {
 checkList.add(checks[i][j]);
 }
 }
 }
 return checkList;
 }
 //是否全部格子占滿,全部占滿則GameOver
 private boolean judgeGameOver() {
 jlblScore.setText(score + "");

 if (!getEmptyChecks().isEmpty()) {
 return false;
 }

 for (int i = 0; i < 3; i++) {
 for (int j = 0; j < 3; j++) {
 //判斷是否存在可合并的方格
 if (checks[i][j].value == checks[i][j + 1].value
 || checks[i][j].value == checks[i + 1][j].value) {
 return false;
 }
 }
 }

 return true;
 }

 private void moveLeft() {
 //找到一個非空格子后checks[i][j].value > 0,可分為三種情況處理
 for (int i = 0; i < 4; i++) {
 for (int j = 1, index = 0; j < 4; j++) {
 if (checks[i][j].value > 0) {
 //第一種情況:checks[i][j](非第1列)與checks[i][index]的數(shù)相等,則合并乘以2,且得分增加
 if (checks[i][j].value == checks[i][index].value) {
 score += checks[i][index].value *= 2;
 checks[i][j].value = 0;
 isadd = true;
 } else if (checks[i][index].value == 0) {
 //第二種:若checks[i][index]為空格子,checks[i][j]就直接移到最左邊checks[i][index]
 checks[i][index].value = checks[i][j].value;
 checks[i][j].value = 0;
 isadd = true;
 } else if (checks[i][++index].value == 0) {
 //第三種:若checks[i][index]不為空格子,并且數(shù)字也不相等,若其旁邊為空格子,則移到其旁邊
 checks[i][index].value = checks[i][j].value;
 checks[i][j].value = 0;
 isadd = true;
 }
 }
 }
 }
 }

 private void moveRight() {
 for (int i = 0; i < 4; i++) {
 for (int j = 2, index = 3; j >= 0; j--) {
 if (checks[i][j].value > 0) {
 if (checks[i][j].value == checks[i][index].value) {
 score += checks[i][index].value *= 2;
 checks[i][j].value = 0;
 isadd = true;
 } else if (checks[i][index].value == 0) {
 checks[i][index].value = checks[i][j].value;
 checks[i][j].value = 0;
 isadd = true;
 } else if (checks[i][--index].value == 0) {
 checks[i][index].value = checks[i][j].value;
 checks[i][j].value = 0;
 isadd = true;
 }
 }
 }
 }
 }

 private void moveUp() {
 for (int i = 0; i < 4; i++) {
 for (int j = 1, index = 0; j < 4; j++) {
 if (checks[j][i].value > 0) {
 if (checks[j][i].value == checks[index][i].value) {
 score += checks[index][i].value *= 2;
 checks[j][i].value = 0;
 isadd = true;
 } else if (checks[index][i].value == 0) {
 checks[index][i].value = checks[j][i].value;
 checks[j][i].value = 0;
 isadd = true;
 } else if (checks[++index][i].value == 0){
 checks[index][i].value = checks[j][i].value;
 checks[j][i].value = 0;
 isadd = true;
 }
 }
 }
 }
 }

 private void moveDown() {
 for (int i = 0; i < 4; i++) {
 for (int j = 2, index = 3; j >= 0; j--) {
 if (checks[j][i].value > 0) {
 if (checks[j][i].value == checks[index][i].value) {
 score += checks[index][i].value *= 2;
 checks[j][i].value = 0;
 isadd = true;
 } else if (checks[index][i].value == 0) {
 checks[index][i].value = checks[j][i].value;
 checks[j][i].value = 0;
 isadd = true;
 } else if (checks[--index][i].value == 0) {
 checks[index][i].value = checks[j][i].value;
 checks[j][i].value = 0;
 isadd = true;
 }
 }
 }
 }
 }

 @Override
 public void paint(Graphics g) {
 super.paint(g);
 for (int i = 0; i < 4; i++) {
 for (int j = 0; j < 4; j++) {
 drawCheck(g, i, j);
 }
 }

 // GameOver
 if (judgeGameOver()) {
 g.setColor(new Color(64, 64, 64, 100));//RGBA最后一個A可以視為透明度
 g.fillRect(0, 0, getWidth(), getHeight());//填充矩形(游戲面板),將暗黑色填充上去
 g.setColor(Color.WHITE);
 g.setFont(topicFont);
 FontMetrics fms = getFontMetrics(topicFont);//FontMetrics字體測量,該類是Paint的內(nèi)部類,通過getFontMetrics()方法可獲取字體相關(guān)屬性
 String value = "Game Over!";
 g.drawString(value, (getWidth()-fms.stringWidth(value)) / 2, getHeight() / 2);//字體居中顯示
 }
 }

 // 繪制方格
 // Graphics2D 類是Graphics 子類,擁有強大的二維圖形處理能力
 private void drawCheck(Graphics g, int i, int j) {
 Graphics2D gg = (Graphics2D) g;
 //下面兩句是抗鋸齒模式,計算和優(yōu)化消除文字鋸齒,字體更清晰順滑
 gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
 gg.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
 //獲取方格
 Check check = checks[i][j];
 //不同數(shù)字設(shè)置背景色
 gg.setColor(check.getBackground());
 // 繪制圓角
 gg.fillRoundRect(CHECK_GAP + (CHECK_GAP + CHECK_SIZE) * j,
 CHECK_GAP + (CHECK_GAP + CHECK_SIZE) * i,
 CHECK_SIZE, CHECK_SIZE, CHECK_ARC, CHECK_ARC);
 //繪制字體及其顏色
 gg.setColor(check.getForeground());
 gg.setFont(check.getCheckFont());

 // 文字測量,并對文字進行繪制
 FontMetrics fms = getFontMetrics(check.getCheckFont());
 String value = String.valueOf(check.value);
 //使用此圖形上下文的當前顏色繪制由指定迭代器給定的文本。
 //getAscent()是FontMetrics中的一個方法,
 //getDescent() 為降部
 gg.drawString(value,
 CHECK_GAP + (CHECK_GAP + CHECK_SIZE) * j +
 (CHECK_SIZE - fms.stringWidth(value)) / 2,
 CHECK_GAP + (CHECK_GAP + CHECK_SIZE) * i +
 (CHECK_SIZE - fms.getAscent() - fms.getDescent()) / 2
 + fms.getAscent());//讓數(shù)字居中顯示
 }

 @Override
 public void keyReleased(KeyEvent e) {
 }

 @Override
 public void keyTyped(KeyEvent e) {
 }

 }

 public void showView() {
 jframeMain.setVisible(true);
 }

}

Main.java

public class Main {
 public static void main(String[] args) {
 new GameView().showView();
 }
}

三、重難點講解

3.1 數(shù)字移動問題

數(shù)字移動是一難點,分三種情況,以moveLeft()為例

(1)按左鍵,若最左邊是相同的,則合并

(2)若左邊是空格,則直接移動到最左即可

(3)若最左邊不為空格,且不相等,則看它右邊是否是空格,是則移動到其旁邊

3.2 繪圖問題—抗鋸齒

java提供的Graphics 2D,它是Graphics 子類

Graphics2D gg = (Graphics2D) g;
gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
gg.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_NORMALIZE);

上面這兩個語句實現(xiàn)的功能是消除文字鋸齒,字體更清晰順滑,可以看下圖沒有setRenderingHint和有setRenderingHint的區(qū)別

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

相關(guān)文章

  • win11?idea?shift+F6快捷鍵失效問題解決方案

    win11?idea?shift+F6快捷鍵失效問題解決方案

    這篇文章主要介紹了win11?idea?shift+F6快捷鍵失效問題,本文給大家分享最新解決方案,需要的朋友可以參考下
    2023-08-08
  • maven如何動態(tài)統(tǒng)一修改版本號的方法步驟

    maven如何動態(tài)統(tǒng)一修改版本號的方法步驟

    這篇文章主要介紹了maven如何動態(tài)統(tǒng)一修改版本號的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • springboot的調(diào)度服務(wù)與異步服務(wù)使用詳解

    springboot的調(diào)度服務(wù)與異步服務(wù)使用詳解

    本文主要介紹了Java的ScheduledExecutorService接口和Spring Boot中如何使用調(diào)度線程池,包括核心參數(shù)、創(chuàng)建方式、自定義線程池、Cron表達式,以及如何在Spring Boot中配置和使用異步任務(wù),此外,還討論了如何模擬系統(tǒng)繁忙和調(diào)整異步線程池的拒絕策略
    2025-02-02
  • SpringBoot+MyBatis-Plus實現(xiàn)分頁示例

    SpringBoot+MyBatis-Plus實現(xiàn)分頁示例

    本文介紹了SpringBoot+MyBatis-Plus實現(xiàn)分頁示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-12-12
  • Java使用反射調(diào)用方法示例

    Java使用反射調(diào)用方法示例

    這篇文章主要介紹了Java使用反射調(diào)用方法,結(jié)合實例形式分析了java使用反射調(diào)用對象方法的相關(guān)操作技巧,需要的朋友可以參考下
    2019-07-07
  • 利用Java自寫一個生成ID的工具類

    利用Java自寫一個生成ID的工具類

    平時項目中只要涉及表,那么一定能接觸到眾多各式各樣的ID編號。本文將通過Java語言實現(xiàn)手寫一個ID生成工具類,需要的小伙伴可以參考一下
    2022-11-11
  • Java如何跳過https的ssl證書驗證詳解

    Java如何跳過https的ssl證書驗證詳解

    這篇文章主要介紹了Java跳過https的ssl證書驗證的解決思路,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,下面我們來深入學(xué)習(xí)下吧
    2019-06-06
  • 養(yǎng)成良好java代碼編碼規(guī)范

    養(yǎng)成良好java代碼編碼規(guī)范

    這篇文章主要介紹了如何養(yǎng)成良好java代碼編碼規(guī)范,規(guī)范需要平時編碼過程中注意,是一個慢慢養(yǎng)成的好習(xí)慣,下面小編就帶大家來一起詳細了解一下吧
    2019-06-06
  • Java?Object類equals方法

    Java?Object類equals方法

    這篇文章主要介紹了Java?Object類equals方法,Object類位于java.lang包中,java.lang包包含著Java最基礎(chǔ)和核心的類,在編譯時會自動導(dǎo)入,下文更多相關(guān)介紹,需要的小伙伴可以參考一下
    2022-04-04
  • Java類中字段可以不賦予初始值的原因分析

    Java類中字段可以不賦予初始值的原因分析

    這篇文章主要介紹了Java類中字段可以不賦予初始值的原因分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09

最新評論

沁阳市| 阿拉善左旗| 东平县| 凤翔县| 赤壁市| 贵德县| 抚州市| 永顺县| 元阳县| 长阳| 浪卡子县| 常德市| 钟祥市| 瑞安市| 毕节市| 宁蒗| 罗山县| 方正县| 道真| 杂多县| 大同县| 泾川县| 米脂县| 绩溪县| 个旧市| 金坛市| 阳曲县| 新沂市| 兴安县| 延安市| 开化县| 四会市| 宁海县| 随州市| 铜梁县| 嘉善县| 聊城市| 盐津县| 武城县| 新丰县| 利川市|