Thursday, January 21, 2010

UpLoader.cs

using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Collections;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

/*Programmer:Engine
*PowerBy:EngineSystem
*Oicq:282602809
*Msn:Cangta2002@hotmail.com
*E-Mail:Hee_jun1985@163.com
*Authorization:Free
*/
namespace PowerTalkBox
{
///
/// 流处理中心
///

public class UpLoader
{
///
/// 输入服务器文件夹路径地址,返回一个流:WebForm
///

/// 服务器文件路径
///
public System.IO.Stream ReadFileStream(string FileName)
{
string path = HttpContext.Current.Server.MapPath(FileName);
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
}
///
/// 输入一个流,输出到http:WebForm
///

/// 图片流
public void OutResponse(System.IO.Stream ImageString)
{
System.IO.Stream ms = ImageString;
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.ExpiresAbsolute = System.DateTime.Now.AddMilliseconds(0);
HttpContext.Current.Response.Expires = 0;
HttpContext.Current.Response.CacheControl = "no-cache";
HttpContext.Current.Response.AppendHeader("Pragma", "No-Cache");
HttpContext.Current.Response.ClearContent();
// HttpContext.Current.Response.ContentType = "image/Png";
int buffersize = (int)ms.Length;
byte[] buffer = new byte[buffersize];
int count = ms.Read(buffer, 0, buffersize);
// HttpContext.Current.Response.BinaryWrite(buffer);
HttpContext.Current.Response.OutputStream.Write(buffer, 0, count);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.Close();
}
///
/// 输出一个流,输出到http:WebForm
///

/// 文件路径
public void OutResponse(string FilePath)
{
FilePath = HttpContext.Current.Server.MapPath(FilePath);
string Filname = FilePath.Substring(FilePath.LastIndexOf('/') + 1);
FileInfo fi = new FileInfo(FilePath);
FileStream MyFileStream = fi.OpenRead();
long FileSize;
FileSize = MyFileStream.Length;
byte[] Buffer = new byte[(int)FileSize];
MyFileStream.Read(Buffer, 0, (int)FileSize);
MyFileStream.Close();
HttpContext.Current.Response.ContentType = "application/octet-stream";
HttpContext.Current.Response.AddFileDependency(Filname);
HttpContext.Current.Response.BinaryWrite(Buffer);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.Close();
}
///
/// 把流存成文件到指定位置:WebForm
///

/// 文件流
/// 服务器文件路径
public void SaveStreamToFile(Stream FlStream, string FilePath)
{
//读
string path = HttpContext.Current.Server.MapPath(FilePath);
int buffersize = (int)FlStream.Length;
byte[] buffer = new byte[buffersize];
int count = FlStream.Read(buffer, 0, buffersize);
//写
FileInfo fi = new FileInfo(path);
FileStream fsw = fi.Create();
fsw.Write(buffer, 0, buffersize);
fsw.Close();

}
///
/// 读流进入字节:Common
///

///路径
public byte[] ReadStream(string FilePath)
{
Stream fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
int buffersize = (int)fs.Length;
byte[] buffer = new byte[buffersize];
int count = fs.Read(buffer, 0, buffersize);
fs.Close();
return buffer;
}
}
}

UIControl.cs

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using YYTetris.Piece;
using System.Windows.Threading;
using System.Collections.Generic;
using System.ComponentModel;

namespace YYTetris
{
public class UIControl : INotifyPropertyChanged
{
///
/// 俄罗斯方块容器
///

public Block[,] Container { get; set; }

///
/// 下一个形状的容器(4×4)
///

public Block[,] NextContainer { get; set; }

///
/// 游戏状态(Ready, Play, Pause, Over)
///

public GameStatus GameStatus { get; set; }

private int _rows = 20; // 行数(Y 方向)
private int _columns = 10; // 列数(X 方向)
private int _positionX = 3; // 形状所属的 4×4 容器的 X 坐标
private int _positionY = 0; // 形状所属的 4×4 容器的 Y 坐标

private List _pieces; // 形状集合

private PieceBase _currentPiece; // 当前形状
private PieceBase _nextPiece; // 下一个形状

private int _initSpeed = 400; // 初始速率(毫秒)
private int _levelSpeed = 50; // 每增加一个级别所需增加的速率(毫秒)

private DispatcherTimer _timer;

///
/// 构造函数
///

public UIControl()
{
// 初始化形状集合,共七种形状
_pieces = new List() { new I(), new L(), new L2(), new N(), new N2(), new O(), new T() };

// 初始化方块容器(用 Block 对象填满整个容器)
Container = new Block[_rows, _columns];
for (int i = 0; i < _rows; i++)
{
for (int j = 0; j < _columns; j++)
{
var block = new Block();
block.Top = i * block.rectangle.ActualHeight;
block.Left = j * block.rectangle.ActualWidth;
block.Color = null;

Container[i, j] = block;
}
}

// 初始化下一个形状的容器(用 Block 对象将其填满)
NextContainer = new Block[4, 4];
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
var block = new Block();
block.Top = i * block.rectangle.ActualHeight;
block.Left = j * block.rectangle.ActualWidth;
block.Color = null;

NextContainer[i, j] = block;
}
}

// 创建一个新的形状
CreatePiece();
// 呈现当前创建出的形状
AddPiece(0, 0);

// Timer 用于定时向下移动形状
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(_initSpeed);
_timer.Tick += new EventHandler(_timer_Tick);

GameStatus = GameStatus.Ready;
}

///
/// 开始游戏(启动计时器)
///

public void Play()
{
GameStatus = GameStatus.Play;
_timer.Start();
}

///
/// 暂停游戏(停止计时器)
///

public void Pause()
{
GameStatus = GameStatus.Pause;
_timer.Stop();
}

///
/// 创建一个新的形状
///

private void CreatePiece()
{
// 逻辑移到 下坠后 的逻辑内
for (int x = 0; x < _columns; x++)
{
if (Container[0, x].Color != null)
{
OnGameOver(null);
break;
}
}

// 计算 当前形状 和 下一个形状
Random random = new Random();
_currentPiece = _nextPiece == null ? _pieces[random.Next(0, 7)] : _nextPiece;
_nextPiece = _pieces[random.Next(0, 7)];

// 形状所属的 4×4 容器的 X 坐标和 Y 坐标
_positionX = 3;
_positionY = 0;

// 设置“下一个形状的容器”的 UI
SetNextContainerUI();
}

private void _timer_Tick(object sender, EventArgs e)
{
MoveToDown();
}

///
/// 向左移动
///

public void MoveToLeft()
{
if (GameStatus != GameStatus.Play) return;

if (!IsBoundary(_currentPiece.Matrix, -1, 0))
{
RemovePiece();
AddPiece(-1, 0);
}
}

///
/// 向右移动
///

public void MoveToRight()
{
if (GameStatus != GameStatus.Play) return;

if (!IsBoundary(_currentPiece.Matrix, 1, 0))
{
RemovePiece();
AddPiece(1, 0);
}
}

///
/// 向下移动
///

public void MoveToDown()
{
if (GameStatus != GameStatus.Play) return;

if (!IsBoundary(_currentPiece.Matrix, 0, 1))
{
RemovePiece();
AddPiece(0, 1);
}
else
{
// 如果触及底边了,则消除可消的行并且创建新的形状
RemoveRow();
CreatePiece();

// 每落下一个形状加 1 分
Score++;
}
}

///
/// 变形
///

public void Rotate()
{
if (GameStatus != GameStatus.Play) return;

if (!IsBoundary(_currentPiece.GetRotate(), 0, 0))
{
RemovePiece();
_currentPiece.Rotate();
AddPiece(0, 0);
}
}

///
/// 清除俄罗斯方块容器
///

public void Clear()
{
for (int x = 0; x < _columns; x++)
{
for (int y = 0; y < _rows; y++)
{
Container[y, x].Color = null;
}
}
}

///
/// 边界判断(是否超过边界)
///

/// 当前操作的形状的4×4矩阵
/// 矩阵 X 方向的偏移量
/// 矩阵 Y 方向的偏移量
///
private bool IsBoundary(int[,] matrix, int offsetX, int offsetY)
{
RemovePiece();

for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (matrix[i, j] == 1)
{
if (j + _positionX + offsetX > _columns - 1 // 超过列的右边界
i + _positionY + offsetY > _rows - 1 // 超过行的下边界
j + _positionX + offsetX < 0 // 超过列的左边界
Container[i + _positionY + offsetY, j + _positionX + offsetX].Color != null) // matrix 所需偏移的地方已经有 Block 占着了
{
AddPiece(0, 0);
return true;
}
}
}
}

AddPiece(0, 0);
return false;
}

///
/// 设置“下一个形状的容器”的 UI
///

private void SetNextContainerUI()
{
// 清空
foreach (Block block in NextContainer)
{
block.Color = null;
}

// 根据 _nextPiece 的矩阵设置相对应的 Block 对象的呈现
for (int x = 0; x < 4; x++)
{
for (int y = 0; y < 4; y++)
{
if (_nextPiece.Matrix[x, y] == 1)
{
NextContainer[x, y].Color = _nextPiece.Color;
}
}
}
}

///
/// 移除 _currentPiece 在界面上的呈现
///

private void RemovePiece()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (_currentPiece.Matrix[i, j] == 1)
{
Container[i + _positionY, j + _positionX].Color = null;
}
}
}
}

///
/// 增加 _currentPiece 在界面上的呈现
///

/// X 方向上的偏移量
/// Y 方向上的偏移量
private void AddPiece(int offsetX, int offsetY)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (_currentPiece.Matrix[i, j] == 1)
{
Container[i + _positionY + offsetY, j + _positionX + offsetX].Color = _currentPiece.Color;
}
}
}

_positionX += offsetX;
_positionY += offsetY;
}

///
/// 根据游戏规则,如果某行出现连续的直线则将其删除,该线以上的部分依次向下移动
///

private void RemoveRow()
{
// 删除的行数
int removeRowCount = 0;

// 行的遍历(Y 方向)
for (int y = 0; y < _rows; y++)
{
// 该行是否是一条连续的直线
bool isLine = true;

// 列的遍历(X 方向)
for (int x = 0; x < _columns; x++)
{
if (Container[y, x].Color == null)
{
// 出现断行,则继续遍历下一行
isLine = false;
break;
}
}

// 该行是一条连续的直线则将其删除,并将该行以上的部分依次向下移动
if (isLine)
{
removeRowCount++;

// 删除该行
for (int x = 0; x < _columns; x++)
{
Container[y, x].Color = null;
}

// 将被删除行的以上行依次向下移动
for (int i = y; i > 0; i--)
{
for (int x = 0; x < _columns; x++)
{
Container[i, x].Color = Container[i - 1, x].Color;
}
}
}
}

// 加分,计算方法: 2 的 removeRowCount 次幂 乘以 10
if (removeRowCount > 0)
Score += 10 * (int)Math.Pow(2, removeRowCount);

// 更新总的已消行数
RemoveRowCount += removeRowCount;

// 根据已消行数计算级别,依据丁学的建议,计算方法: 已消行数/5 的平方根 取整
Level = (int)Math.Sqrt(RemoveRowCount / 5);

// 根据级别计算速率,计算方法: 初始速率 减 (每多一个级别所需增加的速率 乘以 当前级别)
_timer.Interval = TimeSpan.FromMilliseconds(_initSpeed - _levelSpeed * Level > _levelSpeed ? _initSpeed - _levelSpeed * Level : _levelSpeed);
}

private int _score = 0;
///
/// 得分
///

public int Score
{
get { return _score; }
set
{
_score = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Score"));
}
}
}

private int _removeRowCount = 0;
///
/// 总共被消除的行数
///

public int RemoveRowCount
{
get { return _removeRowCount; }
set
{
_removeRowCount = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("RemoveRowCount"));
}
}
}

private int _level = 0;
///
/// 级别(游戏难度)
///

public int Level
{
get { return _level; }
set
{
_level = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Level"));
}
}
}

public event PropertyChangedEventHandler PropertyChanged;

///
/// 游戏结束的事件委托
///

public event EventHandler GameOver;

///
/// 游戏结束后所调用的方法,并触发游戏结束事件
///

///
private void OnGameOver(EventArgs e)
{
GameStatus = GameStatus.Over;
_timer.Interval = TimeSpan.FromMilliseconds(_initSpeed);
_timer.Stop();

EventHandler handler = GameOver;
if (handler != null)
handler(this, e);
}
}
}

Page.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using YYTetris.Piece;
using System.Windows.Threading;

namespace YYTetris
{
public partial class Page : UserControl
{
UIControl _control;

public Page()
{
InitializeComponent();

this.Loaded += new RoutedEventHandler(Page_Loaded);
}

void Page_Loaded(object sender, RoutedEventArgs e)
{
uc.Focus();

_control = new UIControl();
_control.GameOver += new EventHandler(_control_GameOver);
uc.DataContext = _control;

foreach (Block block in _control.Container)
{
canvasBox.Children.Add(block);
}

foreach (Block block in _control.NextContainer)
{
canvasBoxPrev.Children.Add(block);
}
}

void _control_GameOver(object sender, EventArgs e)
{
gameOver.Visibility = Visibility.Visible;
play.Content = "开始游戏";
}

private void uc_KeyDown(object sender, KeyEventArgs e)
{
if (_control.GameStatus != GameStatus.Play) return;

if (e.Key == Key.Left)
{
_control.MoveToLeft();
}
else if (e.Key == Key.Right)
{
_control.MoveToRight();
}
else if (e.Key == Key.Up)
{
_control.Rotate();
}
else if (e.Key == Key.Down)
{
_control.MoveToDown();
}
}

private void start_Click(object sender, RoutedEventArgs e)
{
if (play.Content.ToString() == "开始游戏")
{
if (_control.GameStatus == GameStatus.Over)
{
_control.Clear();
gameOver.Visibility = Visibility.Collapsed;
_control.Score = 0;
_control.Level = 0;
_control.RemoveRowCount = 0;
}

_control.Play();
play.Content = "暂停游戏";
}
else
{
_control.Pause();
play.Content = "开始游戏";
}
}
}
}

Helper.cs

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace YYTetris
{
public class Helper
{
public static Color GetColor(string color)
{
try
{
if (string.IsNullOrEmpty(color))
return Colors.Black;

if (color.Length == 7)
{
byte r = (byte)(Convert.ToUInt32(color.Substring(1, 2), 16));
byte g = (byte)(Convert.ToUInt32(color.Substring(3, 2), 16));
byte b = (byte)(Convert.ToUInt32(color.Substring(5, 2), 16));

return Color.FromArgb(255, r, g, b);
}
else
{
return Colors.Black;
}
}
catch
{
return Colors.Black;
}
}
}
}

GameStauts.cs

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace YYTetris
{
public enum GameStatus
{
Ready,
Play,
Pause,
Over
}
}