写Java上机大作业,太菜了我就用的别人的代码,自己理解将注释添加好了后,顺便加了一个判断游戏合成2048后的赢得游戏的方法。本来想添加声音,然而我失败了,日后有机会再添加回来嘿嘿嘿嘿嘿
原文链接–如果原博主觉得不太好,记得联系我删除哦
版权声明:本文为CSDN博主「chy-7」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/chan272/article/details/87884333
样式接口 Style
将所用的字体样式大小定义好
package game2048;
import java.awt.*;
public interface Style {
Font topicFont = new Font("微软雅黑", Font.BOLD, 50);
Font scoreFont = new Font("微软雅黑", Font.BOLD, 28);
Font normalFont = new Font("宋体", Font.PLAIN, 20);
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);
int normalFontdata = 20;
int topicFontdata = 30;
void init();
void showView();
}
随机数板块Check
package game2048;
import java.awt.*;
public class Check {
public int value;//一个可共用的产生的随机数的值
public Check() {
clear();
}
public void clear() {
value = 0;//每次产生随机数后又将value值变成0
}
public Color getForeground() {
switch (value) {
case 0:
return new Color(0xcdc1b4);
case 2:
case 4:
return Color.BLACK;//2和数字4都是黑色
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 Style.font1;
}
if (value < 100) {
return Style.font2;
}
if (value < 1000) {
return Style.font3;
}
if (value < 10000) {
return Style.font4;
}
return Style.font5;
}//因为数值越来越大,为了避免分数过大,显示不完全,根据的分位数修改分数的字号
}
窗口以及各种主要方法的View
package game2048;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
import java.util.List;
import java.util.ArrayList;
import java.applet.*;//添加音效的
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
public class View implements Style{
//private static final int jframeWidth = 400;
//private static final int jframeHeight = 530;//定义一个静态的框架长宽不会改变。
private static int score = 0;
private JFrame jframeMain;//将这个主框架重新定义一个名字
private JLabel jlblTitle;//窗口最上头的字显示
private JLabel jlblScoreName;//显示得分这两个字
private JLabel jlblScore;//显示游戏得分
private GameBoard gameBoard;
private JLabel jlblTip;//游戏窗口的中的游戏提示
public View() {
init();
}//构造View
@Override
public void init() {
jframeMain = new JFrame("2048小游戏");//窗口名字
jframeMain.setSize(400, 530);//定义窗口的大小
jframeMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗口右上角的×点后关闭窗口
jframeMain.setLocationRelativeTo(null);//将窗口置于屏幕中央
jframeMain.setResizable(false);//false 代表窗口大小不可以随意更改,ture代表窗口可以拖动大小
jframeMain.setLayout(null);//设置为null即为清空布局管理器,之后添加组件
jlblTitle = new JLabel("2048", JLabel.CENTER);
jlblTitle.setFont(topicFont);
jlblTitle.setForeground(Color.BLACK);//2048颜色
jlblTitle.setBounds(50, 0, 150, 60);
jframeMain.add(jlblTitle);//添加到窗口中,否则不显示
// 分数区
jlblScoreName = new JLabel("得 分");
jlblScoreName.setFont(scoreFont);
jlblScoreName.setForeground(Color.WHITE);
jlblScoreName.setOpaque(true);//原样显示组件中的每个像素,也就是正常显示
jlblScoreName.setBackground(Color.GRAY);//背景色
jlblScoreName.setBounds(250, 0, 120, 30);
jframeMain.add(jlblScoreName);
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);
// 说明:
jlblTip = new JLabel("操作: ↑ ↓ ← →, 按esc键重新开始 ",
JLabel.CENTER);
jlblTip.setFont(normalFont);
jlblTip.setForeground(Color.DARK_GRAY);
jlblTip.setBounds(0, 60, 400, 40);
jframeMain.add(jlblTip);
gameBoard = new GameBoard();
gameBoard.setBounds(0, 100, 400, 400);
gameBoard.setBackground(Color.PINK);
gameBoard.setFocusable(true);
gameBoard.setLayout(new FlowLayout());
jframeMain.add(gameBoard);
}
// 游戏面板需要对键值实现侦听,
// 这里采用内部类来继承 JPanel 类,
// 并实现接口 KeyListener 中的 keyPressed 方法,
// 方格是通过
//@SuppressWarnings("serial")
class GameBoard extends JPanel implements KeyListener {
private Check[][] checks = new Check[4][4];//创建4个游戏格子大小的矩阵
private boolean isadd = true;
public GameBoard() {
initGame();//设置游戏爱是的类
addKeyListener(this);//键盘监听设置
}
@Override
public void keyPressed(KeyEvent e) {//键盘监听
switch (e.getKeyCode()) {
case KeyEvent.VK_ESCAPE:
initGame();
break;
case KeyEvent.VK_LEFT:
moveLeft();
createCheck();
judgeGameOver();
judgeGameWon();
break;
case KeyEvent.VK_RIGHT:
moveRight();
createCheck();
judgeGameOver();
judgeGameWon();
break;
case KeyEvent.VK_UP:
moveUp();
createCheck();
judgeGameOver();
judgeGameWon();
break;
case KeyEvent.VK_DOWN:
moveDown();
createCheck();
judgeGameOver();
judgeGameWon();
break;
default:
break;
}
repaint();
}
//添加音效
/*private void palymusci() {
try {
FileInputStream fileau=new FileInputStream("music/music.wav" );
AudioStream as=new AudioStream(fileau);
AudioPlayer.player.start(as);
}catch (Exception e){
e.printStackTrace();
}
}*/
private void initGame() {
score = 0;
for (int indexRow = 0; indexRow < 4; indexRow++) {
for (int indexCol = 0; indexCol < 4; indexCol++) {
checks[indexRow][indexCol] = new Check();
}
}
// 生成两个数
isadd = true;
createCheck();
isadd = true;
createCheck();
}
private void createCheck() {
List<Check> list = getEmptyChecks();//创建一个连续的数组
if (!list.isEmpty() && isadd) {//判断list是否为空且isadd必须为true
Random random = new Random();
int index = random.nextInt(list.size());//index=(0-数组中的数组多少的个数)
Check check = list.get(index);//获取索引位置为index的元素
check.value = (random.nextInt(4) % 3 == 0) ? 2 : 4;// 2, 4出现概率3:1
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;//返回了空白格子的数组,显示出来
}
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 boolean judgeGameWon() {
int max=0;
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
{
if (checks[i][j].value ==2048)
max=max+1;
else
max=max+0;
}
if(max>0)
return true;
else
return false;
}
private boolean moveLeft() {
for (int i = 0; i < 4; i++) {
for (int j = 1, a = 0; j < 4; j++) {//只用判断每行最后三的与前面值是否相等
if (checks[i][j].value > 0) {
if (checks[i][j].value == checks[i][a].value) {//相等就合并
score += checks[i][a].value*2;//checks[i][a].value值乘以2倍score加上合并后的分数
checks[i][a++].value<<=1;//<<=1是将checks[i][a].value值乘以2赋给checks[i][a++]
checks[i][j].value = 0;
isadd = true;
} else if (checks[i][a].value == 0) {//前面有0的位置,后面的就往左移动
checks[i][a].value = checks[i][j].value;
checks[i][j].value = 0;
isadd = true;
} else if (checks[i][++a].value == 0) {//a与j模块值不相等,判断a右边模块的值,等于0则移动j模块
checks[i][a].value = checks[i][j].value;
checks[i][j].value = 0;
isadd = true;
}
}
}
}
return isadd;
}
private boolean moveRight() {
for (int i = 0; i < 4; i++) {
for (int j = 2, a = 3; j >= 0; j--) {//只用判断每行前面三的与最后值是否相等
if (checks[i][j].value > 0) {
if (checks[i][j].value == checks[i][a].value) {//值相等则合并
score += checks[i][a].value * 2;//checks[i][a].value值乘以2倍score加上合并后的分数
checks[i][a--].value <<= 1;//<<=1是将checks[i][a].value值乘以2赋给checks[i][a--]
checks[i][j].value = 0;
isadd = true;
} else if (checks[i][a].value == 0) {
checks[i][a].value = checks[i][j].value;
checks[i][j].value = 0;
isadd = true;
} else if (checks[i][--a].value == 0) {
checks[i][a].value = checks[i][j].value;
checks[i][j].value = 0;
isadd = true;
}
}
}
}
return isadd;
}
private boolean moveUp() {
for (int i = 0; i < 4; i++) {
for (int j = 1, a = 0; j < 4; j++) {
if (checks[j][i].value > 0) {
if (checks[j][i].value == checks[a][i].value) {
score += checks[a][i].value *2;
checks[a++][i].value <<= 1;
checks[j][i].value = 0;
isadd = true;
} else if (checks[a][i].value == 0) {
checks[a][i].value = checks[j][i].value;
checks[j][i].value = 0;
isadd = true;
} else if (checks[++a][i].value == 0){
checks[a][i].value = checks[j][i].value;
checks[j][i].value = 0;
isadd = true;
}
}
}
}
return isadd;
}
private boolean moveDown() {
for (int i = 0; i < 4; i++) {
for (int j = 2, a = 3; j >= 0; j--) {
if (checks[j][i].value > 0) {
if (checks[j][i].value == checks[a][i].value) {
score += checks[a][i].value *1;
checks[a--][i].value <<= 1;
checks[j][i].value = 0;
isadd = true;
} else if (checks[a][i].value == 0) {
checks[a][i].value = checks[j][i].value;
checks[j][i].value = 0;
isadd = true;
} else if (checks[--a][i].value == 0) {
checks[a][i].value = checks[j][i].value;
checks[j][i].value = 0;
isadd = true;
}
}
}
}
return isadd;
}
@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,150));//darkGray = new Color(64, 64, 64);设置不透明度为150,255位完全不透明
g.fillRect(0, 0, 390, 390);//创建一个灰色模板将游戏界面框起来
g.setColor(Color.WHITE);
g.setFont(topicFont);
//FontMetrics fms = getFontMetrics(topicFont);//FontMetrics类让蚊子居中
String value = "Game Over!";
g.drawString(value,51,220);//显示Gameover,位置在窗口中的横纵坐标
}
//GameWon
else if(judgeGameWon()) {
g.setColor(new Color(255, 200, 0,150));//darkGray = new Color(64, 64, 64);设置不透明度为150,255位完全不透明
g.fillRect(0, 0, 390, 390);//创建一个灰色模板将游戏界面框起来
g.setColor(Color.WHITE);
g.setFont(topicFont);
//FontMetrics fms = getFontMetrics(topicFont);//FontMetrics类让蚊子居中
String value = "You Won!";
g.drawString(value,51,220);//显示Gameover,位置在窗口中的横纵坐标
}
}
// 绘制方格
// Graphics2D 类扩展了 Graphics 类,
// 提供了对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
private void drawCheck(Graphics g, int i, int j) {
Graphics2D gg = (Graphics2D) g;
gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);//使图形去除锯齿状,可以得到细腻的图形。
Check check = checks[i][j];
gg.setColor(check.getBackground());
// 绘制圆角
gg.fillRoundRect(10+ (10 + 86) * j,//x - 要填充矩形的 x 坐标
10 + (10 + 86) * i,// y - 要填充矩形的 y 坐标。
86, // width - 要填充矩形的宽度。
86,// height - 要填充矩形的高度。
20, // arcwidth - 4 个角弧度的水平直径。
20// archeight - 4 个角弧度的垂直直径。
);//fillRoundRect画圆角矩形
gg.setColor(check.getForeground());
gg.setFont(check.getCheckFont());
// 对文字的长宽高测量。
FontMetrics fms = getFontMetrics(check.getCheckFont());
String value = String.valueOf(check.value);//将产生的随机数变成String类型
//使用此图形上下文的当前颜色绘制由指定迭代器给定的文本。
//getAscent()是FontMetrics中的一个方法,它返回某字体的基线(baseline)到该字体中大多数字符的升部(ascender)之间的距离
//getDescent 为降部
gg.drawString(value,
10 + (10 + 86) * j +(86 - fms.stringWidth(value)) / 2,
10 + (10 + 86) * i +(86 - fms.getAscent() - fms.getDescent()) / 2+ fms.getAscent());
}
@Override
public void keyReleased(KeyEvent e) {
}//键被弹起
@Override
public void keyTyped(KeyEvent e) {
}//是指有字符被输入
}
@Override
public void showView() {
jframeMain.setVisible(true);
}
}
简单主函数
package game2048;
public class game2048 {
public static void main(String[] args) {
new View().showView();
}
}