不懂java實(shí)現(xiàn)俄羅斯方塊小游戲的方法?其實(shí)想解決這個(gè)問(wèn)題也不難,下面讓小編帶著大家一起學(xué)習(xí)怎么去解決,希望大家閱讀完這篇文章后大所收獲。
在卡若等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專(zhuān)注、極致的服務(wù)理念,為客戶(hù)提供成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作按需網(wǎng)站建設(shè),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站制作,網(wǎng)絡(luò)營(yíng)銷(xiāo)推廣,成都外貿(mào)網(wǎng)站建設(shè)公司,卡若網(wǎng)站建設(shè)費(fèi)用合理。
使用一個(gè)二維數(shù)組保存游戲的地圖:
// 游戲地圖格子,每個(gè)格子保存一個(gè)方塊,數(shù)組紀(jì)錄方塊的狀態(tài) private State map[][] = new State[rows][columns];
游戲前先將所有地圖中的格子初始化為空:
/* 初始化所有的方塊為空 */ for (int i = 0; i < map.length; i++) { for (int j = 0; j < map[i].length; j++) { map[i][j] = State.EMPTY; } }
玩游戲過(guò)程中,我們能夠看到界面上的方塊,那么就得將地圖中所有的方塊繪制出來(lái),當(dāng)然,除了需要繪制方塊外,游戲積分和游戲結(jié)束的字符串在必要的時(shí)候也需要繪制:
/** * 繪制窗體內(nèi)容,包括游戲方塊,游戲積分或結(jié)束字符串 */ @Override public void paint(Graphics g) { super.paint(g); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { if (map[i][j] == State.ACTIVE) { // 繪制活動(dòng)塊 g.setColor(activeColor); g.fillRoundRect(j * BLOCK_SIZE, i * BLOCK_SIZE + 25, BLOCK_SIZE - 1, BLOCK_SIZE - 1, BLOCK_SIZE / 5, BLOCK_SIZE / 5); } else if (map[i][j] == State.STOPED) { // 繪制靜止塊 g.setColor(stopedColor); g.fillRoundRect(j * BLOCK_SIZE, i * BLOCK_SIZE + 25, BLOCK_SIZE - 1, BLOCK_SIZE - 1, BLOCK_SIZE / 5, BLOCK_SIZE / 5); } } } /* 打印得分 */ g.setColor(scoreColor); g.setFont(new Font("Times New Roman", Font.BOLD, 30)); g.drawString("SCORE : " + totalScore, 5, 70); // 游戲結(jié)束,打印結(jié)束字符串 if (!isGoingOn) { g.setColor(Color.RED); g.setFont(new Font("Times New Roman", Font.BOLD, 40)); g.drawString("GAME OVER !", this.getWidth() / 2 - 140, this.getHeight() / 2); } }
通過(guò)隨機(jī)數(shù)的方式產(chǎn)生方塊所組成的幾種圖形,一般七種圖形:條形、田形、正7形、反7形、T形、Z形和反Z形,如生成條形:
map[0][randPos] = map[0][randPos - 1] = map[0][randPos + 1] = map[0][randPos + 2] = State.ACTIVE;
生成圖形后,實(shí)現(xiàn)下落的操作。如果遇到阻礙,則不能再繼續(xù)下落:
isFall = true; // 是否能夠下落 // 從當(dāng)前行檢查,如果遇到阻礙,則停止下落 for (int i = 0; i < blockRows; i++) { for (int j = 0; j < columns; j++) { // 遍歷到行中塊為活動(dòng)塊,而下一行塊為靜止塊,則遇到阻礙 if (map[rowIndex - i][j] == State.ACTIVE && map[rowIndex - i + 1][j] == State.STOPED) { isFall = false; // 停止下落 break; } } if (!isFall) break; }
如果未遇到阻礙,則下落的時(shí)候,方塊圖形整體向下移動(dòng)一行:
// 圖形下落一行 for (int i = 0; i < blockRows; i++) { for (int j = 0; j < columns; j++) { if (map[rowIndex - i][j] == State.ACTIVE) { // 活動(dòng)塊向下移動(dòng)一行 map[rowIndex - i][j] = State.EMPTY; // 原活動(dòng)塊變成空塊 map[rowIndex - i + 1][j] = State.ACTIVE; // 下一行塊變成活動(dòng)塊 } } }
向左、向右方向移動(dòng)時(shí)是類(lèi)似的操作:
/** * 向左走 */ private void left() { // 標(biāo)記左邊是否有阻礙 boolean hasBlock = false; /* 判斷是否左邊有阻礙 */ for (int i = 0; i < blockRows; i++) { if (map[rowIndex - i][0] == State.ACTIVE) { // 判斷左邊是否為墻 hasBlock = true; break; // 有阻礙,不用再循環(huán)判斷行 } else { for (int j = 1; j < columns; j++) { // 判斷左邊是否有其它塊 if (map[rowIndex - i][j] == State.ACTIVE && map[rowIndex - i][j - 1] == State.STOPED) { hasBlock = true; break; // 有阻礙,不用再循環(huán)判斷列 } } if (hasBlock) break; // 有阻礙,不用再循環(huán)判斷行 } } /* 左邊沒(méi)有阻礙,則將圖形向左移動(dòng)一個(gè)塊的距離 */ if (!hasBlock) { for (int i = 0; i < blockRows; i++) { for (int j = 1; j < columns; j++) { if (map[rowIndex - i][j] == State.ACTIVE) { map[rowIndex - i][j] = State.EMPTY; map[rowIndex - i][j - 1] = State.ACTIVE; } } } // 重繪 repaint(); } }
向下加速移動(dòng)時(shí),就是減小每次正常狀態(tài)下落的時(shí)間間隔:
/** * 向下直走 */ private void down() { // 標(biāo)記可以加速下落 immediate = true; }
如何變換圖形方向,這里僅使用了非常簡(jiǎn)單的方法來(lái)實(shí)現(xiàn)方向變換,當(dāng)然可以有更優(yōu)的算法實(shí)現(xiàn)方向變換操作,大家可以自己研究:
/** * 旋轉(zhuǎn)方塊圖形 */ private void rotate() { try { if (shape == 4) { // 方形,旋轉(zhuǎn)前后是同一個(gè)形狀 return; } else if (shape == 0) { // 條狀 // 臨時(shí)數(shù)組,放置旋轉(zhuǎn)后圖形 State[][] tmp = new State[4][4]; int startColumn = 0; // 找到圖形開(kāi)始的第一個(gè)方塊位置 for (int i = 0; i < columns; i++) { if (map[rowIndex][i] == State.ACTIVE) { startColumn = i; break; } } // 查找旋轉(zhuǎn)之后是否有阻礙,如果有阻礙,則不旋轉(zhuǎn) for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (map[rowIndex - 3 + i][j + startColumn] == State.STOPED) { return; } } } if (map[rowIndex][startColumn + 1] == State.ACTIVE) { // 橫向條形,變換為豎立條形 for (int i = 0; i < 4; i++) { tmp[i][0] = State.ACTIVE; for (int j = 1; j < 4; j++) { tmp[i][j] = State.EMPTY; } } blockRows = 4; } else { // 豎立條形,變換為橫向條形 for (int j = 0; j < 4; j++) { tmp[3][j] = State.ACTIVE; for (int i = 0; i < 3; i++) { tmp[i][j] = State.EMPTY; } } blockRows = 1; } // 將原地圖中圖形修改為變換后圖形 for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { map[rowIndex - 3 + i][startColumn + j] = tmp[i][j]; } } } else { // 臨時(shí)數(shù)組,放置旋轉(zhuǎn)后圖形 State[][] tmp = new State[3][3]; int startColumn = columns; // 找到圖形開(kāi)始的第一個(gè)方塊位置 for (int j = 0; j < 3; j++) { for (int i = 0; i < columns; i++) { if (map[rowIndex - j][i] == State.ACTIVE) { startColumn = i < startColumn ? i : startColumn; } } } // 判斷變換后是否會(huì)遇到阻礙 for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (map[rowIndex - 2 + j][startColumn + 2 - i] == State.STOPED) return; } } // 變換 for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { tmp[2 - j][i] = map[rowIndex - 2 + i][startColumn + j]; } } // 將原地圖中圖形修改為變換后圖形 for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { map[rowIndex - 2 + i][startColumn + j] = tmp[i][j]; } } // 重繪 repaint(); // 重新修改行指針 for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (map[rowIndex - i][startColumn + j] != null || map[rowIndex - i][startColumn + j] != State.EMPTY) { rowIndex = rowIndex - i; blockRows = 3; return; } } } } } catch (Exception e) { // 遇到數(shù)組下標(biāo)越界,說(shuō)明不能變換圖形形狀,不作任何處理 } }
當(dāng)圖形下落遇到阻礙時(shí)停止,我們就需要判斷這時(shí)是否有某一行或幾行可以消除掉,這時(shí)可以先獲取每行中方塊的個(gè)數(shù),然后再進(jìn)行判斷:
int[] blocksCount = new int[rows]; // 記錄每行有方塊的列數(shù) int eliminateRows = 0; // 消除的行數(shù) /* 計(jì)算每行方塊數(shù)量 */ for (int i = 0; i < rows; i++) { blocksCount[i] = 0; for (int j = 0; j < columns; j++) { if (map[i][j] == State.STOPED) blocksCount[i]++; } }
如果有滿(mǎn)行的方塊,則消除掉該行方塊:
/* 實(shí)現(xiàn)有滿(mǎn)行的方塊消除操作 */ for (int i = 0; i < rows; i++) { if (blocksCount[i] == columns) { // 清除一行 for (int m = i; m >= 0; m--) { for (int n = 0; n < columns; n++) { map[m][n] = (m == 0) ? State.EMPTY : map[m - 1][n]; } } eliminateRows++; // 記錄消除行數(shù) } }
最后我們?cè)僦乩L顯示積分就可以了。
重復(fù)以上的生成圖形、圖形下落、左右下移動(dòng)、判斷消除行的操作,一個(gè)簡(jiǎn)單的俄羅斯方塊就完成了。
運(yùn)行效果:
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享java實(shí)現(xiàn)俄羅斯方塊小游戲的方法內(nèi)容對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,遇到問(wèn)題就找創(chuàng)新互聯(lián),詳細(xì)的解決方法等著你來(lái)學(xué)習(xí)!