算24点小游戏

思路:

因为总共就4个数字,一般也只针对加减乘除运算,所以可以考虑遍历所有组合情况。

1、先取2个数分别做四种运算;

2、将第一步的结果和从剩下2个数字取1个做四种运算;

3、将第二步结果和剩下的1个数字做四种运算;

先将所有的排列组合结果求出来,再带上四种运算符求出所有可能的结果,如果结果等于24点,就是我们想要的组合;

<?php

class Twenyfour
{
    private $num = [];

    private $stepLogFirst = [];
    private $stepLogSecond = [];
    private $stepLogThrid = [];

    public function __construct($arr)
    {
        if (count($arr) != 4) {
            throw new RuntimeException("the given num is unavailable.");
        }
        array_walk($arr, function ($int) {
            if (!is_numeric($int) || $int < 0 || $int > 10) {
                throw new RuntimeException("the type of parameter must be integer and between 1 and 10.");
            }
        });
        $this->num = $arr;
    }

    public function run()
    {
        $allCombination = $this->getAllCombination();

        $expression = [];
        foreach ($allCombination as $sec) {
            $result = $this->recursionOperation($sec);
            if (in_array(24, $result)) {
                $expression = $this->parseLog();
            }
        }

        $uniqueResult = array_unique($expression);
        array_walk($uniqueResult, function ($exp) {
            preg_match_all("/[1-9]/", $exp, $res);

            sort($res[0]);
            sort($this->num);
            if ($res[0] == $this->num) {
                echo $exp . "\n";
            }
        });
    }

    function parseLog()
    {
        $expr = $expression = [];
        $firstKeys = $this->array_search_all(24, $this->stepLogThrid);
        foreach ($firstKeys as $values) {
            $secondPostfix = substr($values, -2);
            $second = substr($values, 0, -2);
            $secondKeys = $this->array_search_all($second, $this->stepLogSecond);

            foreach ($secondKeys as $value) {
                $thirdPostfix = substr($value, -2);
                $third = substr($value, 0, -2);
                $thirdKeys = $this->array_search_all($third, $this->stepLogFirst);
                $expr[$secondPostfix][$thirdPostfix] = $thirdKeys;

            }
        }

        foreach ($expr as $ke => $val) {
            foreach ($val as $k => $va) {
                foreach ($va as $v) {
                    $expression[] = "(($v)$k)$ke";
                }
            }
        }
        return $expression;
    }

    /*
     * search value return keys
     */
    function array_search_all($needle, $array):array
    {
        $keys = [];
        foreach ($array as $key => $value) {
            if ($value == $needle) {
                $keys[] = $key;
            }
        }
        return $keys;
    }

    /*
     * 获取4个数字所有组合情况
     */
    function getAllCombination()
    {
        $first = $this->first($this->num);
        $second = $this->second($first, $this->num);
        return $second;
    }

    /*
     * 数组相减
     */
    function array_subtract($arrayA, $arrayB)
    {
        foreach ($arrayB as $b) {
            $location = array_search($b, $arrayA);
            if ($location !== false) {
                unset($arrayA[$location]);
            }
        }
        return $arrayA;
    }

    function recursionOperation($array)
    {
        $result = [];
        if (count($array) > 1) {
            $first = array_shift($array);
            $second = array_shift($array);
            $third = array_shift($array);
            $fourth = array_shift($array);

            $middle = $this->operation($first, $second, $this->stepLogFirst);

            array_walk($middle, function ($fir) use ($third, &$result) {

                $result = array_merge($result, $this->operation($fir, $third, $this->stepLogSecond));
            });

            $middle = $result;
            array_walk($middle, function ($fir) use ($fourth, &$result) {
                $result = array_merge($result, $this->operation($fir, $fourth, $this->stepLogThrid));
            });
            return $result;
        } else {
            return $array;
        }
    }

    //递归不好记录日志
//    function recursionOperation($array)
//    {
//        $result = [];
//        if (count($array) > 1) {
//            $first = array_shift($array);
//            $second = array_shift($array);
//            if (is_array($first)) {
//                array_walk($first, function ($fir) use ($second, &$result) {
//                    $result = array_merge($result, $this->operation($fir, $second));
//                });
//            } else {
//                $result = $this->operation($first, $second);
//            }
//            array_unshift($array, $result);
//            return $this->recursionOperation($array);
//        } else {
//            return $array;
//        }
//    }

    /*
     * 第一步
     */
    function first($num)
    {
        return $this->c2($num);
    }

    /*
     * 第二步
     */
    function second($array, $rawArray)
    {
        $result = [];
        foreach ($array as $arr) {
            $diff = $this->array_subtract($rawArray, $arr);
            $result[] = array_merge($arr, $diff);
            $result[] = array_merge($arr, array_reverse($diff));
        }
        return $result;
    }

    /*
     * 一维数组中随机取2个元素
     */
    function c2($array)
    {
        if (count($array) < 3)
            return $array;
        $result = [];
        foreach ($array as $key => $arr) {
            foreach ($array as $k => $ar) {
                if ($key != $k) {
                    $sub = [$arr, $ar];
                    sort($sub);
                    if (!in_array($sub, $result)) {
                        $result[] = $sub;
                    }
                }

            }
        }
        return $result;
    }

    function operation($first, $second, &$log)
    {
        $result = [];
        $a = $first + $second;
        $b = $first - $second;
        $c = $first * $second;
        $d = $first / $second;
        $log["$first+$second"] = $a;
        $log["$first-$second"] = $b;
        $log["$first*$second"] = $c;
        $log["$first/$second"] = $d;
        array_push($result, $a, $b, $c, $d);
        return $result;
    }
}

try {
    $go = new Twentyfour([2, 7, 5, 1]);
    $go->run();

} catch (RuntimeException $e) {
    echo $e->getMessage();
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李昂的数字之旅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值