首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

使用 PHP 與 WinBinder 開發桌面應用程式:以 21 點遊戲為例

     編輯:PHP 相關知識

前言

PHP 不僅限於 Web 開發,配合 WinBinder 擴充套件,也能編寫原生 Windows 桌面應用程式。本文將透過一個經典的「21 點(Blackjack)」遊戲範例,展示如何使用 PHP 建立視窗、元件佈局、事件處理與遊戲邏輯。

環境需求

  • PHP 5.x 或以上版本
  • WinBinder 擴充套件(需啟用 php_winbinder.dll)
  • Windows 作業系統

程式架構說明

專案包含三個主要檔案:

  1. 21point.form.php:定義主視窗與所有 UI 元件(標籤、按鈕、框架等)的位置、大小與 ID。
  2. point_include.php:初始化撲克牌點數對照表、控制項 ID 常數定義。
  3. 21point.phpw:主程式進入點,載入表單與邏輯類別,啟動訊息迴圈。

核心程式碼解析

1. 視窗與元件建立(21point.form.php)

<?php
$winmain = wb_create_window(null, 'AppWindow', '21點遊戲', WBC_CENTER, WBC_CENTER, 800, 495, 0, 0);

// 建立標籤:莊家、玩家
wb_create_control($winmain, 'Label', '莊家', 20, 15, 40, 30, 'LB_1', 0, 0, 0);
wb_create_control($winmain, 'Label', '玩家', 20, 200, 40, 30, 'LB_2', 0, 0, 0);

// 建立撲克牌顯示框架(莊家 5 張、玩家 5 張)
for ($i = 1; $i <= 5; $i++) {
    wb_create_control($winmain, 'Frame', '', 80 + ($i-1)*140, 40, 120, 150, "FR_PC_$i", 0, 0, 0); // 莊家
    wb_create_control($winmain, 'Frame', '', 80 + ($i-1)*140, 230, 120, 150, "FR_U_$i", 0, 0, 0);  // 玩家
}

// 按鈕:發牌、停止
wb_create_control($winmain, 'PushButton', '發牌', 320, 400, 70, 25, 'B_GO', 0x00000002, 0, 0);
wb_create_control($winmain, 'PushButton', '停止', 435, 400, 70, 25, 'B_CHANGE', 0x00000002, 0, 0);
?>

2. 撲克牌點數與控制項 ID 定義(point_include.php)

<?php
// 產生 52 張撲克牌點數陣列
$card = [];
for ($i = 1; $i <= 13; $i++) {
    switch ($i) {
        case 1:  $j = 1;  $key = 'A'; break;
        case 11: $j = 10; $key = 'J'; break;
        case 12: $j = 10; $key = 'Q'; break;
        case 13: $j = 10; $key = 'K'; break;
        default: $key = $j = $i;
    }
    foreach (['黑桃', '紅心', '梅花', '方塊'] as $suit) {
        $card["$suit\n$key"] = $j;
    }
}

// 控制項 ID 對照表
$control_id = [
    'B_GO' => 1001, 'B_CHANGE' => 1002,
    'ME_START' => 2001, 'ME_REMON' => 2002, 'ME_AUTHOR' => 2003, 'ME_QUIT' => IDCLOSE,
    // ... 其餘標籤、框架 ID 略
];
foreach ($control_id as $key => $value) {
    if (!defined(strtoupper($key))) define(strtoupper($key), $value);
}
?>

3. 遊戲邏輯類別(21point.phpw 節錄)

class Ponit {
    private $user_point = 10000;
    private $pc_point   = 10000;
    private $card;
    private $player = 'user';
    private $new_term = false;

    public function __construct($winmain, $card) {
        // 從檔案讀取雙方積分
        list($this->user_point, $this->pc_point) = explode('|', file_get_contents('form/db.db'));
        $this->window = $winmain;
        $this->card   = $card;
        $this->prepare();
    }

    private function prepare() {
        // 設定圖示、選單、字型、初始積分顯示
        wb_set_image($this->window, 'form/hyper.ico');
        // 建立選單:開局、重計分、作者、退出
        wb_create_control($this->window, 'Menu', [ ... ]);
        wb_set_text(wb_get_control($this->window, U_MON), "$this->user_point 分");
        wb_set_text(wb_get_control($this->window, PC_MON), "$this->pc_point 分");
    }

    private function play() {
        static $card_tem = [], $i = 0, $j = 0, $user_total = 0, $pc_total = 0;

        if ($this->new_term) { // 新局初始化
            $card_tem = $this->card;
            $user_total = $pc_total = 0;
            $i = $j = 0;
            $this->new_term = false;
        }

        if ($this->player === 'user') { // 玩家抽牌
            $i++;
            $card_key = array_rand($card_tem);
            $card_val = $card_tem[$card_key];
            $user_total += $card_val;
            // 更新介面顯示
            wb_set_text(wb_get_control($this->window, LB_U_T), "$user_total 點");
            wb_set_text(wb_get_control($this->window, 5000+$i), $card_key);
            wb_set_text(wb_get_control($this->window, 3200+$i), $card_val);

            // 判斷勝負:5 張牌未爆或爆牌
            if ($i >= 5 && $user_total <= 21) { $this->total(20, 'U'); /* 詢問繼續 */ }
            elseif ($user_total > 21) { $this->total(20, 'P'); /* 詢問繼續 */ }
        } else { // 莊家抽牌(自動)
            $j++;
            $card_key = array_rand($card_tem);
            $card_val = $card_tem[$card_key];
            $pc_total += $card_val;
            wb_set_text(wb_get_control($this->window, LB_P_T), "$pc_total 點");
            wb_set_text(wb_get_control($this->window, 4000+$j), $card_key);
            wb_set_text(wb_get_control($this->window, 3100+$j), $card_val);

            // 莊家策略:未達 5 張且未爆則繼續抽牌(usleep 模擬思考)
            if ($j >= 5 && $pc_total <= 21) { $this->total(20, 'P'); /* 詢問繼續 */ }
            elseif ($pc_total > 21) { /* 比較點數判斷勝負 */ }
            else { usleep(800000); $this->play(); }
        }
        unset($card_tem[$card_key]);
    }

    // 積分結算與存檔
    private function total($num, $win) {
        static $u_tem, $p_tem;
        if (empty($u_tem) || $this->remon) { $u_tem = $this->user_point; $p_tem = $this->pc_point; $this->remon = false; }
        $win === 'U' ? ($u_tem += $num, $p_tem -= $num) : ($u_tem -= $num, $p_tem += $num);
        $this->user_point = $u_tem; $this->pc_point = $p_tem;
        wb_set_text(wb_get_control($this->window, U_MON), "$u_tem 分");
        wb_set_text(wb_get_control($this->window, PC_MON), "$p_tem 分");
        file_put_contents('form/db.db', "$u_tem|$p_tem");
    }
}

// 主程式進入點
$wbd = new Ponit($winmain, $card);
wb_set_handler($winmain, 'go_to');
wb_main_loop();

function go_to($window, $id) {
    global $wbd;
    $wbd->key_id = $id;
    return $wbd->main();
}
?>

執行方式

  1. 確認 PHP 已安裝 WinBinder 擴充套件。
  2. 將專案資料夾放置於任意目錄。
  3. 以命令列執行 php 21point.phpw 或直接雙擊 .phpw 檔案(需關聯 php-win.exe)。

總結

此範例展示了 PHP 結合 WinBinder 開發桌面 GUI 應用的完整流程:視窗建立、元件佈局、事件驅動、遊戲狀態管理與本地資料持久化。雖然 WinBinder 目前已較少維護,但對於快速原型開發、內部小工具或教學示範,PHP 桌面開發仍具備獨特優勢。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved