吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1325|回复: 6
收起左侧

[其他原创] 用C# Windows窗体实现一个俄罗斯方块

[复制链接]
Molingo 发表于 2023-12-3 17:02
本帖最后由 Molingo 于 2023-12-3 17:06 编辑

先简单说一下实现思路
1.画板
游戏画面是有10*20的小方格组成,用代码在窗体中创建10*20个label控件,将长宽设为一样大小且统一设置黑色背景;
每个图形都是由四个小方格组成,通过改变画板上label的背景颜色,即可在绘制出图形;


2.图形的移动和变型

游戏中有7中图形,每个图形都是有4个小方格组成,可以左右移动或变形;在每个图形中选择其中一个方块,作为整个图形中心点,并记录这个图形点在整个画布中的(X,Y)坐标;通过中心点的坐标,绘制不同的图形;在移动图形时,只需要改变中心点坐标;例:左右移动时,只需要对中心的X轴-1或+1即可;移动之后,先记录上一次坐标位置,并通过坐标擦除掉图形(将label背景色设为黑色);并根据移动后的坐标进行绘制方块,图形有四种变化,每一次做变型时,根据中心点坐标先擦除在绘制;


3.图形的绘制和移动旋转判断


label是用10*20的数组进行存放,其数组索引即为小方格的坐标; 创建一个10*24的二维数组(需要在画布上方外腾出位置,绘制下落的图形),记录画布中每个方格坐标中是否存在方格,当图形在做移动和旋转时,可通过图形坐标点检查周围是否存在方块,来判定是否可以旋转或移动或下落;在窗体中增加一个定时器,让图形的中心点Y轴-1,来达到自动下落的功能;如图中,根据中心点绘制出红色图形;根据中线点判断灰色部分是否存在方块,来判定图形能否做旋转;
屏幕截图 2023-12-03 153107.png

4.满行消除与游戏结束

当图形无法下落时,通过用来记录方块是否存在的数组,判断画布每一行是否满行;满行后,擦除当行,让上面每一行都往下覆盖,实现消除;当方块无法下落且Y轴坐标高于画布最高的点时,游戏结束;

5.游戏截图

3.png

画布类:
[C#] 纯文本查看 复制代码
   public class Canvas
   {
       private  Label[,] canvals = new Label[20, 10];
       public Label[,] canvals2 = new Label[4, 4];
       public enum MoveDirection
       {
           left,
           right,
           Variant
       }
       private readonly Control Control;
       private readonly Control Control2;
       private Random Random;
       public Score score;
       private Blocks Blocks { get; set; }
       private Blocks NextBlocks { get; set; }
       /// <summary>
       /// 记录是否存在方块
       /// </summary>
       public bool[][] isExitBlock = new bool[24][];

       /// <summary>
       /// 记录方块的颜色
       /// </summary>
       public Color[][] blockColor = new Color[24][];


       /// <summary>
       /// 初始化画板
       /// </summary>
       /// <param name="c"></param>
       /// <param name="c2"></param>
       public Canvas(Control c, Control c2)
       {
           Control = c; Control2 = c2;
           DrawCanvas();
           InitializeGame();
       }
       /// <summary>
       /// 初始化游戏
       /// </summary>
       public void InitializeGame()
       {
           for (int i = 0; i < isExitBlock.Length; i++)
           {
               isExitBlock[i] = new bool[10];
               blockColor[i] = new Color[10];
           }
           Random = new Random((int)DateTime.Now.Ticks);
           Blocks = CreateNextBlock();
           score = new Score();
       }
       /// <summary>
       /// 创建下一个方块
       /// </summary>
       public Blocks CreateNextBlock()
       {
           NextBlocks = CreateBlock();
           NextBlocks.BlockType = Random.Next(1, 5);
           NextBlocks.BlockPoint = new Point(4, 21);
           NextBlocks.NextBlockType = NextBlocks.BlockType;
           return NextBlocks;
       }

       /// <summary>
       /// 随机创建方块
       /// </summary>
       /// <returns></returns>
       private Blocks CreateBlock()
       {
           int type = Random.Next(1, 8);
           switch (type)
           {
               case 1:
                   return new Block1(this);
               case 2:
                   return new Block2(this);
               case 3:
                   return new Block3(this);
               case 4:
                   return new Block4(this);
               case 5:
                   return new Block5(this);
               case 6:
                   return new Block6(this);
               case 7:
                   return new Block7(this);
               default:
                   return new Block1(this);
           }
       }

       /// <summary>
       /// 构建画板
       /// </summary>
       private void DrawCanvas()
       {
           for (int i = 0; i < canvals.GetLength(0); i++)
           {
               for (int j = 0; j < canvals.GetLength(1); j++)
               {

                   Label label = canvals[i, j] = new Label();
                   label.Width = 30;
                   label.Height = 30;
                   label.BorderStyle = BorderStyle.FixedSingle;
                   label.BackColor = Color.Black;
                   label.Location = new Point(j * 30, Control.Height - 30 - i * 30);
                   Control.Controls.Add(label);
               }
           }
           for (int i = 0; i < canvals2.GetLength(0); i++)
           {
               for (int j = 0; j < canvals2.GetLength(1); j++)
               {
                   Label label = canvals2[i, j] = new Label();
                   label.Width = 30;
                   label.Height = 30;
                   label.BorderStyle = BorderStyle.FixedSingle;
                   label.BackColor = Color.White;
                   label.Location = new Point(j * 30, i * 30);
                   Control2.Controls.Add(label);
               }
           }
       }

       /// <summary>
       /// 默认方块下落
       /// </summary>
       /// <param name="block"></param>
       public bool Freefall()
       {
           if (Blocks.IsFall())
           {
               Blocks.PreBlockPoint = Blocks.BlockPoint;
               Blocks.PreBlockType = Blocks.BlockType;
               Blocks.EraseBlock();
               Blocks.SetPointY(Blocks.BlockPoint.Y - 1);
               Blocks.Drawblock();
               ShowBlock();
               if (Blocks.BlockPoint.Y == 20)
               {
                   EraseNextBlock();
                   CreateNextBlock().DrawNextblock();
               }
               return true;
           }
           else
           {
               if (Blocks.BlockPoint.Y == 21)
               {
                   score.GameOverTime = DateTime.Now;
                   score.SaveGamelog();
                   return false;
               }
               FullLineDispel();
               Blocks = NextBlocks;
               return true;
           }
       }

       /// <summary>
       /// 方块显示
       /// </summary>
       /// <param name="blocks"></param>
       public void ShowBlock()
       {
           for (int i = 0; i < canvals.GetLength(0); i++)
           {
               for (int j = 0; j < canvals.GetLength(1); j++)
               {
                   if (isExitBlock[i][j])
                       canvals[i, j].BackColor = blockColor[i][j];
                   else
                       canvals[i, j].BackColor = Color.Black;
               }
           }
       }

       /// <summary>
       /// 方块的移动或变形
       /// </summary>
       /// <param name="move"></param>
       public void MoveOrVariantBlock(MoveDirection move)
       {
           switch (move)
           {
               case MoveDirection.left:
                   if (Blocks.LeftMove())
                   {
                       Blocks.PreBlockType = Blocks.BlockType;
                       Blocks.PreBlockPoint = Blocks.BlockPoint;
                       Blocks.EraseBlock();
                       Blocks.SetPointX(Blocks.BlockPoint.X - 1);
                       Blocks.Drawblock();
                       ShowBlock();
                   }
                   break;
               case MoveDirection.right:
                   if (Blocks.rightMove())
                   {
                       Blocks.PreBlockType = Blocks.BlockType;
                       Blocks.PreBlockPoint = Blocks.BlockPoint;
                       Blocks.EraseBlock();
                       Blocks.SetPointX(Blocks.BlockPoint.X + 1);
                       Blocks.Drawblock();
                       ShowBlock();
                   }
                   break;
               case MoveDirection.Variant:
                   if (Blocks.IsVariant())
                   {
                       Blocks.PreBlockType = Blocks.BlockType;
                       Blocks.PreBlockPoint = Blocks.BlockPoint;
                       Blocks.EraseBlock();
                       Blocks.BlockType += 1;
                       Blocks.Drawblock();
                       ShowBlock();
                   }
                   break;
               default:
                   break;
           }

       }

  /// <summary>
  /// 满行消除
  /// </summary>
  public void FullLineDispel()
  {
      int row = -1;
      for (int i = 0; i <= canvals.GetLength(0); i++)
      {
          int count = 0;
          for (int j = 0; j < canvals.GetLength(1); j++)
          {
              if (isExitBlock[i][j]) count++;
          }

          if (count == canvals.GetLength(1))
          {
              if (row == i)
              {
                  score.GameScore += 2;
              }
              else
              {
                  score.GameScore += 1;
              }
              score.Rows+=1;
              row = i;
              if (score.GameScore % 20 == 0)
              {
                  score.Leave = score.GameScore / 20;
                  score.FallingVelocity -= score.Leave * 50;
              }

              for (int k = i; k < 23; k++)
              {
                  isExitBlock[k] = isExitBlock[k + 1];
                  blockColor[k] = blockColor[k + 1];
              }
              isExitBlock[23] = new bool[10];
              blockColor[23] = new Color[10];
              i--;
          }

      }

  }
       /// <summary>
       /// 擦除显示下一方块的画板
       /// </summary>
       public void EraseNextBlock()
       {
           foreach (var item in canvals2)
           {
               item.BackColor = Color.White;
           }
       }
   }



方块抽象类:
[C#] 纯文本查看 复制代码
 public abstract class Blocks
 {
     public Blocks(Canvas canvas)
     {
         c = canvas;
     }
     protected Canvas c;

     protected static Random random = new Random((int)DateTime.Now.Ticks);
     protected static Color[] Colors = new Color[] {
     Color.Magenta,
     Color.DeepPink,
     Color.Red,
     Color.Orange,
     Color.DarkTurquoise,
     Color.Coral,
     Color.Yellow,
     Color.MediumSpringGreen,
     Color.Cyan,
     Color.DodgerBlue,
     Color.Aqua,
     Color.MediumVioletRed,
     Color.DarkMagenta,
     Color.OrangeRed,
     Color.Aquamarine,
     Color.SeaGreen,
     Color.PaleVioletRed,
     Color.PaleGreen,
     Color.PaleTurquoise,
     Color.SpringGreen,
     Color.Tomato,
     Color.Turquoise,
     Color.Violet,
     Color.LightCoral,
     Color.YellowGreen,
     Color.Plum,
     Color.MediumTurquoise,
     Color.DarkCyan,
     Color.GreenYellow
     };

    
     /// <summary>
     /// 设置当前方块的X坐标
     /// </summary>
     /// <param name="x"></param>
     public void SetPointX(int x) => BlockPoint = new Point(x, BlockPoint.Y);
     /// <summary>
     /// 设置当前方块的y坐标
     /// </summary>
     /// <param name="y"></param>
     public void SetPointY(int y) => BlockPoint = new Point(BlockPoint.X, y);


     private int _blockType;

     /// <summary>
     /// 当前方块的类型
     /// </summary>
     public int BlockType
     {
         get => _blockType;
         set => _blockType = value > 4 ? 1 : value;
     }
     /// <summary>
     /// 当前方块中心点的位置
     /// </summary>
     public Point BlockPoint { get; set; }
     /// <summary>
     /// 当前方块的颜色
     /// </summary>
     public  Color CurrentBlockColor { get; protected set; } = Colors[random.Next(0, Colors.Length)];
     /// <summary>
     /// 方块上一次的中心点位置
     /// </summary>
     public Point PreBlockPoint { get; set; }
     /// <summary>
     /// 上一次方块的类型
     /// </summary>
     public int PreBlockType { get; set; }


     /// <summary>
     /// 下一个方块类型
     /// </summary>
     public int NextBlockType { get; set; }

  

     /// <summary>
     /// 是否可以继续下落
     /// </summary>
     /// <returns></returns>
     public abstract bool IsFall();

     /// <summary>
     /// 是否可以左移
     /// </summary>
     /// <returns></returns>
     public abstract bool LeftMove();


     /// <summary>
     /// 是否可以右移
     /// </summary>
     /// <returns></returns>
     public abstract bool rightMove();


     /// <summary>
     /// 是否可以变形
     /// </summary>
     /// <returns></returns>
     public abstract bool IsVariant();

     /// <summary>
     /// 擦除方块
     /// </summary>
     public abstract void EraseBlock();

     /// <summary>
     /// 绘制方块
     /// </summary>
     public abstract void Drawblock();

     /// <summary>
     /// 绘制下一个方块
     /// </summary>
     public abstract void DrawNextblock();
 }



其中一个方块的实现类
[C#] 纯文本查看 复制代码
class Block3 : Blocks
{
    public Block3(Canvas c) : base(c)
    {
    }

    public override void Drawblock()
    {
        switch (BlockType)
        {
            case 1:
                c.isExitBlock[BlockPoint.Y][BlockPoint.X] = c.isExitBlock[BlockPoint.Y][BlockPoint.X + 1] = c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X] = c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X + 1] = true;
                c.blockColor[BlockPoint.Y][BlockPoint.X] = c.blockColor[BlockPoint.Y][BlockPoint.X + 1] = c.blockColor[BlockPoint.Y + 1][BlockPoint.X] = c.blockColor[BlockPoint.Y - 1][BlockPoint.X + 1] = CurrentBlockColor;break;
            case 2:
                c.isExitBlock[BlockPoint.Y][BlockPoint.X] = c.isExitBlock[BlockPoint.Y][BlockPoint.X + 1] = c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X] = c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X - 1] = true;
                c.blockColor[BlockPoint.Y][BlockPoint.X] = c.blockColor[BlockPoint.Y][BlockPoint.X + 1] = c.blockColor[BlockPoint.Y - 1][BlockPoint.X] = c.blockColor[BlockPoint.Y - 1][BlockPoint.X - 1] = CurrentBlockColor; break;
            case 3:
                c.isExitBlock[BlockPoint.Y][BlockPoint.X] = c.isExitBlock[BlockPoint.Y][BlockPoint.X - 1] = c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X - 1] = c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X] = true;
                c.blockColor[BlockPoint.Y][BlockPoint.X] = c.blockColor[BlockPoint.Y][BlockPoint.X - 1] = c.blockColor[BlockPoint.Y + 1][BlockPoint.X - 1] = c.blockColor[BlockPoint.Y - 1][BlockPoint.X] = CurrentBlockColor; break;
            case 4:
                c.isExitBlock[BlockPoint.Y][BlockPoint.X] = c.isExitBlock[BlockPoint.Y][BlockPoint.X - 1] = c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X] = c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X + 1] = true;
                c.blockColor[BlockPoint.Y][BlockPoint.X] = c.blockColor[BlockPoint.Y][BlockPoint.X - 1] = c.blockColor[BlockPoint.Y + 1][BlockPoint.X] = c.blockColor[BlockPoint.Y + 1][BlockPoint.X + 1] = CurrentBlockColor; break;


        }
    }

    public override void DrawNextblock()
    {
        switch (NextBlockType)
        {
            case 1:
                c.canvals2[0, 1].BackColor = CurrentBlockColor;
                c.canvals2[1, 1].BackColor = CurrentBlockColor;
                c.canvals2[1, 2].BackColor = CurrentBlockColor;
                c.canvals2[2, 2].BackColor = CurrentBlockColor;
                break;
            case 2:
                c.canvals2[1, 1].BackColor = CurrentBlockColor;
                c.canvals2[1, 2].BackColor = CurrentBlockColor;
                c.canvals2[2, 0].BackColor = CurrentBlockColor;
                c.canvals2[2, 1].BackColor = CurrentBlockColor;
                break;
            case 3:
                c.canvals2[0, 0].BackColor = CurrentBlockColor;
                c.canvals2[1, 0].BackColor = CurrentBlockColor;
                c.canvals2[1, 1].BackColor = CurrentBlockColor;
                c.canvals2[2, 1].BackColor = CurrentBlockColor;
                break;
            case 4:
                c.canvals2[0, 1].BackColor = CurrentBlockColor;
                c.canvals2[0, 2].BackColor = CurrentBlockColor;
                c.canvals2[1, 0].BackColor = CurrentBlockColor;
                c.canvals2[1, 1].BackColor = CurrentBlockColor;
                break;
        }
    }

    public override void EraseBlock()
    {
        switch (PreBlockType)
        {
            case 1:
                c.isExitBlock[PreBlockPoint.Y][PreBlockPoint.X] = c.isExitBlock[PreBlockPoint.Y][PreBlockPoint.X + 1] = c.isExitBlock[PreBlockPoint.Y + 1][PreBlockPoint.X] = c.isExitBlock[PreBlockPoint.Y - 1][PreBlockPoint.X + 1] = false; break;
            case 2:
                c.isExitBlock[PreBlockPoint.Y][PreBlockPoint.X] = c.isExitBlock[PreBlockPoint.Y][PreBlockPoint.X + 1] = c.isExitBlock[PreBlockPoint.Y - 1][PreBlockPoint.X] = c.isExitBlock[PreBlockPoint.Y - 1][PreBlockPoint.X - 1] = false; break;
            case 3:
                c.isExitBlock[PreBlockPoint.Y][PreBlockPoint.X] = c.isExitBlock[PreBlockPoint.Y][PreBlockPoint.X - 1] = c.isExitBlock[PreBlockPoint.Y + 1][PreBlockPoint.X - 1] = c.isExitBlock[PreBlockPoint.Y - 1][PreBlockPoint.X] = false; break;
            case 4:
                c.isExitBlock[PreBlockPoint.Y][PreBlockPoint.X] = c.isExitBlock[PreBlockPoint.Y][PreBlockPoint.X - 1] = c.isExitBlock[PreBlockPoint.Y + 1][PreBlockPoint.X] = c.isExitBlock[PreBlockPoint.Y + 1][PreBlockPoint.X + 1] = false; break;

        }
    }

    public override bool IsFall()
    {
        bool b = false;
        switch (BlockType)
        {
            case 1:
                if (BlockPoint.Y > 1 && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X] && !c.isExitBlock[BlockPoint.Y - 2][BlockPoint.X + 1]) b = true;
                break;
            case 2:
                if (BlockPoint.Y > 1 && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X + 1] && !c.isExitBlock[BlockPoint.Y - 2][BlockPoint.X] && !c.isExitBlock[BlockPoint.Y - 2][BlockPoint.X - 1]) b = true;
                break;
            case 3:
                if (BlockPoint.Y > 1 && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X - 1] && !c.isExitBlock[BlockPoint.Y - 2][BlockPoint.X]) b = true;
                break;
            case 4:
                if (BlockPoint.Y > 0 && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X - 1] && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X] && !c.isExitBlock[BlockPoint.Y][BlockPoint.X + 1]) b = true;
                break;
        }
        return b;
    }

    public override bool IsVariant()
    {
        bool b = false;
        switch (BlockType)
        {
            case 1:
                if (BlockPoint.X > 0 && BlockPoint.X < 9 && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X] && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X - 1] && !c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X + 1]) b = true;
                break;
            case 2:
                if (BlockPoint.X > 0 && BlockPoint.X < 9 && !c.isExitBlock[BlockPoint.Y][BlockPoint.X - 1] && !c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X - 1] && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X + 1]) b = true;
                break;
            case 3:
                if (BlockPoint.X > 0 && BlockPoint.X < 9 && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X - 1] && !c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X] && !c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X + 1]) b = true;
                break;
            case 4:
                if (BlockPoint.X > 0 && BlockPoint.X < 9 && BlockPoint.Y > 0 && !c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X - 1] && !c.isExitBlock[BlockPoint.Y ][BlockPoint.X + 1] && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X + 1]) b = true;
                break;
        }
        return b;
    }

    public override bool LeftMove()
    {
        bool b = false;
        switch (BlockType)
        {
            case 1:
                if (BlockPoint.X > 0 && !c.isExitBlock[BlockPoint.Y][BlockPoint.X - 1] && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X] && !c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X - 1]) b = true;
                break;
            case 2:
                if (BlockPoint.X > 1 && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X - 2] && !c.isExitBlock[BlockPoint.Y][BlockPoint.X - 1]) b = true;
                break;
            case 3:
                if (BlockPoint.X > 1 && !c.isExitBlock[BlockPoint.Y][BlockPoint.X - 2] && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X - 1] && !c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X - 2]) b = true;
                break;
            case 4:
                if (BlockPoint.X > 1 && !c.isExitBlock[BlockPoint.Y][BlockPoint.X - 2] && !c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X - 1]) b = true;
                break;
        }
        return b;
    }

    public override bool rightMove()
    {
        bool b = false;
        switch (BlockType)
        {
            case 1:
                if (BlockPoint.X < 8 && !c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X + 1] && !c.isExitBlock[BlockPoint.Y][BlockPoint.X + 2] && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X + 2]) b = true;
                break;
            case 2:
                if (BlockPoint.X < 8 && !c.isExitBlock[BlockPoint.Y][BlockPoint.X + 2] && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X + 1]) b = true;
                break;
            case 3:
                if (BlockPoint.X < 9 && !c.isExitBlock[BlockPoint.Y][BlockPoint.X + 1] && !c.isExitBlock[BlockPoint.Y - 1][BlockPoint.X + 1] && !c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X]) b = true;
                break;
            case 4:
                if (BlockPoint.X < 8 && !c.isExitBlock[BlockPoint.Y][BlockPoint.X + 1] && !c.isExitBlock[BlockPoint.Y + 1][BlockPoint.X + 2]) b = true;
                break;
        }
        return b;
    }
}


完整源代码
MyTetris.zip (304.47 KB, 下载次数: 16)
俄罗斯方块--对应代码的图形参考.zip (10.02 KB, 下载次数: 11)
2.png
屏幕截图 2023-12-03 153107.png

免费评分

参与人数 3威望 +1 吾爱币 +20 热心值 +3 收起 理由
Circulation2020 + 1 谢谢@Thanks!
DanielToyama + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
苏紫方璇 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

xintian 发表于 2023-12-4 09:28
牛啊,我就写不出.
wzbarley 发表于 2023-12-4 10:14
 楼主| Molingo 发表于 2023-12-4 11:16
xenost 发表于 2023-12-5 11:31
这个好东西啊,感谢分享
ycs 发表于 2023-12-5 12:49
这个是认真学习和思考的结果,该表扬。
BI3NWQ 发表于 2023-12-12 11:27
学习一下,顺便体验体验
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 17:51

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表