大作业:JAVA实现2048小游戏

目录

运行环境:

文档要求:

参考:

基础版本:

源代码部分:

进阶功能:

演示效果: 


运行环境:

        java jdk1.8

文档要求:

选题92048游戏

【问题描述】

2048游戏是一款比较流行的数字游戏,每次可以选择上下左右滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢,系统也会在空白的地方乱数出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。不断的叠加最终拼凑出2048这个数字就算成功。

【任务要求】

1) 基本功能:方向控制、计分等。

2) 利用图形化插件实现界面,至少包括游戏介绍、游戏开始、游戏结束三部分。

3) 设计关卡、音效等其他功能。

【测试数据】

自行设定。

【成绩评定】

1) 基本完成任务要求1、2,评定为“及格”或“中等”;

2) 正确完成任务要求1、2,算法优化、报告规范,评定为“良好”或“优秀”;

3) 正确完成任务要求1、2、3,评定为“优秀”。

参考:

参考视频:

用Java实现2048游戏完整版

参考文档:

Java进阶之菜单栏---JMenuBar

java实现actionlistener_ActionListener的三种实现方法

【Java】 Java 实现 2048 小游戏

JAVA实现2048小游戏

java颜色代码对照表

RGB颜色对照表

四个Class

大作业:JAVA实现2048小游戏_第1张图片

基础版本:

源代码部分:

Main.java

package new2048;

public class Main {

	public static void main(String[] args) {
		GameWindow frame = new GameWindow();//创建窗口对象
		GamePanel panel = new GamePanel(frame);//创建画布对象变量为frame
		frame.add(panel);//在窗口中加入画布
		frame.setVisible(true);//设置为可见
		
		}
	}


GameWindow.java

package new2048;
import javax.swing.*;
import java.awt.*;

public class GameWindow extends JFrame {
	public GameWindow(){
		setTitle("2048小游戏");//标题
		setSize(370, 520);//设置窗体大小
		Color blue=new Color(99,184,255);
		getContentPane().setBackground(blue);//设置默认背景颜色
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭后进程退出
		setLocationRelativeTo(null);//居中
		setResizable(false);//设置窗体不允许改变
}
	}

GamePanel.java

package new2048;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.*;
import javax.swing.event.AncestorListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.security.PublicKey;


public class GamePanel extends JPanel implements ActionListener{
	private JFrame frame=null;//创建一个JFrame变量
	private GamePanel panel=null;//创建一个画布变量
	private static final int Long =4;
	private static final int High =4;
	private Card[][] cards = new Card [Long][High] ;
	private String gameFlag = "start";
	private boolean isadd = true;  // 是否新增数字
	JLabel lscore = new JLabel("0", JLabel.CENTER);
	
	public GamePanel(JFrame frame){
		this.setLayout(null);//设置布局为空
		this.setOpaque(false);//设置不透明
		this.frame=frame;//使frame为传入的参数
		this.panel=this;//设panel为new生成的对象
		
		createMenu();//创建菜单
		createLapel();//创建标签
		createCard();//创建卡片
		createRandomNum();//随机生成数字
		createKeyListener();//键盘监听
}
   
	//键盘监听方法
	private void createKeyListener() {
		KeyAdapter l = new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {//监听按下键盘
				if(!"start".equals(gameFlag)) //如果游戏结束则返回
					return ;
				int key = e.getKeyCode();
				switch (key) {
				//向上
					case KeyEvent.VK_UP:
					case KeyEvent.VK_W:
						moveCard(1);
						break;
				//向下
					case KeyEvent.VK_DOWN:
					case KeyEvent.VK_S:
						moveCard(2);
						break;	
						
				//向左
					case KeyEvent.VK_LEFT:
					case KeyEvent.VK_A:
						moveCard(3);
						break;	
						
				//向右
					case KeyEvent.VK_RIGHT:
					case KeyEvent.VK_D:
						moveCard(4);
						break;
				}
			}
		};
		frame.addKeyListener(l);		
	}
		//按下键盘移动卡片
		private void moveCard(int fx){
			clearCard();
			sumScore();
			
				if(fx==1){
					moveCardTop(true);
				}
				else if(fx==2){
					moveCardBottom(true);

				}
				else if(fx==3){
					moveCardLeft(true);

				}
				else if(fx==4){
					moveCardRight(true);
				}
				createRandomNum();//移动后再随机生成数字
				repaint();//重绘卡片
				gameOverOrNot();//判断游戏结束
			}
		
		//计算累计分数
		/*分数算法,自己瞎想的,大概就是遍历每个卡片的数字,然后加起来*/
		int sum=0;
		public int sumScore() {
			Card ovo;
			System.out.println(sum);
			//遍历所有卡片
			sum=0;
			for (int i = 0; i < Long; i++) {
				for (int j = 0; j < High; j++) {
					ovo = cards[i][j];
					sum=sum+ovo.getNum();
				}
			}
			return sum;
		}
		
		//判断游戏是否结束
		private void gameOverOrNot() {
		/*结束条件:
		1.达到2048
		2.卡片已满
		3.没有可以合并的卡片*/
			
		lscore.setText(sum+"");
		
		if(isWin()){//胜利
				gameWin();
		}
		//位置已满
		else if(cardFull())
		{
			if(
			//只要有一个方向可以移动或者合并,表示没结束
				moveCardTop(false)||
				moveCardRight(false)||
				moveCardBottom(false)||
				moveCardLeft(false))
			{
			
				return ;
		//游戏失败
		}else{
			gameOver();
			}
				}
		}
		
		/*自己写的笨办法,通过给win和over赋值判断,因为布尔值有点混*/
		int pd=0;
		//游戏胜利
		private int gameWin() {
			return pd=1;
		}
		//游戏结束
		private int gameOver() {
			return pd=2;
		}
		
		//判断是否胜利
		private boolean isWin(){
			Card card;
			//遍历所有卡片
			for (int i = 0; i < Long; i++) {
				for (int j = 0; j < High; j++) {
					card = cards[i][j];
					//如果有2048
					if(card.getNum()==2048){
						return true;
					}
				}
			}
			return false;
		}
		//清理卡片的合并标记
		private void clearCard() {
			Card card;
			for (int i = 0; i < Long; i++) {
				for (int j = 0; j < High; j++) {
					card = cards[i][j];
					card.setMerge(false);
				}
			}
		}
		//向上移动
	private boolean moveCardTop(boolean bool) {
			boolean res = false;
			Card card;
			for (int i = 1; i < Long; i++) {
				for (int j = 0; j < High; j++) {
					card = cards[i][j];
					if(card.getNum()!=0){//数字不为0
						if(card.moveTop(cards,bool)){
							res = true;
						}
					}
				}
			}
			return res;
		}
	//向下移动
	private boolean moveCardBottom(boolean bool) {
		boolean res = false;
		Card card;
		for (int i = Long-1; i >=0; i--) {
			for (int j = 0; j < High; j++) {
				card = cards[i][j];
				if(card.getNum()!=0){
					if(card.moveBottom(cards,bool)){
						res = true;
					}
				}
			}
		}
		return res;
			}
	//向左移动
	private boolean moveCardLeft(boolean bool) {
		boolean res = false;
		Card card;
		for (int i = 0; i < Long; i++) {
			for (int j = 1; j < High ; j++) {
				card = cards[i][j];
				if(card.getNum()!=0){
					if(card.moveLeft(cards,bool)){
						res = true;
					}
				}
			}
		}
		return res;
	}	
	//向右移动
	private boolean moveCardRight(boolean bool) {
		boolean res = false;
		Card card;
		for (int i = 0; i =0 ; j--) {
				card = cards[i][j];
				if(card.getNum()!=0){
					if(card.moveRight(cards,bool)){
						res = true;
					}
				}
			}
		}
		return res;
	}

	//随机好显示的数字是2或者4
	private void createRandomNum() {
		int num=0;
		Random r = new Random();
		int n = r.nextInt(5);//随机取出0-4
		if(n == 0) {
			num = 4;
		}
		else{
			num = 2;
		}
		if(cardFull()){
			return ;
		}

		Card card = getRandomCard(r);//随机一张card
		if(card!=null){
 			card.setNum(num);
	
		}
	}
	

	private Card getRandomCard(Random r) {//获取随机卡片
		int i = r.nextInt(Long);//i,j坐标随机
		int j = r.nextInt(High);
		
		Card kp = cards[i][j];
		if(kp.getNum()==0){//如果找到空白卡片,就返回该卡片
			return kp;
		}
		else {
			return getRandomCard(r);
		}
		
	}
	//判断卡片是否满了
	private boolean cardFull() {
		Card card;
		for (int i = 0; i < Long; i++) {
			for (int j = 0; j < High; j++) {
				card = cards[i][j];
				if(card.getNum()==0){
					return false;
				}
			}
		}		
		return true;
	}
	
	//创建卡片
		private void createCard() {
		Card card;
		for (int i = 0; i < Long; i++) {
			for (int j = 0; j < High; j++) {
				card = new Card(i,j);
				cards[i][j]=card;
			}
		}
	}
	//绘制面板
	@Override
	public void paint(Graphics g){
		super.paint(g);
		drawCard(g);
		Font title = new Font("微软雅黑", Font.BOLD, 30);
		Font title2 = new Font("微软雅黑", Font.BOLD, 30);
	        //如果游戏成功
	        if (pd==1) {
	            g.setColor(new Color(64, 64, 64, 150));
	            g.fillRect(0, 0, getWidth(), getHeight());  //画矩形
	            g.setColor(Color.RED);  // 画笔颜色为红色
	            g.setFont(title);
	            FontMetrics fm = getFontMetrics(title);
	            String value = "恭喜你达到了2048!";
	            g.drawString(value,
	                    (getWidth() - fm.stringWidth(value)) / 2,
	                    getHeight() / 2);
	          //位置
	        }
	        //游戏失败
	        if (pd==2){
	            g.setColor(new Color(64, 64, 64, 150));
	            g.fillRect(0, 0, getWidth(), getHeight());  // 画矩形
	            g.setColor(Color.WHITE);  // 画笔颜色为白色
	            g.setFont(title2);
	            FontMetrics fm = getFontMetrics(title);
	            String value = "下次加油!";  /*不知道写什么比较好,可以改*/
	            g.drawString(value,
	                    (getWidth() - fm.stringWidth(value)) / 2,
	                    getHeight() / 2);
	            
	        } 
	        //游戏重新开始
	        if(pd==3) {
	        	g.setColor(new Color(64, 64, 64, 0));
	        	g.fillRect(0, 0, getWidth(), getHeight());  //画矩形
	        }
	    }

	//绘制卡片
	private void drawCard(Graphics g) {
		Card card;
		for (int i=0;i

Card.java

package new2048;

import java.awt.Graphics;
import java.awt.Font;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;

public class Card {
	private int x=0; //x坐标
	private int y=0; //y坐标
	private int w=80;//宽
	private int h=80;//高
	private int i=0;//下标i
	private int j=0;//下标j
	
	private int xstart=5;//x方向偏移量
	private int ystart=105;//y方向偏移量
	private int num=0;//数字
	private boolean merge = false;//是否合并,如果已经合并则不能再合并
	
	public Card(int i,int j){
		this.i=i;
		this.j=j;
		
		}
	//计算坐标
	private void sol() {
		this.x = xstart + j*w +(j+1)*5;//偏移量+第几个*宽度+中间间隔
		this.y = ystart + i*h +(i+1)*5;
		
	}
	
	//绘制卡片
	public void draw(Graphics g) {
		sol();
		//根据数字获取对应的颜色
		Color newcolor = getColor();
		Color oldcolor= g.getColor();
		
		//设置新颜色
		g.setColor(newcolor);

		g.fillRoundRect(x,y,w,h,4,4);//绘制圆角矩形
		
		if(num!=0){
			g.setColor(new Color(248,248,255));
			Font n = new Font("微软雅黑",Font.BOLD,28);
			String text = num+"";
			g.setFont(n);
			int textLen = getWordWidth(n,text,g);//获取文字长度
			int tx = x +(w-textLen)/2;//原始坐标+(宽度-字符长度)/2,居中
			int ty = y + 52;
			g.drawString(text,tx,ty);
			}

		//还原颜色
		g.setColor(oldcolor);
	}
	
	//获取字体长度
	public static int getWordWidth(Font font,String content,Graphics g) {
			FontMetrics metrics = g.getFontMetrics(font);
			int width = 0;
			for (int i = 0; i < content.length(); i++) {
			width += metrics.charWidth(content.charAt(i));
			}
			return width;
    }
	
	private Color getColor(){
		Color color=null;
		switch (num) {
		case 2:
			color = new Color(142,229,238);
			break;
		case 4:
			color = new Color(135,206,250);
			break;
		case 8:
			color = new Color(100,149,237);
			break;
		case 16:
			color = new Color(70,130,180);
			break;
		case 32:
			color = new Color(65,105,225);
			break;
		case 64:
			color = new Color(132,112,255);
			break;
		case 128:
			color = new Color(123,104,238);
			break;
		case 256:
			color = new Color(106,90,205);
			break;
		case 512:
			color = new Color(58,95,205);
			break;
		case 1024:
			color = new Color(0,154,205);
			break;
		case 2048:
			color = new Color(16,78,139);
			break;

		default://卡片默认颜色
			color = new Color(24,116,205);
			break;
		}
		
		return color;
	}
	
	public int getNum() {
		return num;
	}
	
	public void setNum(int num) {
		this.num=num;
		
	}
	//向上移动的方法
	public boolean moveTop(Card[][] cards,boolean bool) {
		//设定递归的退出条件
		if(i==0){
			return false;
		}
		//上一个卡片
		Card prev = cards[i-1][j];
		//交换上去的
		if(prev.getNum()==0){
	
			if(bool){
				prev.num=this.num;
				this.num=0;
				prev.moveTop(cards,bool);
			}
			return true;
			//要合并
		}else if(prev.getNum()==num && !prev.merge){
			if(bool){
				prev.merge=true;
				prev.num=this.num*2;
				this.num=0;
			}
			return true;
		}else {
			return false;
		}
	}
	//向下移动的方法
	public boolean moveBottom(Card[][] cards,boolean bool) {
		//设定递归的退出条件
		if(i==3){
			return false;
		}
		//上一个卡片
		Card old = cards[i+1][j];
		//空白卡片直接移动
		if(old.getNum()==0){
			if(bool){
				old.num=this.num;
				this.num=0;
				
				old.moveBottom(cards,bool);
			}
			return true;
		//合并
		}else if(old.getNum()==num && !old.merge){
			if(bool){
				old.merge=true;
				old.num=this.num*2;
				this.num=0;
			}
			return true;
		}else {
			return false;
		}
	
	}
	//向左移动
	public boolean moveLeft(Card[][] cards,boolean bool) {
		//设定递归的退出条件
		if(j==0){
			return false;
		}
		
		Card old = cards[i][j-1];
		if(old.getNum()==0){
			if(bool){
				old.num=this.num;
				this.num=0;
				old.moveLeft(cards,bool);	
			}
			return true;
		}else if(old.getNum()==num && !old.merge){
			if(bool){
				old.merge=true;
				old.num=this.num*2;
				this.num=0;
			}
			return true;
		}else {
			return false;
		}
	}
	//向右移动
	public boolean moveRight(Card[][] cards,boolean bool) {
		if(j==3){
			return false;
		}
		Card old = cards[i][j+1];
		if(old.getNum()==0){

			if(bool){
				old.num=this.num;
				this.num=0;
				old.moveRight(cards,bool);
			}
			return true;
		}else if(old.getNum()==num && !old.merge){
			if(bool){
				old.merge=true;
				old.num=this.num*2;
				this.num=0;
			}
			return true;
		}else {
			return false;
		}
	}
	
	public boolean isMerge() {
		return merge;
	}
	public void setMerge(boolean merge) {
		this.merge = merge;
	}
}





进阶功能:

以上代码应该有点bug,但是忘记是哪个版本了,但是基础功能应该没问题。

后续修改了积分bug和失败后新游戏bug,增加了排行榜,增加了登录页面,添加了背景和logo。代码就不放上来了。

大作业:JAVA实现2048小游戏_第2张图片

演示效果: 

(有bgm慎点,刚好那个时候在放歌)

2048小游戏演示

你可能感兴趣的:(java学习,java,jvm,开发语言)