Java语言程序设计
课程设计
题目 2048游戏的设计与实现
学院数信学院
专业计算机科学与技术
班级计科121 学号 5131
学生姓名郑帅兵
指导教师赵利平
编写日期 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》,其版以后还加入了双人对战。其次比较特别的有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、64、128、256、512、1024、2048.......对应的数字卡片变色
4、游戏的退出:游戏退出时,我们采用弹出对话框的确认玩家是否真的要退出游戏,当然这样做更符合游戏人性化设计的观念。
功能图如下:
四、总体设计
简要设计流程:
程序结构说明:
;
import .*;
import .*;
import .*;
public class Java2048 extends JFrame implements KeyListener{
p rivate static final long serialVersionUID = 1L;
C olor background = new Color(190, 173, 160);ength());
();
}catch(Exception e1){ (null,"找不到同目录下文件或文件已损坏!", "提示", ;
};
}
(0);
}
}
});
restart();
}
v oid restart(){//重新开始
//若是初次运行游戏,则从文件中读入最高分
if(highestScore==0){}
File file=new File("");
BufferedReader br;
try{
br=new BufferedReader(new FileReader(file));
highestScore2=());
();
}catch(Exception e){
(this,"找不到同目录下文件或文件已损坏!", "提示", ;
(0);
};
highestScore=highestScore2;
array=new int[4][4];//清空游戏用2维数组
score=0;//重置分数为零
biggestNumber=0;//重置最大数字为零
//在游戏区随机生成两个2或4
generateRandom2or4();
generateRandom2or4();
}
//绘图方法
public void paint(Graphics g) {
gBuffer=g;
(background);
(30, 40, 185, 90, 20, 20);// 画分数显示区
(30, 40, 185, 90, 20, 20);
(245, 40, 185, 90, 20, 20);// 画最高分显示区
(245, 40, 185, 90, 20, 20);
(0, 150, 454, 460, 10, 10);// 画主游戏区
(0, 150, 454, 460, 10, 10);
(wordFont);
(wordColor);
("SCORE", 90, 70);// 画SCORE
("BEST", 315, 70); // 画BEST
(numberFont);
;
if(score<10){
(score), 110, 115);//画分数数字}else if(score<100){ (score), 100, 115);//画分数数字
}else if(score<1000){
(score), 85, 115);//画分数数字
}else if(score<10000){
(score), 73, 115);//画分数数字
}else if(score<100000){
(score), 60, 115);//画分数数字
}else if(score<1000000){
(score), 50, 115);//画分数数字
}else{
(score), 37, 115);//画分数数字
}
if(highestScore<10){
(highestScore), 325, 115);
//画分数数字
}else if(highestScore<100){
(highestScore), 315, 115);
//画分数数字
}else if(highestScore<1000){
(highestScore), 300, 115);
//画分数数字
}else if(highestScore<10000){
(highestScore), 288, 115);
//画分数数字
}else if(highestScore<100000){
(highestScore), 275, 115);
//画分数数字
}else if(highestScore<1000000){
(highestScore), 265, 115);
//画分数数字
}else{
(highestScore), 252, 115);
//画分数数字
}
(foreground);
f or (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
}
}
f or(int i=0;i<4;i++){
for(int j=0;j<4;j++){
switch (array[i][j]) {
case 2: {
(new Color(238, 228, 218));
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(new Color(122, 113, 104));
(new Font("微软雅黑", , 50));
("2", 45 + j * 112, 230 + i * 113);
break;
}
case 4: {
(new Color(236, 224, 200));
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(new Color(119, 110, 103));
(new Font("微软雅黑", , 50));
("4", 45 + j * 112, 230 + i * 113);
break;
}
case 8: {
(new Color(242, 177, 121));
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(new Color(250, 248, 235));
(new Font("微软雅黑", , 50));
("8", 45 + j * 112, 230 + i * 113);
break;
}
case 16: {
(new Color(245, 149, 101));
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(new Color(252, 244, 242));
(new Font("微软雅黑", , 45));
("16", 33 + j * 112, 230 + i * 111);
break;
}
case 32: {
(new Color(245, 124, 95));
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); (new Color(255, 241, 249));
(new Font("微软雅黑", , 45));
("32", 33 + j * 112, 230 + i * 111);
break;
}
case 64: {
(new Color(246, 93, 59));
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); (new Color(247, 249, 235));
(new Font("微软雅黑", , 45));
("64", 33 + j * 112, 230 + i * 111);
break;
}
case 128: {
(new Color(237, 206, 113));
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); (new Color(248, 246, 255));
(new Font("微软雅黑", , 40));
("128", 23 + j * 112, 228 + i * 111);
break;
}
case 256: {
(new Color(237, 204, 97));
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); (new Color(245, 244, 249));
(new Font("微软雅黑", , 40));
("256", 23 + j * 112, 228 + i * 111);
break;
}
case 512: {
(new Color(235, 201, 78));
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); (new Color(255, 241, 248));
(new Font("微软雅黑", , 40));
("512", 23 + j * 112, 228 +i * 111);
break;
}
case 1024: {
(new Color(237, 197, 63));
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); (new Color(240, 246, 244));
(new Font("微软雅黑", , 35));
("1024", 17 + j * 112, 225 + i * 113);
break;
}
case 2048: {
(new Color(238, 194, 46));
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); (new Color(250, 249, 255));
(new Font("微软雅黑", , 35));
("2048", 17 + j * 112, 225 + i * 113);
break;
}
case 4096: {
(new Color(242, 193, 28));
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); (new Color(248, 246, 255));
(new Font("微软雅黑", , 35));
("4096", 17 + j * 112, 225 + i * 113);
break;
}
case 8192: {
(new Color(236, 173, 57));
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10); (new Color(248, 246, 255));
(new Font("微软雅黑", , 35));
("8192", 17 + j * 112, 225 + i * 113);
break;
}
default: {
(foreground);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
(10 + j * 112, 160 + i * 112, 100, 100, 10, 10);
}
}
}
}
}
p ublic void keyPressed(KeyEvent e) {
if()=={
moveUp();
}else if()=={
moveDown();
}else if()=={
moveLeft();
}else if()=={
moveRight();
}
if(biggestNumber>1024){
switch(biggestNumber){
case 2048:{
if(this, "挑战2048成功!\n是否继续挑战", "提示", =={
biggestNumber++;//防止2048重复判断
}else{
restart();
repaint();
}
break;
}
case 4096:{
if(this, "挑战4096成功!\n是否继续挑战", "提示", =={
biggestNumber++;//防止4096重复判断
}else{
restart();
repaint();
}
break;
}
case 8192:{
if(this, "挑战8192成功!\n是否继续挑战", "提示", =={
biggestNumber++;//防止8192重复判断
}else{
restart();
repaint();
}
break;
}
default:;
}
}
if(judgeFail()){
(this,"挑战失败!", "提示", ;
restart();
repaint();
}
}
@Override
p ublic void keyReleased(KeyEvent e) {
}
@Override
p ublic void keyTyped(KeyEvent e) {
}
//判断是否已经失败,若失败则返回true,否则返回false
public boolean judgeFail(){
for(int j=0;j<4;j++){
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 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;
}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 j=0;j<4;j++){
process[j][0]=array[i][j];
process[j][1]=1;
}
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;
}
}
}
}
for(int i=0;i<4;i++){
for(int j=3;j>-1;j--){
process[3-j][0]=array[i][j];
process[3-j][1]=1;
}
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;
}
}
}
}
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(array[i][j]==0){
return false;
}
}
}
return true;
}
p ublic 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;p ublic void moveDown(){
ifGenerate2or4=false;
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();
}
}
//向左滑动,若各行均没有方块相消或移动,则返回false,否则返回true;p ublic void moveLeft(){
ifGenerate2or4=false;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
process[j][0]=array[i][j];
process[j][1]=1;
}
processProcess();
for(int j=0;j<4;j++){
array[i][j]=process[j][0];
}
}
if(ifGenerate2or4){
generateRandom2or4();
repaint();
}
}
//向右滑动,若各行均没有方块相消或移动,则返回false,否则返回true;p ublic void moveRight(){
ifGenerate2or4=false;
for(int i=0;i<4;i++){
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];
}
}
if(ifGenerate2or4){
generateRandom2or4();
repaint();
}
}
//在游戏区空闲处随机生成2或4
p ublic 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;
}
}
}
int tempI=rd[(rdCount+1)];
if()<{//随机生成2和4,其比例大致为9:1
array[tempI/10][tempI%10]=4;
}else{
array[tempI/10][tempI%10]=2;
}
}
//单行或单列处理方法,若该行或列没有方块相消或移动,则返回false,否则返回true;p ublic void processProcess(){
for(int i=1;i<4;i++){
int k=i;
while(k>0){
if(process[k][0]==0){
break;
}else if(process[k-1][0]==0){
process[k-1][0]=process[k][0];
process[k][0]=0;
k--;
ifGenerate2or4=true;
}else if(process[k-1][0]==process[k][0]){
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){
biggestNumber=process[k-1][0];
}
if(score>highestScore){
highestScore=score;
}
process[k-1][1]=0;
}
break;
}else{
break;
}
}
}
}
}
运行结果:
挑战失败:
退出游戏:
五、总结
通过此次课程设计,使我更加扎实的掌握了有关Java设计方面的知识,在设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所在,也暴露出了前期我在这方面的知识欠缺和经验不足。实践出真知,通过亲自动手制作,使我们掌握的知识不再是纸上谈兵。过而能改,善莫大焉。在课程设计过程中,我们不断发现错误,不断改正,不断领悟,不断获取。最终的检测调试环节,本身就是在践行“过而能改,善莫大焉”的知行观。这次课程设计终于顺利完成了,在今后社会的发展和学习实践过程中,一定要不懈努力,不能遇到问题就想到要退缩。Java课程设计诚然是一门专业课,给我很多专业知识以及专业技能上的提升,同时又是一门讲道课,一门辩思课,给了我许多道,给了我很多思,给了我莫大的空
间。同时,设计让我感触很深。使我对抽象的理论有了具体的认识。我认为,在这学期的实验中,不仅培养了独立思考、动手操作的能力,在各种其它能力上也都有了提高。更重要的是,在实验课上,我们学会了很多学习的方法。而这是日后最实用的,真的是受益匪浅。要面对社会的挑战,只有不断的学习、实践,再学习、再实践。