C# 俄罗斯方块游戏

俄罗斯方块游戏,使用C#和Windows Forms实现。

完整代码实现

csharp 复制代码
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Diagnostics;

namespace TetrisGame
{
    public partial class TetrisForm : Form
    {
        // 游戏常量
        private const int BoardWidth = 10;
        private const int BoardHeight = 20;
        private const int CellSize = 30;
        private const int PreviewSize = 5;
        
        // 游戏状态
        private int[,] gameBoard;
        private Tetromino currentPiece;
        private Tetromino nextPiece;
        private Random random;
        private bool isGameActive;
        private int score;
        private int level;
        private int linesCleared;
        private int fallSpeed;
        private int fallCounter;
        private Stopwatch gameTimer;
        
        // 颜色定义
        private readonly Color[] tetrominoColors = 
        {
            Color.Cyan,     // I
            Color.Blue,     // J
            Color.Orange,   // L
            Color.Yellow,   // O
            Color.Green,    // S
            Color.Purple,   // T
            Color.Red       // Z
        };
        
        // 方块形状定义
        private readonly int[][,] tetrominoShapes = 
        {
            // I
            new int[,] { {1,1,1,1} },
            // J
            new int[,] { {1,0,0}, {1,1,1} },
            // L
            new int[,] { {0,0,1}, {1,1,1} },
            // O
            new int[,] { {1,1}, {1,1} },
            // S
            new int[,] { {0,1,1}, {1,1,0} },
            // T
            new int[,] { {0,1,0}, {1,1,1} },
            // Z
            new int[,] { {1,1,0}, {0,1,1} }
        };
        
        // UI组件
        private Panel gamePanel;
        private Panel previewPanel;
        private Label scoreLabel;
        private Label levelLabel;
        private Label linesLabel;
        private Button startButton;
        private Button pauseButton;
        private Label gameStatusLabel;
        
        public TetrisForm()
        {
            InitializeGame();
            InitializeComponents();
            SetupGameLoop();
        }
        
        private void InitializeGame()
        {
            gameBoard = new int[BoardHeight, BoardWidth];
            random = new Random();
            isGameActive = false;
            score = 0;
            level = 1;
            linesCleared = 0;
            fallSpeed = 30; // 初始下落速度(值越小越快)
            fallCounter = 0;
            gameTimer = new Stopwatch();
        }
        
        private void InitializeComponents()
        {
            // 窗体设置
            this.Text = "俄罗斯方块 - C# 实现";
            this.ClientSize = new Size(800, 650);
            this.BackColor = Color.FromArgb(30, 30, 50);
            this.FormBorderStyle = FormBorderStyle.FixedSingle;
            this.MaximizeBox = false;
            this.KeyPreview = true;
            this.KeyDown += TetrisForm_KeyDown;
            
            // 游戏主面板
            gamePanel = new Panel
            {
                Location = new Point(20, 20),
                Size = new Size(BoardWidth * CellSize, BoardHeight * CellSize),
                BackColor = Color.Black,
                BorderStyle = BorderStyle.Fixed3D
            };
            gamePanel.Paint += GamePanel_Paint;
            this.Controls.Add(gamePanel);
            
            // 预览面板
            previewPanel = new Panel
            {
                Location = new Point(400, 20),
                Size = new Size(PreviewSize * CellSize, PreviewSize * CellSize),
                BackColor = Color.Black,
                BorderStyle = BorderStyle.Fixed3D
            };
            previewPanel.Paint += PreviewPanel_Paint;
            this.Controls.Add(previewPanel);
            
            // 分数标签
            scoreLabel = new Label
            {
                Location = new Point(400, 200),
                Size = new Size(200, 30),
                Text = "分数: 0",
                Font = new Font("Arial", 14, FontStyle.Bold),
                ForeColor = Color.White,
                BackColor = Color.Transparent
            };
            this.Controls.Add(scoreLabel);
            
            // 等级标签
            levelLabel = new Label
            {
                Location = new Point(400, 240),
                Size = new Size(200, 30),
                Text = "等级: 1",
                Font = new Font("Arial", 14, FontStyle.Bold),
                ForeColor = Color.White,
                BackColor = Color.Transparent
            };
            this.Controls.Add(levelLabel);
            
            // 消除行数标签
            linesLabel = new Label
            {
                Location = new Point(400, 280),
                Size = new Size(200, 30),
                Text = "消除行数: 0",
                Font = new Font("Arial", 14, FontStyle.Bold),
                ForeColor = Color.White,
                BackColor = Color.Transparent
            };
            this.Controls.Add(linesLabel);
            
            // 游戏状态标签
            gameStatusLabel = new Label
            {
                Location = new Point(400, 120),
                Size = new Size(200, 60),
                Text = "按开始游戏",
                Font = new Font("Arial", 16, FontStyle.Bold),
                ForeColor = Color.Yellow,
                BackColor = Color.Transparent,
                TextAlign = ContentAlignment.MiddleCenter
            };
            this.Controls.Add(gameStatusLabel);
            
            // 开始按钮
            startButton = new Button
            {
                Location = new Point(400, 350),
                Size = new Size(120, 40),
                Text = "开始游戏",
                Font = new Font("Arial", 12, FontStyle.Bold),
                BackColor = Color.FromArgb(70, 130, 180),
                ForeColor = Color.White,
                FlatStyle = FlatStyle.Flat
            };
            startButton.Click += StartButton_Click;
            this.Controls.Add(startButton);
            
            // 暂停按钮
            pauseButton = new Button
            {
                Location = new Point(540, 350),
                Size = new Size(120, 40),
                Text = "暂停游戏",
                Font = new Font("Arial", 12, FontStyle.Bold),
                BackColor = Color.FromArgb(70, 130, 180),
                ForeColor = Color.White,
                FlatStyle = FlatStyle.Flat,
                Enabled = false
            };
            pauseButton.Click += PauseButton_Click;
            this.Controls.Add(pauseButton);
            
            // 控制说明标签
            Label controlsLabel = new Label
            {
                Location = new Point(400, 420),
                Size = new Size(300, 200),
                Text = "控制说明:\n" +
                       "← → : 左右移动\n" +
                       "↑ : 旋转方块\n" +
                       "↓ : 加速下落\n" +
                       "空格 : 直接落下\n" +
                       "P : 暂停/继续\n" +
                       "R : 重新开始",
                Font = new Font("Arial", 11),
                ForeColor = Color.LightGray,
                BackColor = Color.Transparent
            };
            this.Controls.Add(controlsLabel);
        }
        
        private void SetupGameLoop()
        {
            // 设置游戏循环计时器
            Timer gameTimer = new Timer
            {
                Interval = 50 // 50ms更新一次
            };
            gameTimer.Tick += GameTimer_Tick;
            gameTimer.Start();
        }
        
        private void GameTimer_Tick(object sender, EventArgs e)
        {
            if (!isGameActive) return;
            
            fallCounter++;
            if (fallCounter >= fallSpeed)
            {
                MovePieceDown();
                fallCounter = 0;
            }
            
            // 重绘游戏区域
            gamePanel.Invalidate();
            previewPanel.Invalidate();
        }
        
        private void StartNewGame()
        {
            // 重置游戏板
            for (int y = 0; y < BoardHeight; y++)
                for (int x = 0; x < BoardWidth; x++)
                    gameBoard[y, x] = 0;
            
            // 重置游戏状态
            score = 0;
            level = 1;
            linesCleared = 0;
            fallSpeed = 30;
            
            // 生成第一个和下一个方块
            currentPiece = CreateRandomTetromino();
            nextPiece = CreateRandomTetromino();
            
            // 更新UI
            UpdateLabels();
            gameStatusLabel.Text = "游戏进行中";
            gameStatusLabel.ForeColor = Color.LimeGreen;
            
            // 激活游戏
            isGameActive = true;
            startButton.Enabled = false;
            pauseButton.Enabled = true;
            pauseButton.Text = "暂停游戏";
            
            gameTimer = Stopwatch.StartNew();
        }
        
        private Tetromino CreateRandomTetromino()
        {
            int shapeIndex = random.Next(0, tetrominoShapes.Length);
            int[,] shape = tetrominoShapes[shapeIndex];
            Color color = tetrominoColors[shapeIndex];
            
            // 计算初始位置(居中)
            int startX = (BoardWidth - shape.GetLength(1)) / 2;
            
            return new Tetromino(shape, color, startX, 0);
        }
        
        private void MovePieceDown()
        {
            if (CanMove(currentPiece, 0, 1))
            {
                currentPiece.Y++;
            }
            else
            {
                // 锁定方块到游戏板
                LockPiece();
                
                // 检查并清除完整的行
                int lines = CheckAndClearLines();
                if (lines > 0)
                {
                    AddScore(lines);
                    UpdateLevel();
                }
                
                // 生成新的方块
                currentPiece = nextPiece;
                nextPiece = CreateRandomTetromino();
                
                // 检查游戏是否结束
                if (!CanMove(currentPiece, 0, 0))
                {
                    GameOver();
                }
            }
        }
        
        private void MovePieceLeft()
        {
            if (CanMove(currentPiece, -1, 0))
                currentPiece.X--;
        }
        
        private void MovePieceRight()
        {
            if (CanMove(currentPiece, 1, 0))
                currentPiece.X++;
        }
        
        private void RotatePiece()
        {
            Tetromino rotatedPiece = currentPiece.Rotate();
            
            // 检查旋转后是否有效
            if (CanMove(rotatedPiece, 0, 0))
            {
                currentPiece = rotatedPiece;
            }
            else
            {
                // 尝试墙踢(wall kick) - 如果旋转后碰撞,尝试左右移动一格
                if (CanMove(rotatedPiece, -1, 0))
                {
                    rotatedPiece.X--;
                    currentPiece = rotatedPiece;
                }
                else if (CanMove(rotatedPiece, 1, 0))
                {
                    rotatedPiece.X++;
                    currentPiece = rotatedPiece;
                }
            }
        }
        
        private void HardDrop()
        {
            while (CanMove(currentPiece, 0, 1))
            {
                currentPiece.Y++;
                score += 1; // 硬降奖励分数
            }
            
            // 立即锁定方块
            LockPiece();
            
            // 检查并清除完整的行
            int lines = CheckAndClearLines();
            if (lines > 0)
            {
                AddScore(lines);
                UpdateLevel();
            }
            
            // 生成新的方块
            currentPiece = nextPiece;
            nextPiece = CreateRandomTetromino();
            
            // 检查游戏是否结束
            if (!CanMove(currentPiece, 0, 0))
            {
                GameOver();
            }
            
            UpdateLabels();
        }
        
        private bool CanMove(Tetromino piece, int deltaX, int deltaY)
        {
            int newX = piece.X + deltaX;
            int newY = piece.Y + deltaY;
            
            for (int y = 0; y < piece.Height; y++)
            {
                for (int x = 0; x < piece.Width; x++)
                {
                    if (piece.Shape[y, x] == 1)
                    {
                        int boardX = newX + x;
                        int boardY = newY + y;
                        
                        // 检查边界
                        if (boardX < 0 || boardX >= BoardWidth || boardY >= BoardHeight)
                            return false;
                        
                        // 检查是否与已有方块碰撞
                        if (boardY >= 0 && gameBoard[boardY, boardX] != 0)
                            return false;
                    }
                }
            }
            
            return true;
        }
        
        private void LockPiece()
        {
            for (int y = 0; y < currentPiece.Height; y++)
            {
                for (int x = 0; x < currentPiece.Width; x++)
                {
                    if (currentPiece.Shape[y, x] == 1)
                    {
                        int boardX = currentPiece.X + x;
                        int boardY = currentPiece.Y + y;
                        
                        if (boardY >= 0) // 确保在游戏板内
                        {
                            // 存储颜色索引(从1开始,0表示空)
                            int colorIndex = Array.IndexOf(tetrominoColors, currentPiece.Color) + 1;
                            gameBoard[boardY, boardX] = colorIndex;
                        }
                    }
                }
            }
        }
        
        private int CheckAndClearLines()
        {
            int linesClearedCount = 0;
            
            for (int y = BoardHeight - 1; y >= 0; y--)
            {
                bool lineComplete = true;
                
                // 检查行是否完整
                for (int x = 0; x < BoardWidth; x++)
                {
                    if (gameBoard[y, x] == 0)
                    {
                        lineComplete = false;
                        break;
                    }
                }
                
                // 如果行完整,清除它并将上面的行下移
                if (lineComplete)
                {
                    linesClearedCount++;
                    
                    // 将上面的所有行下移
                    for (int ny = y; ny > 0; ny--)
                    {
                        for (int x = 0; x < BoardWidth; x++)
                        {
                            gameBoard[ny, x] = gameBoard[ny - 1, x];
                        }
                    }
                    
                    // 清空最顶部一行
                    for (int x = 0; x < BoardWidth; x++)
                    {
                        gameBoard[0, x] = 0;
                    }
                    
                    // 重新检查当前行(因为已经下移了一行)
                    y++;
                }
            }
            
            linesCleared += linesClearedCount;
            return linesClearedCount;
        }
        
        private void AddScore(int lines)
        {
            // 根据一次消除的行数给予不同分数
            int points = 0;
            switch (lines)
            {
                case 1: points = 100 * level; break;
                case 2: points = 300 * level; break;
                case 3: points = 500 * level; break;
                case 4: points = 800 * level; break;
            }
            
            score += points;
            UpdateLabels();
        }
        
        private void UpdateLevel()
        {
            // 每消除10行升一级
            int newLevel = (linesCleared / 10) + 1;
            
            if (newLevel > level)
            {
                level = newLevel;
                // 随着等级提高,下落速度加快
                fallSpeed = Math.Max(5, 30 - (level - 1) * 2);
                UpdateLabels();
            }
        }
        
        private void GameOver()
        {
            isGameActive = false;
            gameStatusLabel.Text = "游戏结束!";
            gameStatusLabel.ForeColor = Color.Red;
            startButton.Enabled = true;
            pauseButton.Enabled = false;
            
            // 显示最终分数
            MessageBox.Show($"游戏结束!\n最终分数: {score}\n消除行数: {linesCleared}\n等级: {level}", 
                          "游戏结束", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        
        private void UpdateLabels()
        {
            scoreLabel.Text = $"分数: {score}";
            levelLabel.Text = $"等级: {level}";
            linesLabel.Text = $"消除行数: {linesCleared}";
        }
        
        private void GamePanel_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            
            // 绘制网格背景
            for (int y = 0; y < BoardHeight; y++)
            {
                for (int x = 0; x < BoardWidth; x++)
                {
                    Rectangle rect = new Rectangle(
                        x * CellSize, 
                        y * CellSize, 
                        CellSize, 
                        CellSize);
                    
                    // 绘制游戏板上的方块
                    if (gameBoard[y, x] != 0)
                    {
                        int colorIndex = gameBoard[y, x] - 1;
                        Color color = tetrominoColors[colorIndex];
                        
                        using (Brush brush = new SolidBrush(color))
                        {
                            g.FillRectangle(brush, rect);
                        }
                        
                        // 绘制方块边框
                        using (Pen pen = new Pen(Color.White, 1))
                        {
                            g.DrawRectangle(pen, rect);
                        }
                    }
                    else
                    {
                        // 绘制空单元格
                        using (Brush brush = new SolidBrush(Color.FromArgb(30, 30, 30)))
                        {
                            g.FillRectangle(brush, rect);
                        }
                        
                        // 绘制网格线
                        using (Pen pen = new Pen(Color.FromArgb(60, 60, 60), 1))
                        {
                            g.DrawRectangle(pen, rect);
                        }
                    }
                }
            }
            
            // 绘制当前下落的方块
            if (currentPiece != null && isGameActive)
            {
                DrawTetromino(g, currentPiece, currentPiece.X, currentPiece.Y);
            }
        }
        
        private void PreviewPanel_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            
            // 清空预览面板
            g.Clear(Color.Black);
            
            if (nextPiece != null)
            {
                // 计算居中位置
                int offsetX = (PreviewSize - nextPiece.Width) * CellSize / 2;
                int offsetY = (PreviewSize - nextPiece.Height) * CellSize / 2;
                
                DrawTetromino(g, nextPiece, offsetX / CellSize, offsetY / CellSize, true);
            }
        }
        
        private void DrawTetromino(Graphics g, Tetromino piece, int boardX, int boardY, bool isPreview = false)
        {
            for (int y = 0; y < piece.Height; y++)
            {
                for (int x = 0; x < piece.Width; x++)
                {
                    if (piece.Shape[y, x] == 1)
                    {
                        Rectangle rect = new Rectangle(
                            (boardX + x) * CellSize, 
                            (boardY + y) * CellSize, 
                            CellSize, 
                            CellSize);
                        
                        using (Brush brush = new SolidBrush(piece.Color))
                        {
                            g.FillRectangle(brush, rect);
                        }
                        
                        // 绘制方块边框
                        using (Pen pen = new Pen(Color.White, 1))
                        {
                            g.DrawRectangle(pen, rect);
                        }
                        
                        // 为预览方块添加半透明效果
                        if (isPreview)
                        {
                            using (Brush overlay = new SolidBrush(Color.FromArgb(100, 255, 255, 255)))
                            {
                                g.FillRectangle(overlay, rect);
                            }
                        }
                    }
                }
            }
        }
        
        private void TetrisForm_KeyDown(object sender, KeyEventArgs e)
        {
            if (!isGameActive && e.KeyCode != Keys.R && e.KeyCode != Keys.P)
                return;
                
            switch (e.KeyCode)
            {
                case Keys.Left:
                    MovePieceLeft();
                    break;
                case Keys.Right:
                    MovePieceRight();
                    break;
                case Keys.Down:
                    MovePieceDown();
                    score += 1; // 软降奖励分数
                    UpdateLabels();
                    break;
                case Keys.Up:
                    RotatePiece();
                    break;
                case Keys.Space:
                    HardDrop();
                    break;
                case Keys.P:
                    TogglePause();
                    break;
                case Keys.R:
                    StartNewGame();
                    break;
            }
            
            // 重绘游戏区域
            gamePanel.Invalidate();
        }
        
        private void StartButton_Click(object sender, EventArgs e)
        {
            StartNewGame();
        }
        
        private void PauseButton_Click(object sender, EventArgs e)
        {
            TogglePause();
        }
        
        private void TogglePause()
        {
            if (!isGameActive && pauseButton.Text == "继续游戏")
            {
                // 继续游戏
                isGameActive = true;
                pauseButton.Text = "暂停游戏";
                gameStatusLabel.Text = "游戏进行中";
                gameStatusLabel.ForeColor = Color.LimeGreen;
                gameTimer?.Start();
            }
            else if (isGameActive)
            {
                // 暂停游戏
                isGameActive = false;
                pauseButton.Text = "继续游戏";
                gameStatusLabel.Text = "游戏暂停";
                gameStatusLabel.ForeColor = Color.Yellow;
                gameTimer?.Stop();
            }
        }
        
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new TetrisForm());
        }
    }
    
    // 方块类
    public class Tetromino
    {
        public int[,] Shape { get; set; }
        public Color Color { get; set; }
        public int X { get; set; }
        public int Y { get; set; }
        
        public int Width => Shape.GetLength(1);
        public int Height => Shape.GetLength(0);
        
        public Tetromino(int[,] shape, Color color, int x, int y)
        {
            Shape = shape;
            Color = color;
            X = x;
            Y = y;
        }
        
        public Tetromino Rotate()
        {
            int rows = Shape.GetLength(0);
            int cols = Shape.GetLength(1);
            
            // 创建新的旋转后的形状
            int[,] rotated = new int[cols, rows];
            
            for (int y = 0; y < rows; y++)
            {
                for (int x = 0; x < cols; x++)
                {
                    rotated[x, rows - 1 - y] = Shape[y, x];
                }
            }
            
            // 返回新的Tetromino实例,保持其他属性不变
            return new Tetromino(rotated, Color, X, Y);
        }
    }
}

项目设置说明

  1. 在Visual Studio中创建新的Windows Forms应用项目
  2. 将上述代码复制粘贴到Form1.cs文件中(或重命名为TetrisForm.cs)
  3. 确保项目中引用了System.Drawing命名空间

游戏功能特性

  1. 核心游戏机制

    • 标准俄罗斯方块玩法
    • 7种不同形状的方块
    • 方块旋转、移动和下落
    • 行消除和分数计算
  2. 游戏控制

    • 左右箭头:移动方块
    • 上箭头:旋转方块
    • 下箭头:加速下落
    • 空格键:直接落下(硬降)
    • P键:暂停/继续游戏
    • R键:重新开始游戏
  3. 游戏界面

    • 主游戏区域显示当前方块和已固定的方块
    • 预览区域显示下一个方块
    • 分数、等级和消除行数显示
    • 开始/暂停按钮
  4. 游戏逻辑

    • 分数系统(消除行数越多得分越高)
    • 等级系统(消除行数越多等级越高,下落速度越快)
    • 碰撞检测
    • 游戏结束判定

参考代码 C# 拼图游戏 www.youwenfan.com/csa/93149.html

扩展建议

如果您想进一步扩展这个游戏,可以考虑添加以下功能:

  1. 保存最高分记录
  2. 添加音效和背景音乐
  3. 实现更多方块旋转规则(如SRS旋转系统)
  4. 添加游戏难度选择
  5. 实现方块阴影(显示方块将落下的位置)
  6. 添加游戏暂停时的封面画面
  7. 实现网络排行榜功能
相关推荐
huaqianzkh2 小时前
WinForm + DevExpress 控件的「完整继承关系」
开发语言
a***59263 小时前
C++跨平台开发:挑战与解决方案
开发语言·c++
青槿吖3 小时前
Java 集合操作:HashSet、LinkedHashSet 和 TreeSet
java·开发语言·jvm
chao1898443 小时前
C#实现OMRON FINS-TCP协议与PLC通信
网络·tcp/ip·c#
刘联其3 小时前
Prism Region注册父子区域 子区域初始化导航没生效解决
java·开发语言
CoderCodingNo3 小时前
【GESP】C++六级考试大纲知识点梳理, (5) 动态规划与背包问题
开发语言·c++·动态规划
移幻漂流3 小时前
Lua脚本的游戏开发优势与应用开发局限:技术对比与行业实践深度解析
开发语言·junit·lua
情缘晓梦.3 小时前
C++ 类和对象(完)
开发语言·jvm·c++
移幻漂流3 小时前
Lua脚本编译全解:从源码到字节码的深度剖析
开发语言·junit·lua