Java课程设计 俄罗斯方块.docx
《Java课程设计 俄罗斯方块.docx》由会员分享,可在线阅读,更多相关《Java课程设计 俄罗斯方块.docx(15页珍藏版)》请在冰豆网上搜索。
Java课程设计俄罗斯方块
课程设计报告
(本科)
课程:
Java语言程序设计
学号:
1010411008
1010411024
1010411076
姓名:
李思贤马军福董国运
班级:
计算机科学与技术(计算机应用)
教师:
时间:
计算机科学与技术系
设计名称:
俄罗斯方块
设计内容、目的与要求:
要求:
界面美观,功能布局合理;要求具有左右移动以及反转的功能;完成俄罗斯方块游戏的基本操作功能,并能够显示失败和胜利的信息。
计划与进度安排:
12月17日~12月21日:
完成选题,并且弄明白本次课程设计的具体要求;
12月21日~12月23日:
通过各种方式进行相关资料的收集,包括上网,查阅相关资料,学习相关的要求知识。
这段时间内我们小组成员自学了jpanel中使用Graphics类的知识,键盘触发事件的知识、以及Timer类的知识。
12月24日~12月27日:
小组成员讨论本程序的大致框架,划分出所需函数的各自功能,小组分工,马军福负责函数实现功能大致要求,列出程序功能表,划分各数据成员的具体功能。
李思贤和董国运负责各个函数功能的具体实现,两个人密切合作,最终每一个人完成各自负责的函数,并且两个人详细的列出了各函数的接口数据的详细说明。
到28日时候所有程序组件合并。
12月28日~12月30日:
小组成员在一起对函数之间的接口错误,以及变量命名错误进行了修改,在这个过程中遇到的问题最多,进度比较慢,我们三个人多次共同商议各函数的功能,对一些函数的功能进行了返工修改,实现了各函数之间的功能协调。
12月31日~1月2日:
小组完成课程设计报告的正式版。
设计过程、步骤(可加页):
设计说明:
1.这个程序定义了两个类,一个是BlockFrame类,另一个是Block类。
前一个负责整体外部布局,后一个负责方块的变化过程的显示,这两个类分别继承了Jframe类和Jpanel类,所以在整个程序运行过程中大量调用了父类的成员方法。
(1):
第一个类BlockFrame类的setSize()函数用于设置整个框架的大小,setTitle()函数用于设置框架标题的显示,setResizable()用于框架大小不可调整的设置。
(2):
第二个类Block调用了paintComponent()函数,先声明一个Graphics对象g,依照内部map数组的数据调用g.fillRect()进行方块的显示,并且调用了repaint()成员方法进行重新刷新方块面板的显示。
2.为了让使用者及时感觉到方块界面的动态,这个程序使用了Timer类,用于定时刷新面板。
3.内部数据的操作过程全部封装在类Block中,成员变量有blockType、score、turnSate、x、y、i、j和flag以及三维数组shapes[][][],二维数组map[][]。
blockType代表方块类型,一共有7种方块类型。
Score代表游戏过程中的积分,turnSate代表翻转状态,对于每一个方块分别有四种状态。
x和y代表运行的方块的坐标,(x,y)这个点是4*4方块最左上方的那个小方块,而这个坐标是相对于map[][]数组来说的。
i和j用于map[][]数组的遍历,起到一个数组元素定位的参数作用。
flag用于判断在面板中是否已经有一个运行的方块,如果有flag值=1就创建一个新的移动的方块在面板中。
三维数组shapes[][][]是表示一个方块的内部数据,一个方块一共有16个点,在空间中排列以4*4的方式显示出来,值为1的点代表实心,值为0的点代表空心。
Map函数是整个面板所对应的内部数据,值为1的点代表实心,值为0的点代表空心。
4.为了实现对map[][]和shapes[][][]的操作,我们分别定义了newblock()函数、drawwall()函数、newmap()函数、turn()函数、left()函数、right()函数、down()函数、blow()函数、delline()函数、gameover()函数和add()
(1):
newblock()函数的作用是随机生成任何一种类型的方块,采用math.Random()实现随机选择。
(2):
newmap()函数用于初始化地图。
(3):
drawwall()函数就是对面板中表示围墙的数据进行赋值。
(4):
turn()函数用于方块旋转的实现,也是仅仅对turnState的值进行合法修改。
(5):
left()函数用于方块左移的实现,是对x的值进行进行减1合法修改。
(6):
right()函数用于方块右移的实现,是对x的值进行进行加1合法修改。
(7):
down()函数用于方块左移的实现,是对y的值进行进行加1合法修改。
(8):
blow()函数用于判断方块是否到底以及是否触碰到其他已经到底的方块。
返回值为1表示可以继续下移、变换。
返回值为0表示已经到底或者触碰到其他已经到底的方块。
这个函数主要起到一个辅助其他函数实现功能的作用。
(9):
delline()函数通过操作map[][]数组实现消行功能。
(10):
gameover()函数表示面板中方块已满,游戏结束。
(11):
add()函数的作用是把到底的方块数据shapes转给面板数据map。
5.第二个类Block还继承了KeyListener接口,用于实现键盘触发事件与程序的结合,通过编写键盘的按钮触发事件调用内部函数。
从而实现玩家和内部数据的交互。
功能结构:
结果与分析(可以加页):
(1):
游戏结束时的界面
(2):
游戏中对方块进行变形的前后对比
变形前:
变形后:
(3)消行后分值的变化:
(4):
实现左移的操作:
变化前:
变化后:
(5):
实现右移的操作:
变化前:
变化后:
整个游戏界面分为两层,第一层是整个框架,第二层是面板。
面板又分为两部分,第一部分是方块的操作区,第二部分包括score,代表游戏得分,还有我们小组成员的姓名及学号的静态显示。
这个方块游戏程序可以实现对界面中方块的左移、右一、下移和变换的控制,并且每消一行后可以获得10分值,分值一直累加下去。
当面板内的空间填满的时候,方块无法下移,与顶端接触,到此游戏结束。
游戏本身实现了功能要求的基本功能,程序代码短,结构清晰、明确。
通过键盘中的方向键的上键、下键、左键、右键分别对应方块的变形、下移、左移和右移的功能,操作简单。
但是,本程序确实存在许多的缺点,比如没有调用JMenu的功能,不能实现对游戏的设置,比如难易程度、不同的风格以及缺少最重要的功能,就是对游戏的暂停、结束、重新开始的操作。
设计体会与建议:
通过这次的课程设计,我更加了解java语言,学会更好的使用java语言函数调用和结构体等,把学过的知识运用于实践中,而不仅仅停留于对课本的单纯理解;设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所在,也暴露出了前期我在这方面的知识欠缺和经验不足。
这次设计也让我知道我懂的太少,要学习的东西还有很多。
想完成一项功能就要用很复杂的语句去实现,所以整个程序变的很长,复杂,但是如果前期工作如果准备的比较充分,如程序的总体功能的明确,以及各函数功能的细分又可使程序的编写工作变的简单,这将大大降低编写的难度。
实验过程中,也对团队精神的进行了考察,让我们在合作起来更加默契,在成功后一起体会喜悦的心情。
在今后社会的发展和学习实践过程中,一定要不懈努力,不能遇到问题就想到要退缩,一定要不厌其烦的发现问题所在,然后一一进行解决,只有这样,才能成功的做成想做的事。
packagerussia1;
importjava.awt.*;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
importjava.awt.event.KeyEvent;
importjava.awt.event.KeyListener;
importjavax.swing.*;
importjavax.swing.Timer;
publicclassBlockFrameextendsJFrame{
publicBlockFrame(){
Blocka=newBlock();
addKeyListener(a);
add(a);
}
publicstaticvoidmain(String[]args){
BlockFrameframe=newBlockFrame();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(240,240);
frame.setTitle("计算机应用");
frame.setVisible(true);
frame.setResizable(false);
}
}
classBlockextendsJPanelimplementsKeyListener{
privateintblockType;
privateintscore=0;
privateintturnState;
privateintx;
privateinty;
privateinti=0;
intj=0;
intflag=0;
int[][]map=newint[13][23];
privatefinalintshapes[][][]=newint[][][]{
{{0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0},
{0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0},
{0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0},
{0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}},
{{0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0},
{1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0},
{0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0},
{1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}},
{{1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0},
{0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0},
{1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0},
{0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0}},
{{0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0},
{1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},
{1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0},
{1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0}},
{{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},
{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},
{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},
{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}},
{{1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0},
{1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0},
{1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0},
{0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0}},
{{0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0},
{0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0},
{1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0},
{0,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0}}};
publicvoidnewblock(){
blockType=(int)(Math.random()*1000)%7;
turnState=(int)(Math.random()*1000)%4;
x=4;
y=0;
if(gameover(x,y)==1){
newmap();
drawwall();
score=0;
JOptionPane.showMessageDialog(null,"GAMEOVER");
}
}
publicvoiddrawwall(){
for(i=0;i<12;i++){
map[i][21]=2;
}
for(j=0;j<22;j++){
map[11][j]=2;
map[0][j]=2;
}
}
publicvoidnewmap(){
for(i=0;i<12;i++){
for(j=0;j<22;j++){
map[i][j]=0;
}}}
Block(){
newblock();
newmap();
drawwall();
Timertimer=newTimer(1000,newTimerListener());
timer.start();
}
publicvoidturn(){
inttempturnState=turnState;
turnState=(turnState+1)%4;
if(blow(x,y,blockType,turnState)==1){
}
if(blow(x,y,blockType,turnState)==0){
turnState=tempturnState;
}
repaint();
}
publicvoidleft(){
if(blow(x-1,y,blockType,turnState)==1){
x=x-1;
}
repaint();
}
publicvoidright(){
if(blow(x+1,y,blockType,turnState)==1)
{
x=x+1;
}
repaint();
}
publicvoiddown(){
if(blow(x,y+1,blockType,turnState)==1)
{
y=y+1;
delline();
}
if(blow(x,y+1,blockType,turnState)==0){
add(x,y,blockType,turnState);
newblock();
delline();
}
repaint();
}
publicintblow(intx,inty,intblockType,intturnState){
for(inta=0;a<4;a++){
for(intb=0;b<4;b++){
if(((shapes[blockType][turnState][a*4+b]==1)&&(map[x
+b+1][y+a]==1))||((shapes[blockType][turnState][a*4+b]==1)&&(map[x+b+1][y+a]==2)))
{
return0;
}
}
}
return1;
}
publicvoiddelline(){
intc=0;
for(intb=0;b<22;b++){
for(inta=0;a<12;a++){
if(map[a][b]==1){
c=c+1;
if(c==10){
score+=10;
for(intd=b;d>0;d--){
for(inte=0;e<11;e++){
map[e][d]=map[e][d-1];
}
}
}
}
}
c=0;
}
}
publicintgameover(intx,inty){
if(blow(x,y,blockType,turnState)==0){
return1;
}
return0;
}
publicvoidadd(intx,inty,intblockType,intturnState){
intj=0;
for(inta=0;a<4;a++){
for(intb=0;b<4;b++){
if(map[x+b+1][y+a]==0){
map[x+b+1][y+a]=shapes[blockType][turnState][j];
}
j++;
}
}
}
publicvoidpaintComponent(Graphicsg){
super.paintComponent(g);
for(j=0;j<16;j++){
if(shapes[blockType][turnState][j]==1)
{
g.fillRect((j%4+x+1)*10,(j/4+y)*10,10,10);
}
}
g.drawString("score="+score,125,10);
g.drawString("姓名:
马军福",125,50);
g.drawString("学号:
1010411024",125,70);
g.drawString("姓名:
董国运",125,90);
g.drawString("学号:
1010411008",125,110);
g.drawString("姓名:
李思贤",125,130);
g.drawString("学号:
1010411076",125,150);
for(j=0;j<22;j++){
for(i=0;i<12;i++){
if(map[i][j]==1){
g.fillRect(i*10,j*10,10,10);
}
if(map[i][j]==2){
g.drawRect(i*10,j*10,10,10);
}
}
}
}
publicvoidkeyPressed(KeyEvente){
switch(e.getKeyCode()){
caseKeyEvent.VK_DOWN:
down();
break;
caseKeyEvent.VK_UP:
turn();
break;
caseKeyEvent.VK_RIGHT:
right();
break;
caseKeyEvent.VK_LEFT:
left();
break;
}
}
publicvoidkeyReleased(KeyEvente){
}
publicvoidkeyTyped(KeyEvente){
}
classTimerListenerimplementsActionListener{
publicvoidactionPerformed(ActionEvente){
repaint();
if(blow(x,y+1,blockType,turnState)==1){
y=y+1;
delline();
}
if(blow(x,y+1,blockType,turnState)==0){
if(flag==1){
add(x,y,blockType,turnState);
delline();
newblock();
flag=0;
}
flag=1;
}
}
}
}