Загрузка данных
<Window x:Class="KeyboardTrainer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Клавиатурный тренажёр" Height="550" Width="1000"
WindowStartupLocation="CenterScreen"
KeyDown="Window_KeyDown">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Панель статистики -->
<Border Grid.Row="0" Margin="5" Padding="10" Background="#F0F0F0" CornerRadius="8">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Text="Скорость: " FontSize="18" FontWeight="Bold"/>
<TextBlock x:Name="SpeedText" Text="0" FontSize="18" FontWeight="Bold" Foreground="Green"/>
<TextBlock Text=" симв/мин" FontSize="18"/>
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Text="Ошибки: " FontSize="18" FontWeight="Bold"/>
<TextBlock x:Name="ErrorsText" Text="0" FontSize="18" FontWeight="Bold" Foreground="Red"/>
</StackPanel>
<StackPanel Grid.Column="2" Orientation="Horizontal">
<Button x:Name="StartButton" Content="Start" Width="80" Margin="5" Click="StartButton_Click"/>
<Button x:Name="StopButton" Content="Stop" Width="80" Margin="5" Click="StopButton_Click" IsEnabled="False"/>
<ComboBox x:Name="DifficultyCombo" Width="120" Margin="5" SelectedIndex="1">
<ComboBoxItem Content="Лёгкий (a-z)"/>
<ComboBoxItem Content="Средний (+Shift)"/>
<ComboBoxItem Content="Сложный (+цифры/знаки)"/>
</ComboBox>
</StackPanel>
</Grid>
</Border>
<!-- Строка для ввода -->
<Border Grid.Row="1" Margin="5" Padding="10" Background="#FFFACD" CornerRadius="8">
<StackPanel>
<TextBlock Text="Введите текст:" FontWeight="Bold" Margin="0,0,0,5"/>
<TextBlock x:Name="TargetTextBlock" Text="Нажмите Start" FontSize="16" FontFamily="Courier New" FontWeight="Bold" Margin="0,0,0,10"/>
<TextBox x:Name="InputTextBox" FontSize="16" FontFamily="Courier New" IsEnabled="False" KeyDown="InputTextBox_KeyDown"/>
</StackPanel>
</Border>
<!-- Клавиатура (ряды) -->
<StackPanel Grid.Row="2" Margin="5">
<!-- Ряд 1 -->
<WrapPanel Margin="0,2">
<Button x:Name="Key_Tab" Content="Tab" Width="60" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_Q" Content="Q" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_W" Content="W" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_E" Content="E" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_R" Content="R" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_T" Content="T" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_Y" Content="Y" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_U" Content="U" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_I" Content="I" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_O" Content="O" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_P" Content="P" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_BracketOpen" Content="[" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_BracketClose" Content="]" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
</WrapPanel>
<!-- Ряд 2 -->
<WrapPanel Margin="0,2">
<Button x:Name="Key_Caps" Content="Caps" Width="75" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_A" Content="A" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_S" Content="S" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_D" Content="D" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_F" Content="F" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_G" Content="G" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_H" Content="H" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_J" Content="J" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_K" Content="K" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_L" Content="L" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_Semicolon" Content=":" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_Quote" Content="'" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_Enter" Content="Enter" Width="80" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
</WrapPanel>
<!-- Ряд 3 -->
<WrapPanel Margin="0,2">
<Button x:Name="Key_ShiftLeft" Content="Shift" Width="85" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_Z" Content="Z" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_X" Content="X" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_C" Content="C" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_V" Content="V" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_B" Content="B" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_N" Content="N" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_M" Content="M" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_Less" Content="<" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_Greater" Content=">" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_Question" Content="?" Width="50" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
<Button x:Name="Key_ShiftRight" Content="Shift" Width="85" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
</WrapPanel>
<!-- Пробел -->
<WrapPanel Margin="0,2" HorizontalAlignment="Center">
<Button x:Name="Key_Space" Content="Space" Width="300" Height="50" Margin="2" Style="{StaticResource KeyButtonStyle}"/>
</WrapPanel>
</StackPanel>
</Grid>
</Window>
<Application x:Class="KeyboardTrainer.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style x:Key="KeyButtonStyle" TargetType="Button">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="BorderBrush" Value="Gray"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="4">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
</Style>
</Application.Resources>
</Application>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Threading;
using System.Windows.Threading;
namespace KeyboardTrainer
{
public partial class MainWindow : Window
{
private bool isTrainingActive = false;
private string targetText = "";
private int currentPosition = 0;
private int errorCount = 0;
private DateTime sessionStartTime;
private DispatcherTimer timer;
private Dictionary<Key, Button> keyMap;
public MainWindow()
{
InitializeComponent();
InitializeKeyMap();
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(0.5);
timer.Tick += Timer_Tick;
}
private void InitializeKeyMap()
{
keyMap = new Dictionary<Key, Button>
{
{ Key.Q, Key_Q }, { Key.W, Key_W }, { Key.E, Key_E }, { Key.R, Key_R },
{ Key.T, Key_T }, { Key.Y, Key_Y }, { Key.U, Key_U }, { Key.I, Key_I },
{ Key.O, Key_O }, { Key.P, Key_P }, { Key.A, Key_A }, { Key.S, Key_S },
{ Key.D, Key_D }, { Key.F, Key_F }, { Key.G, Key_G }, { Key.H, Key_H },
{ Key.J, Key_J }, { Key.K, Key_K }, { Key.L, Key_L }, { Key.Z, Key_Z },
{ Key.X, Key_X }, { Key.C, Key_C }, { Key.V, Key_V }, { Key.B, Key_B },
{ Key.N, Key_N }, { Key.M, Key_M }, { Key.Space, Key_Space },
{ Key.Enter, Key_Enter }, { Key.Tab, Key_Tab },
{ Key.LeftShift, Key_ShiftLeft }, { Key.RightShift, Key_ShiftRight }
};
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (!isTrainingActive) return;
HighlightKey(e.Key, Brushes.LightGreen);
if (e.Key == Key.Back)
{
if (currentPosition > 0)
{
currentPosition--;
errorCount = Math.Max(0, errorCount - 1);
UpdateErrors();
}
e.Handled = true;
return;
}
char pressed = GetCharFromKey(e.Key);
if (currentPosition < targetText.Length && pressed == targetText[currentPosition])
{
currentPosition++;
UpdateSpeed();
}
else
{
errorCount++;
UpdateErrors();
}
if (currentPosition == targetText.Length)
{
StopTraining();
MessageBox.Show("Поздравляем! Текст набран полностью.", "Отлично!");
}
}
private void HighlightKey(Key key, SolidColorBrush color)
{
if (keyMap.ContainsKey(key))
{
var btn = keyMap[key];
var original = btn.Background;
btn.Background = color;
var timer = new System.Timers.Timer(150);
timer.Elapsed += (s, e) => Dispatcher.Invoke(() => btn.Background = original);
timer.AutoReset = false;
timer.Start();
}
}
private char GetCharFromKey(Key key)
{
if (key == Key.Space) return ' ';
if (key == Key.Enter) return '\n';
string k = key.ToString();
if (k.Length == 1) return k[0];
return '\0';
}
private void UpdateSpeed()
{
double minutes = (DateTime.Now - sessionStartTime).TotalMinutes;
if (minutes <= 0) minutes = 0.01;
int speed = (int)(currentPosition / minutes);
SpeedText.Text = speed.ToString();
}
private void UpdateErrors()
{
ErrorsText.Text = errorCount.ToString();
}
private void Timer_Tick(object sender, EventArgs e)
{
UpdateSpeed();
}
private void StartButton_Click(object sender, RoutedEventArgs e)
{
StartTraining();
}
private void StopButton_Click(object sender, RoutedEventArgs e)
{
StopTraining();
}
private void StartTraining()
{
targetText = GenerateText();
TargetTextBlock.Text = targetText;
currentPosition = 0;
errorCount = 0;
sessionStartTime = DateTime.Now;
isTrainingActive = true;
InputTextBox.IsEnabled = true;
InputTextBox.Clear();
InputTextBox.Focus();
StartButton.IsEnabled = false;
StopButton.IsEnabled = true;
timer.Start();
UpdateErrors();
SpeedText.Text = "0";
}
private void StopTraining()
{
isTrainingActive = false;
InputTextBox.IsEnabled = false;
StartButton.IsEnabled = true;
StopButton.IsEnabled = false;
timer.Stop();
}
private string GenerateText()
{
var random = new Random();
int length = 30;
string chars = "";
int level = DifficultyCombo.SelectedIndex;
switch (level)
{
case 0: chars = "abcdefghijklmnopqrstuvwxyz "; break;
case 1: chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "; break;
case 2: chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.?!- "; break;
}
return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
}
private void InputTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (!isTrainingActive) return;
if (e.Key == Key.Back) return;
string currentInput = InputTextBox.Text;
if (currentInput.Length < targetText.Length && e.Key != Key.Enter)
{
e.Handled = true;
char pressed = GetCharFromKey(e.Key);
if (pressed != '\0')
{
InputTextBox.AppendText(pressed.ToString());
Window_KeyDown(sender, e);
}
}
else if (currentInput.Length >= targetText.Length)
{
StopTraining();
}
}
}
}