1. 程式人生 > >java小遊戲第一彈 簡易俄羅斯

java小遊戲第一彈 簡易俄羅斯

/*
 * 俄羅斯方塊是一個經典的遊戲。本版只是簡易製作
 * 思想:俄羅斯方塊分層處理
 * (表現層)一個int[][] map陣列來展示n*m的方格,有方塊的為1,一次遍歷陣列,畫出方塊
 * (資料層)int[][][][] shapes陣列用01來區分方塊形狀
 * (控制層)int x,y記錄下落方塊位置,通過shapes[][][i][j]&map[x+i][y+j]的結果來判斷是否碰撞而進行一系列操作

 */


package cn.hncu.games;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.Timer;

public class Tetris extends JFrame{
	
	private nextBlockJPanel p;
	private TetrisPanel a; 
	private int set_delay=1000;

	private JMenu[] jmenu;
	private JMenuItem[][] jmenuItem;
	/*
	 * 動態監聽選單
	 */
	private ActionListener jmenuListener=new ActionListener() {
		
		@Override
		public void actionPerformed(ActionEvent e) {
			if(e.getActionCommand().equals("newGame")){
				a.newGame();
				jmenuItem[0][2].setEnabled(false);
				jmenuItem[0][1].setEnabled(true);
				for (int i = 0; i < jmenuItem[1].length; i++) {
					jmenuItem[1][i].setEnabled(false);
				}
				for (int i = 0; i < jmenuItem[2].length; i++) {
					jmenuItem[2][i].setEnabled(false);
				}
			}else if(e.getActionCommand().equals("break")){
				if(a.timer!=null)
					a.timer.stop();
				jmenuItem[0][1].setEnabled(false);
				jmenuItem[0][2].setEnabled(true);
				for (int i = 0; i < jmenuItem[1].length; i++) {
					jmenuItem[1][i].setEnabled(true);
				}
			}else if(e.getActionCommand().equals("continue")){
				if(a.timer!=null)
					a.timer.restart();
				jmenuItem[0][2].setEnabled(false);
				jmenuItem[0][1].setEnabled(true);
				for (int i = 0; i < jmenuItem[1].length; i++) {
					jmenuItem[1][i].setEnabled(false);
				}
				p.score=p.now_score;
				for (int i = 0; i < a.map.length; i++) {
					for (int j = 0; j < a.map[i].length; j++) {
						a.map[i][j]=a.now_map[i][j];
					}
				}
				a.repaint();
				p.repaint();
			}else if(e.getActionCommand().equals("exit")){
				if (a.timer!=null&&a.timer.isRunning()) {
					a.timer.stop();
				}
				//System.exit(0);
				dispose();
			}else if(e.getActionCommand().equals("last_score")){
				if(a.timer!=null)
					a.timer.stop();
				p.score=p.last_score;
				for (int i = 0; i < a.map.length; i++) {
					for (int j = 0; j < a.map[i].length; j++) {
						a.map[i][j]=a.last_map[i][j];
					}
				}
				a.repaint();
				p.repaint();
			}else if(e.getActionCommand().equals("optimal_score")){
				if(a.timer!=null)
					a.timer.stop();
				p.score=p.optimal_score;
				for (int i = 0; i < a.map.length; i++) {
					for (int j = 0; j < a.map[i].length; j++) {
						a.map[i][j]=a.optimal_map[i][j];
					}
				}
				a.repaint();
				p.repaint();
			}else if(e.getActionCommand().equals("hard")){
				set_delay=200;
			}else if(e.getActionCommand().equals("middle")){
				set_delay=600;
			}else if(e.getActionCommand().equals("low")){
				set_delay=1000;
			}
			
		}
	};
	/*
	 * 俄羅斯方塊形狀
	 */
	private int[][][][] shapes=new int[][][][]{
			//T
			{{         {0,1,0}, {1,1,1}},
			 {{0,0,1}, {0,1,1}, {0,0,1}},
			 {{1,1,1}, {0,1,0}         },
			 {{1,0,0}, {1,1,0}, {1,0,0}}},
			//L
			{{{0,1,0}, {0,1,0}, {0,1,1}},
			 {{0,0,1}, {1,1,1}},
			 {{1,1,0}, {0,1,0}, {0,1,0}},
			 {         {1,1,1}, {1,0,0}}},
			//J
			{{{0,1,0}, {0,1,0}, {1,1,0}},
			 {         {1,1,1}, {0,0,1}},
			 {{0,1,1}, {0,1,0}, {0,1,0}},
			 {{1,0,0}, {1,1,1}        }},
			//S
			{{{0,1,1}, {1,1,0}         },
			 {{0,1,0}, {0,1,1}, {0,0,1}}},
			 //Z
			{{{1,1,0}, {0,1,1}         },
			 {{0,1,0}, {1,1,0}, {1,0,0}}},
			 //O
			{{{1,1}, {1,1}}},
			//I
			{{{1,1,1,1}         },
			 {{1}, {1}, {1}, {1}}}
	};
	
	public Tetris() {
		super("俄羅斯方塊簡易版");
		setBounds(200, 100, 700, 600);
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		//getContentPane().setLayout(new BorderLayout());
		
		//選單
		JMenuBar bar=new JMenuBar();
		//for新增一系列選單,
		String[] str={"選項","記錄","難度"};
		String[][] strs={{"新遊戲","暫停","繼續","退出"},
				         {"上輪成績","最佳成績"},
				         {"難","中","低"}};
		String[][] strs_english={{"newGame","break","continue","exit"},
				{"last_score","optimal_score"},
				{"hard","middle","low"}};
		jmenu=new JMenu[str.length];
		jmenuItem=new JMenuItem[strs.length][];
		for (int i = 0; i < jmenu.length; i++) {
			jmenu[i]=new JMenu(str[i]);
			jmenuItem[i]=new JMenuItem[strs[i].length];
			for (int j = 0; j < jmenuItem[i].length; j++) {
				jmenuItem[i][j]=new JMenuItem(strs[i][j]);
				jmenuItem[i][j].addActionListener(jmenuListener);
				jmenuItem[i][j].setActionCommand(strs_english[i][j]);
				if(jmenuItem[i][j].getActionCommand().equals("continue"))
					jmenuItem[i][j].setEnabled(false);
				if(jmenuItem[i][j].getActionCommand().equals("break"))
					jmenuItem[i][j].setEnabled(false);
				jmenu[i].add(jmenuItem[i][j]);
			}
			bar.add(jmenu[i]);
		}
		setJMenuBar(bar);
		
		//記分面板
		p=new nextBlockJPanel();
		//遊戲繪畫面板
		a = new TetrisPanel(p);
		addKeyListener(a.timerListeren);
		JSplitPane sp=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,a,p);
		sp.setDividerLocation(400);
		getContentPane().add(sp);
		
		
		setVisible(true);
	}

	public class TetrisPanel extends JPanel{
		private nextBlockJPanel p;
		
		private int blockType; 
		private int turnState;
		
		private int local_x;
		private int local_y;
		
		private int delay;
		private TimerListeren timerListeren=new TimerListeren();
		
		private Timer timer;
	
		
		private int[][] map=new int[27][20];
		private int[][] now_map=new int[27][20];
		private int[][] last_map=new int[27][20];
		private int[][] optimal_map=new int[27][20];
	
		/*
		 * 建構函式並map初始化,構造牆壁
		 */
		public TetrisPanel(nextBlockJPanel p){
			this.p=p;
			for (int i = 0; i <map.length; i++) {
				for (int j = 0; j <map[i].length; j++) {
					if(j==0||j==map[i].length-1||i==map.length-1){
						map[i][j]=3;
					}else{
						map[i][j]=0;
					}
				}
			
			}
		}

		/*
		 * 遊戲開始
		 */
		private void newGame() {
			for (int i = 0; i <map.length; i++) {
				for (int j = 0; j <map[i].length; j++) {
					if(j==0||j==map[i].length-1||i==map.length-1){
						map[i][j]=3;
					}else{
						map[i][j]=0;
					}
				}
			
			}

			nextBlock();
			p.score=0;
			for (int i = 0; i < map.length; i++) {
				for (int j = 0; j < map[i].length; j++) {
					now_map[i][j]=map[i][j];
				}
			}
			p.now_score=p.score;
			delay=set_delay;
			timer=new Timer(delay, timerListeren);
			timer.start();
		}

		/*
		 * 下一方塊形狀
		 */
		private void nextBlock() {
			blockType=p.blockType;
			turnState=p.turnState;
			local_x=8;
			local_y=0;
			p.nextBlock();
			repaint();
			isGameOver();
		}
		//下落
		private void down(){
			if(crash(blockType,turnState,local_x,local_y+1)==1){
				local_y++;
			}else{
				add(blockType,turnState,local_x,local_y);
				nextBlock();
				
			}
			repaint();
		}
		//鍵盤方向鍵操作
		private void left() {
			local_x-=crash(blockType, turnState, local_x-1, local_y);
			repaint();
			
		}

		private void right() {
			local_x+=crash(blockType, turnState, local_x+1, local_y);
			repaint();
		}

		private void trun() {
			turnState=(turnState+crash(blockType, (turnState+1)%shapes[blockType].length, local_x, local_y))%shapes[blockType].length;
			repaint();
		}
		//加方塊
		private void add(int blockType, int turnState, int local_x,int local_y) {
			for (int i = 0; i < shapes[blockType][turnState].length; i++) {
				for (int j = 0; j < shapes[blockType][turnState][i].length; j++) {
					if(shapes[blockType][turnState][i][j]!=0)
						map[local_y+i][local_x+j]=shapes[blockType][turnState][i][j];
				}
			}
			Deline();
			for (int i = 0; i < map.length; i++) {
				for (int j = 0; j < map[i].length; j++) {
					now_map[i][j]=map[i][j];
				}
			}
			p.now_score=p.score;
		}
		//是否遊戲結束
        private void isGameOver() {
			if(crash(blockType, turnState, local_x, local_y)==0){
				p.last_score=p.score;
				for (int i = 0; i < map.length; i++) {
					for (int j = 0; j < map[i].length; j++) {
						last_map[i][j]=map[i][j];
					}
				}
				if(p.score>p.optimal_score){
					p.optimal_score=p.score;
					for (int i = 0; i < map.length; i++) {
						for (int j = 0; j < map[i].length; j++) {
							optimal_map[i][j]=map[i][j];
						}
					}
				}
				timer.stop();
				JOptionPane.showMessageDialog(null, "遊戲得分為:"+p.score);
				int option=JOptionPane.showConfirmDialog(null, "是否再來一局?", "", JOptionPane.YES_NO_OPTION);
				if(option==JOptionPane.OK_OPTION){
					newGame();
				}else{
					//System.exit(0);
					dispose();
				}
			}
			
		}

		//消方塊
		private void Deline() {
			int count=0;
			for (int i = 0; i < map.length-1; i++) {
				int c=1;
				for (int j = 1; j < map[i].length-1; j++) {
					c=c&map[i][j];
				}
				if(c==1){
					for (int i2 = i; i2 >0; i2--) {
						for (int j = 1; j < map[i2].length-1; j++) {
							map[i2][j]=map[i2-1][j];
						}
					}
					for (int j = 1; j < map[i].length-1; j++) {
						map[0][j]=0;
					}
					count++;
				}
			}
			if(count!=0){
				p.score+=10*(int)Math.pow(2, count);
				p.repaint();
			}
			timer.setDelay(delay-p.score/100);
		}

		//判斷是否碰撞
		private int crash(int blockType, int turnState, int local_x, int local_y) {
			for (int i = 0; i < shapes[blockType][turnState].length; i++) {
				for (int j = 0; j < shapes[blockType][turnState][i].length; j++) {
					try {
						if((shapes[blockType][turnState][i][j]&map[local_y+i][local_x+j])==1)
							return 0;
					} catch (Exception e) {
						return 0;
					}
				}
			}
			return 1;
		}
 
		@Override
		protected void printComponent(Graphics g) {
			super.printComponent(g);
			//畫出遊戲介面
			for (int i = 0; i <map.length; i++) {
				for (int j = 0; j < map[i].length; j++) {
					if(map[i][j]==3){
						g.setColor(Color.gray);
						g.fillRect(j*20, i*20, 20, 20);
					}
					if(map[i][j]==1){
						g.setColor(Color.blue);
						g.fillRect(j*20, i*20, 20, 20);
					}
				}
			}
			if(timer!=null&&timer.isRunning())
			for (int i = 0; i < shapes[blockType][turnState].length; i++) {
				for (int j = 0; j < shapes[blockType][turnState][i].length; j++) {
					if(shapes[blockType][turnState][i][j]==1){
						g.setColor(Color.cyan);
						g.drawRect((local_x+j)*20, (local_y+i)*20, 20, 20);
						g.setColor(Color.blue);
						g.fillRect((local_x+j)*20+1, (local_y+i)*20+1, 19, 19);
					}
				}
			}
			
		}

		@Override
		public void paint(Graphics g) {
			printComponent(g);
		}
        /*
         * 鍵盤控制
         */
        class TimerListeren extends KeyAdapter implements ActionListener{

			@Override
			public void actionPerformed(ActionEvent e) {
				down();
			}

			@Override
			public void keyPressed(KeyEvent e) {
				if(timer==null||!timer.isRunning())
					return;
				int keyCode=e.getKeyCode();
				switch(keyCode){
				case KeyEvent.VK_DOWN:
					down();
					break;
				case KeyEvent.VK_UP:
					trun();
					break;
				case KeyEvent.VK_LEFT:
					left();
					break;
				case KeyEvent.VK_RIGHT:
					right();
					break;
				}
			}

        }

	}
	
	public class nextBlockJPanel extends JPanel {
		
		private int blockType;
		private int turnState; 
		
		private int score;
		private int now_score;
		private int last_score;
		private int optimal_score;
		
		public nextBlockJPanel(){
			nextBlock();
			score=0;
		}

		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.drawString("下一個方塊形狀:", 20, 20);

			for (int i = 0; i <shapes[blockType][turnState].length ; i++) {
				for (int j = 0; j < shapes[blockType][turnState][i].length; j++) {
					if(shapes[blockType][turnState][i][j]==1){
						g.setColor(Color.cyan);
						g.drawRect(40+j*20, 40+i*20, 20, 20);
						g.setColor(Color.blue);
						g.fillRect(40+j*20+1, 40+i*20+1, 19, 19);
					}
				}
			}
			g.setColor(Color.red);
			g.drawString("Score:", 140, 20);
			g.setFont(new Font("score",Font.BOLD,50));
			g.drawString(""+score, 140, 80);
			g.setFont(new Font("aa", Font.PLAIN, 32));
			g.drawString("拒絕盜版遊戲,", 20, 320);
			g.drawString("注意自我保護。", 20, 350);
			g.drawString("謹防受騙上當。", 20, 380);
			g.drawString("適度遊戲益腦,", 20, 410);
			g.drawString("沉迷遊戲傷身。", 20, 440);
			g.drawString("合理安排時間,", 20, 470);
			g.drawString("享受健康生活。", 20, 500);
		}

		@Override
		public void paint(Graphics g) {
			super.paint(g);
			paintComponent(g);
		}
		//下一個方塊
		private void nextBlock() {
			blockType=(new Random()).nextInt(shapes.length);
			turnState=(new Random()).nextInt(shapes[blockType].length);
			repaint();
			
		}
		

	}
	
	public static void main(String[] args) {
		new Tetris();
	}
	
	

}

相關推薦

java遊戲第一 簡易俄羅斯

/*  * 俄羅斯方塊是一個經典的遊戲。本版只是簡易製作  * 思想:俄羅斯方塊分層處理  * (表現層)一個int[][] map陣列來展示n*m的方格,有方塊的為1,一次遍歷陣列,畫出方塊  * (資料層)int[][][][] shapes陣列用01來區分方塊形狀  

java遊戲-猜數字

stat next equal pan () 1-1 main alt pre 程序設計思路 隨機產生一個1-100的隨機數字。 用戶輸入一個數字,然後做判斷並輸出判斷結果。 用戶根據判斷結果再次決定要輸入的數字。 重復上面兩步,直到用戶輸入正確或者用戶放棄輸入。 程序流程

Java遊戲DanceWithStars(二):修改本地文件中的圖片(圖片寬高和圖片型別)以及將圖片設定為JButton的影象

1. 修改本地文件中的圖片(圖片寬高和圖片型別) 為了使下載的圖片素材都具有統一的width和height,需要對下載來的圖片重新處理並另存 主要思想是:構造一個BufferedImage物件,用ImageIO.read()讀入,再用ImageIO.write()重畫 程式碼如下: 1 pac

java遊戲——猜數字

arr 小遊戲 tint ati tin spa java ger port import java.util.ArrayList; import java.util.List; import java.util.Random; public class Num01 {

製作的第一個java遊戲

package java1; import java.awt.*; public class java1 extends Frame { //球桌和桌球圖片 Image ball = Toolkit.getDefaultToolkit().getImage("images/bal

java遊戲大魚吃魚入門(音樂新增+魚頭轉向+背景移動+背景泡泡效果)

上一篇講了如何寫基礎簡易的大魚吃小魚,接下來需要一些新增使遊戲介面效果更好。 1.新增音樂: 需要新增背景音樂和吃魚的效果音效等等音樂,將播放這些音樂的方法寫在一個類中,適時呼叫會很方便,即使只想新增背景音樂也可以寫在類中,方便以後直接在類種新增其他音樂的播放。

JAVA第一

JAVA的基礎組成 關鍵字 變數和常量 識別符號 運算子 註釋 語句 資料型別以及資料型別之間的轉換 方法 陣列 Java關鍵字 什麼是關鍵字 關鍵字就是被Java賦予特殊含義的單詞.Java中關鍵詞的特點是所有字母都是小寫,Java關鍵字不一定要求會背

C++遊戲(原創)——俄羅斯方塊

/* Designed by Ziwen 2018/09/26. */ #include<iostream> #include<cstring> #include<stdlib.h> #include<time.h&

Java遊戲——是男人就堅持20秒

/* * 程式的主窗體 */ public class FrmMain extends JFrame { /* * 初始的一些全域性變數 1是否存活 2方向 3子彈數量 4飛機 */ // 1是否存活 public static boolean isRun = true; // 2方向

Java遊戲系列之華容道

連結:https://pan.baidu.com/s/1-3qE0xCgmsDBkkYeD0eIiA 提取碼:dc8m 華容道小遊戲是我在網上看到的一個和貪吃蛇類似的小遊戲,也是利用swing和陣列來實現的益智類小遊戲,個人比較喜歡每個按鈕上的圖片,故而將其傳到部落格上,後面有時間的話會

Java遊戲迷宮遊戲

遊戲規則 按照位置為0的路線移動,上下左右方向鍵依次為 8、2、4、6 遊戲編碼 編碼思路:   定義一個二維陣列,七個一維陣列,每個一維陣列七個元素,並且按照遊戲規則設定0,1,初始值位置列印陣列,

Java遊戲之鬥地主遊戲例項Map集合

Map的特點是什麼? 1、Map物件是一個雙列的容器 2、兩列分別對應key和value,二者一一對應,是對映關係 3、Map中的資料以鍵值對的形式儲存 4、鍵值是唯一的,不能重複的 HashSet()和HashMap()之間的關係? HashSet()底層是HashMap

java遊戲基礎設計參考程式碼

{        this.setTitle("射擊遊戲");        this.getContentPane().setLayout(new BorderLayout());                this.getContentPane().add(panel1,"Center");     

JAVA遊戲——猜字母

遊戲規則 玩家需要任意輸入五個不同的大寫英文字母,每次輸入後都會返回兩個提示,一個是當前猜對的字母數,還有一個是字母和位置都匹配的數目,通過提示猜出正確的結果。 玩家起始分值設為500分,每猜錯一次減10分,遊戲結束顯示最終得分。 (無圖形介面) 遊戲原

白爬蟲第一之抓取妹子圖【更新版】

mozilla dir mac print 1.0 bsp 實例化 com def 最近對爬蟲感興趣,參考了 http://cuiqingcai.com/3179.html 這篇文章,琢磨的小試身手,但是按照原文發現圖片下載下來全是打不開的圖片,這不是我想要的啊,嘗試

java----猜字符遊戲

sys 編碼 har 改變 ann mat 生成 字符串 cor 剛學了方法,做了個小項目,猜字符小遊戲,這裏和大家分享一下。我們通過要達到的效果來分析: 1首先命令行窗口提示用戶進入猜字符遊戲,並顯示“猜吧” 2然後用戶輸入

C語言實現簡易2048遊戲

blog 而在 而是 null 移動 是我 我們 空指針 主體 一直很喜歡玩這個小遊戲,簡單的遊戲中包含運氣與思考與策略,喜歡這種簡約又不失內涵的遊戲風格。於是萌生了用C語言實現一下的想法。 具體代碼是模仿這個:https://www.cnblogs.com/judgeyo

c語言 遊戲

windows keys 計算 print 小球 隨機 lse pri include #include <stdio.h>#include <stdlib.h>#include <windows.h>#include <time.

【開發記錄】微信遊戲開發入門——俄羅斯方塊

了解 分享 公眾 lib 不必要 並且 視頻 text box 叨叨   我在前一陣子,打算做一個微信小遊戲,當然是單機的,只是為了了解小遊戲開發的過程,最終選擇了俄羅斯方塊這一經典小遊戲作為demo,源代碼已托管值github,當然,這個遊戲demo對用不並不友好,但是已

java:打字母遊戲demo

在一個300*400的窗體上,有隨機產生的字母向下落。在鍵盤上敲字母,如果對了就消掉,初始成績為1000分,每敲對一個字母加10分,如果字母落到螢幕下方,或者敲錯,扣100分。 import java.awt.Color; import java.awt.Graphics; import j