Java语言程序设计 课程设计
题 目 2048游戏的设计与实现 学 院 数信学院 专 业 计算机科学与技术 班 级 计科121 学 号 201259225131 学生姓名 郑帅兵 指导教师 赵利平 编写日期 2014-7—8
目 录
1。 需求分析 ................................................................................................... 错误!未定义书签。 2. 系统运行环境 ........................................................................................... 错误!未定义书签。 3. 功能需求描述 ........................................................................................... 错误!未定义书签。 4。 总体设计 ................................................................................................... 错误!未定义书签。 5. 程序模块设计 ........................................................................................... 错误!未定义书签。 6。 总结........................................................................................................... 错误!未定义书签。
一、 需求分析
《2048》是比较流行的一款数字游戏.原版2048首先在github上发布,原作者是Gabriele Cirulli.它是基于《1024》和《小3传奇》的玩法开发而成的新型数字游戏[1] 。
随后2048便出现各种版本,走各大平台。由Ketchapp公司移植到IOS的版本最为火热,现在约有1000万下载,其名字跟原版一模一样。衍生版中最 出名的是《2048六边形》版本,先后在全球81个国家中的board game中排进了前200.安卓版非常火爆的有《挑战2048》,其2。0.0版以后还加入了双人对战。其次比较特别的有2048中国朝代版。更有 2048自定义版,可以自己定义文字和图片。《2048》是IOS中流行的一款。
本课程设计通过设计与开发JVM平台上的2048游戏,进一步掌握所学Java课程的知识,体验Java的跨平台性,同时将Java设计方面的知识拓展应用
二、 系统运行环境 1、硬件环境: 2、软件环境:
操作系统:WindowsXP/Windows7
软件:集成开发环境Eclipse 三、
功能需求描述
1、图形用户界面:2048的最大特点就是玩家对图形界面里的数字进行操作,也就是是玩家与游戏的互动
2、当前分数SCORE与最高分数的显示:在我们设计的2048游戏中当前分数取了页面内所有数字相加的值为分数,对玩家玩游戏的进展有直接性、客观性的展现;同时,最高分数取了以往玩家退出游戏时所保存分数的最高分
3、数字颜色:游戏中数字的颜色以2为首项的等比数列变化,即2、4、8、16、32、、128、256、512、1024、2048。.。....对应的数字卡片变色
4、游戏的退出:游戏退出时,我们采用弹出对话框的确认玩家是否真的要退出游戏,当然这样做更符合游戏人性化设计的观念。 功能图如下: 四、
总体设计
简要设计流程:
2048游戏游戏算法画图移动方向
随机数是否结束前景色背景色字体键盘事件鼠标事件
程序结构说明:
//重新开始,若是初次运行游戏,则从文件中读入最高分
void restart()
//控制方法
public void keyPressed(KeyEvent e)
//绘图方法
public void paint(Graphics g)
//判断是否已经失败,若失败则返回true,否则返回false
public boolean judgeFail()
//向下滑动,若各列均没有方块相消或移动,则返回false,否则返回true; public void moveDown() //向左滑动,若各行均没有方块相消或移动,则返回false,否则返回true; public void moveLeft() //向右滑动,若各行均没有方块相消或移动,则返回false,否则返回true; public void moveRight() //向上滑动,若各行均没有方块相消或移动,则返回false,否则返回true; Public void moveUp() //在游戏区空闲处随机生成2或4
public void generateRandom2or4()
五、
源码如下:
Main类:
程序模块设计
import javax。swing。JFrame;
public class Main {
public static void main(String[] args){
JFrame frame=new Java2048(); frame.setTitle(”Java2048\"); frame。setSize(455,610);
frame.setLocationRelativeTo(null);
frame。setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE ); frame.setVisible(true);
} }
Java2048类:
import java。awt。*; import java.awt.event.*; import java.io.*; import java。util.*; import javax。swing。*;
public class Java2048 extends JFrame implements KeyListener{
private static final long serialVersionUID = 1L; Color background = new Color(190, 173, 160);// 背景色 Color foreground = new Color(204, 192, 178);// 前景色 Color wordColor = new Color(232, 216, 203);// 单词色
Font wordFont = new Font(”微软雅黑\", Font。PLAIN, 20);// 单词字体 Font numberFont = new Font(\"微软雅黑”, Font.BOLD, 40);// 数字字体 Random random=new Random();//随机数发生器 int[][] array;//游戏用2维数组
//逐行或逐列处理数组,第一个参数为实际数字,第二个为判断值,用来判断是否应该消除int[][] process=new int [4][2]; int score;//分数,初始化为零 int highestScore;//游戏中最高分 int highestScore2=0;//文件中最高分 int biggestNumber=0; boolean ifGenerate2or4;
相同的数字
int[] rd=new int[16];//生成随机2或4的位置 private Graphics gBuffer; //构造方法
public Java2048(){
addKeyListener(this);
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
if(JOptionPane.showConfirmDialog(null, \"确定退出?”, ”
提示”, JOptionPane。YES_NO_OPTION)==JOptionPane。YES_NO_OPTION){
if(highestScore>highestScore2){//若在本次游戏中破了纪录,则更新
highestScore2=highestScore;
File file=new File(”Java2048beta1.txt”); BufferedWriter bw; try{
bw=new BufferedWriter(new FileWriter(file));
bw。write(String.valueOf(highestScore2),0,
文件中的最高分
String。valueOf(highestScore2)。length());
bw。close(); }catch(Exception e1){
JOptionPane.showMessageDialog(null,”找不到同目录下Java2048beta1。txt
文件或文件已损坏!\", \"提示\", JOptionPane.INFORMATION_MESSAGE); };
}
}
System。exit(0); }
});
restart(); }
void restart(){//重新开始
//若是初次运行游戏,则从文件中读入最高分 if(highestScore==0){}
File file=new File(\"Java2048beta1.txt”); BufferedReader br; try{
br=new BufferedReader(new FileReader(file)); highestScore2=Integer。valueOf(br。readLine());
br。close();
}catch(Exception e){
JOptionPane。showMessageDialog(this,”找不到同目录下Java2048beta1.txt
System。exit(0);
文件或文件已损坏!”, \"提示\", JOptionPane。INFORMATION_MESSAGE);
}
};
highestScore=highestScore2;
array=new int[4][4];//清空游戏用2维数组 score=0;//重置分数为零
biggestNumber=0;//重置最大数字为零 //在游戏区随机生成两个2或4 generateRandom2or4(); generateRandom2or4();
//绘图方法
gBuffer=g;
gBuffer.setColor(background);
gBuffer.drawRoundRect(30, 40, 185, 90, 20, 20);// 画分数显示区 gBuffer。fillRoundRect(30, 40, 185, 90, 20, 20);
gBuffer。drawRoundRect(245, 40, 185, 90, 20, 20);// 画最高分显示区
public void paint(Graphics g) {
字 字 字 字
gBuffer.fillRoundRect(245, 40, 185, 90, 20, 20);
gBuffer.drawRoundRect(0, 150, 454, 460, 10, 10);// 画主游戏区 gBuffer。fillRoundRect(0, 150, 454, 460, 10, 10); gBuffer.setFont(wordFont); gBuffer.setColor(wordColor);
gBuffer。drawString(\"SCORE\", 90, 70);// 画SCORE gBuffer。drawString(\"BEST\", 315, 70); // 画BEST gBuffer.setFont(numberFont); gBuffer.setColor(Color.white);
gBuffer。drawString(String.valueOf(score), 110, 115);//画分数数字}else if(score<100){
gBuffer。drawString(String。valueOf(score), 100, 115);//画分数数字 }else if(score〈1000){
gBuffer。drawString(String.valueOf(score), 85, 115);//画分数数
if(score<10){
}else if(score〈10000){
gBuffer.drawString(String.valueOf(score), 73, 115);//画分数数
}else if(score<100000){
gBuffer.drawString(String.valueOf(score), 60, 115);//画分数数
}else if(score<1000000){
gBuffer.drawString(String.valueOf(score), 50, 115);//画分数数
}else{
gBuffer。drawString(String。valueOf(score), 37, 115);//画分数数
字
}
if(highestScore〈10){
gBuffer.drawString(String.valueOf(highestScore), 325, 115); }else if(highestScore<100){
gBuffer。drawString(String。valueOf(highestScore), 315, 115);
//画分数数字
//画分数数字
}else if(highestScore〈1000){
gBuffer.drawString(String。valueOf(highestScore), 300, 115);
//画分数数字
}else if(highestScore〈10000){
gBuffer。drawString(String.valueOf(highestScore), 288, 115);
//画分数数字
}else if(highestScore<100000){
gBuffer.drawString(String.valueOf(highestScore), 275, 115);
//画分数数字
}else if(highestScore〈1000000){
gBuffer。drawString(String。valueOf(highestScore), 265, 115);
//画分数数字 }else{
gBuffer。drawString(String。valueOf(highestScore), 252, 115); }
gBuffer。setColor(foreground); for (int i = 0; i < 4; i++) {
for (int j = 0; j 〈 4; j++) {
//画分数数字
gBuffer。drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer.fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
}
for(int i=0;i<4;i++){
for(int j=0;j〈4;j++){
switch (array[i][j]) { }
case 2: {
gBuffer.setColor(new Color(238, 228, 218));
gBuffer。drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer。fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
gBuffer。setColor(new Color(122, 113, 104));
gBuffer。setFont(new Font(\"微软雅黑\", Font.BOLD, 50)); gBuffer.drawString(\"2”, 45 + j * 112, 230 + i * 113);
break;
}
case 4: {
gBuffer.setColor(new Color(236, 224, 200));
gBuffer。drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer。fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
gBuffer。setColor(new Color(119, 110, 103));
gBuffer。setFont(new Font(”微软雅黑”, Font.BOLD, 50));
break; }
gBuffer。drawString(”4”, 45 + j * 112, 230 + i * 113);
case 8: {
gBuffer。setColor(new Color(242, 177, 121));
gBuffer。drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer.fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
gBuffer。setColor(new Color(250, 248, 235));
gBuffer。setFont(new Font(”微软雅黑\", Font.BOLD, 50));
gBuffer。drawString(”8\", 45 + j * 112, 230 + i * 113); break;
}
case 16: {
gBuffer.setColor(new Color(245, 149, 101));
gBuffer.drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer.fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
gBuffer.setColor(new Color(252, 244, 242)); gBuffer.setFont(new Font(\"微软雅黑”, Font.BOLD, 45)); gBuffer。drawString(\"16”, 33 + j * 112, 230 + i * 111); break;
}
case 32: {
gBuffer。setColor(new Color(245, 124, 95));
gBuffer。drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer.fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
gBuffer。setColor(new Color(255, 241, 249));
gBuffer.setFont(new Font(”微软雅黑”, Font.BOLD, 45));
break; }
gBuffer.drawString(\"32”, 33 + j * 112, 230 + i * 111);
case : {
gBuffer。setColor(new Color(246, 93, 59));
gBuffer。drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer。fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
gBuffer。setColor(new Color(247, 249, 235));
gBuffer.setFont(new Font(”微软雅黑”, Font。BOLD, 45)); gBuffer.drawString(”\", 33 + j * 112, 230 + i * 111);
}
break;
case 128: {
gBuffer.setColor(new Color(237, 206, 113));
gBuffer。drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer。fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
gBuffer.setColor(new Color(248, 246, 255));
gBuffer。setFont(new Font(”微软雅黑”, Font.BOLD, 40)); gBuffer.drawString(\"128\", 23 + j * 112, 228 + i * 111); break;
}
case 256: {
gBuffer。setColor(new Color(237, 204, 97));
gBuffer。drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer.fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
gBuffer.setColor(new Color(245, 244, 249));
gBuffer。setFont(new Font(”微软雅黑\", Font。BOLD, 40));
gBuffer.drawString(”256\", 23 + j * 112, 228 + i * 111); break;
}
case 512: {
gBuffer.setColor(new Color(235, 201, 78));
gBuffer.drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer。fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
gBuffer。setColor(new Color(255, 241, 248));
gBuffer.setFont(new Font(”微软雅黑\", Font。BOLD, 40));
break; }
gBuffer。drawString(”512”, 23 + j * 112, 228 +i * 111);
case 1024: {
gBuffer.setColor(new Color(237, 197, 63));
gBuffer.drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer。fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
gBuffer。setColor(new Color(240, 246, 244));
gBuffer.setFont(new Font(”微软雅黑\", Font.BOLD, 35)); gBuffer。drawString(”1024\", 17 + j * 112, 225 + i * 113);
break; }
case 2048: {
gBuffer.setColor(new Color(238, 194, 46));
gBuffer。drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer.fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
gBuffer。setColor(new Color(250, 249, 255));
gBuffer.setFont(new Font(\"微软雅黑\", Font。BOLD, 35));
gBuffer。drawString(\"2048\", 17 + j * 112, 225 + i * 113); break;
}
case 4096: {
gBuffer。setColor(new Color(242, 193, 28));
gBuffer。drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer。fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
gBuffer。setColor(new Color(248, 246, 255));
gBuffer。setFont(new Font(”微软雅黑\", Font.BOLD, 35));
gBuffer.drawString(\"4096\", 17 + j * 112, 225 + i * 113); break;
}
case 8192: {
gBuffer.setColor(new Color(236, 173, 57));
gBuffer。drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer。fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
gBuffer。setColor(new Color(248, 246, 255));
gBuffer。setFont(new Font(\"微软雅黑”, Font.BOLD, 35));
gBuffer.drawString(\"8192\", 17 + j * 112, 225 + i * 113); break;
}
default: { gBuffer.setColor(foreground);
gBuffer。drawRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); gBuffer。fillRoundRect(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
}
public void keyPressed(KeyEvent e) {
if(e。getKeyCode()==KeyEvent.VK_UP){
moveUp(); moveDown();
}else if(e.getKeyCode()==KeyEvent.VK_DOWN){ }else if(e。getKeyCode()==KeyEvent.VK_LEFT){ moveLeft(); }else if(e。getKeyCode()==KeyEvent。VK_RIGHT){ moveRight(); }
if(biggestNumber>1024){
switch(biggestNumber){ case 2048:{
if(JOptionPane.showConfirmDialog(this, \"挑战2048成功!\\n
}
}
} }
是否继续挑战?”, \"提示\", JOptionPane。YES_NO_OPTION)==JOptionPane.YES_OPTION){
biggestNumber++;//防止2048重复判断 restart(); }else{
repaint(); }
break; }
case 4096:{
if(JOptionPane.showConfirmDialog(this, ”挑战4096成功!\\n
是否继续挑战?\", ”提示”, JOptionPane。YES_NO_OPTION)==JOptionPane。YES_OPTION){
}
case 8192:{
if(JOptionPane。showConfirmDialog(this, \"挑战8192成功!\\n
} break;
biggestNumber++;//防止4096重复判断 restart(); repaint();
}else{
是否继续挑战?”, \"提示”, JOptionPane。
YES_NO_OPTION)==JOptionPane.YES_OPTION){
}
if(judgeFail()){
}
default:; }
}else{
restart(); repaint();
biggestNumber++;//防止8192重复判断
}
break;
JOptionPane。showMessageDialog(this,\"挑战失败!\", ”提示”, JOptionPane.INFORMATION_MESSAGE);
restart(); repaint(); }
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) { }
//判断是否已经失败,若失败则返回true,否则返回false public boolean judgeFail(){
for(int j=0;j〈4;j++){ }
for(int j=0;j<4;j++){
for(int i=3;i〉-1;i-—){
process[3-i][0]=array[i][j]; process[3-i][1]=1; }
for(int i=1;i〈4;i++){ int k=i;
while(k〉0){ if(process[k][0]==0){
return false; return false;
}else if(process[k-1][0]==0){
}else if(process[k-1][0]==process[k][0]){ return false; }else{ break; }
for(int i=0;i〈4;i++){
process[i][0]=array[i][j]; process[i][1]=1;
}
for(int i=1;i<4;i++){ int k=i; }
while(k〉0){
if(process[k][0]==0){
return false;
}else if(process[k—1][0]==0){ return false;
}else if(process[k—1][0]==process[k][0]){ return false; }else{
break;
} }
}
} }
for(int i=0;i〈4;i++){ }
for(int i=0;i<4;i++){ }
for(int i=0;i〈4;i++){
for(int j=3;j〉—1;j-—){ }
for(int l=1;l<4;l++){ int k=l; }
while(k>0){ }
if(process[k][0]==0){ return false;
}else if(process[k-1][0]==0){
return false; return false;
}else if(process[k—1][0]==process[k][0]){ }else{ break; }
process[3-j][0]=array[i][j]; process[3-j][1]=1; for(int j=0;j<4;j++){ }
for(int l=1;l<4;l++){
int k=l; while(k>0){
if(process[k][0]==0){ return false;
}else if(process[k-1][0]==0){ return false;
}else if(process[k—1][0]==process[k][0]){ return false; }else{ break; }
process[j][0]=array[i][j]; process[j][1]=1;
}
}
}
for(int j=0;j<4;j++){
if(array[i][j]==0){ return false;
} }
}
return true;
public void moveUp(){
ifGenerate2or4=false; for(int j=0;j<4;j++){
for(int i=0;i<4;i++){
process[i][0]=array[i][j]; process[i][1]=1; }
processProcess(); for(int i=0;i<4;i++){
array[i][j]=process[i][0];
} }
if(ifGenerate2or4){
generateRandom2or4(); repaint();
} }
//向下滑动,若各列均没有方块相消或移动,则返回false,否则返回true; public void moveDown(){ ifGenerate2or4=false; }
//向左滑动,若各行均没有方块相消或移动,则返回false,否则返回true;
for(int j=0;j<4;j++){
for(int i=3;i>—1;i--){
process[3—i][0]=array[i][j]; process[3—i][1]=1; }
processProcess(); for(int i=3;i>—1;i-—){
array[i][j]=process[3—i][0];
} }
if(ifGenerate2or4){
generateRandom2or4(); repaint(); }
public void moveLeft(){ ifGenerate2or4=false; }
//向右滑动,若各行均没有方块相消或移动,则返回false,否则返回true; public void moveRight(){ ifGenerate2or4=false; }
//在游戏区空闲处随机生成2或4
public void generateRandom2or4(){
int rdCount=-1;//记录需要生成2或4的位置的数量 for(int i=0;i〈4;i++){
for(int j=0;j〈4;j++){ }
if(array[i][j]==0){ rd[++rdCount]=i*10+j; }
for(int i=0;i<4;i++){ }
if(ifGenerate2or4){
generateRandom2or4(); repaint(); }
for(int j=3;j〉-1;j—-){
process[3—j][0]=array[i][j]; process[3-j][1]=1; }
processProcess(); for(int j=3;j〉-1;j-—){
array[i][j]=process[3—j][0]; }
for(int i=0;i<4;i++){ }
if(ifGenerate2or4){
generateRandom2or4(); repaint(); }
for(int j=0;j〈4;j++){ }
processProcess(); for(int j=0;j<4;j++){
array[i][j]=process[j][0]; }
process[j][0]=array[i][j]; process[j][1]=1;
}
}
}
int tempI=rd[random。nextInt(rdCount+1)];
if(random.nextDouble()〈0。1){//随机生成2和4,其比例大致为9:1 }
array[tempI/10][tempI%10]=4; array[tempI/10][tempI%10]=2; }else{
//单行或单列处理方法,若该行或列没有方块相消或移动,则返回false,否则返回true; public void processProcess(){ for(int i=1;i<4;i++){ }
}
int k=i; while(k〉0){
if(process[k][0]==0){
break;
process[k-1][0]=process[k][0]; process[k][0]=0; k——;
ifGenerate2or4=true; if(process[k—1][1]==1){
ifGenerate2or4=true;
process[k-1][0]=2*process[k][0]; process[k][0]=0; score+=process[k—1][0];
if(process[k—1][0]>biggestNumber){ }
if(score>highestScore){ highestScore=score; }
biggestNumber=process[k-1][0];
}else if(process[k—1][0]==0){
}else if(process[k-1][0]==process[k][0]){
process[k—1][1]=0; } break;
}else{ break;
} }
运行结果:
挑战失败:
退出游戏:
六、
总结
通过此次课程设计,使我更加扎实的掌握了有关Java设计方面的知识,在设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所在,也暴露出了前期我在这方面的知识欠缺和经验不足。实践出真知,通过亲自动手制作,使我们掌握的知识不再是纸上谈兵。过而能改,善莫大焉。在课程设计过程中,我们不断发现错误,不断改正,不断领悟,不断获取。最终的检测调试环节,本身就是在践行“过而能改,善莫大焉\"的知行观.这次课程设计终于顺利完成了,在今后社会的发展和学习实践过程中,一定要不懈努力,不能遇到问题就想到要退缩。Java课程设计诚然是一门专业课,给我很多专业知识以及专业技能上的提升,同时又是一门讲道课,一门辩思课,给了我许多道,给了我很多思,给了我莫大的空间。同时,设
计让我感触很深.使我对抽象的理论有了具体的认识。我认为,在这学期的实验中,不仅培养了思考、动手操作的能力,在各种其它能力上也都有了提高。更重要的是,在实验课上,我们学会了很多学习的方法.而这是日后最实用的,真的是受益匪浅。要面对社会的挑战,只有不断的学习、实践,再学习、再实践。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- aiwanbo.com 版权所有 赣ICP备2024042808号-3
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务