基于C#实现的双人对战与道具赛的俄罗斯方块小游戏

catastrophe

发布日期: 2019-04-20 16:17:42 浏览量: 1986
评分:
star star star star star star star star star star_border
*转载请注明来自write-bug.com

1.系统总体设计

要完成本系统中俄罗斯方块,必须考虑以下几个问题:

  • 如何判断一个方块下落到底部或是发生碰撞

  • 如何预测一个方块最终能下落到达的位置并给以玩家提示

  • 如何判断一个方块在进行左右移动或是旋转时不碰触边界与其他方块

  • 如何让一个方块时时下落更新

  • 如何将道具俄罗斯方块与普通俄罗斯方块区分

为此,需要为上面的几个判断依次写明方法,最后可重用,而对于俄罗斯方块的位置可以使用数组存放。

特别的,对于双人俄罗斯方块,还需要考虑:

  • 要实现本玩家消除多行时给对面玩家添加相应行数

  • 要实现本玩家消除特定行时给对面玩家添加捣乱方块

为此,需要写明2个方法记录自己相应的消除行数以及添加给对面玩家。

数据结构:数组,全局变量。

2.系统功能设计

本程序的主要功能如下图所示:

  • 运行程序进入主界面,选择单人或双人游戏

  • 单人游戏

    • 用方向键来移动,上方向键来旋转
    • 下落过程中方块会实时产生下落预测图
    • 方块碰到左右边界无法继续移动,方块旋转后产生的图形超过边界或碰到已有方块则不能旋转,方块下落到边界或碰到已有方块则不再下落并随机生成新方块
    • 新方块有一定几率是特殊方块,红色方块能令所在行随机消除,绿色则是随机填充
    • 当方块产生的初始位置被填充,游戏结束
  • 双人游戏

    • 玩家一用方向键移动,上方向键旋转,玩家二用wasd移动,w键旋转
    • 2内bcde
    • 当玩家连续消除2行或3行方块时,给对手增加这些方块
    • 当玩家连续消除4行方块时,给对方添加特殊方块,红色方块能令所在行随机消除,绿色则是随机填充
  • 游戏结束

3.类的设计

类名 Form1
属性 int x1 玩家一方块一的x坐标
属性 int y1 玩家一方块一的y坐标
属性 int x2 玩家一方块二的x坐标
属性 int y2 玩家一方块二的y坐标
属性 int x3 玩家一方块三的x坐标
属性 int y3 玩家一方块三的y坐标
属性 int x4 玩家一方块四的x坐标
属性 int y4 玩家一方块四的y坐标
属性 int x5 玩家二方块一的x坐标
属性 int y5 玩家二方块一的y坐标
属性 int x6 玩家二方块二的x坐标
属性 int y6 玩家二方块二的y坐标
属性 int x7 玩家二方块三的x坐标
属性 int y7 玩家二方块三的y坐标
属性 int x8 玩家二方块四的x坐标
属性 int y8 玩家二方块四的y坐标
属性 int size 方块的长宽
属性 int youtu[,] 记录玩家一各个区域有无方块
属性 int P2youtu[,] 记录玩家二各个区域有无方块
属性 int type 记录玩家一方块代号
属性 int P2type 记录玩家二方块代号
属性 int turn 记录玩家一方块旋转次数
属性 int P2turn 记录玩家二方块旋转次数
属性 int specialtype 记录玩家一特殊方块代号
属性 int P2specialtype 记录玩家二特殊方块代号
属性 bool onlyone 记录是否是单人模式
方法 private bool meetnow(int tempx1,int tempx2,int tempx3,int tempx4, int tempy1, int tempy2,int tempy3,int tempy4,int[,] temp) //旋转后是否碰撞的计算函数
方法 private void special_init(ref int tempspecialtype)//特殊方块生成
方法 private void block_init(ref int type,ref int turn)//玩家一普通方块生成
方法 private void P2block_init(ref int P2type, ref int P2turn) //玩家二普通方块生成
方法 private void tianblock_init(ref int x1,ref int x2,ref int y1,ref int y2,ref int x3,ref int x4,ref int y3,ref int y4)//田子型block初始化
方法 private void long_init(ref int x1, ref int x2, ref int y1, ref int y2,ref int x3,ref int x4,ref int y3,ref int y4)//长条型block,type1
方法 private void turn0_long_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn)//长条型block旋转
方法 private void turn1_long_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4, ref int tempturn)//长条型block旋转2
方法 private void tublock_init(ref int x1, ref int x2, ref int y1, ref int y2, ref int x3, ref int x4, ref int y3, ref int y4)//凸型block初始化
方法 private void turn0_tublock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn)//凸型block旋转
方法 private void turn1_tublock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4, ref int tempturn)//凸型block旋转2
方法 private void turn2_tublock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4, ref int tempturn)//凸型block旋转3
方法 private void turn3_tublock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4, ref int tempturn)//凸型block旋转4
方法 private void RZblock_init(ref int x1, ref int x2, ref int y1, ref int y2, ref int x3, ref int x4, ref int y3, ref int y4)//RZ型block
方法 private void turn0_RZblock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn)//RZ型block旋转
方法 private void turn1_RZblock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn) //RZ型block旋转2
方法 private void LZblock_init(ref int x1, ref int x2, ref int y1, ref int y2, ref int x3, ref int x4, ref int y3, ref int y4)//LZ型block
方法 private void turn0_LZblock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn) //LZ型block旋转
方法 private void turn1_LZblock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn)// LZ型block旋转2
方法 private void LLblock_init(ref int x1, ref int x2, ref int y1, ref int y2, ref int x3, ref int x4, ref int y3, ref int y4)//LL型block
方法 private void turn0_LLblock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn) //LL型block旋转
方法 private void turn1_LLblock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn) //LL型block旋转1
方法 private void turn2_LLblock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn) //LL型block旋转2
方法 private void turn3_LLblock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn) //LL型block旋转3
方法 private void RLblock_init(ref int x1, ref int x2, ref int y1, ref int y2, ref int x3, ref int x4, ref int y3, ref int y4)//RL型block,
方法 private void turn0_RLblock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn)
方法 private void turn1_RLblock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn)
方法 private void turn2_RLblock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn)
方法 private void turn3_RLblock_init(ref int tempx1, ref int tempx2, ref int tempy1, ref int tempy2, ref int tempx3, ref int tempx4, ref int tempy3, ref int tempy4,ref int tempturn)
方法 private void button1_Click(object sender, EventArgs e)//单人游戏开始
方法 private void button2_Click(object sender, EventArgs e) 双人游戏
方法 private void timer2_Tick(object sender, EventArgs e) 双人游戏页面实时刷新
方法 private void timer1_Tick(object sender, EventArgs e) 单人游戏页面实时刷新
方法 protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 键盘监听方法重写

主要成员方法的流程图

  1. private bool meetnow(int tempx1,int tempx2,int tempx3,int tempx4, int tempy1, int tempy2,int tempy3,int tempy4,int[,] temp) //旋转后是否碰撞的计算函数

  1. private void block_init(ref int type,ref int turn)

  1. private void button1_Click(object sender, EventArgs e)//单人游戏开始

4.主程序设计

  • 定义了变量int x1-x8,y1-y8 记录方块坐标

  • 定义了变量int size 记录方块大小

  • 定义了变量两个数组int youtu[,],int P2youtu[,] 存放已经下落的方块

  • 定义了变量 int type P2type 记录玩家方块代号

  • 定义了变量int turn int P2turn 记录玩家方块旋转次数

  • 定义了变量int specialtype int P2specialtype 记录玩家特殊方块代号

  • 定义了变量bool onlyone 记录是否是单人模式

  • 主要的功能实现是在Form1.cs中实现的

在 类 Form1中

  • 根据游戏区的长宽对方块大小初始化中

  • 实时刷新页面下落方块以及生成下落预测页面,并检测当前方块是否发生碰撞,如果发生碰撞,则调用block_init重新生成新方块,如果最上方已经有方块,则游戏结束

  • 通过方法ProcessCmdKey(ref Message msg, Keys keyData)与meetnow,实现玩家用方向键或wasd键改变方块坐标并检测该坐标是否有方块,以此实现方块的左右移动,加速下落,旋转方块

5.调试分析

  • 画图闪烁

    解决方式:不在控件上直接绘图,使用双缓冲,先构造新的位图,在其上绘图,然后将picturebox的图片设置为该图,而不是在picturebox上绘图。

  • 如何让方块保留在图上同时有让新的方块下落

    解决方法:构造两个新的位图,一个为背景图,一个为前景图。

  • 键盘响应事件对方向键无反应

    解决方法:重写键盘响应事件。

  • 如果一开始就按下方向键会报错

    解决方法:如果一开始就按下方向键会报错,因为是将坐标转换为数组的10*20行这样y1/size的坐标就是负的, 数组没有负的,故在该方法执行前判断是否y大于0。

  • 如果向左或向右突然插空到已有方块上方,图形会向下一格再绘图,而不是like检测到碰撞

    解决方法:更改原先绘图算法,原先算法有问题,在实时刷新时是先向下下落再检测是否会碰撞,未考虑键盘事件的影响,故将算法改为实时刷新时先检测碰撞再绘制图片。

  • 左右移动碰撞被阻拦会闪烁

    解决方法:键盘按下时是单独处理的 这时候也应该进行绘图。

  • 图片旋转后总是下降一行

    解决方法:键盘按下时是单独处理的 刷新写在计时器,应该旋转也写一个。

  • 双人在给对方增加行的时候下面有方块的全部往上挪,也即如果该列有方块,会填满到该列最上层

    解决方法:原先算法有问题,在给对方增加行的时候 不止上一行等于当前这行,当前这行也得置

  • 特殊方块中的生长方块上线行生长几乎一样,消除方块消除也总是一样,给对面增加行的时候留空也几乎一样

    解决方法:C#random是伪随机,短时间内生成的随机数几乎一样,故使用guid做随机数种子真随机

  • 在最后一行旋转时报超出数组边界

    解决方法:最后一行旋转产生的图片可能会超过边界,这时候要先判断是否到底

6.测试结果

启动程序

下落方块

特殊方块1

特殊方块1效果

特殊方块2

特殊方块2效果

上传的附件 cloud_download 基于C#实现的双人对战与道具赛的俄罗斯方块小游戏.7z ( 297.71kb, 18次下载 )
error_outline 下载需要13点积分

keyboard_arrow_left上一篇 : 基于JAVA的俄罗斯方块游戏 基于C语言的运动会成绩管理系统 : 下一篇keyboard_arrow_right



catastrophe
2019-04-20 16:17:24
基于C#实现的双人对战与道具赛的俄罗斯方块小游戏
vivid
2020-01-02 15:38:26
太喜欢了🐋🐋🐋
冰洋
2021-06-12 18:22:53
太棒了

发送私信

如果你改变不了沙漠,又没本事离开沙漠,那你只能把自己变成仙人掌

9
文章数
13
评论数
eject