zoukankan      html  css  js  c++  java
  • 开发.Net版的纸牌游戏

            最近我刚完成一个大项目后有一段比较休闲的时光。但是休息久了也很无聊,偶尔玩玩小游戏,像纸牌之类的.大游戏不敢玩,怕被领导发现,嘿嘿

            想必大家都玩过Windows自带的一个小游戏"纸牌"吧。在空闲时间我也开发了一个.net版的纸牌游戏,其界面、功能及操作都跟Windows的差不多。下图就是我的作品的截图:

                

    源代码文件说明:
    CardsResources.resx ---------------牌图像资源
    Cards.cs----------------------------牌对象
    CardCollections.cs------------------牌列表对象
    GamePlace.cs-----------------------游戏平台
    GameForm.cs-----------------------游戏窗口
    OptionForm.cs----------------------选项设置窗口
    BackImageForm.cs------------------牌背面选择窗口
    ImageBrowser.cs--------------------图片浏览控件
    PassPlayer.cs------------------------过关动画播放器

            说到像这类似的牌类游戏,也许大家都有自己的思路和想法,下面我就来谈谈我在开发过程中的思路以及遇到的问题和处理方法。


            一,建立对象(包括资源对象,牌对象,牌列表对象)
                (一)资源对象:将所有牌的图像(包括背景和其他特殊图片)做成资源"CardsResources.resx",我一共做了69张图片,54张牌面+12张背景+1张阴影图片+2张发牌底面。
                (二)牌对象 Card:继承System.Windows.Forms.PictureBox,其图像源即为资源中的牌图像.首先建立Cards用于创建牌的图像

    /// <summary>
        
    /// 创建牌的图像资源。
        
    /// </summary>

        public class Cards
        
    {
            
    private static Image[] cardImages;

            
    /// <summary>
            
    /// 牌的尺寸
            
    /// </summary>

            public static readonly Size CardImageSize=new Size(71,96);

            
    /// <summary>
            
    /// 牌的图像列表
            
    /// </summary>

            internal static Image[] CardImages
            
    {
                
    get
                
    {
                    
    return cardImages;
                }

            }


            
    /// <summary>
            
    /// 创建图像列表
            
    /// </summary>

            public static void CreateCardsImages()
            
    {
                ResourceManager resmanager
    =new ResourceManager("CardGame.CardsResources",Assembly.GetExecutingAssembly());
                cardImages
    =new Image[69];
                
                
    for(int i=0;i<69;i++)
                
    {
                    cardImages[i]
    =(resmanager.GetObject(i+""as Image);
                }

            }


            
    /// <summary>
            
    /// 获得牌的显示区域
            
    /// </summary>
            
    /// <param name="size">牌的尺寸</param>
            
    /// <returns>牌的显示区域</returns>

            public static Region GetCardRegion(Size size)
            
    {
                GraphicsPath gp 
    = new GraphicsPath();
                gp.AddPolygon(
    new Point[]{
                                             
    new Point(0,2),

                                             
    new Point(2,0),
                                             
    new Point(size.Width-2,0),

                                             
    new Point(size.Width,2),
                                             
    new Point(size.Width,size.Height-2),

                                             
    new Point(size.Width-2,size.Height),
                                             
    new Point(2,size.Height),

                                             
    new Point(0,size.Height-2),
                                             
    new Point(0,2)
                                         }
    );
                
    return new Region(gp);
            }

        }

    然后创建牌基类(Card)

        /// <summary>
        
    /// 牌的基类
        
    /// </summary>

        public abstract class Card:PictureBox
        
    {
            
    protected int cardFaceImageIndex;
            
    protected int cardBackImageIndex;
            
    protected bool isFace=true;
            
    protected int index=0;
            
    private CardCollections cardsGroup;
            
            
    protected Card():base()
            
    {
                
    base.BackColor=Color.Transparent;
                
    base.Size=Cards.CardImageSize;
                
    base.Region=Cards.GetCardRegion(base.Size);
                
    base.SizeMode=PictureBoxSizeMode.AutoSize;
                
    base.Location=new Point(-1,-1);
            }


            
    /// <summary>
            
    /// 所属的牌列表
            
    /// </summary>

            public CardCollections CardsGroup
            
    {
                
    get
                
    {
                    
    return cardsGroup;
                }

                
    set
                
    {
                    cardsGroup
    =value;
                }

            }


            
    /// <summary>
            
    /// 所在牌列表的索引
            
    /// </summary>

            public int Index
            
    {
                
    get
                
    {
                    
    return index;
                }

                
    set
                
    {
                    index
    =value;
                }

            }


            
    /// <summary>
            
    /// 是否显示的是牌的正面
            
    /// </summary>

            public bool IsFace
            
    {
                
    get
                
    {
                    
    return isFace;
                }

            }

            
            
    /// <summary>
            
    /// 牌正面的图像列表索引
            
    /// </summary>

            public int CardFaceImageIndex
            
    {
                
    get
                
    {
                    
    return cardFaceImageIndex;
                }

            }


            
    /// <summary>
            
    /// 牌背面的图像列表索引
            
    /// </summary>

            public int CardBackImageIndex
            
    {
                
    get
                
    {
                    
    return cardBackImageIndex;
                }

                
    set
                
    {
                    cardBackImageIndex
    =value;
                }

            }


            
    public Card(int cardFaceImageIndex):this(cardFaceImageIndex,-1)
            
    {

            }


            
    public Card(int cardFaceImageIndex,int cardBackImageIndex):this()
            
    {
                
    this.cardFaceImageIndex=cardFaceImageIndex;
                
    this.cardBackImageIndex=cardBackImageIndex;
            }


            
    /// <summary>
            
    /// 显示正面
            
    /// </summary>

            public void ShowFace()
            
    {
                
    if(cardFaceImageIndex>=0&&cardFaceImageIndex<Cards.CardImages.Length)
                
    {
                    
    base.Image=Cards.CardImages[cardFaceImageIndex];
                }

                
    else
                
    {
                    
    base.Image=null;
                }

                isFace
    =true;
            }


            
    /// <summary>
            
    /// 显示背面
            
    /// </summary>

            public void ShowBack()
            
    {
                
    if(cardBackImageIndex>=0&&cardBackImageIndex<Cards.CardImages.Length)
                
    {
                    
    base.Image=Cards.CardImages[cardBackImageIndex];
                }

                
    else
                
    {
                    
    base.Image=null;
                }

                isFace
    =false;
            }

        }


    有了基类Card后就可以派生出一般的扑克牌NormalCard以及其他的牌.对于NormalCard我们可以这样来派生:

    /// <summary>
        
    /// 普通牌
        
    /// </summary>

        public class NormalCard:Card
        
    {
            
    public static int[] CardBackImageIndexSection;
            
    private int faceNum;
            
    private NormalCardFaceType faceType;

            
    /// <summary>
            
    /// 牌面数字
            
    /// </summary>

            public int FaceNum
            
    {
                
    get{return faceNum;}
            }


            
    /// <summary>
            
    /// 牌面类型,如:红黑梅方
            
    /// </summary>

            public NormalCardFaceType FaceType
            
    {
                
    get{return faceType;}
            }


            
    static NormalCard()
            
    {
                CardBackImageIndexSection
    =new int[12];
                
    for(int i=54;i<=65;i++)
                
    {
                    CardBackImageIndexSection[i
    -54]=i;
                }

            }

            
            
    public NormalCard(int cardFaceImageIndex,int cardBackImageIndex):base(cardFaceImageIndex,cardBackImageIndex)
            
    {
                
    if(base.cardFaceImageIndex<0||base.cardFaceImageIndex>51)base.cardFaceImageIndex=0;
                
    if(base.cardBackImageIndex<54||base.cardBackImageIndex>65)base.cardBackImageIndex=54;
                
    this.faceType=(NormalCardFaceType)(cardFaceImageIndex%4);
                
    this.faceNum=(int)(cardFaceImageIndex-(int)this.faceType)/4+1;
                ShowBack();
            }

            
    public NormalCard(int faceNum,NormalCardFaceType faceType,int cardBackImageIndex):this((faceNum-1)*4+(int)faceType,cardBackImageIndex)
            
    {
            }

            
            
    /// <summary>
            
    /// 改变背面图像
            
    /// </summary>
            
    /// <param name="cardBackImageIndex">背面索引</param>

            public void ChangeBack(int cardBackImageIndex)
            
    {
                
    base.cardBackImageIndex=cardBackImageIndex;
                
    if(!isFace)ShowBack();
            }


            
    /// <summary>
            
    /// Hearts 红心,Clubs 梅花,Diamonds 方块,Spade=黑桃
            
    /// </summary>

            public enum NormalCardFaceType:int
            
    {
                Clubs
    =0,
                Diamonds
    =1,
                Hearts
    =2,
                Spade
    =3
            }

        }


    还有其他的牌的派生,这里就不介绍了.

                (三)牌列表对象:关于这个概念其实就是,牌所属的区域,比如发牌区,排列区(又称非处理区),以及收集区(又称处理区)如下图:

    这个对象是由CollectionBase继承而来的.在列表对象里我们可以定义拍的正面和方面的排列方式,以及可以接受的牌的性质等,比如在排列区,背面的位置偏移是(0,3),正面是(0,15),可以接受的牌为不同颜色而且牌面数比最上面一张牌小一,诸如此类的定义都将类个对象里完成,在实际的游戏操作过程中,也就是调用此类的一系列方法.

    对象建立完成以后,就可以创建一个游戏平台类了,我将它命名为 "GamePlace".

        二,创建游戏平台,
            在此平台中我们将要完成,与用户的交互,洗牌功能,创建并初始化牌列表,以及如何将52张牌分配给各个牌列表区.以上这一些都是些逻辑功能,只要玩过纸牌游戏的人想必都有思路了吧.关于GamePlace的代码有点长,这里就不给出了.

            三,结束语:
                  该类游戏的关键主要在于对象的创建,对象创建得合理,那么用起来就方便,我认为这也是对象编程思想的难点吧.这篇文章只提供大家一些思路.我已经完成了这个游戏的开发,也测试过了.

    点击此处下载源代码

    给新手参考,请高手指教,大家交个朋友~~~~~

    我的联系方式:QQ:26387232,email:dotnetbar@gmail.com

  • 相关阅读:
    MongoDB知识
    SELECT INTO 和 INSERT INTO SELECT 两种表复制语句
    SQL Server 触发器
    TSQL游标使用
    python和C#的区别
    bcp和SqlDataAdapter进行批量跟新插入方法
    SQL Server中索引视图用法详解
    hdu 1950 Bridging signals
    UVA 116 Unidirectional TSP
    poj 3230 Travel
  • 原文地址:https://www.cnblogs.com/volcano/p/268711.html
Copyright © 2011-2022 走看看