「玩一玩」自制一个《倒水解密》游戏
© Conmajia 2012本文所有源代码和VisualStudio2010(.NET Fx 2.0)工程打包在本文最后下载。(别找我要源码,一概不理会)
《倒水解密》是一款很不错的手机益智类游戏,游戏界面如下:
规则是这样的:
有N个容量不同的瓶子,指定「将a升水倒入容量为b的瓶子」。游戏要求通过装水、倒水,达成给定的目标。
该游戏虽然简单,但可玩性高,也可有不同的难度变化,并且能锻炼玩家的心算能力。《倒水解密》不失为一个很好的繁忙工作之余的休闲方式。
说到这里,大家应该能猜到我想干什么了。没错,山寨之。
下面是山寨游戏的屏幕录像:
虽然界面有点简陋,但至少实现了。(屏幕录像软件不能录入鼠标光标,实际上鼠标光标是动态的)。
游戏操作方式如下:
•在瓶子上双击右键可以把瓶子灌满水
•双击左键可以把瓶子里的水倒掉
•将一个瓶子拖动到另一个瓶子上可以把水倒过去
下面是游戏的模型结构。
Bottle类,表示瓶子。保存了瓶子的关键属性如容量、储量,以及基本方法如倒入、倒出。该类实现了IVisible可视化接口。这个接口很简单,只是提供了一个Draw()方法,用于重绘瓶子自身并返回图像。使用这种方式,可以方便的修改瓶子的外观样式而不用修改其他部分代码。例如可以简单的用矩形画瓶子,也可以像上面的手机游戏截图一样用非常的漂亮的贴图来做。
public class Bottle : Element, IVisible
{
const int SIZE_FACTOR = 10;
#region Variables
int content = 0;
int capacity = 0;
Size size = Size.Empty;
Rectangle bounds = Rectangle.Empty;
Bitmap canvas;
Graphics painter;
bool dirty = true;
#endregion
#region Properties
public int FreeSpace
{
get { return capacity - content; }
}
public int Content
{
get { return content; }
}
public int Capacity
{
get { return capacity; }
}
public bool IsEmpty
{
get { return content == 0; }
}
public bool IsFull
{
get { return content == capacity; }
}
#endregion
#region Initiators
public Bottle(int capacity)
: this(capacity, 0)
{
}
public Bottle(int capacity, int content)
{
if (capacity > 0)
{
this.capacity = capacity;
if (content > -1 && content <= capacity)
this.content = content;
size.Width = 30;
size.Height = SIZE_FACTOR * capacity;
bounds.Size = size;
canvas = new Bitmap(size.Width, size.Height);
painter = Graphics.FromImage(canvas);
}
}
#endregion
#region Methods
public void DropIn()
{
DropIn(capacity);
}
public void DropIn(int amount)
{
if (amount > 0)
{
content += amount;
if (content > capacity)
content = capacity;
dirty = true;
}
}
public void DropOut()
{
DropOut(capacity);
}
public void DropOut(int amount)
{
if (amount > 0 && amount < content)
{
content -= amount;
}
else
{
content = 0;
}
dirty = true;
}
#endregion
#region IVisible
public Rectangle Bounds
{
get { return bounds; }
}
public int X
{
get { return bounds.X; }
set { bounds.X = value; }
}
public int Y
{
get { return bounds.Y; }
set { bounds.Y = value; }
}
public Bitmap Draw()
{
if (dirty)
{
painter.Clear(Color.Transparent);
// simple look bottle
int contentHeight = (int)((float)bounds.Height * ((float)content / (float)capacity));
if (contentHeight > 0)
{
using (Brush b = new LinearGradientBrush(
new Rectangle(
0,
bounds.Height - contentHeight - 1,
bounds.Width,
contentHeight
),
Color.LightBlue,
Color.DarkBlue,
90))
{
Rectangle contentRect = new Rectangle(
0,
bounds.Height - contentHeight,
bounds.Width,
contentHeight
);
painter.FillRectangle(b, contentRect);
}
}
painter.DrawRectangle(
Pens.Silver,
0,
0,
bounds.Width - 1,
bounds.Height - 1
);
string s = string.Format("{0}/{1}", content, capacity);
painter.DrawString(
s,
SystemFonts.DefaultFont,
Brushes.Black,
2,
1
);
painter.DrawString(
s,
SystemFonts.DefaultFont,
Brushes.Black,
1,
2
);
painter.DrawString(
s,
SystemFonts.DefaultFont,
Brushes.Black,
2,
3
);
painter.DrawString(
s,
SystemFonts.DefaultFont,
Brushes.Black,
3,
2
);
painter.DrawString(
s,
SystemFonts.DefaultFont,
Brushes.White,
2,
2
);
dirty = false;
}
return canvas;
}
#endregion
#region Elemenet
public override Type Type
{
get { return typeof(Bottle); }
}
#endregion
}
World类,表示瓶子所在世界。存储了所有的瓶子,用于和游戏交互。
public class World
{
const int PADDING = 20;
#region Variables
List<Bottle> bottles = new List<Bottle>();
Rectangle bounds = Rectangle.Empty;
#endregion
#region Properties
public List<Bottle> Bottles
{
get { return bottles; }
}
public Rectangle Bounds
{
get { return bounds; }
set
{
bounds = value;
arrangeBottles();
}
}
#endregion
#region Initiators
public World()
{
}
public World(Rectangle bounds)
{
this.bounds = bounds;
}
#endregion
#region world methods
public Bottle CreateBottle(int capacity)
{
return CreateBottle(capacity, 0);
}
public Bottle CreateBottle(int capacity, int content)
{
Bottle b = new Bottle(capacity, content);
bottles.Add(b);
arrangeBottles();
return b;
}
public void DestroyBottle()
{
bottles.Clear();
}
public void DestroyBottle(Bottle b)
{
bottles.Remove(b);
}
public void DestroyBottle(int capacity)
{
List<Bottle> tmp = new List<Bottle>();
foreach (Bottle b in bottles)
{
if (b.Capacity != capacity)
tmp.Add(b);
}
bottles.Clear();
bottles.AddRange(tmp);
}
#endregion
#region paint helpers
Size getTotalSize()
{
Size sz = Size.Empty;
foreach (Bottle b in bottles)
{
sz.Width += PADDING + b.Bounds.Width;
if (sz.Height < b.Bounds.Height)
sz.Height = b.Bounds.Height;
}
return sz;
}
void arrangeBottles()
{
Size sz = getTotalSize();
Point offset = new Point(
(bounds.Width - sz.Width) / 2,
(bounds.Height - sz.Height) / 2 + sz.Height
);
foreach (Bottle b in bottles)
{
b.X = offset.X;
b.Y = offset.Y - b.Bounds.Height;
offset.X += PADDING + b.Bounds.Width;
}
}
#endregion
}
Game类,游戏类。保存游戏世界,负责自动生成游戏和判定游戏胜利。
public class Game
{
string name = string.Empty;
int bottleCount = 0;
bool initiated = false;
int targetBottle = -1;
int targetAmount = -1;
World world;
Random rand = new Random();
public string Name
{
get { return name; }
}
public int Target
{
get { return targetBottle; }
}
public int Amount
{
get { return targetAmount; }
}
public World World
{
get { return world; }
}
public Game()
{
world = new World();
}
/// <summary>
/// Difficaulty of game.
/// </summary>
/// <param name="difficaulty">Difficaulty from 1 to 3.</param>
public void AutoGenerate(int difficaulty)
{
if (difficaulty < 1)
return;
world.DestroyBottle();
int bottleCount = rand.Next(3, 5); //3 + difficaulty);
targetBottle = rand.Next(0, bottleCount - 1);
int maxAmount = 10;
for (int i = 0; i < bottleCount; i++)
{
int cap = 0;
do
cap = rand.Next(3, maxAmount + difficaulty);
while (capacityInside(cap));
world.CreateBottle(cap);
}
targetAmount = rand.Next(1, world.Bottles[targetBottle].Capacity);
initiated = true;
}
bool capacityInside(int cap)
{
foreach (Bottle b in world.Bottles)
if (b.Capacity == cap)
return true;
return false;
}
public bool CheckSuccess()
{
if (targetBottle > -1)
if (initiated && world.Bottles.Count > targetBottle)
return world.Bottles[targetBottle].Content == targetAmount;
return false;
}
}
游戏的计时、计步、界面操作等统统放在主窗体,这里不做赘述。
简单的实现,还有倒计时、高分榜等功能可以扩展,界面也可以做的更漂亮些,欢迎大家扩展。
源码及工程文件(VS2010)打包 :点击下载
© Conmajia 2012
--------------------编程问答-------------------- --------------------编程问答-------------------- 睡觉
--------------------编程问答-------------------- 年纪轻轻,睡啥觉啊。。。 --------------------编程问答-------------------- 没有写啥注释,我相信只要能看懂英文就能看懂源码。。 --------------------编程问答-------------------- 顶!!!必须支持一下!!! --------------------编程问答-------------------- --------------------编程问答-------------------- LZ终于出作品了,还以为你收山了呢
--------------------编程问答--------------------
好东西 --------------------编程问答--------------------
+1
--------------------编程问答-------------------- 野比牛人 啊 --------------------编程问答-------------------- 顶一个 --------------------编程问答-------------------- 看不懂英文的肿么半!!! --------------------编程问答-------------------- --------------------编程问答-------------------- 支持啊,野比哥总能吸引眼球 --------------------编程问答-------------------- 期待下一个分享帖 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 这个的确有意思,这个要支持的! --------------------编程问答-------------------- 看起来很是吃力 呀 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 嗯,挺有意思的! --------------------编程问答-------------------- --------------------编程问答-------------------- 低级.. --------------------编程问答-------------------- 仰视。 --------------------编程问答-------------------- 嗯,不错不错 --------------------编程问答-------------------- 我什么时间能达到的高度 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 野比小王子一出手必是精品 --------------------编程问答-------------------- 进来求所有关卡数据和解决方法 我也想山寨一个(⊙o⊙) --------------------编程问答-------------------- 野比小王子的作品,必须支持! --------------------编程问答-------------------- 好东西!!! --------------------编程问答-------------------- 很好很强大,支持一下.不知道是不是可以直接在wp8上面玩. --------------------编程问答-------------------- 野比现在又来搞游戏了 --------------------编程问答-------------------- --------------------编程问答-------------------- 太阁立志 里面的 配药游戏? --------------------编程问答-------------------- 支持了。。 --------------------编程问答-------------------- 哇咔咔搞定。。 谢谢分享。。 哇咔咔!!! --------------------编程问答-------------------- 就是代码还没看懂。。哎。。 --------------------编程问答-------------------- 回复能拿分吗? --------------------编程问答-------------------- 赞一个~~~~~~~~~~。收藏,用到时慢慢研究 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 感谢楼主分享! --------------------编程问答-------------------- 前面说过,只需要修改Bottle.Draw()方法就可以改变瓶子的显示外观。于是我用画图鼠绘了一个丑陋的瓶子,就像这样:
--------------------编程问答-------------------- 不错,googd --------------------编程问答-------------------- --------------------编程问答-------------------- 用 js 在浏览器里实现可能更有意思。
瓶子可以用图片 --------------------编程问答-------------------- 这种情况的发生是因为算法问题么~!!!! --------------------编程问答-------------------- 发现好多基础都忘了。。 趁机学习学习。。哇咔咔!!! --------------------编程问答--------------------
2222222 --------------------编程问答--------------------
你想表达什么!!! --------------------编程问答-------------------- 学习 不过。 。。。。想表达什么 --------------------编程问答-------------------- --------------------编程问答--------------------
这个瓶子 更卡通一些,耐看 --------------------编程问答-------------------- 野比好强! --------------------编程问答-------------------- 有啥算法啊。。就随机分了几个数。。哈哈。。 --------------------编程问答-------------------- 牛人,支持楼主 --------------------编程问答-------------------- 楼主真是牛人。可惜我看不懂这种语言。。。
就会一点点C。。 --------------------编程问答-------------------- 支持,学习下。
--------------------编程问答-------------------- 又见野比,每次见到都会有个惊喜! --------------------编程问答--------------------
哈哈你赶紧改改,这可不好,过不了关了。 --------------------编程问答-------------------- --------------------编程问答-------------------- 学习了,谢谢共享。 --------------------编程问答-------------------- 好东西啊!!! --------------------编程问答-------------------- 好东西,有耐心 --------------------编程问答-------------------- 好东西 --------------------编程问答-------------------- --------------------编程问答-------------------- 这个有些意思。 --------------------编程问答-------------------- 看了许久才知道这个游戏怎么玩。。。。数学盲看这类东西都是要花更久的时间才看懂的。 --------------------编程问答-------------------- 你是大师,欢迎再加工。 --------------------编程问答-------------------- 牛人,顶一个 --------------------编程问答-------------------- 好东西顶一下! --------------------编程问答-------------------- lz有的实现不了把,比如十升瓶子放入三升水,两边是八升和四升,偶数之间再怎么加减也成不了奇数吧。这点应该改进一下,不能出现全偶数的瓶子把 --------------------编程问答-------------------- 3,6,12,分2升出来,怎么分? --------------------编程问答-------------------- 3,6,9分2升出来,怎么分? --------------------编程问答-------------------- 这只是个原型,欢迎自己改着玩。。 --------------------编程问答-------------------- 不错不错不错不错不错不错不错 --------------------编程问答-------------------- --------------------编程问答-------------------- 不错,古墓丽影4水袋称重迷题的增强版。 --------------------编程问答-------------------- 好东西啊 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答-------------------- 好。。。 挺支持这个东西。 --------------------编程问答-------------------- 好,支持这个.... --------------------编程问答-------------------- --------------------编程问答-------------------- 不错,顶一个! --------------------编程问答-------------------- 没看懂什么意思 --------------------编程问答-------------------- 看完了。。好像对面向对象编程有了更清晰的轮廓... --------------------编程问答-------------------- 挺有意思啊。 --------------------编程问答-------------------- 楼主好厉害 榜样 --------------------编程问答-------------------- 我看这个真的挺有意思啊。 --------------------编程问答-------------------- 看上去很好玩的样子呢~~~ --------------------编程问答-------------------- 看上去好像不错啊 --------------------编程问答-------------------- 还以为有算法。。。 --------------------编程问答-------------------- 挺好的一款游戏啊 --------------------编程问答-------------------- 楼主厉害,路过学习下。
补充:.NET技术 , C#