dinary 发表于 2016-11-12 10:55

俄罗斯方块C语言版

一、问题描述
该程序是一个简易俄罗斯方块的任务,其完成几个重要的功能:游戏界面、方块的下落,旋转,左右的移动,判断是否能够继续下落,速度的设置,清除满的行,计算成绩,下个方块的预览等。
二、需求分析
1、界面
作为一个游戏,界面不能太简陋,首先大小要适当。而且颜色不能单调,还要把光标隐藏。
2、操作方法
还是用用户友好性较强的方向键,↑表示图形的旋转,→表示左移,↓表示加速,←表示右移,空格暂停。这就要用到ASCII码来判断用户按键。
3、产生方块
产生方块要求随机性,一个是方块随机,一个是方块的方向也要随机。
4、方块的移动
方块的自由下落,左右移动,加速下落以及旋转都需要想办法实现。
5、检查方块是否满足消除条件。
每次有方块下落到底,都要检查每行是否满足消除的条件,若符合就需要进行消除,并计入成绩。

三、主要问题分析
1.首先界面的问题,窗口大小,控制台字符颜色以及光标的隐藏,这必然要用到Windows API,SetConsoleScreenBufferSize();用来设置缓冲区大小 SetConsoleWindowInfo();用来设置窗口大小,然后 用SetConsoleCursorInfo()隐藏光标的闪烁。
2.接下来就是最主要的游戏容器问题,结合游戏需要完成的功能和控制台编程的特性,以及我们在原始那种小游戏机上的经验。我们可以通过类“像素”的方法,把界面看做成像素点的集合,然后一切的游戏进行都可以通过对像素点的操作来实现。于是可以用一个二维的数组,container 来实现。这个数组中的每个点都是一个像素点,但是要注意的是一个方格要用一个纵坐标两个横坐标。然后就相当于是建立了一个坐标系:
//■                                       ■
//■         ■ ■                     ■
//■            ■                     ■
//■            ■                     ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■                                       ■
//■ ■ ■ ■ ■ ■ ■ ■ ■         ■ ■ ■ ■■
//■ ■ ■ ■ ■ ■ ■ ■      ■ ■ ■ ■ ■ ■ ■
//■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■
// 12 345 678 9 10 11 12 13 14 15 16 17
这样可以使问题得到很大的简化,所有的运动变化的问题都变成了静止打印的问题。附带的我们需要定义一个函数:
void gotoxy(int x,int y){
        HANDLE app;
        COORDpos;
        pos.X=x;
        pos.Y=y;//X表示横坐标,Y表示纵坐标
        app=GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleCursorPosition(app,pos);
本来以为conio.h头文件应该会有这个函数,没想到Dev里好像没有定义,因此需要自己通过Windows API自己来定义。这个函数的功能就是可以将光标定位到缓冲区里的任意位置。
3.有了游戏界面的像素化,方块就是由4个像素拼出来的图形,而这四个像素作为一个整体是相互联系的,本来考虑到可不可以用链表来实现,用一个四个节点的链表,每个节点来存储一个坐标,操作的时候对链表节点的坐标统一进行操作,但是这无疑会增加很多抽象的东西,带来很大的难度。然后就考虑用数组,用一个4*4的二维数组来存储像素点的有无,这样就能表现出方块的图形。所有一切对方块的操作都变成了对二维数组的操作。
4.方块的旋转问题。这个问题有两种解决办法。
第一种方法是,把一共7种方块的每种旋转状态都用数组定义出来,然后根据旋转直接进行二维数组的替换就可以了。这样就需要定义一共4+4+2+2+4+1+2=19种不同的二维数组。大大增加了内存的使用和代码的长度,于是想到利用图形旋转坐标的关系。
block_next=block_transit;//顺时针旋转90度
block_next=block_transit;//顺时针旋转180度
block_next=block_transit;//顺时针旋转270度
这样的话,只需要定义基本的7种不同的方块,然后所有的旋转都通过坐标的这种关系来实现。
5.暂停的问题。
实现暂停本来是想通过打印的方法,也就是说只要调用暂停的函数,就实现保存当前界面的数组情况,然后清屏函数清屏,等再次击键就把保存的数组还原出来。但是最后发现,其实最最简单的方法是用getch()函数,因为它自带一个等待用户输入的效果,所以暂停的效果一个库函数就实现了。但是这也有一定的弊端,就是不管输入的是什么字符都会开始,理想状态下是只有空格键才可以。
6.消除问题。
有了游戏界面的像素化,数组化,判断是否符合消除条件,只需要一个简单的遍历就行,从上一个方块的落点行向上遍历4行(因为一个方块只能影响4行),然后每行从头遍历到尾,一旦有数组元素为零就可以continue执行下一行遍历,直到遇到满行的。这里一个需要注意的点就是消除一行以后,上面所有行的纵坐标都要-1。
7.除此以外,其他的问题都是简单的数组操作问题了。
四、逻辑架构
        生成界面样式和欢迎界面;
        通过生成随机数来随机生成方块;
        通过一个死循环使游戏不断进行:(游戏进行时)
        将方块定位到初始位置
        方块开始下落,设置移动时间间隔
        读取键盘输入使得方块可以上移、左移、右移、旋转
        某一行满了将整行方块消除
        游戏结束则显示的结束页面


I朗朗you 发表于 2016-11-15 12:51

从小小的一个俄罗斯方块游戏,就可以看出,写一个软件是多么的不容易,请大家善待这些人,勿喷!!你觉得人家写的不够好!可以提出宝贵的意见,我想这才是这个论坛最终的目的,《共同学习》

dinary 发表于 2016-11-12 10:55

自占沙发~

a542013194 发表于 2016-11-12 11:08

占楼回复

Zombies 发表于 2016-11-12 11:09

这个不错,初学C语言的可以练练手

散漫小主 发表于 2016-11-12 11:11

俄罗斯方块适合新手

GKK 发表于 2016-11-12 11:12

初学c语言的新人已经保存= =

sunzhitong_1987 发表于 2016-11-12 11:15

从小小的一个俄罗斯方块游戏,就可以看出,写一个软件是多么的不容易,请大家善待这些人,勿喷!!你觉得人家写的不够好!可以提出宝贵的意见,我想这才是这个论坛最终的目的,《共同学习》

pengkang 发表于 2016-11-12 11:19

感谢楼主,初学C语言可以研究下

放肆小恋人 发表于 2016-11-12 11:24

初学语音 瞧瞧代码~

Ezio117 发表于 2016-11-12 11:41

感谢分享!
页: [1] 2 3 4
查看完整版本: 俄罗斯方块C语言版