iis服务器助手广告
返回顶部
首页 > 资讯 > 精选 >基于WPF如何实现经典纸牌游戏
  • 475
分享到

基于WPF如何实现经典纸牌游戏

2023-07-05 06:07:48 475人浏览 安东尼
摘要

这篇“基于WPF如何实现经典纸牌游戏”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“基于WPF如何实现经典纸牌游戏”文章吧。1

这篇“基于WPF如何实现经典纸牌游戏”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“基于WPF如何实现经典纸牌游戏”文章吧。

1 纸牌类

之所以产生这个无聊至极的念头,是因为发现Unicode中竟然有这种字符。

基于WPF如何实现经典纸牌游戏

这就意味着不用任何资源就可以实现一些纸牌游戏,效果如下图所示

基于WPF如何实现经典纸牌游戏

这就意味着不用任何资源就可以实现一些纸牌游戏,效果如下图所示

#region 常量private static readonly Dictionary<string, string[]> CardNames = new Dictionary<string, string[]>{{"Spade", new string[13]{"????","????","????","????","????","????","????","????","????","????","????","????","????" } },{"Heart", new string[13]{"????", "????", "????", "????", "????", "????", "????", "????", "????", "????", "????", "????", "????" } },{"Diamond", new string[13]{"????", "????", "????", "????", "????", "????", "????", "????", "????", "????", "????", "????", "????" } },{"Club" , new string[13]{"????", "????", "????", "????", "????", "????", "????", "????", "????", "????", "????", "????", "????"}}};#endregion#region 卡牌类型private class Card{public Card(string name, int number, string type, bool red, int index){Name =name;Number = number;Type = type;Red = red;Index = index;}public int Index;public string Name;public int Number;public bool Red;public string Type;public int Region;}#endregion

在实现了纸牌类之后,将每个纸牌放到一个Button的Tag中,然后再 为Button添加各种事件,就能实现这个游戏了。

2 布局

由于是动态布局,所以建议使用canvas,xaml界面十分简洁,除了一个刷新按钮,剩下的就只有画布了。

    <StackPanel>        <ToolBar DockPanel.Dock="Top" Margin="0 0 0 20">            <Button Content="????" Click="btnUpdate_Click"/>        </ToolBar>        <Canvas x:Name="cvMain" Height="400"/>    </StackPanel>

经典纸牌游戏大致可以分为12个区域,如图所示

基于WPF如何实现经典纸牌游戏

这些个区域就可决定纸牌的位置,所以需要一个用来存放区间信息的变量

private List<int>[] cardIndex;

cardIndex是由12个List<int>组成的数组,然后每个Button的位置用下面的方式来设定

private void setBtnPosition(Button btn, int region){    Canvas.SetLeft(btn, region % 6 * dw);    Canvas.SetTop(btn, region / 6 * dh);    Canvas.SetZIndex(btn, cardIndex[region].Count);}

其中,SetLeft即控件据Canvas左端的距离,可以理解为x坐标;dw,dh为全局变量,用来存放每个区间的尺寸。SetTop对应的为y坐标。SetZIndex表示层级关系,值越大则越在上面。

3 初始化

初始化需要一个随机数组,目的是将牌打散。这里用了一个非常Low的方案,即生成随机数,然后交换自然序列中两个随机数所在位置的值。

private int[] RandomArray(int length){    int[] arr = new int[length];    for (int i = 0; i < length; i++)        arr[i] = i;    int times = rand.Next(10, 100);    for (int i = 0; i < times; i++)    {        int a = rand.Next(0, length - 1);        int b = rand.Next(0, length - 1);        var temp = arr[a];        arr[a] = arr[b];        arr[b] = temp;    }    return arr;}

接下来就是初始化代码,这里按照平时发牌的顺序,先生成这个区域的纸牌

基于WPF如何实现经典纸牌游戏

然后再生成牌堆。

public void InitCards(){    cvMain.Children.Clear();    cards = new List<Card>();    cardIndex = new List<int>[12];          //所有的扑克被划分为12个区域    for (int i = 0; i < 12; i++)        cardIndex[i] = new List<int>();    int index = 0;    foreach (var key in CardNames.Keys)        for (int i = 0; i < 13; i++)            cards.Add(new Card(CardNames[key][i], i, key,                key == "Heart" || key == "Diamond", index++));        var orders = RandomArray(52);    index = 0;    for (int i = 0; i < 6; i++)        for (int j = i; j < 6; j++)        {            var card = cards[orders[index++]];            cardIndex[6 + j].Add(cvMain.Children.Count);            var btn = setOneButton(card);            if (i == j)            {                coverCard(btn, false);      //当i==j时翻面                SetOneColumn(i);            }            card.Region = 6 + j;            setBtnPosition(btn, card.Region);        }    while (index<52)    {        var card = cards[orders[index++]];        cardIndex[0].Add(cvMain.Children.Count);        var btn = setOneButton(card);        card.Region = 0;        setBtnPosition(btn, 0);        btn.Click += Card_Click;    }}

其中,SetOneColumn用于下面牌的上下排序,定义为

private void SetOneColumn(int region){    var count = cardIndex[region].Count;    var left = (region - 6) * dw;    var top0 = dh;    int i = 0;    var ddh = (0.8 + 2.5 * count / 15) * dh / count;    foreach (var index in cardIndex[region])    {        var btn = cvMain.Children[index];        Canvas.SetLeft(btn, left);        Canvas.SetTop(btn, top0 + ddh * (i++));        Canvas.SetZIndex(btn, i);    }}

4 事件

针对纸牌游戏来说,鼠标事件可分为两类,一是点击牌堆需要发牌;二是拖动其他位置的牌。

点击牌堆

点击牌堆需要注意,当牌堆中的牌没有了之后,需要将1区的牌还给牌堆。

private void Card_Click(object sender, RoutedEventArgs e){    var btn = sender as Button;    var card = btn.Tag as Card;    if (card.Region > 0)        return;    var count = cardIndex[0].Count;    var num = Math.Min(count, numCard);    for (int _ = 0; _ < num; _++)    {        var index = cardIndex[0][count - num];      //canvas中的顺序        cardIndex[0].Remove(index);        cardIndex[1].Add(index);        btn = cvMain.Children[index] as Button;        btn.Click -= Card_Click;        btn.PreviewMouseLeftButtonDown += Card_PreviewLeftDown;        coverCard(btn, false);        setBtnPosition(btn, 1);        card = btn.Tag as Card;        card.Region = 1;    }    if (cardIndex[0].Count > 0 || cardIndex[1].Count <= numCard)        return;    foreach (var index in cardIndex[1])    {        cardIndex[0].Add(index);        btn = cvMain.Children[index] as Button;        btn.Click += Card_Click;        btn.PreviewMouseLeftButtonDown -= Card_PreviewLeftDown;        coverCard(btn, true);        setBtnPosition(btn, 0);        card = btn.Tag as Card;        card.Region = 0;    }    cardIndex[1] = new List<int>();}

拖动

拖动主要包含三个动作,即鼠标按下、鼠标挪动、鼠标弹开,所以对应三个函数,且当鼠标按下之后,才挂载鼠标挪动的事件。而鼠标弹起之后,则判断我们拖动的牌的最终位置。

private void Card_PreviewLeftDown(object sender, MouseButtonEventArgs e){    btnNow = sender as Button;    if (btnNow.Content.ToString() == bGCard)        return;    var card = btnNow.Tag as Card;    regionNow = cardIndex[card.Region];    indexNow = regionNow.IndexOf(        cvMain.Children.IndexOf(btnNow));    var count = regionNow.Count;    offsets = new List<Point>();    for (int i = indexNow; i < count; i++)    {        var btn = cvMain.Children[regionNow[i]] as Button;        offsets.Add(Mouse.GetPosition(btn));        Canvas.SetZIndex(btnNow, 100 + i);    }    btnNow.PreviewMouseLeftButtonUp += Card_PreviewLeftUp;    btnNow.PreviewMouseMove += Card_PreviewMouseMove;}private void Card_PreviewMouseMove(object sender, MouseEventArgs e){    var p = Mouse.GetPosition(cvMain);    for (int i = indexNow; i < regionNow.Count; i++)    {        var btn = cvMain.Children[regionNow[i]] as Button;        Canvas.SetLeft(btn, p.X - offsets[i - indexNow].X);        Canvas.SetTop(btn, p.Y - offsets[i - indexNow].Y);    }}private void Card_PreviewLeftUp(object sender, MouseButtonEventArgs e){    btnNow.PreviewMouseLeftButtonUp -= Card_PreviewLeftUp;    btnNow.PreviewMouseMove -= Card_PreviewMouseMove;    var p = Mouse.GetPosition(cvMain);    int region = (int)(p.X / dw) + (p.Y > dh ? 6 : 0);    var index = cardIndex[region].Count - 1;        //目标区域最上面的牌的序号    var card = btnNow.Tag as Card;    int srcRegion = card.Region;    //牌在挪动之后有两种可能,一种是成功了,另一种是失败了    bool suc = region != srcRegion;     //如果挪动的区域相同,则必失败    bool subSuc;    suc &= region > 1;              //如果向牌堆挪动,则必失败。    if (index < 0)    {//A和K的情况满足任何一种即可成功        subSuc = region > 1 && region < 6 && card.Number == 0;        subSuc |= region > 5 && card.Number == 12;    }    else    {        var tarBtn = cvMain.Children[cardIndex[region][index]] as Button;        var tarCard = tarBtn.Tag as Card;        var flag = tarCard.Type == card.Type;        var minus = card.Number - tarCard.Number;        subSuc = region > 1 && region < 6 && flag && (minus == 1);        subSuc |= region > 5 && (!flag) && (minus == -1);    }    reGroup(suc & subSuc, card, srcRegion, region);}

牌的去留

通过reGroup函数决定牌最终的状态。

private void reGroup(bool suc, Card card, int srcRegion, int tarRegion){    if (suc)    {        if (tarRegion > 5)            setNewRegion(srcRegion, tarRegion);        else            setNewRegion(btnNow, card, srcRegion, tarRegion);    }    if (srcRegion < 6)        setBtnPosition(btnNow, srcRegion);    else    {        SetOneColumn(srcRegion);        var i = regionNow.Count;        if (i > 0)        {            var btn = cvMain.Children[regionNow[i - 1]] as Button;            coverCard(btn, false);        }    }}private void setNewRegion(Button btn, Card card, int src, int tar){    int i = cardIndex[src].Count - 1;    cardIndex[tar].Add(cardIndex[src][i]);    cardIndex[src].RemoveAt(i);    card.Region = tar;    setBtnPosition(btn, tar);}//src和tar均为大区private void setNewRegion(int src, int tar){    var count = regionNow.Count;    for (int i = indexNow; i < count; i++)    {        var btn = cvMain.Children[regionNow[indexNow]] as Button;        cardIndex[tar].Add(regionNow[indexNow]);        regionNow.RemoveAt(indexNow);        var card = btn.Tag as Card;        card.Region = tar;        Canvas.SetZIndex(btn, cardIndex[tar].Count);    }    SetOneColumn(tar);    if (regionNow.Count > 0)    {        var btn = cvMain.Children[regionNow[indexNow - 1]] as Button;        coverCard(btn, false);    }}

以上就是关于“基于WPF如何实现经典纸牌游戏”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网精选频道。

--结束END--

本文标题: 基于WPF如何实现经典纸牌游戏

本文链接: https://www.lsjlt.com/news/350103.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 基于WPF实现经典纸牌游戏
    目录1 纸牌类2 布局3 初始化4 事件点击牌堆拖动牌的去留1 纸牌类 之所以产生这个无聊至极的念头,是因为发现Unicode中竟然有这种字符。。。 这就意味着不用任何资源就可以实...
    99+
    2023-02-27
    WPF实现纸牌游戏 WPF纸牌游戏 WPF游戏
  • 基于WPF如何实现经典纸牌游戏
    这篇“基于WPF如何实现经典纸牌游戏”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“基于WPF如何实现经典纸牌游戏”文章吧。1...
    99+
    2023-07-05
  • 基于Java实现经典蜘蛛纸牌游戏
    目录效果展示游戏结构核心代码AboutDialog.java类PKCard.java类SpiderMenuBar.java类Spider.java 类效果展示 前面的导入过...
    99+
    2024-04-02
  • 基于Java怎么实现经典蜘蛛纸牌游戏
    本文小编为大家详细介绍“基于Java怎么实现经典蜘蛛纸牌游戏”,内容详细,步骤清晰,细节处理妥当,希望这篇“基于Java怎么实现经典蜘蛛纸牌游戏”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。效果展示前面的导入过程...
    99+
    2023-06-30
  • 纸牌回归 Wind10重现经典纸牌游戏
    尽管纸牌,微软还是选择在Windows 8中删除了这些游戏,尽管消费者可以在Windows应用商店当中下载或者购买这些游戏的最新版本。但是用户从开始>程序>附件>游戏当中找到经典Windows游戏更加怀...
    99+
    2023-06-14
    纸牌 Win10 游戏 经典
  • 基于HTML+CSS+JS实现纸牌记忆游戏
    目录知识点HTML 用户界面CSS 部分一些基本样式纸牌的样式分数面板的样式祝贺面板的样式动画媒体查询JavaScript 部分洗牌功能开始新游戏的功能显示卡片的功能当卡片匹配时的功...
    99+
    2024-04-02
  • 基于Python+Pygame实现经典赛车游戏
    目录导语一、环境安装二、代码展示1.主程序main.py2.地图设置maps.py三、效果展示1.游戏界面2.游戏运行中3.15分到手导语 哈喽!哈喽~我是木木子,很久没给大家更新游...
    99+
    2024-04-02
  • 基于JS实现经典的井字棋游戏
    目录先看成品游戏初始化界面:玩家获胜AI电脑获胜思路生成棋盘重新开始玩家落子电脑落子代码HTMLCSSjs井字棋作为我们在上学时代必玩的一款连珠游戏,你知道如何做到先手必然不会输吗?...
    99+
    2024-04-02
  • 基于Python+Pygame怎么实现经典赛车游戏
    这篇文章主要介绍“基于Python+Pygame怎么实现经典赛车游戏”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“基于Python+Pygame怎么实现经典赛车游戏”文章能帮助大家解决问题。一、环境...
    99+
    2023-06-30
  • 基于Python实现经典植物大战僵尸游戏
    目录游戏截图动态演示源码分享state/tool.pystate/constants.pystate/main.py主执行文件main.py游戏截图 动态演示 源码分享 st...
    99+
    2024-04-02
  • 如何使用Java实现经典游戏2048
    这篇文章主要介绍如何使用Java实现经典游戏2048,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!主要设计游戏面板生成显示方块设计键盘监听,方向键控制数字移动数字移动逻辑算法处理数字累加到2048,游戏胜利功能截图游...
    99+
    2023-06-29
  • Unity3D实现经典小游戏Pacman
    目录项目概况整体布局地图介绍玩法介绍相关知识版本说明项目源码项目概况 整体布局 地图介绍 除了音效,游戏地图上的元素有: 普通糖豆(玩家通过移动,经过的普通糖豆会被吃掉,...
    99+
    2024-04-02
  • js实现经典扫雷游戏
    本文实例为大家分享了js实现经典扫雷游戏的具体代码,供大家参考,具体内容如下 项目结构 实现效果 思路流程 1、写出基本的布局 2、利用js生成扫雷的table表格 3、利用随...
    99+
    2024-04-02
  • 如何用Pygame实现经典外星人游戏
    本篇内容介绍了“如何用Pygame实现经典外星人游戏”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!安装环境下载python3,或如Anaco...
    99+
    2023-06-26
  • Java如何实现经典游戏复杂迷宫
    这篇文章主要为大家展示了“Java如何实现经典游戏复杂迷宫”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java如何实现经典游戏复杂迷宫”这篇文章吧。前言人类建造迷宫已有5000年的历史。在世界...
    99+
    2023-06-29
  • 怎样用C语言实现纸牌游戏
    今天就跟大家聊聊有关怎样用C语言实现纸牌游戏,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1. 基本要求一副没有花牌(J、Q、K、A、大小王)的扑克牌,两个人进行纸牌游戏,其中一个人...
    99+
    2023-06-22
  • Python+numpy实现一个蜘蛛纸牌游戏
    目录1.过程2.思路3.配置4.代码四.效果图1.过程 蜘蛛纸牌大家玩过没有?之前的电脑上自带的游戏,用他来摸鱼过的举个手。 但是现在的电脑上已经没有蜘蛛纸牌了。所以…...
    99+
    2022-12-08
    Python numpy蜘蛛纸牌游戏 Python numpy蜘蛛纸牌 Python 蜘蛛纸牌 Python 游戏
  • JavaScript实现经典贪吃蛇游戏
    本文实例为大家分享了JavaScript实现经典贪吃蛇游戏的具体代码,供大家参考,具体内容如下 主要使用单例模式,所有元素动态创建; 1.创建地图 var Map; fu...
    99+
    2024-04-02
  • 如何使用Java实现经典游戏推箱子
    这篇文章将为大家详细讲解有关如何使用Java实现经典游戏推箱子,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。主要设计游戏面板生成显示地图生成算法人物移动算法播放背景音乐箱子移动算法全部箱子移动到指定位置,...
    99+
    2023-06-29
  • JS+HTML实现经典游戏吃豆人
    目录前言HTML代码JS代码游戏截图前言 很早就知道canvas,当时一直没应用到,最近闲来无事就顺便写写看。吃豆游戏可以说是我们80,90后共同的回忆录,小时候常常在学习机上玩,所...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作