C# 24點游戲求解算法(修訂1)


經常跟兒子玩24點,有時候比較難算的,算一會兒,兩人算不出來,就收了,當作沒法算。

以我的數學能力,一般來說,算不出來的,大概率確實是算不出來的。

但是遇到比較變態的,當作算不出來是可能的,所以一直想找一個直接能解24點的程序。

可是網上找了一圈,一直沒找到。

想着自己寫一個,可是這里面的邏輯一直理不清楚,不知道這個算法應該怎么寫。

下午坐在電腦前面想的時候,不知道為啥,像是突然開竅了。寫着寫着居然寫出來了。

貼出來供有興趣的朋友參考,有問題請指正。

修訂1:增加(a,b),(c,d)的算法

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace Calc24Point
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            while (true)
            {
                var a = int.Parse(Console.ReadLine());
                var b = int.Parse(Console.ReadLine());
                var c = int.Parse(Console.ReadLine());
                var d = int.Parse(Console.ReadLine());

                Console.Clear();
                Console.WriteLine($"{a}, {b}, {c}, {d}");
                Console.WriteLine("------------------------");

                var items = CalcHelper.CalcResult(a, b, c, d);
                if (items?.Any() == true)
                {
                    foreach (var item in items)
                    {
                        Console.WriteLine(item);
                    }
                }
                else
                {
                    Console.WriteLine("無解");
                }
                Console.WriteLine("------------------------");
            }
        }
    }

    public class CalcHelper
    {
        public static List<string> CalcResult(double a, double b, double c, double d)
        {
            List<string> myList = new List<string>();
            List<CalcInfo> items = MakeCalcs(a, b, c, d);
            foreach (var item in items)
            {
                var result = item.GetResult();
                if (double.IsNaN(result) == false && IsEqual(result, 24))
                {
                    var text = item.GetString();
                    if (myList.Contains(text) == false)
                    {
                        myList.Add(text);
                    }
                }
            }

            return myList;
        }

        private static bool IsEqual(double a, double b)
        {
            return Math.Abs(a - b) < 0.000001;
        }

        private static List<CalcInfo> MakeCalcs(double a, double b, double c, double d)
        {
            var items = new List<CalcInfo>();
            items.AddRange(MakeCalcs(a, (b, c, d)));
            items.AddRange(MakeCalcs(b, (a, c, d)));
            items.AddRange(MakeCalcs(c, (b, a, d)));
            items.AddRange(MakeCalcs(d, (b, c, a)));

            items.AddRange(MakeCalcs((a, b), (c, d)));
            items.AddRange(MakeCalcs((a, c), (b, d)));
            items.AddRange(MakeCalcs((a, d), (c, b)));

            return items;
        }

        private static IEnumerable<CalcInfo> MakeCalcs((double a, double b) p1, (double c, double d) p2)
        {
            foreach (CalcInfo item1 in MakeCalcs(p1.a, p1.b))
            {
                foreach (CalcInfo item2 in MakeCalcs(p2.c, p2.d))
                {
                    yield return new CalcInfo(item1, item2, EMode.加);
                    yield return new CalcInfo(item1, item2, EMode.減);
                    yield return new CalcInfo(item2, item1, EMode.減);
                    yield return new CalcInfo(item1, item2, EMode.乘);
                    yield return new CalcInfo(item1, item2, EMode.除);
                    yield return new CalcInfo(item2, item1, EMode.除);
                }
            }
        }

        private static IEnumerable<CalcInfo> MakeCalcs(double item1, (double b, double c, double d) p)
        {
            foreach (CalcInfo item2 in MakeCalcs(p.b, (p.c, p.d)))
            {
                yield return new CalcInfo(item1, item2, EMode.加);
                yield return new CalcInfo(item1, item2, EMode.減);
                yield return new CalcInfo(item2, item1, EMode.減);
                yield return new CalcInfo(item1, item2, EMode.乘);
                yield return new CalcInfo(item1, item2, EMode.除);
                yield return new CalcInfo(item2, item1, EMode.除);
            }

            foreach (CalcInfo item2 in MakeCalcs(p.c, (p.b, p.d)))
            {
                yield return new CalcInfo(item1, item2, EMode.加);
                yield return new CalcInfo(item1, item2, EMode.減);
                yield return new CalcInfo(item2, item1, EMode.減);
                yield return new CalcInfo(item1, item2, EMode.乘);
                yield return new CalcInfo(item1, item2, EMode.除);
                yield return new CalcInfo(item2, item1, EMode.除);
            }

            foreach (CalcInfo item2 in MakeCalcs(p.d, (p.b, p.c)))
            {
                yield return new CalcInfo(item1, item2, EMode.加);
                yield return new CalcInfo(item1, item2, EMode.減);
                yield return new CalcInfo(item2, item1, EMode.減);
                yield return new CalcInfo(item1, item2, EMode.乘);
                yield return new CalcInfo(item1, item2, EMode.除);
                yield return new CalcInfo(item2, item1, EMode.除);
            }
        }

        private static IEnumerable<CalcInfo> MakeCalcs(double item1, (double c, double d) p)
        {
            foreach (CalcInfo item2 in MakeCalcs(p.c, p.d))
            {
                yield return new CalcInfo(item1, item2, EMode.加);
                yield return new CalcInfo(item1, item2, EMode.減);
                yield return new CalcInfo(item2, item1, EMode.減);
                yield return new CalcInfo(item1, item2, EMode.乘);
                yield return new CalcInfo(item1, item2, EMode.除);
                yield return new CalcInfo(item2, item1, EMode.除);
            }
        }

        private static IEnumerable<CalcInfo> MakeCalcs(double item1, double item2)
        {
            yield return new CalcInfo(item1, item2, EMode.加);
            yield return new CalcInfo(item1, item2, EMode.減);
            yield return new CalcInfo(item2, item1, EMode.減);
            yield return new CalcInfo(item1, item2, EMode.乘);
            yield return new CalcInfo(item1, item2, EMode.除);
            yield return new CalcInfo(item2, item1, EMode.除);
        }
    }

    public class CalcInfo
    {
        public CalcInfo Items1 { get; set; }
        public CalcInfo Items2 { get; set; }
        public EMode? Mode { get; set; }
        public double Result { get; set; }

        public CalcInfo(double value)
        {
            Result = value;
        }

        public CalcInfo(double value1, double value2, EMode mode) : this(new CalcInfo(value1), new CalcInfo(value2), mode)
        {
        }

        public CalcInfo(double value1, CalcInfo value2, EMode mode) : this(new CalcInfo(value1), value2, mode)
        {
        }

        public CalcInfo(CalcInfo value1, double value2, EMode mode) : this(value1, new CalcInfo(value2), mode)
        {
        }

        public CalcInfo(CalcInfo value1, CalcInfo value2, EMode mode)
        {
            Items1 = value1;
            Items2 = value2;
            Mode = mode;
        }

        public double GetResult()
        {
            if (Mode == null)
            {
                return Result;
            }

            var item1 = Items1.GetResult();
            var item2 = Items2.GetResult();
            if (double.IsNaN(item1) || double.IsNaN(item1))
            {
                return double.NaN;
            }

            switch (Mode.Value)
            {
                case EMode.加:
                    return item1 + item2;
                case EMode.減:
                    return item1 - item2;
                case EMode.乘:
                    return item1 * item2;
                case EMode.除:
                    if (item2 == 0)
                    {
                        return double.NaN;
                    }

                    return item1 / item2;
                default:
                    Debug.Assert(false);
                    break;
            }

            return double.NaN;
        }

        public string GetString()
        {
            if (Mode == null)
            {
                return Result.ToString();
            }

            switch (Mode.Value)
            {
                case EMode.加:
                    return $"({Items1.GetString()} + {Items2.GetString()})";
                case EMode.減:
                    return $"({Items1.GetString()} - {Items2.GetString()})";
                case EMode.乘:
                    return $"({Items1.GetString()} * {Items2.GetString()})";
                case EMode.除:
                    return $"({Items1.GetString()} / {Items2.GetString()})";
                default:
                    Debug.Assert(false);
                    break;
            }

            return null;
        }
    }

    public enum EMode
    {
        加,
        減,
        乘,
        除,
    }
}

 

源碼地址:https://gitee.com/wzwyc/Calc24Point


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM