首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

自各儿动手实现一个《倒水解密》游戏

2012-09-20 
自己动手实现一个《倒水解密》游戏? Conmajia 2012本文所有源代码和VisualStudio2010(.NET Fx 2.0)工程打包

自己动手实现一个《倒水解密》游戏

? 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

 

热点排行