iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 23
0
Software Development

後端基礎PHP+Mysql & Laravel 30日養成計畫系列 第 23

Day 23 實做猜數字遊戲(三):產生答案及線索

  • 分享至 

  • xImage
  •  

玩家輸入猜的數字後會進入到這支程式,進行以下動作:
1.判斷是否已產生過正確答案(是否是第一次猜),若還未產生,呼叫judge的answer()來產生答案
2.判斷玩家輸入的數字是否符合格式(4位數),若不符合,會重刷頁面讓玩家再輸入一次
3.呼叫judge的check(),比對猜的數字與正解並生出線索後,將這些資料存進資料庫
4.若猜到正解,計算花費時間並跳轉到恭喜玩家猜中的頁面(correct.php)
guess.php

<?php
session_start();
include "db.php";
include "judge.php";
include "style.html";
	$guess = $_POST["subject"];
    $no = $_SESSION["no"] = $_POST["no"]; $sure = $_SESSION["sure"] = $_POST["sure"];
	$reg1 = $_SESSION["reg1"] = $_POST["reg1"]; $reg2 = $_SESSION["reg2"] = $_POST["reg2"]; $reg3 = $_SESSION["reg3"] = $_POST["reg3"]; $reg4 = $_SESSION["reg4"]  = $_POST["reg4"];
    $i = 0;
	while($i<10){
	    $i++;
    }

    $judge = new judge;
    if(!$_SESSION["answer"]){
        $ans = $_SESSION["answer"]= $judge->answer();
        $_SESSION["startTime"] = $startTime = date("H")*3600+date("i")*60+date("s");
    }else{
        $ans = $_SESSION["answer"];
    }

    if(strlen($guess) < 4 ){
        //若輸入數字少於4位數,回到主畫面再輸入一次
        header("location:main.php");
    }else{
        $hint = $judge->check($guess,$ans);
        $answer = implode($ans);
        $sql1 = "INSERT guess(guess, hint) VALUES ('$guess', '$hint')";
        if (!mysqli_query($db, $sql1)) {
            echo "insert error";
        }else if($hint == "Answer Correct"){ 
            //遊戲結束,計算花費時間
           $_SESSION["endTime"] = $endTime = date("H")*3600+date("i")*60+date("s");
            header("location:correct.php");
        }
        else{
            header("location:main.php");
        }
    }

implode()這個函式是用來把array轉成字串的,反過來要將字串拆解成array,可以用explode()。

產生答案和線索的程式:
judge.php

<?php
	class judge
    {
        public $MAX_LENGTH = 4;
        //產生答案
        function answer()
        {
                $i = 0;
                while ($i < $this->MAX_LENGTH) {
                    //隨機產生出0~9之間的數字
                    $ans[$i] = rand() % 10;
                    $i++;
                }
                return $ans;
        }
        //產生線索
        function check($guessString, $ans){
            $guess = str_split ( $guessString);
            $A = 0;
            $ans_appear_times[10] = array();
            $guess_appear_times[10] = array();
        //計算有幾個A
        for($i=0; $i< $this->MAX_LENGTH; $i++) {

            if($guess[$i] == $ans[$i]) {
                $A++;
            }
            else {
                $ans_appear_times[$ans[$i]]++;
                $guess_appear_times[$guess[$i]]++;
            }
        }
        //計算有幾個B(已排除計算過的A)
        $B = 0;
        for($i=0; $i<10; $i++) { 
            if($guess_appear_times[$i] >= $ans_appear_times[$i]) {
                $B += $ans_appear_times[$i];
            }
            else {
                $B += $guess_appear_times[$i];
            }
        }
        //若4位數都對,回傳'Answer Correct'
        if($A==$this->MAX_LENGTH && $B==0)	{
            return "Answer Correct";
        }

    $hint = $A."A".$B."B";

    return $hint;
        }
    }

產出線索的部份會先開出數字0~9,每個分別記錄正解和玩家猜的數字出現的次數。
計算A的概念很直覺,猜的位數和正解位數一致就加一,若不一樣,則該位數中正解和玩家猜的數字出現的次數各加一;
例如:正解為1212,玩家猜2284,
迴圈跑第一次時,$ans_appear_times[1]加一,$guess_appear_times[2]也加一。
迴圈跑第二次時,A加一,依此類推,總共會跑4次迴圈。
而計算B的概念則是根據計算完A後,此時已經計算完0~9在正解和玩家猜的數字中出現(排除A)的次數,
因此只要從[0~9]各跑一次去取$ans_appear_times[]或$guess_appear_times[]比較小的那個為B,
累加上去最後的總數就是B的總數了。
舉剛才的例子:
正解為1212,玩家猜2284,計算A的迴圈跑完後,
因為第二位數的2是A,因此不會被計算到appear_times的array中:
$ans_appear_times[1] = 2,
$guess_appear_times[2] = 1,
其餘為零。
$guess_appear_times[2] = 1,
$guess_appear_times[4] = 1,
$guess_appear_times[8] = 1,
其餘為零。
計算B的時候,$guess_appear_times[2] 等於 $guess_appear_times[2] 等於 1,因此B加一,其餘都是零。


上一篇
Day 22 實做猜數字遊戲(二):遊戲主畫面
下一篇
Day 24 實做猜數字遊戲(四):排行榜
系列文
後端基礎PHP+Mysql & Laravel 30日養成計畫36
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言