WPF 做一個超級簡單的 1024 數字接龍游戲

来源:https://www.cnblogs.com/lindexi/p/18264294
-Advertisement-
Play Games

官網:Git for Windows 點擊下載安裝。 右擊滑鼠會出現GUI和Bash 選擇git bash here 配置全局用戶名和郵箱(gitee) git config --global user.name "你的名字" git config --global user.email 你的郵箱 ...


這是一個我給自己做著玩的游戲,沒有什麼複雜的界面,就一些簡單的邏輯

游戲的規則十分簡單,那就是有多個列表。程式會給出一個數字,玩家決定數字放在哪個列表裡面。如果放入列表裡面的數字和列表裡面最後一個數字相同,那兩個數字將會疊加進行合併,合併兩個 1024 將會自動清理掉整個列表

如下圖,有 5 個列表。最右邊有一個數字。此時點擊列表下方的 "點擊" 按鈕,即表示將最右邊的數字放在這一列表中

如下圖,就是點擊了首個列表的“點擊”按鈕,將上圖的 1024 數字放在首個列表裡

如下圖,首個列表裡面的最後一個是 2 的數字,最右邊的數字也是 2 的數字,可以將其進行合併

如下圖,合併之後,首個列表的 2 將會和最右邊的數字 2 合併為 4 作為最後一個數字

規則介紹完了,接下來咱來開始開發咯。如果只是想玩這個簡單的游戲的伙伴,可以快速到本文末尾,找到本文的所有代碼的下載方法

如上面的界面圖,可以看到有多個列表,那不如每個列表就一個 UserControl 用戶控制項好了。這裡沒有什麼最佳實踐,這麼簡單的應用,想怎麼寫就怎麼寫就好了

我這裡都不想好好命名,直接就用 Whitman 工具隨機一個名為 CecaqemdarYefarqukeafai 的控制項名好了

在 CecaqemdarYefarqukeafai.xaml.cs 裡面存放一個 ObservableCollection<int> 集合,用來表示界面上每個列表裡面的數據,代碼如下

    public ObservableCollection<int> Collection { get; } = new ObservableCollection<int>();

在 CecaqemdarYefarqukeafai.xaml 的界面寫一個 ListView 進行綁定這個 Collection 屬性,代碼如下

        <ListView ItemsSource="{Binding ElementName=Root,Path=Collection}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding .}"></TextBlock>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

這裡我寫的綁定是 ElementName=Root 的方式,這是我的習慣使用方法。對於簡單沒有 MVVM 的模式下,可以將控制項自身當成自己的綁定源,這樣在控制項後臺代碼編寫的屬性就可以很方便進行綁定

具體的實現方法就是將用戶控制項自身加上 x:Name="Root" 屬性,加上之後的用戶控制項的代碼大概如下

<UserControl x:Class="BawjadurbaWurahuwa.CecaqemdarYefarqukeafai"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:BawjadurbaWurahuwa"
             mc:Ignorable="d" 
             x:Name="Root"
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        ... 忽略其他代碼
        <ListView ItemsSource="{Binding ElementName=Root,Path=Collection}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding .}"></TextBlock>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        ... 忽略其他代碼
    </Grid>
</UserControl>

如上圖界面,可以看到每個列表下方都有一個點擊按鈕。那就繼續修改 CecaqemdarYefarqukeafai.xaml 界面,加上一個按鈕,代碼如下

        <Button Margin="10,10,10,10" HorizontalAlignment="Center" Click="Button_OnClick">點擊</Button>

加上按鈕需要稍微修改一下佈局,修改一下 Grid 加上兩行,代碼如下

        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>

以上就配置了列表的地方有多少空間使用多少空間,配置下麵一行給按鈕使用,按鈕需要多少空間再給多少空間

修改之後的 CecaqemdarYefarqukeafai.xaml 的全部代碼如下

<UserControl x:Class="BawjadurbaWurahuwa.CecaqemdarYefarqukeafai"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:BawjadurbaWurahuwa"
             mc:Ignorable="d" 
             x:Name="Root"
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <ListView ItemsSource="{Binding ElementName=Root,Path=Collection}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding .}"></TextBlock>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <Button Grid.Row="1" Margin="10,10,10,10" HorizontalAlignment="Center" Click="Button_OnClick">點擊</Button>
    </Grid>
</UserControl>

可以看到實現非常簡單,即使不使用用戶控制項也是可以的

這裡的點擊按鈕需要將事件給到外面訂閱,編輯後臺 CecaqemdarYefarqukeafai.xaml.cs 代碼,實現按鈕點擊邏輯,代碼如下

    public event EventHandler<CecaqemdarYefarqukeafai>? Click;

    private void Button_OnClick(object sender, RoutedEventArgs e)
    {
        Click?.Invoke(this, this);
    }

如此即可在點擊按鈕的時候,觸發 Click 事件給到外面訂閱

修改之後的 CecaqemdarYefarqukeafai.xaml.cs 的全部代碼如下

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace BawjadurbaWurahuwa;

/// <summary>
/// CecaqemdarYefarqukeafai.xaml 的交互邏輯
/// </summary>
public partial class CecaqemdarYefarqukeafai : UserControl
{
    public CecaqemdarYefarqukeafai()
    {
        InitializeComponent();
    }

    public ObservableCollection<int> Collection { get; } = new ObservableCollection<int>();

    public event EventHandler<CecaqemdarYefarqukeafai>? Click;

    private void Button_OnClick(object sender, RoutedEventArgs e)
    {
        Click?.Invoke(this, this);
    }
}

回到主界面

主界面需要顯示 5 列,那就直接寫 5 個 CecaqemdarYefarqukeafai 控制項好了。如果數量更多的話,那可以試試寫一個 ListView 之類的控制項

如上圖,整個主界面可以分為 6 列,其中前面 5 列是 CecaqemdarYefarqukeafai 控制項,最後一列是一個文本,用來說明下一個數字

實現的 MainWindow.xaml 代碼如下

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <local:CecaqemdarYefarqukeafai Click="CecaqemdarYefarqukeafai_OnClick"/>
        <local:CecaqemdarYefarqukeafai Grid.Column="1" Click="CecaqemdarYefarqukeafai_OnClick"/>
        <local:CecaqemdarYefarqukeafai Grid.Column="2" Click="CecaqemdarYefarqukeafai_OnClick"/>
        <local:CecaqemdarYefarqukeafai Grid.Column="3" Click="CecaqemdarYefarqukeafai_OnClick"/>
        <local:CecaqemdarYefarqukeafai Grid.Column="4" Click="CecaqemdarYefarqukeafai_OnClick"/>

        <TextBlock x:Name="CurrentTextBlock" Grid.Column="5" HorizontalAlignment="Center"></TextBlock>
    </Grid>

也許有伙伴開始好奇了,為什麼上面代碼裡面的 5 個 CecaqemdarYefarqukeafai 的 Click 事件都是相同的方法,那方法內是如何區分點擊的是哪個列表的?答案是不需要區分,在 CecaqemdarYefarqukeafai 的定義事件的代碼裡面,就將列表控制項自身給傳遞進入了,如下麵代碼

public partial class CecaqemdarYefarqukeafai : UserControl
{
    ... // 忽略其他代碼

    public event EventHandler<CecaqemdarYefarqukeafai>? Click;

    ... // 忽略其他代碼
}

於是在 MainWindow.xaml.cs 後臺代碼實現方法裡面,就可以通過參數瞭解到當前點擊按鈕屬於哪個用戶控制項了

    private void CecaqemdarYefarqukeafai_OnClick(object? sender, CecaqemdarYefarqukeafai e)
    {
        ... // 忽略其他代碼
    }

為了方便拿到和表示當前最右側顯示的當前的數字,咱使用的是建立一個數組和一個索引的方式表示。如此即可實現後續進行隨機給一個數字的方法,也可以讓給出的數字一定在數組內。定義在 MainWindow.xaml.cs 的欄位代碼如下

    private int _index;

    private readonly int[] _list = new int[] { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2 };

那是否可以省略這個數組,沒錯,因為這些都是 2 的倍數,想要省略也是可以的。省略了這個數組,那就每次自己計算就好了。可不要覺得每次都重新計算速度很慢,對於現代 CPU 來說,你接近測試不出來這兩者的性能差異。但總之這個數組也很小,占用記憶體基本可以忽略,就隨大家想用什麼就用什麼咯

為什麼有時候數組很小我也會關註,有時候數組即使不小我也不會關註。這其實和業務有關係,在本文例子裡面的這個數組只有一次定義,且全局只有一個,那這個數組就這點空間,自然就可以忽略其占用記憶體了。但如果這個數組是需要每次都創建的,那這時候我可能會稍微考慮一下。如果這個數組是每次都需要創建的,且創建之後很難釋放,那才會考慮一下

回到點擊事件裡面,通過索引和數組即可拿到當前最右側的數字,代碼如下

    private void CecaqemdarYefarqukeafai_OnClick(object? sender, CecaqemdarYefarqukeafai e)
    {
        var number = _list[_index];

        ... // 忽略其他代碼
    }

將此數字加入到 CecaqemdarYefarqukeafai 的集合裡面,代碼如下

    private void CecaqemdarYefarqukeafai_OnClick(object? sender, CecaqemdarYefarqukeafai e)
    {
        var number = _list[_index];

        e.Collection.Add(number);

        ... // 忽略其他代碼
    }

如此就完成了點擊按鈕就將數字加到所點擊的一列的基礎邏輯了

根據游戲規則,如果列表裡面最後相鄰的兩個數字是相同的,則進行合併。接下來再寫一個方法,這個方法用於合併集合的數字,代碼如下

    private static void Clean(ObservableCollection<int> collection)
    {
        while (collection.Count > 1)
        {
            var n1 = collection[^1];
            var n2 = collection[^2];

            if (n1 == n2)
            {
                collection.RemoveAt(collection.Count - 1);
                collection.RemoveAt(collection.Count - 1);
                collection.Add(n1 + n2);
            }
            else
            {
                break;
            }
        }

        if (collection[^1] == 1024 * 2)
        {
            collection.Clear();
        }
    }

為了這個方法需要一個迴圈?這是因為如果最後的數字剛好是 4、2、2 的話,那就可以先對 2 和 2 進行合併,合併完成拿到的 4 再和 4 進行合併

合併的方法就是移除這兩個數字,再添加一個新的更大的數字

為什麼移除的時候都是使用 collection.RemoveAt(collection.Count - 1); 代碼移除,為什麼兩次移除都是相同的代碼?這是因為首先集合列表數組都是從 0 開始的,想象一下,一個只有元素的集合,想要移除最後一個元素,那下標是多少,沒錯就是 0 作為下標。因此 collection.Count - 1 表示的是最後一個元素。那為什麼調用兩次?這是因為第一次調用的時候,最後一個元素就被移除了。那原本倒數的第二個元素現在就成為倒數第一個元素了,自然再次移除最後一個元素就是移除掉原先的倒數第二個元素。舉個例子,假如你每次都是全班倒數第二,某天全班倒數第一退學了,那你是不是就成為全班倒數第一了

如何全部合併之後,最後一個數字是兩倍的 1024 則將列表清空。嗯,這裡的話,只去掉當前這個數也可以,這個看大家的規則

完成了 Clean 方法之後,嘗試調用一下,代碼如下

    private void CecaqemdarYefarqukeafai_OnClick(object? sender, CecaqemdarYefarqukeafai e)
    {
        var number = _list[_index];

        e.Collection.Add(number);

        Clean(e.Collection);

        ... // 忽略其他代碼
    }

如此就完成了將數字加入到所點擊的列表裡面,且如果數字和列表最後一個數字相同則進行合併

根據游戲的規則,此時咱就需要再生成最右側的新的數字了。如上文可以知道,最右側的數字是使用數組和索引表示的,那就是隨機生成一個在數組範圍內的索引就可以了。既可以降低難度,按照順序生成索引,如下麵代碼

    private void CecaqemdarYefarqukeafai_OnClick(object? sender, CecaqemdarYefarqukeafai e)
    {
        ... // 忽略其他代碼

        _index++;
        if (_index == _list.Length)
        {
            _index = 0;
        }

        ... // 忽略其他代碼
    }

也可以使用隨機數生成,代碼如下

    private void CecaqemdarYefarqukeafai_OnClick(object? sender, CecaqemdarYefarqukeafai e)
    {
        ... // 忽略其他代碼

        _index = Random.Shared.Next(_list.Length);

        ... // 忽略其他代碼
    }

生成完成之後,將結果設置到界面的 CurrentTextBlock 控制項裡面,如此即可在界面顯示

    private void CecaqemdarYefarqukeafai_OnClick(object? sender, CecaqemdarYefarqukeafai e)
    {
        ... // 忽略其他代碼
        CurrentTextBlock.Text = $"第 {_count} 次\r\n下一個 {_list[_index]}";
    }

上述的 _count 欄位這時一個類似游戲分數的作用,表示的是當前是第多少次,實現代碼如下

    private void CecaqemdarYefarqukeafai_OnClick(object? sender, CecaqemdarYefarqukeafai e)
    {
        _count++;
        ... // 忽略其他代碼
        CurrentTextBlock.Text = $"第 {_count} 次\r\n下一個 {_list[_index]}";
    }

    private int _count;

最後別忘了修改一下 MainWindow 構造函數,在其初始化時給最右側一個數字,代碼如下

    public MainWindow()
    {
        InitializeComponent();
        CurrentTextBlock.Text = _list[_index].ToString();
    }

如此即可完成簡單的實現邏輯,代碼大概如下

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        CurrentTextBlock.Text = _list[_index].ToString();
    }

    private void CecaqemdarYefarqukeafai_OnClick(object? sender, CecaqemdarYefarqukeafai e)
    {
        _count++;

        var number = _list[_index];

        e.Collection.Add(number);

        Clean(e.Collection);

        _index++;
        if (_index == _list.Length)
        {
            _index = 0;
        }
        CurrentTextBlock.Text = $"第 {_count} 次\r\n下一個 {_list[_index]}";
    }

    private static void Clean(ObservableCollection<int> collection)
    {
        while (collection.Count > 1)
        {
            var n1 = collection[^1];
            var n2 = collection[^2];

            if (n1 == n2)
            {
                collection.RemoveAt(collection.Count - 1);
                collection.RemoveAt(collection.Count - 1);
                collection.Add(n1 + n2);
            }
            else
            {
                break;
            }
        }

        if (collection[^1] == 1024 * 2)
        {
            collection.Clear();
        }
    }

    private int _index;
    private int _count;

    private readonly int[] _list = new int[] { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2 };
}

作為開發者,我玩著玩著就想著看程式自己玩,做成掛機游戲。於是再寫點演算法讓程式自己玩好了,實現代碼如下

    public MainWindow()
    {
        InitializeComponent();
        CurrentTextBlock.Text = _list[_index].ToString();

        Loaded += MainWindow_Loaded;
    }

    private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        while (Content is Grid grid)
        {
            var number = _list[_index];

            var maxValue = 1024;

            var cecaqemdarYefarqukeafai =
                grid.Children.OfType<CecaqemdarYefarqukeafai>()
                    .FirstOrDefault(t => t.Collection.Count > 0 && t.Collection[^1] == number);

            cecaqemdarYefarqukeafai ??= grid.Children.OfType<CecaqemdarYefarqukeafai>().Where(t => t.Collection.Count > 0 && t.Collection[^1] > number).MinBy(t => t.Collection[^1]);

            cecaqemdarYefarqukeafai ??= grid.Children.OfType<CecaqemdarYefarqukeafai>()
                .FirstOrDefault(t => t.Collection.Count == 0);

            cecaqemdarYefarqukeafai ??= grid.Children.OfType<CecaqemdarYefarqukeafai>().MinBy(t =>
            {
                if (t.Collection.Count > 0)
                {
                    var lastValue = t.Collection[^1];
                    if (lastValue > number)
                    {
                        return lastValue;
                    }
                    else
                    {
                        return maxValue;
                    }
                }

                return 0;
            });

            if (cecaqemdarYefarqukeafai is null)
            {
                continue;
            }

            cecaqemdarYefarqukeafai.Collection.Add(number);
            Clean(cecaqemdarYefarqukeafai.Collection);

            _index = Random.Shared.Next(_list.Length);
            _count++;
            CurrentTextBlock.Text = $"第 {_count} 次\r\n下一個 {_list[_index]}";

            await Task.Delay(300);
        }
    }

相信以上的邏輯大家看看也能明白,這是我隨意寫的簡單演算法,核心只是決定將數字放在哪個列表而已

完成之後的代碼如下

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace BawjadurbaWurahuwa;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        CurrentTextBlock.Text = _list[_index].ToString();

        Loaded += MainWindow_Loaded;
    }

    private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        while (Content is Grid grid)
        {
            var number = _list[_index];

            var maxValue = 1024;

            var cecaqemdarYefarqukeafai =
                grid.Children.OfType<CecaqemdarYefarqukeafai>()
                    .FirstOrDefault(t => t.Collection.Count > 0 && t.Collection[^1] == number);

            cecaqemdarYefarqukeafai ??= grid.Children.OfType<CecaqemdarYefarqukeafai>().Where(t => t.Collection.Count > 0 && t.Collection[^1] > number).MinBy(t => t.Collection[^1]);

            cecaqemdarYefarqukeafai ??= grid.Children.OfType<CecaqemdarYefarqukeafai>()
                .FirstOrDefault(t => t.Collection.Count == 0);

            cecaqemdarYefarqukeafai ??= grid.Children.OfType<CecaqemdarYefarqukeafai>().MinBy(t =>
            {
                if (t.Collection.Count > 0)
                {
                    var lastValue = t.Collection[^1];
                    if (lastValue > number)
                    {
                        return lastValue;
                    }
                    else
                    {
                        return maxValue;
                    }
                }

                return 0;
            });

            if (cecaqemdarYefarqukeafai is null)
            {
                continue;
            }

            cecaqemdarYefarqukeafai.Collection.Add(number);
            Clean(cecaqemdarYefarqukeafai.Collection);

            _index = Random.Shared.Next(_list.Length);
            _count++;
            CurrentTextBlock.Text = $"第 {_count} 次\r\n下一個 {_list[_index]}";

            await Task.Delay(300);


        }
    }

    private void CecaqemdarYefarqukeafai_OnClick(object? sender, CecaqemdarYefarqukeafai e)
    {
        _count++;

        var number = _list[_index];

        e.Collection.Add(number);

        Clean(e.Collection);

        _index++;
        if (_index == _list.Length)
        {
            _index = 0;
        }
        CurrentTextBlock.Text = $"第 {_count} 次\r\n下一個 {_list[_index]}";
    }

    private static void Clean(ObservableCollection<int> collection)
    {
        while (collection.Count > 1)
        {
            var n1 = collection[^1];
            var n2 = collection[^2];

            if (n1 == n2)
            {
                collection.RemoveAt(collection.Count - 1);
                collection.RemoveAt(collection.Count - 1);
                collection.Add(n1 + n2);
            }
            else
            {
                break;
            }
        }

        if (collection[^1] == 1024 * 2)
        {
            collection.Clear();
        }
    }

    private int _index;
    private int _count;

    private readonly int[] _list = new int[] { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2 };
}

本文以上代碼放在 githubgitee 上,可以使用如下命令行拉取代碼

先創建一個空文件夾,接著使用命令行 cd 命令進入此空文件夾,在命令行裡面輸入以下代碼,即可獲取到本文的代碼

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 243d50c0b94013e5beb782e384c98a7b6e3f629d

以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源。請在命令行繼續輸入以下代碼,將 gitee 源換成 github 源進行拉取代碼

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 243d50c0b94013e5beb782e384c98a7b6e3f629d

獲取代碼之後,進入 WPFDemo/BawjadurbaWurahuwa 文件夾,即可獲取到源代碼

進入文件夾之後使用 VisualStudio 2022 或更高版本的 VisualStudio 打開 BawjadurbaWurahuwa.sln 文件,然後試試按下 F5 進行構建且運行即可開始玩游戲

博客園博客只做備份,博客發佈就不再更新,如果想看最新博客,請訪問 https://blog.lindexi.com/

如圖片看不見,請在瀏覽器開啟不安全http內容相容

知識共用許可協議
本作品採用知識共用署名-非商業性使用-相同方式共用 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發佈,但務必保留文章署名[林德熙](https://www.cnblogs.com/lindexi)(包含鏈接:https://www.cnblogs.com/lindexi ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請與我[聯繫](mailto:[email protected])。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • SingleStringMathTex是Mobjects分類中用來顯示數學公式的class。manim中有3個可以用來顯示數學公式的class,還有兩個是MathTex和Tex,後續再介紹。 從SingleStringMathTex的名稱中也可以看出,它是用來顯示只有一行的簡單公式。SingleSt ...
  • 1 模型 來看兩種不同類型的模型--LLM 和聊天模型。然後,它將介紹如何使用提示模板來格式化這些模型的輸入,以及如何使用輸出解析器來處理輸出。 LangChain 中的語言模型有兩種類型: 1.1 Chat Models 聊天模型通常由 LLM 支持,但專門針對會話進行了調整。提供者 API 使用 ...
  • 今天我們還講講Consumer、Supplier、Predicate、Function這幾個介面的用法,在 Java8 的用法當中,這幾個介面雖然沒有明目張膽的使用,但是,卻是潤物細無聲的。為什麼這麼說呢?這幾個介面都在 java.util.function 包下的,分別是Consumer(消費型) ...
  • pip install --upgrade langchain==0.0.279 -i https://pypi.org/simple 1 創建一個LLM 自有算力平臺+開源大模型(需要有龐大的GPU資源)企業自己訓練數據 第三方大模型API(openai/百度文心/阿裡通義千問...)數據無所謂 ...
  • LLM大模型與AI應用的粘合劑。 1 langchain是什麼以及發展過程 LangChain是一個開源框架,旨在簡化使用大型語言模型構建端到端應用程式的過程,也是ReAct(reason+act)論文的落地實現。 2022年10月25日開源 54K+ star 種子輪一周1000萬美金,A輪250 ...
  • 1.創建一個文件夾HCJV_01 2.vscode打開該文件夾,打開終端。 3.使用vite安裝,選擇vue,選擇JavaScript,項目名稱demo01 cnpm create vite@latest 4.跳轉demo01目錄下 cd demo01 5.安裝cnpm cnpm install 嘗 ...
  • 下麵將完成的展示,使用MAPI介面操作Outlook完成通訊錄更新。 using Microsoft.Office.Interop.Outlook; using Microsoft.VisualBasic; using System; using System.Collections; using ...
  • 前言 之前已經分享過幾篇關於中台項目框架的文章,相關介紹就不再贅述 所謂工欲善其事必先利其器,一個項目擁有一個代碼生成器是很有必要的,能夠大大的節省時間,減少手誤,提供開發效率(ps:特別小團隊搞微服務但是沒有代碼生成器,簡直要了老命) 本文將分享如何在中台框架項目 Admin.Core 中添加代碼 ...
一周排行
    -Advertisement-
    Play Games
  • 一:背景 1. 講故事 前些天有位朋友找到我,說他們的程式會偶發性的卡死一段時間,然後又好了,讓我幫忙看下怎麼回事?窗體類的程式解決起來相對來說比較簡單,讓朋友用procdump自動抓一個卡死時的dump,拿到dump之後,上 windbg 說話。 二:WinDbg 分析 1. 主線程在做什麼 要想 ...
  • 功能說明 使用ListView時,希望可以在單元格顯示圖片或其他控制項,發現原生的ListView不支持,於是通過拓展,實現ListView可以顯示任意控制項的功能,效果如下: 實現方法 本來想著在單元格裡面實現控制項的自繪的,但是沒找到辦法,最後是通過在單元格的錶面顯示對應控制項的,浮於錶面達到目的。 實 ...
  • 由於.NET Framework 4.0 是比較古老的版本,只有New Relic 7.0以下的版本才會支持.NET Framework 4.0的引用程式。 Technical support for .NET Framework 4.0 or lower 你可以參考這個官方Install New ...
  • 前言 隨著 DEV24.1.3 的發佈,XAF Blazor 中的屬性編輯器(PropertyEditor)也進行了很大的改動,在使用體驗上也更接近 WinForm 了,由於進行了大量的封裝,理解上沒有 WinForm 直觀,所以本文通過對屬性編輯器的原理進行解析,並對比新舊版本中的變化,使大家能夠 ...
  • OPC基金會提供了OPC UA .NET標準庫以及示常式序,但官方文檔過於簡單,光看官方文檔和示常式序很難弄懂OPC UA .NET標準庫怎麼用,花了不少時間摸索才略微弄懂如何使用,以下記錄如何從一個控制台程式開發一個OPC UA伺服器。 安裝Nuget包 安裝OPCFoundation.NetSt ...
  • 今天在技術群里,石頭哥向大家提了個問題:"如何在一個以System身份運行的.NET程式(Windows Services)中,以其它活動的用戶身份啟動可互動式進程(桌面應用程式、控制台程式、等帶有UI和互動式體驗的程式)"? 我以前有過類似的需求,是在GitLab流水線中運行帶有UI的自動化測試程 ...
  • .Net 中提供了一系列的管理對象集合的類型,數組、可變列表、字典等。從類型安全上集合分為兩類,泛型集合 和 非泛型集合,傳統的非泛型集合存儲為Object,需要類型轉。而泛型集合提供了更好的性能、編譯時類型安全,推薦使用。 ...
  • 在以前我做程式的時候,一般在登錄視窗裡面顯示程式名稱,登錄視窗一般設置一張背景圖片,由於程式的名稱一般都是確定的,所以也不存在太大的問題,不過如果客戶定製不同的系統的時候,需要使用Photoshop修改下圖層的文字,再生成圖片,然後替換一下也可以了。不過本著減少客戶使用繁瑣性,也可以使用空白名稱的通... ...
  • 一:背景 1. 講故事 在dump分析的過程中經常會看到很多線程卡在Monitor.Wait方法上,曾經也有不少人問我為什麼用 !syncblk 看不到 Monitor.Wait 上的鎖信息,剛好昨天有時間我就來研究一下。 二:Monitor.Wait 底層怎麼玩的 1. 案例演示 為了方便講述,先 ...
  • 目錄前言學習參考過程總結: 前言 做個自由仔。 學習參考 ChatGpt; https://www.cnblogs.com/zhili/p/DesignPatternSummery.html(大佬的,看了好多次) 過程 原由: 一開始只是想查查鏈式調用原理,以為是要繼承什麼介面,實現什麼方法才可以實 ...