【Winform开发2048小游戏】
先来看一下界面:
游戏帮助类
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 ,完成了。
【Winform开发2048小游戏】的更多相关文章
- C# 开发2048小游戏
这应该是几个月前,闲的手痒,敲了一上午代码搞出来的,随之就把它丢弃了,当时让别人玩过,提过几条更改建议,但是时至今日,我也没有进行过优化和更改(本人只会作案,不会收场,嘎嘎),下面的建议要给代码爱好的 ...
- jQuery实践-网页版2048小游戏
▓▓▓▓▓▓ 大致介绍 看了一个实现网页版2048小游戏的视频,觉得能做出自己以前喜欢玩的小游戏很有意思便自己动手试了试,真正的验证了这句话-不要以为你以为的就是你以为的,看视频时觉得看懂了,会写了, ...
- Swift实战之2048小游戏
上周在图书馆借了一本Swift语言实战入门,入个门玩一玩^_^正好这本书的后面有一个2048小游戏的实例,笔者跟着实战了一把. 差不多一周的时间,到今天,游戏的基本功能已基本实现,细节我已不打算继续完 ...
- 如何在CentOS上安装一个2048小游戏
如何在centos上安装一个2048小游戏 最近在学习CentOS系统,就琢磨着玩点什么,然后我看到有人在玩2048小游戏,所有我就在想,为啥不装一个2048小游戏搞一下嘞,于是乎,我就开始工作啦 由 ...
- js、jQuery实现2048小游戏
2048小游戏 一.游戏简介: 2048是一款休闲益智类的数字叠加小游戏 二. 游戏玩法: 在4*4的16宫格中,您可以选择上.下.左.右四个方向进行操作,数字会按方向移动,相邻的两个数字相同就会合 ...
- 用js实现2048小游戏
用js实现2048小游戏 笔记仓库:https://github.com/nnngu/LearningNotes 1.游戏简介 2048是一款休闲益智类的数字叠加小游戏.(文末给出源代码和演示地址) ...
- 2048小游戏代码解析 C语言版
2048小游戏,也算是风靡一时的益智游戏.其背后实现的逻辑比较简单,代码量不算多,而且趣味性强,适合作为有语言基础的童鞋来加强编程训练.本篇分析2048小游戏的C语言实现代码. 前言 游戏截图: 游 ...
- 【转】利用 three.js 开发微信小游戏的尝试
前言 这是一次利用 three.js 开发微信小游戏的尝试,并不能算作是教程,只能算是一篇笔记吧. 微信 WeChat 6.6.1 开始引入了微信小游戏,初期上线了一批质量相当不错的小游戏.我在查阅各 ...
- 使用Laya引擎开发微信小游戏(上)
本文由云+社区发表 使用一个简单的游戏开发示例,由浅入深,介绍了如何用Laya引擎开发微信小游戏. 作者:马晓东,腾讯前端高级工程师. 微信小游戏的推出也快一年时间了,在IEG的游戏运营活动中,也出现 ...
随机推荐
- tempo 2.0 学习记录
最近在做项目时使用了tempo,感觉还不错,但是发现网上对于tempo 2.0 的介绍比较少,我也是在GitHub才找到了比较完整的使用说明,我也简单记录一下自己的使用过程,重新学习一下tempo 2 ...
- 解决Delphi自带UTF8解码缺陷(使用API)
因为Delphi自带的转换函数遇到其无法识别的字符串就返回空,下面函数可解决该问题. function DecodeUtf8Str(const S: UTF8String): WideString;v ...
- 转载文章:Windows Azure 基础结构服务上的 Microsoft Dynamics NAV 和 Microsoft Dynamics GP!
Windows Azure 基础结构服务(虚拟机和虚拟网络)可提供按需基础结构,该基础结构可进行伸缩以适应不断变化的业务需求.无论您是在虚拟机中创建新应用程序,还是运行现有应用程序,我们都将按分钟收费 ...
- LINQ 图解 LINQ学习第三篇 [转]
LINQ,语言集成查询(Language INtegrated Query)是一组用于c#和Visual Basic语言的扩展.它允许编写C#或者Visual Basic代码以查询数据库相同的方式操作 ...
- SDUT OJ 2783 小P寻宝记
#include<iostream> #include<memory.h> #define N 10020 using namespace std; int dp[N],pi[ ...
- 批处理就是windows的杰作啊
今天要为了解决vs不能同时开启调试和编写的问题,我就上网查找了一些批处理的命令,用批处理调用exe,和打开txt,虽然一行代码就解决了但是我没用过啊,很陌生. call 路径\a.exe 就相当于 ...
- eclipse中输入的中文为繁体的问题
今天在eclipse中编写注释的时候发现,输入的中文都为繁体,且只在eclipse编辑器中为繁体,切换到网页中则为正常. 最后发现,竟然是输入法的shift+ctrl+F快捷键和eclipse的冲突. ...
- ARM和x86的区别
CPU的指令集从主流的体系结构上分为精简指令集(RISC)和复杂指令集(CISC).嵌入式系统中的主流处理器——ARM处理器,所使用的就是精简指 令集.而桌面领域的处理器大部分使用的是复杂指令集,比如 ...
- EassyMock实践 捕获参数
在测试接口过程中,有时我们希望知道自己期望传入的参数是什么,以此来判断传入参数的正确行,这时就需要用到EassyMock的capture方法.该方法能捕获传入的参数存放到自定义的变量中,然后用捕获的参 ...
- leetcode Combination Sum python
Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C wher ...