❶ 关于俄罗斯方块的写法
最好办法就是在网上搜一些关与俄罗斯方块的算法,再看看别人的源代码。
❷ java初级俄罗斯方块写法
1:首先自己定义一个类,比如MyLabel,继承jlabel,设置大小比如 (40,40)设置成方块,这就是游戏里面最小的单位,下落的图形,就是四个这个样的单位组合到一起,位置不同。
2:定义自己的图形(就是游戏中下落的部分)比如MyPic ,这个类是控制MyLabel的,一般是4个MyLabel组合成一个MyPic,
3:定义自己的面板,大小是 (n*40,m*40 )就是上面最小单位的整数行和列,然后建一个二位数组
int [n][m],数组里面默认为0,标示这个位置没有MyLabel ,是空的,如果位置有 MyLabel,设置成1
,这个是数组是,图形下落的时候判断是否继续下落还是要停下了,下面有了就停,否则继续下落,下落停止后,根据数组,看某一行是否全部为1 是的话,把这行清空
图形的下落要用定时器或者自己写线程实现,然后就是判断下面是否有东西,是下落,还是停止,
图形的旋转的话,自己研究吧,位置的变换,也不好做
❸ 俄罗斯方块论文怎么写
5月15日 16:34 游戏起源、历史、简介
俄罗斯方块是一款风靡全球的电视游戏机和掌上游戏机游戏,它曾经造成的轰动与造成的经济价值可以说是游戏史上的一件大事。这款游戏最初是由苏联的游戏制作人Alex Pajitnov制作的,它看似简单但却变化无穷,令人上瘾。相信大多数用户都还记得为它痴迷得茶不思饭不想的那个俄罗斯方块时代。
究其历史,俄罗斯方块最早还是出现在PC机上,而我国的用户都是通过红白机了解、喜欢上它的。现在联众又将重新掀起这股让人沉迷的俄罗斯方块风潮。对一般用户来说,它的规则简单,容易上手,且游戏过程变化无穷,而在"联众俄罗斯方块"中,更有一些联众网络游戏所独有的魅力――有单机作战与两人在线对战两种模式,用户可任选一种进行游戏。网络模式还增加了积分制,使用户既能感受到游戏中的乐趣,也给用户提供了一个展现自己高超技艺的场所。
★★ 一些和俄罗斯方块有关的故事
俄罗斯方块操作简单,难度却不低。作为家喻户晓老少皆宜的大众游戏,时至今日玩游戏的人(以及许多不怎么玩游戏的人)中谁要是不知道的话可真所谓是火星上的熊猫了。但是,谁知道这么优秀的娱乐工具,出自哪位神人之手呢?
顾名思义,俄罗斯方块自然是俄罗斯人发明的。这位伟人叫做阿列克谢·帕基特诺夫(Alexey Patnov) 。
然而,很少有人知道,这个着名的游戏在80年代曾经在法律界掀起轩然大波,那就是着名的俄罗斯方块产权之争。这次产权争夺,几家欢喜,几家哀愁,几家公司倒闭,几家公司赚钱,其中的是是非非,一言难尽。
1985年6月
工作于莫斯科科学计算机中心的阿列克谢·帕基特诺夫在玩过一个拼图游戏之后受到启发,从而制作了一个以Electronica 60(一种计算机)为平台的俄罗斯方块的游戏。后来经瓦丁·格拉西莫夫(Vadim Gerasimov)移植到PC上,并且在莫斯科的电脑界传播。帕基特诺夫因此开始小有名气。
1986年7月
PC版俄罗斯方块在匈牙利的布达佩斯被当地的一群电脑专家移植到了Apple II 和 Commodore 64 上,这些版本的软件引起了当时英国一个叫Andromeda的游戏公司经理罗伯特·斯坦恩(Robert Stein)的注意,他向帕基特诺夫以及匈牙利的电脑专家们收购了俄罗斯方块的版权,并且在买到版权之前把它们倒手卖给了英国的Mirrorsoft (注意不是Microsoft!) 以及美国的Spectrum Holobyte。
1986年11月
斯坦恩和帕基特诺夫经过谈判,就版权收购问题未取得成果。斯坦恩甚至直接飞到莫斯科和帕基特诺夫面谈,但是空手而归。由于俄罗斯人对于已经在西方兴起的电子游戏产业知道不多,斯坦恩决定窃取Tetris的版权,于是他放出谣言说这是匈牙利人开发的游戏。
与此同时,PC版的俄罗斯方块已经由英国的Mirrorsoft出品并且在欧洲销售,受到当时人们的极大关注。不仅仅因为这个游戏好玩,而且这是“第一个来自铁幕国家的游戏。”当时的游戏宣传海报上有浓郁的冷战色彩,比如战争画面,加加林太空飞行等。而斯坦恩仍然没有正式合法的版权。
1987年6月
斯坦恩最终取得了在IBM-PC及其兼容机上的Tetris的版权,版权机种包括“其他任何电脑系统”。但是,他没有和苏联方面签署协议,也就是说,这个版权是不完全的。(注: 这个“其他任何电脑系统”在原文中的描述是any other computer system,这种说法在当时看来也很不严密,从而为后来的产权之争埋下了伏笔)
1988年1月
Tetris在电脑平台的热销,一时造成“洛阳纸贵”(伦敦磁盘贵??)的局面。而当CBS晚报采访了俄罗斯方块之父帕基特诺夫之后,斯坦恩盗窃版权的计划彻底泡汤了。一个新的公司ELORG(Electronorgtechinca,苏联一家软件公司)开始和斯坦恩就游戏程序问题进行协商。ELORG的负责人亚历山大·阿列欣科( Alexander Alexinko)知道斯坦恩虽然没有版权,但是会以手中的游戏开发程序为筹码威胁中断谈判。
1988年5月
经过几个月的争吵之后,筋疲力尽的斯坦恩终于和ELORG签定了PC俄罗斯方块版权的合约。当时的合约禁止开发街机版和掌机版的方块游戏,而电脑版的Tetris则成为当时最畅销的游戏。
1988年7月
斯坦恩与阿列欣科商谈开发街机版俄罗斯方块的问题。阿列欣科当时尚未从斯坦恩那里拿到一分钱的版权费,但是同时的Spectrum 和 Mirrorsoft已经开始向电子游戏商出售了俄罗斯方块的版权。Spectrum 将Tetris的游戏机和PC在日本的版权卖给了Bullet-Proof Software (FC和GB版俄罗斯方块的制作商),而Mirrorsoft则把它在日本和北美的版权卖给了美国的Atari。这样一来两家公司的矛盾就开始了。1988年11月,BPS在FC上发行的俄罗斯方块(大家不很熟悉的俄罗斯方块1)在日本发售,销量达200万份。
1988年11月
随着GB的开发,NOA(任天堂美国分公司)的经理荒川实(任天堂山内溥老爷子的女婿)希望将Tetris做成GB上的游戏。于是他联系了BPS的总裁亨克·罗杰斯(Henk Rogers),罗杰斯再与斯坦恩联系的时候却吃了闭门羹。于是他直接去莫斯科购买版权。而斯坦恩觉察出风头,也乘飞机前往莫斯科;与此同时,Spectrum的负责人罗伯特·麦克斯韦(Robert Maxwell)的儿子凯文·麦克斯韦(Kevin Maxwell) 也在向莫斯科进发。就这样,三路人马几乎在同时赶到了冰天雪地的红色都市。
1989年2月21日
罗杰斯首先会见了ELORG的代表叶甫盖尼·别里科夫(Evgeni Belikov,和那个“装在套子里的人”同名)。他给帕基特诺夫等苏联人留下了深刻印象,并且签了手掌机方块游戏的版权。之后他向俄国人展示了FC版Tetris,这使别里科夫极为震惊。因为他并没有授予罗杰斯家用机的版权!罗杰斯则向他们说这是向TENGEN购买的版权,但是别里科夫也从来听说过TENGEN这个公司的名字。罗杰斯为了缓和尴尬的局面,将斯坦恩隐瞒的事实如数告诉了别里科夫,并且答应付给苏联方面更多支票作为已经卖出的FC版俄罗斯方块的版权费用。这时罗杰斯发现自己有机会买到Tetris全部机种的版权(但是当时还没买),虽然Atari会对他虎视耽耽,但是别忘了,他和BPS的背后还有任天堂这个大靠山给自己撑腰。
注意:罗伯特·斯坦恩原先所签的协议只是电脑版Tetris的版权,其他的版权并不是他的。
后来,斯坦恩和ELORG重新签署了协议。别里科夫强迫他重签的合约中修改的内容是:“电脑的定义:包含有中央处理器,监视器,磁盘驱动器,键盘和操作系统的机器”。而斯坦恩当时却没有仔细看这些定义。(这回轮到他犯混了……)后来他才意识到这是罗杰斯从自己手中抢走版权而耍的花招。但是为时已晚。第二天他被告知虽然签署的文件已经不能改过来,但是他还可以得到街机版Tetris的开发权。三天之后,他签下了街机版的协议。
1989年2月22日
凯文·麦克斯韦访问了ELORG。别里科夫拿出罗杰斯给他的FC游戏卡向他询问这件事情。麦克斯韦在卡带上看到了Mirrorsoft的名字后才想起他的公司已经把部分版权倒卖给了Atari。(糊涂人办糊涂事……)当他想继续谈街机和手掌机版权的问题的时候,却发现他自己能够签的,就只有除电脑,街机,家用机和掌机以外的协议了。(其实等于没有协议可签,除非他发明一种新的娱乐系统,比方说俄罗斯方块积木……)在糊涂之余这家伙灵机一动,告诉别里科夫说此卡带为盗版(汗……),然后也要签家用机的协议。
最后的结果是:凯文·麦克斯韦只带走一张白纸,罗伯特·斯坦恩带走了街机协议书。由于麦克斯韦声称所有的FC卡都是盗版,ELORG保留了家用机的版权,没卖给任何人。假如麦克斯韦想获得家用机版权的话,就必须出价比任天堂高才行。亨克·罗杰斯买到了掌机的版权,并且通知了荒川实。BPS就制作GB版Tetris向任天堂达成交易:这笔交易额高大500万-1000万美元。
1989年3月15日
亨克·罗杰斯回到莫斯科,并且代表任天堂出巨资收购家用机版Tetris的版权。版权费的价格虽然没有向外界透露,但是这个数字将是Mirrorsoft永远拿不出来的。连荒川实和NOA的首席执行官霍华德·林肯(Howard Lincoln)都亲自前往苏联助阵。
1989年3月22日
ELORG和任天堂的家用机协议终于达成。任天堂方面坚持加入一款声明,在协议签定之后,如果和其他出现法律纠纷,苏联方面必须派人去美国的法庭上做证。实际上,这种法律上的争端将是不可避免的。据说ELORG仅仅得到的定金有300-500万美元之多。别里科夫向Mirrorsoft通知,说Mirrorsoft, Andromeda和Tengen都没有家用机的版权,现在版权都归任天堂所有。当天晚上任天堂和BPS的头目们在莫斯科酒店里举行了庆祝party。
(各位看明白了,现在家用机和掌机的版权已经被任天堂和BPS分别掌握在手中。无论是Atari还是Tengen都没有权利制作FC版的俄罗斯方块。)
1989年3月31日
霍华德·林肯愉快(幸灾乐祸?)地向Atari发去最后通牒(传真),告诉他们立刻停止FC(NES)版的俄罗斯方块游戏。这使得Atari和麦克斯韦都十分震怒。他们以Tengen的名义回信说在4月7日那天他们就已经享有家用机俄罗斯方块的版权了。
1989年4月13日
Tengen撰写了一份申请书,要求拥有Tetris的“影音作品,源程序和游戏音乐”版权。但是申请书中并没有提及阿列克谢·帕基特诺夫和任天堂的游戏版权问题。(忽视了阿列克谢·帕基特诺夫真是个大错误!)
与此同时,麦克斯韦利用自己掌握的媒体势力,企图夺回Tetris的阵地。甚至搬出了苏联与英国政府,对俄罗斯方块版权问题进行干预。(好大的面子啊!)结果挑起了苏共与ELORG之间的矛盾。甚至连戈尔巴乔夫都向麦克斯韦保证“以后不用担心日本公司的问题”。(汗……这位麦克斯韦果然不是善主……伟大的苏联政府都对俄罗斯方块关注起来了……)
在4月晚些时候,霍华德·林肯回到莫斯科的时候,发现ELORG已经在苏联政府的打压下抬不起头来,而就在那天半夜,NOA方面给他打电话,说Tengen已经起诉了任天堂。(山雨欲来风满楼啊……)
第二天,他面会了别里科夫,帕基特诺夫和其他几位ELORG的成员,以确保他们能够为任天堂的官司佐证。(这回合同里的条款可生效了)随后NOA立刻反诉Tengen,并且开始收集证据。
1989年5月17日
Tengen在USA Today上登载了大幅Tertis广告,虽然法庭大战已经迫在眉睫。
1989年6月
Tengen与任天堂的案子终于开庭审理。
论战主要围绕一个议题展开:NES(FC)究竟是电脑,还是电子游戏机。(大家不许笑,在法庭上这可是很严肃的话题)Atari认为NES是电脑系统,因为它拥有扩展机能,而且日本的Famicom也有网络功能存在。而任天堂的证据则更加切题:ELORG中的苏联人从来没有意向出售Tetris的家用机版权,而所谓的“电脑”的概念则早在和斯坦恩的协议中提到了。
1989年6月15日
法庭召开听证会,讨论关于任天堂和Tengen互相命令对方终止生产和销售各自的Tetris软件的行为。法官福恩·史密斯(Fern Smith)宣布Mirrorsoft 与 Spectrum Holobyte均没有家用机版权,因此他们提供给Tengen的权利也不能生效。任天堂的请求最后得到了许可。
1989年6月21日
Tengen版的俄罗斯方块全部撤下了货架,该游戏卡带的生产也被迫中止。数十万份软件留在包装盒里,封存在仓库中。
1989年7月
任天堂NES版Tetris在美国发售。全美销量大约300万。与此同时,和GB版Tetris捆绑销售的Game Boy席卷美国,美利坚大地上刮起一阵方块旋风。
关于Tetris的混战此时已经告一段落。而任天堂和Tengen之间的法庭纠纷则一直持续到1993年。
尾声
Atari Games仍然开发了街机版的Tetris,共卖出约2万台机器。近来Atari Games 被 Williams/WMS收购,而那些封存在仓库里的NES版Tetris的命运则没人知道。Tengen不能从其他途径把它们处理掉,所以估计这些软件都被销毁了。但是据说仍然有约10万份Tengen版的Tetris流入了市场。
我们今天在64合一等游戏D版卡里玩到的所谓“俄罗斯方块2”其实就是当年的Tengen版,平心而论,这一版的方块比BPS的版本要好玩许多。首先,这版的操作感和按键设定十分到位,AB分别是正转和反转,而BPS版是用十字键的下来转动,只支持一个方向,按A就直接“啪”地落下来,手感十分不爽;其次,它支持的二人对战,与电脑竞争和合作的模式也让人耳目一新。还有,音乐也是没的说。
罗伯特·斯坦恩,这个版权问题的始作俑者,在Tetris上总共只赚了25万美元。本来他可以挣多点钱的,但是Atari和Mirrorsoft在付他版税的时候没有给足。(应得的报应……)
Spectrum Holobyte 则需要和ELORG重新协商,以确保电脑版Tetris的版权。
罗伯特·麦克斯韦的媒体堡垒在混战中逐渐分崩离析,老麦克斯韦在做生意时做幕后黑手的事实也在调查中,而他却突然暴病身亡。(气死的……)Mirrorsoft 英国公司也惨淡地退出了历史舞台。
真正的大赢家是BPS的总裁亨克·罗杰斯,还有幕后的任天堂。俄罗斯方块究竟为任天堂赚了多少银子呢?答案恐怕永远说不清了。想一想吧,在美国GB都是和Tetris捆绑销售,以增加GB的出货量……然后因为Tetris买了GB的人还会买其他的GB卡……要是这么算起来的话,那利润简直就像滚雪球一样了。现在GB版的Tetris(Z版)总共生产了3000万张。(后来GB的俄罗斯方块又在SFC上出了复刻版,和《马里奥医生》一起出现在屏幕上,成为不朽之作。)
至于苏联方面,除了苏联政府,谁也没有从Tetris那里得到多少好处。苏联解体之后,原ELORG的人员都四散到了全国乃至世界各地,许多人继续开发游戏(比方说帕基特诺夫)。
阿列克谢·帕基特诺夫几乎没有从Tetris上赚到一分钱。ELORG本来打算给他Tetris的销售权,但是旋即取消了这笔交易。不过帕基特诺夫仍然为自己能够制作出这么一个世界闻名的优秀游戏而欣慰。他从科学院里得到一台286(当时在苏联可是了不起的电脑)作为奖励。而且分到了比同事们家宽敞明亮的房子。在1996年,亨克·罗杰斯支付给他一笔报酬(还算是个知恩图报的人),帕基特诺夫组建了Tetris Company LLC 公司,终于能够自己创作游戏,并且收取版权费了。
注:当年俄罗斯方块红遍世界的各个角落,一个本来是吃大锅饭的人在消极怠工的时候发明的娱乐工具成了造福全人类的宝贝,它的价值远远超越了开发这个软件时候的预想。Atari虽然在法庭上惨败,但是拜亚洲盗版商人所赐,Tengen版的俄罗斯方块已经在中国玩家心目中生根发芽,长叶开花,任天堂的正统Tetris在中国反而没人玩了。其实说了那么多,归根到底,平平淡淡才是真。有机会的话,下载一个FC的模拟器和一个64合一的经典ROM,回家体会一下俄罗斯方块的魅力吧……
附上Alex Pajitnov照片一张。
该回答在5月15日 19:30由回答者修改过
❹ 如何用最简单的语句写一个俄罗斯方块
动脑子
❺ 怎样写一个俄罗斯方块用JAVA SWING
将游戏区划成小格
设定一个移动像素,比如5
设定好几个方块的类,比如--,⊥等等。都由小格组成
随机NEW那一个类。
判断方块最下面的的小格是否已到“底”,底:下面是小格是否已被添满。
判断一行从左到右是否没有空格,否则删除这行,再调用向下方法。
❻ 一个简单的c语言写的俄罗斯方块程序
1、考虑怎么存储俄罗斯方块
俄罗斯方块的形状一共有19种类型,如果拿数组来表示的话,可能会比较会浪费空间(网上有很多实现代码)
考虑到每种方块形状的范围是4 *4的小方块,用 字模点阵的方式来存储,即设置一个4行4列的数组,元素置1即代表这个位置有小
方块,元素置0即代表这个位置无小方块,这个整个的4*4的数组组成俄罗斯方块的形状。
1000
1000
1100
0000
上述4*4来表示L形状的方块。
4*4 =16 bit 正好为short类型,所以每一个方块可以用一个short类型的数据来表示。
我们把俄罗斯方块点阵的数位存在rockArray中,我们可以事先把这19种方块的字模点阵自己转化成十六进制,然后在rockArray数组的初始化时赋值进去。
但是这种方式扩展性不好,每当有一种新方块时需要改动,
所以可以写一个配置文件来表示19种方块。(RockShape.ini)
@###@###@@######1234
从配置文件中读取方块的类型的代码在(Init.h的ReadRock函数中)在下面3中解释下代码如何实现
2如何画出方块
可以使用EasyX库来画出简单的图形,
EasyX库是在VC下实现TC的简单绘图功能的一个库,这个库很容易学会(直接 网络EasyX库,里面有详细的教程)
那么如何画出方块,方块已经存储到一个short类型中了
从short中读取出,可以用一个掩码mask = 1来与short的每个bit位相与,结果为1,则画出一个小方块;
函数声明:
void DisplayRock(int rockIdx, RockLocation_t* LocatePtr, bool displayed)1
参数1:表示在数组中的下标,取出short类型的方块表示数据
参数2:表示当前坐标,即画出方块的左上角的坐标x,y
参数3:true表示画出该方块,false 表示擦除该方块。
//方块在图形窗口中的位置(即定位4*4大块的左上角坐标) typedef struct LOCATE
{ int left; int top;
} RockLocation_t;123456
3如何实现同一种类型方块的翻转,
在按‘↑’时应该翻转同一种类型的方块,
比如下面的横杆和竖杆
@###@###@###@###@@@@############****1234567891011
可以假想成静态循环链表来实现这种方式
使同一种类型的方块循环起来,
用一个struct结构来表示一种方块
typedef struct ROCK
{ //用来表示方块的形状(每一个字节是8位,用每4位表示方块中的一行)
unsigned short rockShapeBits; int nextRockIndex; //下一个方块,在数组中的下标 } RockType;123456
定义一个RockType类型的数组来存储19种方块
RockType RockArray[19] = { (0, 0) };
当我们按“↑”时,把传入画方块函数DrawRock中的rockIndex变为当前方块结构体中的nextRockIndex即可。
简单解释下ReadRock函数的实现:当读取到空行的时候表示 一种方块已经读取完毕,当读取到****行时 表示同一种类型的方块读取完毕,具体看代码实现,代码中具体的注释
4、主要游戏实现的逻辑
贴一个预览图吧
注:上述预览图的游戏控制区和游戏显示区在Draw.h的DrawGameWindow()函数实现的
(1)在初始位置画出方块,在预览区画出下一次的方块
(2)方块有两种行为:响应键盘命令UserHitKeyBoard(),自由下落
如果敲击键盘了(w ,a ,s ,d, )空格表示暂停,如果在规定时间内没有敲击键盘的话,方块自由下落一个单位
if (kbhit()) //如果敲击键盘了 就处理按键
{
userHit = getch();
UserHitKeyBoard(userHit, &curRockIndex, &curRockLocation);
} //没有 就自动下移一个单位 :不能用else,因为可能按键不是上下左右
DWORD newtime = GetTickCount(); if (newtime - oldtime >= (unsigned int)(300) && moveAbled == TRUE)
{
oldtime = newtime;
DisplayRock(curRockIndex, &curRockLocation, false);
curRockLocation.top += ROCK_SQUARE_WIDTH; //下落一格
}1234567891011121314
(3)当方块落地(即不能下移了)时,判断是否满行,如果满行则消除,然后再判断游戏是否结束,游戏结束的话,直接退出游戏
判断满行:FullLine()函数,从最底下的一行开始判断,直到遇到一行空行,
while (count != xROCK_SQUARE_NUM ) //遇到空行 14
{
linefull = true; count = 0; for (int i = 1; i <= xROCK_SQUARE_NUM; ++i)
{ if (game_board[idx][i] == 0)
{
linefull = false; count++;
}
} if (linefull) //满行,消除当前行,更新分数
{
DelCurLine(idx);//消除满行
game_socres += 3;
UpdateSocres(game_socres);
idx++;//因为下面要减1
}
idx--;
}
(4)消除满行
将要删除的满行擦除:即将方块化成与背景色相同的,该代码为黑色
然后将上面的一行向下移,移一行删除一行,直到遇到空行
具体看代码的具体实现 game.h
void DelCurLine(int rowIdx)
(4)判断方块是否能移动
在game.h中实现
bool MoveAble(int rockIndex, RockLocation_t* currentLocatePtr, int f_direction)1
**比较当前位置的坐标(左上角)开始,能否放下rockIndex的方块。
注:f_direction为”↑”的话,则传入的rockIndex为下一个方块**
如果不能移动的话,给游戏game_board设置标记表示该位置被占有
//全局变量-游戏板的状态描述(即表示当前界面哪些位置有方块) //0表示没有,1表示有(多加了两行和两列,形成一个围墙,便于判断方块是否能够移动) int game_board[yROCK_SQUARE_NUM + 2][xROCK_SQUARE_NUM + 2] = { 0 };123
实现过程遇到的一些问题
(1)在快速下落的时候,可能方块会掉出围墙的范围内,
快速下落是使方块每次下落2个单位距离。
在判断不能下落时,使当前坐标的top即y减去一个单位的距离
(2)遇到多行满行时消除不了,
在判断满行时,循环找出满行,找出一个满行,就消除一行,然后继续判断是否满行,直到遇到空行
❼ 俄罗斯方块如何编写及代码
网上很多呀,有很多javascript写的网页俄罗斯方块游戏,可以直接查看网页源码,偷懒的话修改成c++的就成了。
但也不要太懒了,如果你是学生的话。。。。。。
❽ 问下 用C 语言写俄罗斯方块 怎么写啊 最好那个人才能帮我写个 谢谢
用C写?
我有一个Delphi / CBC版本的.
基本思想:
定义基本的7种方块(含四种状态)二维数组变量.
Terial[7][4]. 用数组下标索引方块的种类和状态.
定义方块运行的区域(二维数组变量) 如(高23,宽10)
用它存储方块下落后的状态.
左移和右移判断是方块是否左右溢出、是否会叠在运行区的格子上。
同样改变状态(变形)也得判断是否会出现左右溢出、是否会叠在运行区格子上。
下落后,对运行区的空格子进行赋值。
❾ 用c语言编写俄罗斯方块程序 求详解
1、用C语言绘制图形界面
EasyX图形库(http://www.easyx.cn)即TC的图形库在VC下的移植。
包含库#include <graphics.h>
先初始化图形窗口
initgraph(WINDOW_WIDTH, WINDOW_HIGH) ;WINDOW_WIDTH为窗口的宽带,WINDOW_HIGH为窗口的高度。
清空绘图设备
cleardevice();
设置画笔颜色
setcolor(RED) ;
设置线条风格
setlinestyle(PS_SOLID, NULL, 0);
画矩形
rectangle
还有画线、显示文字等函数,可以参照其帮助文档。
注意:由于我们用的是EasyX图形库,故源文件后缀要为.cpp,但其中内容都是C的语法。
2、存储表示出俄罗斯方块的形状
一、我们可以用编号,不同的编号代表不同的俄罗斯方块,根据编号把不同方块的画法写在代码中,这样19种
方块就得有19种相应的代码来描绘。而且这样扩展性不好,若以后设计了新的方块,则需要更改大量源代码。
二、我们很自然的想到可用字模点阵的形式来表示,即设置一个4行4列的数组,元素置1即代表这个位置有小
方块,元素置0即代表这个位置无小方块,这个整个的4*4的数组组成俄罗斯方块的形状。
1000
1000
1100
0000
我们把俄罗斯方块点阵的数位存在rockArray中,我们可以事先把这19种方块的字模点阵自己转化成十六进制,然后在rockArray数组的初始化时赋值进去。
但这样做未免有点太费力,且扩展性也不太好,若以后设计的新方块种类加入,要改变数组rockArray中的值。
我们可以考虑把所有俄罗斯方块的点阵存储在配置文件中,在程序初始化时读取文件,把这些点阵转换成unsigned int的变量存储在rockArray中。
这样,以后我们增添新的方块形状只需要在配置文件中增加新的点阵即可。
@###
@###
@@##
####(为使得看起来更醒目,我们用@表示1,用#表示0)
3、让图形动起来
在某位置处用函数DrawRock在屏幕上画出俄罗斯方块,然后再擦除掉(即用背景色在原位置处重绘一次方块),最后在下落的下一个位置处用函数DrawRock在屏幕上画出俄罗斯方块,如此循环,中间用计时器间隔一段时间以控制下落的速度。
同理,按下屏幕的左右键也是如此,只是在按下键盘时把方块的位置重新计算了。
那么按下上方向键时,如何让方块翻转呢?
我们在配置文件中就把方块的顺时针翻转形态放在了一起:
@###
@###
@@##
####
@@@#
@###
####
####
@@##
#@##
#@##
####
##@#
@@@#
####
####
我们每按一次上方向键改变一次方块的形状即可。若一直按上键,形状应该是循环地翻滚。
我们想到了循环链表的数据结构可实现这个效果。
可是我们若把这些一种类的方块的各种形态串成循环链表形式,那么每次重新生成方块时我们就难以随机地生成方块了。
故还是得用数组来存储,但又要有循环链表的功能,于是我们想到了静态循环链表。
我们用结构体来作为一个方块在rockArray中的元素
typedef struct ROCK
{ //用来表示方块的形状(每一个字节是8位,用每4位表示方块中的一行)
unsigned int rockShapeBits ;
int nextRockIndex ; //下一个方块,在数组中的下标
} RockType ;
这样,当我们按下上方向键时,把传入函数DrawRock中的rockIndex变为当前方块结构体中的nextRockIndex即可。
❿ 怎样用c语言编写俄罗斯方块程序
俄罗斯方块C源代码
#include<stdio.h>
#include<windows.h>
#include<conio.h>
#include<time.h>
#defineZL4 //坐标增量,不使游戏窗口靠边
#defineWID36 //游戏窗口的宽度
#defineHEI20 //游戏窗口的高度
inti,j,Ta,Tb,Tc; //Ta,Tb,Tc用于记住和转换方块变量的值
inta[60][60]={0}; //标记游戏屏幕各坐标点:0,1,2分别为空、方块、边框
intb[4]; //标记4个"口"方块:1有,0无,类似开关
intx,y,level,score,speed; //方块中心位置的x,y坐标,游戏等级、得分和游戏速度
intflag,next; //当前要操作的方块类型序号,下一个方块类型序号
voidgtxy(intm,intn); //以下声明要用到的自编函数
voidgflag(); //获得下一方块序号
voidcsh(); //初始化界面
voidstart(); //开始部分
voidprfk(); //打印方块
voidclfk(); //清除方块
voidmkfk(); //制作方块
voidkeyD(); //按键操作
intifmov(); //判断方块能否移动或变体
void clHA(); //清除满行的方块
voidclNEXT(); //清除边框外的NEXT方块
intmain()
{csh();
while(1)
{start();//开始部分
while(1)
{prfk();
Sleep(speed); //延时
clfk();
Tb=x;Tc=flag;//临存当前x坐标和序号,以备撤销操作
keyD();
y++;//方块向下移动
if(ifmov()==0){y--;prfk();dlHA();break;}//不可动放下,删行,跨出循环
}
for(i=y-2;i<y+2;i++){if(i==ZL){j=0;}} //方块触到框顶
if(j==0){system("cls");gtxy(10,10);printf("游戏结束!");getch();break;}
clNEXT(); //清除框外的NEXT方块
}
return0;
}
voidgtxy(intm,intn)//控制光标移动
{COORDpos;//定义变量
pos.X=m;//横坐标
pos.Y=n;//纵坐标
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}
voidcsh()//初始化界面
{gtxy(ZL+WID/2-5,ZL-2);printf("俄罗斯方块");//打印游戏名称
gtxy(ZL+WID+3,ZL+7);printf("*******NEXT:");//打印菜单信息
gtxy(ZL+WID+3,ZL+13);printf("**********");
gtxy(ZL+WID+3,ZL+15);printf("Esc:退出游戏");
gtxy(ZL+WID+3,ZL+17);printf("↑键:变体");
gtxy(ZL+WID+3,ZL+19);printf("空格:暂停游戏");
gtxy(ZL,ZL);printf("╔");gtxy(ZL+WID-2,ZL);printf("╗");//打印框角
gtxy(ZL,ZL+HEI);printf("╚");gtxy(ZL+WID-2,ZL+HEI);printf("╝");
a[ZL][ZL+HEI]=2;a[ZL+WID-2][ZL+HEI]=2;//记住有图案
for(i=2;i<WID-2;i+=2){gtxy(ZL+i,ZL);printf("═");}//打印上横框
for(i=2;i<WID-2;i+=2){gtxy(ZL+i,ZL+HEI);printf("═");a[ZL+i][ZL+HEI]=2;}//下框
for(i=1;i<HEI;i++){gtxy(ZL,ZL+i);printf("║");a[ZL][ZL+i]=2;}//左竖框记住有图案
for(i=1;i<HEI;i++){gtxy(ZL+WID-2,ZL+i);printf("║");a[ZL+WID-2][ZL+i]=2;}//右框
CONSOLE_CURSOR_INFOcursor_info={1,0};//以下是隐藏光标的设置
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
level=1;score=0;speed=400;
gflag();flag=next;//获得一个当前方块序号
}
voidgflag() //获得下一个方块的序号
{srand((unsigned)time(NULL));next=rand()%19+1; }
voidstart()//开始部分
{gflag();Ta=flag;flag=next;//保存当前方块序号,将下一方块序号临时操作
x=ZL+WID+6;y=ZL+10;prfk();//给x,y赋值,在框外打印出下一方块
flag=Ta;x=ZL+WID/2;y=ZL-1;//取回当前方块序号,并给x,y赋值
}
voidprfk()//打印俄罗斯方块
{for(i=0;i<4;i++){b[i]=1;}//数组b[4]每个元素的值都为1
mkfk();//制作俄罗斯方块
for(i=x-2;i<=x+4;i+=2)//打印方块
{for(j=y-2;j<=y+1;j++){if(a[i][j]==1&&j>ZL){gtxy(i,j);printf("□");}}}
gtxy(ZL+WID+3,ZL+1); printf("level:%d",level); //以下打印菜单信息
gtxy(ZL+WID+3,ZL+3); printf("score:%d",score);
gtxy(ZL+WID+3,ZL+5); printf("speed:%d",speed);
}
voidclfk()//清除俄罗斯方块
{for(i=0;i<4;i++){b[i]=0;}//数组b[4]每个元素的值都为0
mkfk();//制作俄罗斯方块
for(i=x-2;i<=x+4;i+=2)//清除方块
{for(j=y-2;j<=y+1;j++){if(a[i][j]==0&&j>ZL){gtxy(i,j);printf("");}}}
}
voidmkfk()//制作俄罗斯方块
{a[x][y]=b[0];//方块中心位置状态:1-有,0-无
switch(flag)//共6大类,19种小类型
{case1:{a[x][y-1]=b[1];a[x+2][y-1]=b[2];a[x+2][y]=b[3];break;}//田字方块
case2:{a[x-2][y]=b[1];a[x+2][y]=b[2];a[x+4][y]=b[3];break;}//直线方块:----
case3:{a[x][y-1]=b[1];a[x][y-2]=b[2];a[x][y+1]=b[3];break;}//直线方块:|
case4:{a[x-2][y]=b[1];a[x+2][y]=b[2];a[x][y+1]=b[3];break;}//T字方块
case5:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x-2][y]=b[3];break;}//T字顺时针转90度
case6:{a[x][y-1]=b[1];a[x-2][y]=b[2];a[x+2][y]=b[3];break;}//T字顺转180度
case7:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x+2][y]=b[3];break;}//T字顺转270度
case8:{a[x][y+1]=b[1];a[x-2][y]=b[2];a[x+2][y+1]=b[3];break;}//Z字方块
case9:{a[x][y-1]=b[1];a[x-2][y]=b[2];a[x-2][y+1]=b[3];break;}//Z字顺转90度
case10:{a[x][y-1]=b[1];a[x-2][y-1]=b[2];a[x+2][y]=b[3];break;}//Z字顺转180度
case11:{a[x][y+1]=b[1];a[x+2][y-1]=b[2];a[x+2][y]=b[3];break;}//Z字顺转270度
case12:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x-2][y-1]=b[3];break;}//7字方块
case13:{a[x-2][y]=b[1];a[x+2][y-1]=b[2];a[x+2][y]=b[3];break;}//7字顺转90度
case14:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x+2][y+1]=b[3];break;}//7字顺转180度
case15:{a[x-2][y]=b[1];a[x-2][y+1]=b[2];a[x+2][y]=b[3];break;}//7字顺转270度
case16:{a[x][y+1]=b[1];a[x][y-1]=b[2];a[x+2][y-1]=b[3];break;}//倒7字方块
case17:{a[x-2][y]=b[1];a[x+2][y+1]=b[2];a[x+2][y]=b[3];break;}//倒7字顺转90度
case18:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x-2][y+1]=b[3];break;}//倒7字顺转180度
case19:{a[x-2][y]=b[1];a[x-2][y-1]=b[2];a[x+2][y]=b[3];break;}//倒7字顺转270度
}
}
voidkeyD()//按键操作
{if(kbhit())
{intkey;
key=getch();
if(key==224)
{key=getch();
if(key==75){x-=2;}//按下左方向键,中心横坐标减2
if(key==77){x+=2;}//按下右方向键,中心横坐标加2
if(key==72)//按下向上方向键,方块变体
{if(flag>=2&&flag<=3){flag++;flag%=2;flag+=2;}
if(flag>=4&&flag<=7){flag++;flag%=4;flag+=4;}
if(flag>=8&&flag<=11){flag++;flag%=4;flag+=8;}
if(flag>=12&&flag<=15){flag++;flag%=4;flag+=12;}
if(flag>=16&&flag<=19){flag++;flag%=4;flag+=16;}}
}
if(key==32)//按空格键,暂停
{prfk();while(1){if(getch()==32){clfk();break;}}} //再按空格键,继续游戏
if(ifmov()==0){x=Tb;flag=Tc;} //如果不可动,撤销上面操作
else{prfk();Sleep(speed);clfk();Tb=x;Tc=flag;} //如果可动,执行操作
}
}
intifmov()//判断能否移动
{if(a[x][y]!=0){return0;}//方块中心处有图案返回0,不可移动
else{if((flag==1&&(a[x][y-1]==0&&a[x+2][y-1]==0&&a[x+2][y]==0))||
(flag==2&&(a[x-2][y]==0&&a[x+2][y]==0&&a[x+4][y]==0))||
(flag==3&&(a[x][y-1]==0&&a[x][y-2]==0&&a[x][y+1]==0))||
(flag==4&&(a[x-2][y]==0&&a[x+2][y]==0&&a[x][y+1]==0))||
(flag==5&&(a[x][y-1]==0&&a[x][y+1]==0&&a[x-2][y]==0))||
(flag==6&&(a[x][y-1]==0&&a[x-2][y]==0&&a[x+2][y]==0))||
(flag==7&&(a[x][y-1]==0&&a[x][y+1]==0&&a[x+2][y]==0))||
(flag==8&&(a[x][y+1]==0&&a[x-2][y]==0&&a[x+2][y+1]==0))||
(flag==9&&(a[x][y-1]==0&&a[x-2][y]==0&&a[x-2][y+1]==0))||
(flag==10&&(a[x][y-1]==0&&a[x-2][y-1]==0&&a[x+2][y]==0))||
(flag==11&&(a[x][y+1]==0&&a[x+2][y-1]==0&&a[x+2][y]==0))||
(flag==12&&(a[x][y-1]==0&&a[x][y+1]==0&&a[x-2][y-1]==0))||
( flag==13 && ( a[x-2][y]==0 && a[x+2][y-1]==0 && a[x+2][y]==0 ) ) ||
( flag==14 && ( a[x][y-1]==0 && a[x][y+1]==0 && a[x+2][y+1]==0 ) ) ||
(flag==15 && ( a[x-2][y]==0 && a[x-2][y+1]==0 && a[x+2][y]==0 ) ) ||
(flag==16 && ( a[x][y+1]==0 && a[x][y-1]==0 && a[x+2][y-1]==0 ) ) ||
( flag==17 && ( a[x-2][y]==0 && a[x+2][y+1]==0 && a[x+2][y]==0 ) ) ||
(flag==18 && ( a[x][y-1]==0 &&a[x][y+1]==0 && a[x-2][y+1]==0 ) ) ||
(flag==19 && ( a[x-2][y]==0 && a[x-2][y-1]==0
&&a[x+2][y]==0))){return1;}
}
return0; //其它情况返回0
}
voidclNEXT() //清除框外的NEXT方块
{flag=next;x=ZL+WID+6;y=ZL+10;clfk();}
void clHA() //清除满行的方块
{intk,Hang=0; //k是某行方块个数,Hang是删除的方块行数
for(j=ZL+HEI-1;j>=ZL+1;j--)//当某行有WID/2-2个方块时,则为满行
{k=0;for(i=ZL+2;i<ZL+WID-2;i+=2)
{if(a[i][j]==1)//竖坐标从下往上,横坐标由左至右依次判断是否满行
{k++; //下面将操作删除行
if(k==WID/2-2) { for(k=ZL+2;k<ZL+WID-2;k+=2)
{a[k][j]=0;gtxy(k,j);printf("");Sleep(1);}
for(k=j-1;k>ZL;k--)
{for(i=ZL+2;i<ZL+WID-2;i+=2)//已删行数上面有方块,先清除再全部下移一行
{if(a[i][k]==1){a[i][k]=0;gtxy(i,k);printf("");a[i][k+1]=1;
gtxy(i,k+1);printf("□");}}
}
j++;//方块下移后,重新判断删除行是否满行
Hang++;//记录删除方块的行数
}
}
}
}
score+=100*Hang; //每删除一行,得100分
if(Hang>0&&(score%500==0||score/500>level-1)) //得分满500速度加快升一级
{speed-=20;level++;if(speed<200)speed+=20; }
}