わかりました、これは一種の一般的なプログラムです。ユーザーがコンピューター プレイヤーとやり取りできるポーカー プログラムを作成しようとしています。ただし、単純化するために、2 人のプレーヤーがコンピューターから数字を推測しようとする、はるかに単純なプログラムでテストしています。1 つは人間のプレーヤーで、もう 1 つはコンピューターのプレーヤーです。
ゲームでは、プレイヤーは順番に、プログラムによって設定された数字を推測します。コンピューター プレーヤーは数字をランダム化するだけで、ユーザーは数字を入力して推測ボタンを押す必要があります (または終了するオプションがあります)。
私の問題は、プレイヤーが行動するのが人間の場合、人間がボタンを押したりテキストを入力したりして応答するために、ゲームの実行を一時停止するにはどうすればよいですか?
タイマーを使用して開始し、スレッドが終了するのを待ってみましたが、それでもGUIがフリーズするようです。
また、バックグラウンド ワーカー スレッドからメッセージを送信して GUI を更新しようとしましたが、別のスレッドから GUI 要素にアクセスできないというエラーが表示されます。
これを実装する方法について何か提案はありますか?
これは完全なプログラムではないことに注意してください。これは、実行中に GUI と対話する方法を理解するために作成したものです。
数推測クラス:
public class NumberGuesser {
public Player HumanPlayer { get; private set; }
public Player ComputerPlayer { get; private set;}
private Player[] _players = new Player[2];
private int _maxNumber = 20;
private bool _done = false;
private Random random;
public NumberGuesser() {
HumanPlayer = new HumanPlayer("Me");
ComputerPlayer = new ComputerPlayer("HAL9000");
_players[0] = HumanPlayer;
_players[1] = ComputerPlayer;
random = new Random((int) DateTime.Now.Ticks);
}
public void Play() {
var myNumber = random.Next(_maxNumber);
var index = 0;
while (!_done) {
var currentPlayer = _players[index];
var guess = currentPlayer.Act(_maxNumber);
if (guess == myNumber) {
currentPlayer.Score++;
}
index = (1 + index)%2;
}
}
}
コンピューター プレーヤー:
public class ComputerPlayer : Player {
private readonly Random _random = new Random((int)DateTime.Now.Ticks);
public ComputerPlayer(string name) : base(name) {
}
public override int Act(int max) {
return _random.Next(max);
}
}
人間のプレイヤー:
public class HumanPlayer : Player {
public HumanPlayer(string name) : base(name) {
}
public override int Act(int max) {
return UserGuess();
}
private int UserGuess() {
return 0;
}
}
プレイヤークラス:
public class Player {
public string Name { get; private set; }
public int Score { get; set; }
public Player(string name) {
Name = name;
}
public virtual int Act(int max) {
// How should the human enter the guess here???
return 0;
}
}
私のメインウィンドウ:
<Window x:Class="GuessMyNumber.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="395" Width="728">
<Grid>
<Label Content="Guess my number!" Height="28" HorizontalAlignment="Left" Margin="122,58,0,0" Name="label1" VerticalAlignment="Top" />
<Grid Height="174" HorizontalAlignment="Left" Margin="31,170,0,0" Name="grid1" VerticalAlignment="Top" Width="272" DataContext="{Binding Path=HumanPlayer}">
<Label Content="Human player" Height="28" HorizontalAlignment="Left" Margin="6,6,0,0" Name="label2" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="55,92,0,0" Name="textBox1" VerticalAlignment="Top" Width="120"
Text="{Binding Path=HumanGuess, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="Guess" Height="23" HorizontalAlignment="Left" Margin="79,130,0,0" Name="button1" VerticalAlignment="Top" Width="75"
Command="{Binding Path=GuessCommand}"/>
<Label Content="{Binding Path=Name}" Height="28" HorizontalAlignment="Left" Margin="96,6,0,0" Name="label3" VerticalAlignment="Top" />
<Label Content="Score" Height="28" HorizontalAlignment="Left" Margin="6,40,0,0" Name="label4" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="55,42,0,0" Name="textBox2" VerticalAlignment="Top" Width="75" Text="{Binding Path=Score, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" />
<Button Content="Quit" Height="23" HorizontalAlignment="Left" Margin="182,130,0,0" Name="buttonQuit" VerticalAlignment="Top" Width="75" Command="{Binding Path=QuitCommand}" />
</Grid>
<Grid Height="174" HorizontalAlignment="Left" Margin="328,170,0,0" Name="grid2" VerticalAlignment="Top" Width="270" DataContext="{Binding Path=ComputerPlayer}" >
<Label Content="Computer player" Height="28" HorizontalAlignment="Left" Margin="6,6,0,0" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="55,92,0,0" VerticalAlignment="Top" Width="120" Text="{Binding Path=HumanGuess, UpdateSourceTrigger=PropertyChanged}"/>
<Label Content="{Binding Path=Name}" Height="28" HorizontalAlignment="Left" Margin="111,6,0,0" VerticalAlignment="Top" />
<Label Content="Score" Height="28" HorizontalAlignment="Left" Margin="6,40,0,0" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="55,42,0,0" VerticalAlignment="Top" Width="75" Text="{Binding Path=Score, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" />
</Grid>
<Button Content="Start Playing" Height="23" HorizontalAlignment="Left" Margin="254,59,0,0" Name="buttonStartPlay" VerticalAlignment="Top" Width="75" Click="buttonStartPlay_Click" />
</Grid>
そして背後にあるコード:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
private readonly NumberGuesser _numberGuesser;
public MainWindow() {
InitializeComponent();
_numberGuesser = new NumberGuesser();
DataContext = _numberGuesser;
}
private void buttonStartPlay_Click(object sender, RoutedEventArgs e) {
_numberGuesser.Play();
}
}