当前位置:主页 > 查看内容

扑克牌算24点

发布时间:2021-07-13 00:00| 位朋友查看

简介:扑克牌算24点 简介 代码 简介 小时候一个人无聊的时候最喜欢玩的游戏一副扑克牌每次发4张加减乘除算得24玩的贼溜。曾今在初中的时候有次和同学玩算24点几乎次次在牌亮出后我就能说出公式惊呆了我的小伙伴~~~ 最近又想起了这个小游戏于是利用工作之余写了一个……

扑克牌算24点

简介

    小时候一个人无聊的时候最喜欢玩的游戏,一副扑克牌每次发4张,加减乘除算得24,玩的贼溜。曾今在初中的时候有次和同学玩算24点,几乎次次在牌亮出后我就能说出公式,惊呆了我的小伙伴~~~
    最近又想起了这个小游戏,于是利用工作之余写了一个C#版的算24点,怀恋下小时候的情怀!

代码

啥都不说了,直接上代码。

//Program.cs
class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("    ***************************************************");
            Console.WriteLine("    *                   扑克牌算24                    *");
            Console.WriteLine("    *              Copyright 2021 凌风游              *");
            Console.WriteLine("    *     https://gitee.com/lkj1420428992/poker24     *");
            Console.WriteLine("    ***************************************************");
            Console.WriteLine();
            Console.WriteLine("    用+-*/运算,算出结果24。AJQK作为数字1");
            Console.WriteLine("    play:开始发牌; exit:退出; answer:查看答案");
            bool isExit = false;
            PlayPoker playPoker = new PlayPoker();
            while (!isExit) {
                string msg = Console.ReadLine();
                if (msg == "exit") {
                    isExit = true;
                    break;
                }
                else if (msg == "play") {
                    string title = playPoker.Play();
                    Console.WriteLine($"发牌:{title} 请写出公式:");
                    Console.WriteLine();
                    string formula = playPoker.InputFormula();
                    if (formula == "answer")
                    {
                        Console.WriteLine("正确答案:");
                        showAnswer(playPoker.PokerResult());                        
                    }
                    else {
                        var res = playPoker.CheckFormula(formula);
                        if (res)
                        {
                            Console.WriteLine("回答正确");
                        }
                        else {
                            Console.WriteLine("回答错误");
                            Console.WriteLine("正确答案:");
                            showAnswer(playPoker.PokerResult());
                        }
                    }
                }          
            }
        }
        static void showAnswer(List<string> answers) {

            if (answers == null || answers.Count == 0) return;
            answers.ForEach(item=> {
                Console.WriteLine(item);
            });
        }
    }
//PlayPoker.cs
public class PlayPoker
    {
        public string[] Pokers = new string[13] {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
        private string pokerA, pokerB, pokerC, pokerD = null;
        private DataTable dataTable = new DataTable();
        private Poker24 p24 = new Poker24();

		//发牌
        public string Play() {         
            pokerA = GetRandomPoker();
            pokerB = GetRandomPoker();
            pokerC = GetRandomPoker();
            pokerD = GetRandomPoker();
            return $"{pokerA} {pokerB} {pokerC} {pokerD}";
        }

        private string ConvertPoker(string poker) {
            string res = null;
            switch (poker) {
                case "A":
                    res = "1";
                    break;
                case "J":
                    res = "1";
                    break;
                case "Q":
                    res = "1";
                    break;
                case "K":
                    res = "1";
                    break;
                default:
                    res = poker;
                    break;
            }
            return res;
        }
		
		//随机获取扑克牌
        private string GetRandomPoker() {
            byte[] buffer = Guid.NewGuid().ToByteArray();
            int iSeed = BitConverter.ToInt32(buffer, 0);
            Random ran = new Random(iSeed);
            int index = ran.Next(0, Pokers.Length);
            return Pokers[index];
        }

		//输入公式
        public string InputFormula() {
            string formula = string.Empty;
            Boolean isComplete = false;
            while (!isComplete) {
                formula = Console.ReadLine();
                isComplete = true;
            }
            return formula;
        }

		//检查公式结果是否正确
        public Boolean CheckFormula(string formula) {
            try {
                var res = dataTable.Compute(formula, null).ToString();
                return res == "24";
            }
            catch (Exception err) {
                return false;
            }           
        }
		
		//返回所有结果
        public List<string> PokerResult() {
            try {
                p24.DealFourCards(ConvertPoker(pokerA), ConvertPoker(pokerB), ConvertPoker(pokerC), ConvertPoker(pokerD));
                var res = p24.Calc24();
                if (res == null || res.Count == 0) return null;
                return res.Select(x => $"{x.Formula()} = 24").ToList();
            }
            catch (Exception err) {
                return null;
            }         
        }
    }
//Poker24.cs
public sealed class Poker24
    {
        private string[] poker = new string[4];
        private string[] signArr = new string[4] { "+", "-", "*", "/" };

        public Poker24()
        {
        }

        public void DealFourCards(string pokerA, string pokerB, string pokerC, string pokerD)
        {
            poker[0] = pokerA;
            poker[1] = pokerB;
            poker[2] = pokerC;
            poker[3] = pokerD;
        }

        public List<CalcBlock> Calc24()
        {
            List<CalcBlock> pbs = new List<CalcBlock>();
            List<string[]> list = new List<string[]>();
            //4个数字共有4*3*2*1=24种排列组合
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    if (i == j) continue;
                    for (int k = 0; k < 4; k++)
                    {
                        if (i == k || j == k) continue;
                        for (int m = 0; m < 4; m++)
                        {
                            if (i == m || j == m || k == m) continue;
                            list.Add(new string[4] { poker[i], poker[j], poker[k], poker[m] });
                        }
                    }
                }
            }

            //三个=-*/位置共有4*4*4=64种组合
            List<string[]> signList = new List<string[]>();
            for (int i = 0; i < signArr.Length; i++)
            {
                for (int j = 0; j < signArr.Length; j++)
                {
                    for (int k = 0; k < signArr.Length; k++)
                    {
                        signList.Add(new string[3] { signArr[i], signArr[j], signArr[k] });
                    }
                }
            }

            //数字和符号位 组合共有 24*64=1536种组合
            List<Tuple<string[], string[]>> formulaList = new List<Tuple<string[], string[]>>();
            for (int i = 0; i < list.Count; i++)
            {
                for (int j = 0; j < signList.Count; j++)
                {
                    formulaList.Add(new Tuple<string[], string[]>(list[i], signList[j]));
                }
            }
            //共有6中括号位置可能  共有1536*6=9216种组合
            foreach (var item in formulaList)
            {
                string[] a = item.Item1;
                string[] b = item.Item2;
                
                //筛选结果等于24的计算公式
                var af1 = AnalyticFormula($"{a[0]}{b[0]}{a[1]}{b[1]}{a[2]}{b[2]}{a[3]}");
                if (af1.Calc() == 24) pbs.Add(af1);
                af1 = AnalyticFormula($"({a[0]}{b[0]}{a[1]}){b[1]}{a[2]}{b[2]}{a[3]}");
                if (af1.Calc() == 24) pbs.Add(af1);
                af1 = AnalyticFormula($"({a[0]}{b[0]}{a[1]}{b[1]}{a[2]}){b[2]}{a[3]}");
                if (af1.Calc() == 24) pbs.Add(af1);
                af1 = AnalyticFormula($"{a[0]}{b[0]}({a[1]}{b[1]}{a[2]}){b[2]}{a[3]}");
                if (af1.Calc() == 24) pbs.Add(af1);
                af1 = AnalyticFormula($"{a[0]}{b[0]}({a[1]}{b[1]}{a[2]}{b[2]}{a[3]})");
                if (af1.Calc() == 24) pbs.Add(af1);
                af1 = AnalyticFormula($"{a[0]}{b[0]}{a[1]}{b[1]}({a[2]}{b[2]}{a[3]})");
                if (af1.Calc() == 24) pbs.Add(af1);
            }
            //排除重复的计算公式
            pbs = pbs.Distinct(new CalcPokerBlockComparer()).ToList();
            //交换律排除重复的计算公式
            ExcludeOfExchange(pbs);
            return pbs;
        }

        /// <summary>
        /// 分析计算公式,将字符串计算公式解析为CalcBlock
        /// </summary>
        private CalcBlock AnalyticFormula(string formula)
        {
            var b = formula.ToArray();
            Stack<PokerBlock> stacks = new Stack<PokerBlock>();
            List<PokerBlock> list = new List<PokerBlock>();

            string c = "";
            for (var i = 0; i < b.Length; i++)
            {
                if (char.IsDigit(b[i]))
                {
                    c += b[i];

                    if (i == b.Length - 1) list.Add(new ValueBlock(double.Parse(c)));
                }
                else
                {
                    if (c != "") list.Add(new ValueBlock(double.Parse(c)));
                    list.Add(new SignBlock(b[i].ToString()));
                    c = "";
                }
            }
            //利用栈逐步解析公式
            int signCount = 0;
            SignBlock preSign = null;
            foreach (var item in list)
            {
                var sb = item as SignBlock;
                if (sb != null) //符号
                {
                    if (sb.IsRightBracket)
                    {
                        if (preSign != null && signCount > 1)
                        {
                            SignPop(stacks);
                        }
                        RightBracketPop(stacks);
                        preSign = null;
                        signCount = 0;
                    }
                    else if (sb.IsLeftBracket)
                    {
                        preSign = null;
                        signCount = 0;
                        stacks.Push(item);
                    }
                    else
                    {
                        if (preSign == null)
                        {
                            preSign = sb;
                            signCount++;
                            stacks.Push(item);
                        }
                        else
                        {
                            if (sb.ComparePriority(preSign) <= 0)
                            {
                                preSign = sb;
                                signCount = 1;
                                SignPop(stacks);
                                stacks.Push(item);
                            }
                            else
                            {
                                preSign = sb;
                                signCount++;
                                stacks.Push(item);
                            }
                        }
                    }
                }
                else
                { //数字
                    stacks.Push(item);
                }
            }
            End(stacks);
            var res = stacks.Pop();
            return res as CalcBlock;
        }

        /// <summary>
        /// 右括号出栈
        /// </summary>
        private void RightBracketPop(Stack<PokerBlock> stacks)
        {
            var d = stacks.Pop(); // 3
            var c = stacks.Pop(); // +
            var b = stacks.Pop(); // 5
            var a = stacks.Pop(); // (

            var e = c as SignBlock;
            var f = e.Merge(b as CalcBlock, d as CalcBlock);
            stacks.Push(f);
        }

        // +-*/符号出栈
        private void SignPop(Stack<PokerBlock> stacks)
        {
            var c = stacks.Pop(); // 3
            var b = stacks.Pop(); // +
            var a = stacks.Pop(); // 5

            var d = b as SignBlock;
            var e = d.Merge(a as CalcBlock, c as CalcBlock);
            stacks.Push(e);
        }

        /// <summary>
        /// 最后全部出栈
        /// </summary>
        private void End(Stack<PokerBlock> stacks)
        {
            if (stacks.Count == 1) return;

            var c = stacks.Pop(); // 3
            var b = stacks.Pop(); // +
            var a = stacks.Pop(); // 5

            var d = b as SignBlock;
            var e = d.Merge(a as CalcBlock, c as CalcBlock);
            stacks.Push(e);
            End(stacks);
        }

        /// <summary>
        /// 交换律排除重复
        /// </summary>
        private void ExcludeOfExchange(List<CalcBlock> pbs)
        {
            List<CalcBlock> removePbs = new List<CalcBlock>();
            for (int i = 0; i < pbs.Count - 1; i++)
            {
                string exchangeFormula = pbs[i].LawOfExchange();
                if (exchangeFormula == null) continue;
                for (int j = i + 1; j < pbs.Count; j++)
                {
                    string formula = pbs[j].Formula();
                    if (exchangeFormula == formula)
                    {
                        removePbs.Add(pbs[j]);
                    }
                }
            }

            if (removePbs.Count > 0) removePbs.ForEach(item => { pbs.Remove(item); });
        }
    }
//PokerBlock.cs
/// <summary>
    /// 基础块
    /// </summary>
    public abstract class PokerBlock
    {
    }

    /// <summary>
    /// 计算块
    /// </summary>
    public abstract class CalcBlock : PokerBlock
    {
        public abstract string Formula();
        public abstract double Calc();

        /// <summary>
        /// 交换律
        /// </summary>
        public virtual string LawOfExchange()
        {
            return null;
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            if (this.GetType() != obj.GetType()) return false;
            return Equals((CalcBlock)obj);
        }

        public bool Equals(CalcBlock obj)
        {
            if (obj == null) return false;
            if (ReferenceEquals(this, obj)) return true;
            return (Formula() == obj.Formula());
        }

        public static bool operator ==(CalcBlock p1, CalcBlock p2)
        {
            if (ReferenceEquals(p1, null)) return ReferenceEquals(p2, null);
            return (p1.Equals(p2));
        }
        
        public static bool operator !=(CalcBlock p1, CalcBlock p2)
        {
            return !(p1 == p2);
        }

        public override int GetHashCode()
        {
            string a = Formula();
            return a.GetHashCode();
        }
    }

    /// <summary>
    /// 符号块
    /// </summary>
    public sealed class SignBlock : PokerBlock
    {
        private string Sign { get; set; }

        public SignBlock(string sign)
        {
            this.Sign = sign;
        }

        /// <summary>
        /// 比较优先级  大于0  优先级高,等于0相等,小于0 优先级小
        /// </summary>
        public int ComparePriority(SignBlock sb)
        {
            return this.GetPriority() - sb.GetPriority();
        }

        public Boolean IsLeftBracket
        {
            get
            {
                return Sign == "(";
            }
        }

        public Boolean IsRightBracket
        {
            get
            {
                return Sign == ")";
            }
        }

        public int GetPriority()
        {
            int p = 0;
            switch (Sign)
            {
                case "+":
                    p = 10;
                    break;
                case "-":
                    p = 10;
                    break;
                case "*":
                    p = 20;
                    break;
                case "/":
                    p = 20;
                    break;
            }
            return p;
        }

        public CalcBlock Merge(CalcBlock a, CalcBlock b)
        {
            CalcBlock res = null;
            switch (Sign)
            {
                case "+":
                    res = new AddCalcBlock(a, b);
                    break;
                case "-":
                    res = new SubCalcBlock(a, b);
                    break;
                case "*":
                    res = new MultiCalcBlock(a, b);
                    break;
                case "/":
                    res = new DivisionCalcBlock(a, b);
                    break;
            }
            return res;
        }
    }

    /// <summary>
    /// 数值块
    /// </summary>
    public sealed class ValueBlock : CalcBlock
    {
        private double Value { get; set; }

        public ValueBlock(double value)
        {
            this.Value = value;
        }

        public override double Calc()
        {
            return Value;
        }

        public override string Formula()
        {
            return Value.ToString();
        }
    }

    /// <summary>
    /// 加法块
    /// </summary>
    public sealed class AddCalcBlock : CalcBlock
    {
        private CalcBlock LeftBlock { get; set; }
        private CalcBlock RightBlock { get; set; }

        public AddCalcBlock(CalcBlock leftBlock, CalcBlock rightBlock)
        {
            this.LeftBlock = leftBlock;
            this.RightBlock = rightBlock;
        }

        public override double Calc()
        {
            return LeftBlock.Calc() + RightBlock.Calc();
        }

        public override string Formula()
        {
            return $"{LeftBlock.Formula()} + {RightBlock.Formula()}";
        }

        public override string LawOfExchange()
        {
            return $"{RightBlock.Formula()} + {LeftBlock.Formula()}";
        }
    }

    /// <summary>
    /// 减法块
    /// </summary>
    public sealed class SubCalcBlock : CalcBlock
    {
        private CalcBlock LeftBlock { get; set; }
        private CalcBlock RightBlock { get; set; }

        public SubCalcBlock(CalcBlock leftBlock, CalcBlock rightBlock)
        {
            this.LeftBlock = leftBlock;
            this.RightBlock = rightBlock;
        }

        public override double Calc()
        {
            return LeftBlock.Calc() - RightBlock.Calc();
        }

        public override string Formula()
        {
            if (RightBlock is SubCalcBlock)
            {
                return $"{LeftBlock.Formula()} - ( {RightBlock.Formula()} )";
            }
            return $"{LeftBlock.Formula()} - {RightBlock.Formula()}";
        }
    }

    /// <summary>
    /// 乘法块
    /// </summary>
    public sealed class MultiCalcBlock : CalcBlock
    {
        private CalcBlock LeftBlock { get; set; }
        private CalcBlock RightBlock { get; set; }

        public MultiCalcBlock(CalcBlock leftBlock, CalcBlock rightBlock)
        {
            this.LeftBlock = leftBlock;
            this.RightBlock = rightBlock;
        }

        public override double Calc()
        {
            return LeftBlock.Calc() * RightBlock.Calc();
        }

        public override string Formula()
        {
            string left = "";
            string right = "";
            if (LeftBlock is AddCalcBlock || LeftBlock is SubCalcBlock)
            {
                left = $"( {LeftBlock.Formula()} )";
            }
            else
            {
                left = LeftBlock.Formula();
            }

            if (RightBlock is AddCalcBlock || RightBlock is SubCalcBlock)
            {
                right = $"( {RightBlock.Formula()} )";
            }
            else
            {
                right = RightBlock.Formula();
            }

            return $"{left} * {right}";
        }

        public override string LawOfExchange()
        {
            string left = "";
            string right = "";
            if (LeftBlock is AddCalcBlock || LeftBlock is SubCalcBlock)
            {
                left = $"( {LeftBlock.Formula()} )";
            }
            else
            {
                left = LeftBlock.Formula();
            }

            if (RightBlock is AddCalcBlock || RightBlock is SubCalcBlock)
            {
                right = $"( {RightBlock.Formula()} )";
            }
            else
            {
                right = RightBlock.Formula();
            }
            return $"{right} * {left}";
        }
    }

    /// <summary>
    /// 除法块
    /// </summary>
    public sealed class DivisionCalcBlock : CalcBlock
    {
        private CalcBlock LeftBlock { get; set; }
        private CalcBlock RightBlock { get; set; }
        public DivisionCalcBlock(CalcBlock leftBlock, CalcBlock rightBlock)
        {
            this.LeftBlock = leftBlock;
            this.RightBlock = rightBlock;
        }

        public override double Calc()
        {
            return LeftBlock.Calc() / RightBlock.Calc();
        }

        public override string Formula()
        {
            string left = "";
            string right = "";
            if (LeftBlock is AddCalcBlock || LeftBlock is SubCalcBlock)
            {
                left = $"( {LeftBlock.Formula()} )";
            }
            else
            {
                left = LeftBlock.Formula();
            }

            if (RightBlock is AddCalcBlock || RightBlock is SubCalcBlock)
            {
                right = $"( {RightBlock.Formula()} )";
            }
            else
            {
                right = RightBlock.Formula();
            }
            return $"{left} / {right}";
        }
    }


    public sealed class CalcPokerBlockComparer : IEqualityComparer<CalcBlock>
    {
        public bool Equals(CalcBlock x, CalcBlock y)
        {
            if (x == null)
                return y == null;
            return x == y;
        }

        public int GetHashCode(CalcBlock obj)
        {
            if (obj == null)
                return 0;
            return obj.GetHashCode();
        }
    }

扑克牌算24 demo

;原文链接:https://blog.csdn.net/lukejianlubing/article/details/115690303
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!
上一篇:用数组写三子棋游戏 下一篇:没有了

推荐图文


随机推荐