先来看一下界面:
游戏帮助类
class GameCore
{
//游戏地图
private int[,] map = new int[4, 4];
//合并时用到的临时数组
private int[] mergeArr = new int[4];
//空位数量
private int emptyCount = 16;
//所有空位位置
private Location[] emptyArr = new Location[16];
private Random random = new Random();
//画板
private Graphics gp = null;
//用位图做画板
private Image image = null;
// 游戏项大小
private const int ITEMSIZE = 80;
//游戏得分
private int score = 0; public bool IsChange { get; set; } /// <summary>
/// 当前得分
/// </summary>
public int Score
{
get { return score; }
} /// <summary>
/// 空位数量
/// </summary>
public int EmptyCount
{
get
{
return emptyCount;
}
} /// <summary>
/// 游戏初始化
/// </summary>
public GameCore()
{
ComputeEmptyCount();
// 初始化数组
Location loc1;
GenerateNum(out loc1); ComputeEmptyCount();
GenerateNum(out loc1);
//初始化画板
image = new Bitmap(ITEMSIZE * 4 + 5 * 8,
ITEMSIZE * 4 + 5 * 8);
gp = Graphics.FromImage(image); } #region 移动并合并相邻的相同数字 /// <summary>
/// 移动单元格数据
/// </summary>
/// <param name="direction"></param>
public void Move(string direction)
{
IsChange = false;
switch (direction)
{
case "Up": MoveUp(); break;
case "Down": MoveDown(); break;
case "Left": MoveLeft(); break;
case "Right": MoveRight(); break;
}
}
/// <summary>
/// 上移
/// </summary>
public void MoveUp()
{
//1
for (int c = 0; c < 4; c++)//列
{
for (int r = 0, index = 0; r < 4; r++)//行
{
if (map[r, c] != 0)//非零
{
mergeArr[index++] = map[r, c];//放入合并数组
}
//数字位置发生变化
if (mergeArr[r] != map[r, c])
{
IsChange = true;
}
map[r, c] = 0;//将矩阵中取走的清零 }
//2合并
MergeCell();
//3 将合并后的数据放入矩阵
for (int i = 0, r = 0; i < 4; i++)
{
if (mergeArr[i] != 0)
{
map[r++, c] = mergeArr[i];
mergeArr[i] = 0;
}
}
}
} /// <summary>
/// 下移
/// </summary>
public void MoveDown()
{
//1
for (int c = 0; c < 4; c++)//列
{
for (int r = 3, index = 0; r >= 0; r--)//行
{
if (map[r, c] != 0)//非零
{
mergeArr[index++] = map[r, c];//放入合并数组
}
if (mergeArr[3-r] != map[r, c])
{
IsChange = true;
}
map[r, c] = 0;//将矩阵中取走的清零
}
//2合并
MergeCell();
//3 将合并后的数据放入矩阵
for (int i = 0, r = 3; i < 4; i++)
{
if (mergeArr[i] != 0)
{
map[r--, c] = mergeArr[i];
mergeArr[i] = 0;
}
}
} } /// <summary>
/// 合并单元格
/// </summary>
private void MergeCell()
{
for (int i = 0; i < 3; i++)
{
if (mergeArr[i] != 0 && mergeArr[i] == mergeArr[i + 1] )
{
mergeArr[i] += mergeArr[i + 1];
score += mergeArr[i];
IsChange = true;
mergeArr[i + 1] = 0;
}
}
} /// <summary>
/// 左移
/// </summary>
public void MoveLeft()
{
//1
for (int r = 0; r < 4; r++)//行
{
for (int c = 0, index = 0; c < 4; c++)//列
{
if (map[r, c] != 0)//非零
{
mergeArr[index++] = map[r, c];//放入合并数组
}
if (mergeArr[c] != map[r, c])
{
IsChange = true;
}
map[r, c] = 0;//将矩阵中取走的清零
}
//2合并
MergeCell();
//3 将合并后的数据放入矩阵
for (int i = 0, c = 0; i < 4; i++)
{
if (mergeArr[i] != 0)
{
map[r, c++] = mergeArr[i];
mergeArr[i] = 0;
}
}
}
} /// <summary>
/// 右移
/// </summary>
public void MoveRight()
{
//1
for (int r = 0; r < 4; r++)//行
{
for (int c = 3, index = 0; c >= 0; c--)//列
{
if (map[r, c] != 0)//非零
mergeArr[index++] = map[r, c];//放入合并数组 if (mergeArr[3-c] != map[r, c])
IsChange = true; map[r, c] = 0;//将矩阵中取走的清零
}
//2合并
MergeCell();
//3 将合并后的数据放入矩阵
for (int i = 0, c = 3; i < 4; i++)
{
if (mergeArr[i] != 0)
{
map[r, c--] = mergeArr[i];
mergeArr[i] = 0;
}
}
}
} #endregion /// <summary>
/// 计算空位数量
/// </summary>
public void ComputeEmptyCount()
{
emptyCount = 0;
Array.Clear(emptyArr, 0, 16); for (int r = 0; r < 4; r++)//行
{
for (int c = 0; c < 4; c++)//列
{
if (map[r, c] == 0)
{
emptyArr[emptyCount++] = new Location(r, c);
}
}
}
} /// <summary>
/// 生成新数字
/// </summary>
public int GenerateNum(out Location location)
{
int index = random.Next(0, emptyCount);
location = emptyArr[index];
map[location.X, location.Y] = random.Next() % 10 == 0 ? 4 : 2;
return map[location.X, location.Y];
} /// <summary>
/// 判断游戏是否结束
/// </summary>
/// <returns></returns>
public bool IsGameOver()
{
ComputeEmptyCount();
//如果还有空位,游戏未结束
if (EmptyCount > 0)
return false;
//检查横纵相邻单元格中是否有相同的数字,
for (int r = 0; r < 4; r++)
{
for (int c = 0; c < 3; c++)
{
//横
if (map[r, c] == map[r, c + 1])
return false; //纵
if (map[c, r] == map[c + 1, r])
return false;
}
}
return true; } #region 绘制游戏画面
/// <summary>
/// 绘制游戏画面
/// </summary>
/// <returns></returns>
public Image DrawMap()
{
//清空画板原有内容
gp.Clear(Color.DarkGray);
for (int r = 0; r < map.GetLength(0); r++)
{
for (int c = 0; c < map.GetLength(1); c++)
{
DrawItem(r, c, GetColor(map[r, c]));
}
}
return image;
} /// <summary>
/// 通过数字从程序集资源中找图片
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public Image GetColor(int num)
{
return Properties.Resources.
ResourceManager.
GetObject("_" + num.ToString()) as Image;
} /// <summary>
/// 绘制一个数字块
/// </summary>
/// <param name="rowindex">行索引</param>
/// <param name="columnIndex">列索引</param>
/// <param name="img">要绘制的图片</param>
private void DrawItem(int rowindex, int columnIndex, Image img)
{
//画在哪 rowindex columnindex
int x = (columnIndex + 1) * 8 + columnIndex * ITEMSIZE; int y = (rowindex + 1) * 8 + rowindex * ITEMSIZE; //绘制内容img 画多大 itemSize
gp.DrawImage(img, x, y, ITEMSIZE, ITEMSIZE);
} #endregion }
定义一个结构:
struct Location
{
private int x;
private int y; public Location(int x, int y)
{
this.x = x;
this.y = y;
} public int X
{
get { return x; }
}
public int Y
{
get { return y; }
}
}
窗体代码:
public partial class FrmMain : Form
{
private GameCore gameCore = null; public FrmMain()
{
InitializeComponent();
} public void DrawGameMap()
{
this.picMap.Image = gameCore.DrawMap();
} //开始游戏
private void FrmMain_Load(object sender, EventArgs e)
{
StartGame();
} private void StartGame()
{
//得分清零
lblScore.Text = "0";
gameCore = new GameCore();
DrawGameMap();
} private void btnStart_Click(object sender, EventArgs e)
{
StartGame();
} //用键盘控制游戏动作
private void FrmMain_KeyDown(object sender, KeyEventArgs e)
{
string keyString = e.KeyData.ToString();
switch (keyString)
{
case "Up":
case "Down":
case "Left":
case "Right":
gameCore.Move(keyString);
//更新游戏地图
UpdateGameMap();
break;
}
} public void UpdateGameMap()
{
//游戏流程?
//地图发生过变化
if (gameCore.IsChange)
{
//绘制游戏地图
DrawGameMap();
//刷新得分
this.lblScore.Text = gameCore.Score.ToString();
//重新计算空位
gameCore.ComputeEmptyCount();
//如果空位数大于0
if (gameCore.EmptyCount > 0)
{
//产生新数
Location loc;
int num = gameCore.GenerateNum(out loc);
//开启绘制新数的动画 异步调用
Action<int,int,int> handler = DrawNewNumber;
handler.BeginInvoke(loc.X, loc.Y, num,
null, null); } //判断游戏是否继续
if (gameCore.IsGameOver())
{
MessageBox.Show("GAME OVER");
}
} } public void DrawNewNumber(int r,int c,int num)
{
int xOfMap = (c + 1) * 8 + c * 80;
int yOfMap = (r + 1) * 8 + r * 80;
Graphics gp = this.picMap.CreateGraphics(); Image img = gameCore.GetColor(num);
//数字出现由小及大,最小宽为10 最大为80
int w = 10; while (w <= 80)
{
int x =xOfMap+ 80 / 2 - w / 2;
int y =yOfMap+ 80 / 2 - w / 2;
gp.DrawImage(img, x, y, w, w);
w += 5;
System.Threading.Thread.Sleep(10);
}
}
}
OK ,完成了。