前言
学习C#之初,主要感兴趣的还是WinForm 软件的开发,后来随着工作的需要一直在进行Web开发。曾经在学校写过的代码,多年之后看看仍然感觉很有意思
代码地址:https://gitee.com/john273766764/tetris
一、先看看效果
二、核心代码
1.代码结构
2.资源文件
3.定义面板控件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace 方块2
{
class GamePanel:Panel
{
public GamePanel()
{
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true);
}
}
}
4.方块类定义
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using 方块2.Properties;
namespace 方块2
{
public class Block
{
#region 申明变量和属性
private static Image[] imgBlocks = new Image[]
{
Resources .block0 ,
Resources .block1 ,
Resources .block2 ,
Resources .block3 ,
Resources .block4 ,
Resources .block5 ,
Resources .block6 ,
Resources .block7 ,
Resources .block8
};
public static int speed;
public int colorNum = 0;
public int xPos { get; set; }
public int yPos { get; set; }
public bool[,] blockCode = new bool[4, 4];
public static bool Islive = true;//判断是否结束
public static bool IsSuspend = true;//判断是否暂停
Random rad = new Random();
private bool[,] P_blockCode;
private int P_colorNum;
#endregion
/// <summary>
/// 构造函数,初始化
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
public Block()
{
this.xPos = 4;
this.yPos = -2;
this.blockCode = Blocks.getcode();
colorNum = rad.Next(0, 8);
P_blockCode = Blocks.getcode();
P_colorNum = rad.Next(0, 8);
}
#region 方法
public void Preview()//预先找出下一个图形
{
P_blockCode = Blocks.getcode();
P_colorNum = rad.Next(0, imgBlocks .Length );
}
public void CreateNew()//创建一个新的block;
{
if (Islive == true)
{
IsSuspend = false;
blockCode = P_blockCode;
colorNum = P_colorNum;
Preview();
this.xPos = 4;
this.yPos = -2;
}
else
{
GameOver();
}
}
public void MoveLeft()
{
if (TestFill(-1, 0, blockCode) == false)// BlockGroup 中没有方块
{
this.xPos--;
}
else
{
return;
}
}
public void MoveRight()
{
if (TestFill(1, 0, blockCode) == false)
{
this.xPos++;
}
else
{
return;
}
}
public void TurnRight()
{
bool[,] temp = new bool[4, 4];
for (int line = 0; line < 4; line++)
{
for (int colum = 0; colum < 4; colum++)
{
temp[line, colum] = blockCode[3 - colum, line];
}
}
if (TestFill(0, 0, temp) == false)
{
blockCode = temp;
}
}
public void TurnLeft()
{
bool[,] temp = new bool[4, 4];
for (int line = 0; line < 4; line++)
{
for (int colum = 0; colum < 4; colum++)
{
temp[line, colum] = blockCode[colum, 3 - line];
}
}
if (TestFill(0, 0, temp) == false)
{
blockCode = temp;
}
}
public void Down()
{
if (IsSuspend == true)
{
return;
}
if (TestFill(0, 1,blockCode ) == false )// BlockGroup 中没有方块
{
this.yPos++;
}
else
{
SendBlock();
BlockGroup.CheckBlock();
CreateNew();
}
}
public void Draw(Graphics g)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (blockCode[i, j] == true)
{
g.DrawImage(imgBlocks[colorNum], (xPos + j) * 35, (yPos + i) * 35);
}
}
}
}
public void KeyDown(KeyEventArgs e)
{
if (IsSuspend == true)
{
return;
}
if (e.KeyCode == Keys.S)
{
Down();
}
if (e.KeyCode == Keys.A)
{
MoveLeft();
}
if (e.KeyCode == Keys.D)
{
MoveRight();
}
if (e.KeyCode == Keys.W)
{
TurnLeft();
}
if (e.KeyCode == Keys.R)
{
TurnRight();
}
}
public void DrawPreview(Graphics g)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (P_blockCode[i, j] == true)
{
g.DrawImage(imgBlocks[P_colorNum],j * 35+10,i* 35+30);
}
}
}
}
public bool TestFill(int right, int down,bool [,] Code)//x,y表示移动方向
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (Code [i,j]==true)
{
if (BlockGroup.IsFill(yPos + i + down, xPos + j + right) == true)
{
return true;
}
}
}
}
return false;
}
public void SendBlock()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (blockCode[i, j] == true)
{
BlockGroup.AddBlock(yPos + i, xPos + j, colorNum);
}
}
}
}
public void GameOver()
{
IsSuspend = true;
if (MessageBox.Show("您的分数是:" + BlockGroup.credit*100 + "。\n想重新开始游戏,再次突破自己的分数吗?", "重新开始游戏", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
BlockGroup.NewGame();
Islive = true;
CreateNew();
}
else
{
Application.Exit();
}
}
#endregion
}
}
5.方块形状定义
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 方块2
{
/// <summary>
/// 存储block的形状信息
/// </summary>
public class Blocks
{
#region block的形状信息
public static bool[][,] blockCodes = new bool[][,]
{
new bool [4,4]
{
{false,false,false,false},
{false,true,true,false},
{false,true,true,false},
{false,false,false,false}
},
new bool [4,4]
{
{false,true,false,false},
{false,true,false,false},
{false,true,false,false},
{false,true,false,false}
},
new bool [4,4]
{
{false,false,false,false},
{false,true,false,false},
{false,true,true,false},
{false,true,false,false}
},
new bool [4,4]
{
{false,false,false,false},
{false,false,true,false},
{false,true,true,false},
{false,false,true,false}
},
new bool [4,4]
{
{false,false,false,false},
{false,true,false,false},
{false,true,false,false},
{false,true,true,false}
},
new bool [4,4]
{
{false,false,false,false},
{false,true,false,false},
{false,true,true,false},
{false,false,true,false}
},
new bool [4,4]
{
{false,false,false,false},
{false,false,true,false},
{false,true,true,false},
{false,true,false,false}
},
new bool [4,4]
{
{false,false,false,false},
{false,true,true,false},
{false,true,false,false},
{false,true,false,false}
}
};
#endregion
public static bool[,] getcode()// 随机取得Block信息
{
Random rad = new Random();
return blockCodes[rad.Next(0, blockCodes.Length)];
}
}
}
6.方块面板展示逻辑
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using 方块2.Properties;
using System.Windows.Forms;
using System.Media;
namespace 方块2
{
public class BlockGroup //控制panel中的block的动作
{
public static SoundPlayer soundMoveDown = new SoundPlayer(Resources.GotCreit);
public static int credit = 0;
private static int lines = 18, columns = 11;
private static int[,] blocks = new int[lines, columns];
private static Image[] imgBlock = new Image[]
{
Resources .block0 ,
Resources .block1 ,
Resources .block2 ,
Resources .block3 ,
Resources .block4 ,
Resources .block5 ,
Resources .block6 ,
Resources .block7 ,
Resources .block8
};
public BlockGroup()
{
soundMoveDown.Load();
InitGroup();
}
private static void InitGroup()//初始化面板18x11
{
for (int line = 0; line < lines; line++)
{
for (int column = 0; column < columns; column++)
{
blocks[line, column] = 0;
}
}
}
public void Draw(Graphics g)
{
for (int line = 0; line < lines; line++)
{
for (int column = 0; column < columns; column++)
{
if (blocks[line, column] == 0)
{
continue;
}
else
{
g.DrawImage(imgBlock[blocks[line, column]-1], column * 35, line * 35);
}
}
}
}
public static bool IsFill(int lin,int col)
{
if (lin <0)
{
return false;
}
if (col <0)
{
return true;
}
if (lin > 17)
{
return true;
}
if (col > 10)
{
return true;
}
if (blocks[lin, col] > 0)
{
return true;
}
else
{
return false;
}
}
public static void AddBlock(int x,int y,int colorNum)
{
if (x > 0)
{
blocks[x, y] = colorNum + 1;
}
else
{
Block.Islive = false;
}
return;
}
public static void CheckBlock()//检查一行是否已满
{
for (int line = 1; line < lines; line++)
{
for (int colum = 0; colum < columns; colum++)
{
if (blocks[line, colum] < 1)
{
break;
}
if (colum == columns - 1)
{
MoveDown(line);
}
}
}
}
public static void NewGame()
{
InitGroup();
credit = 0;
}
public static void MoveDown(int lineNum)//向下移动
{
soundMoveDown.Play();
for (int line = lineNum; line > 0; line--)
{
for (int colum = 0; colum < columns; colum++)
{
blocks[line, colum] = blocks[line - 1, colum];
}
}
credit += 1;
}
}
}
7.主窗口代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using 方块2.Properties;
using System.Media;
namespace 方块2
{
public partial class MainForm : Form
{
//拖动窗口
Point offset = new Point();
bool isMove = false;
BlockGroup BG = new BlockGroup();
Block Bl = new Block();
SoundPlayer sound = new SoundPlayer(Resources.PressKey);
public MainForm()
{
InitializeComponent();
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true);
this.BackgroundImage = Resources.backgrand;
this.timer1.Interval = 1000 - BlockGroup.credit * 100;
this.timer1.Enabled = true;
sound.Load();
}
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
Bl.KeyDown(e);
this.gamePanel.Invalidate();
}
private void MainForm_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.offset = new Point(MousePosition.X - this.Location.X, MousePosition.Y - this.Location.Y);
isMove = true;
}
}
private void MainForm_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && isMove == true)
{
this.Location = new Point(MousePosition.X - offset.X, MousePosition.Y - offset.Y);
}
}
private void MainForm_MouseUp(object sender, MouseEventArgs e)
{
isMove = false;
}
private void gamePanel_Paint(object sender, PaintEventArgs e)
{
BG.Draw(e.Graphics);
Bl.Draw(e.Graphics);
}
private void timer1_Tick(object sender, EventArgs e)
{
Block.speed = (BlockGroup.credit/10)*10+10;
if (this.timer1.Interval > 300)
{
this.timer1.Interval = 1000 - (Block.speed-10) * 10;
}
Bl.Down();
this.gamePanel.Invalidate();
this.Preview_panel.Invalidate();
this.labCredit.Text = "分数:" + BlockGroup.credit*100;
this.labSpeed.Text = "速度:" + Block.speed;
}
private void Preview_panel_Paint(object sender, PaintEventArgs e)
{
Bl.DrawPreview(e.Graphics);
}
private void btnSuspend_Click(object sender, EventArgs e)
{
Block.IsSuspend = true;
}
private void btnStart_Click(object sender, EventArgs e)
{
Block.IsSuspend = false;
}
private void 开始ToolStripMenuItem_Click(object sender, EventArgs e)
{
Block.IsSuspend = false;
}
private void 暂停ToolStripMenuItem_Click(object sender, EventArgs e)
{
Block.IsSuspend = true;
}
private void 帮助ToolStripMenuItem_Click(object sender, EventArgs e)
{
Block.IsSuspend = true;
MessageBox.Show("按键信息:\n\n下:S\n左:A\n右:D\n左转:W\n右转:R", "按键信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
Block.IsSuspend = false;
}
private void MainForm_KeyUp(object sender, KeyEventArgs e)
{
sound.Play ();
}
}
}
总结
有机会多写写自己想写的代码