Научная статья на тему 'РАЗРАБОТКА ИГРОВОГО ПРИЛОЖЕНИЯ КРЕСТИКИ - НОЛИКИ НА ЯЗЫКЕ ПРОГРАММИРОВАНИЯ С#'

РАЗРАБОТКА ИГРОВОГО ПРИЛОЖЕНИЯ КРЕСТИКИ - НОЛИКИ НА ЯЗЫКЕ ПРОГРАММИРОВАНИЯ С# Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
300
23
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
ПРИЛОЖЕНИЕ / КРЕСТИКИ-НОЛИКИ / С# / ПРОГРАММИРОВАНИЕ / APPLICATION / TIC-TAC-TOE / C # / PROGRAMMING

Аннотация научной статьи по компьютерным и информационным наукам, автор научной работы — Федотов В.А.

Статья посвящена разработке игрового приложения крестики - нолики на языке программирования с#.

i Надоели баннеры? Вы всегда можете отключить рекламу.
iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

DEVELOPMENT OF THE GAME APPLICATION TIC-TAC-TOE IN C # PROGRAMMING LANGUAGE

The article is devoted to the development of the game application tic-tac-toe in the programming language C #.

Текст научной работы на тему «РАЗРАБОТКА ИГРОВОГО ПРИЛОЖЕНИЯ КРЕСТИКИ - НОЛИКИ НА ЯЗЫКЕ ПРОГРАММИРОВАНИЯ С#»

УДК 004

Федотов В.А. студент 2 курса

факультет «Информационные системы и технологии» Северный Арктический федеральный университет Высшая школа информационных технологий и

автоматизированных систем Россия, г. Архангельск РАЗРАБОТКА ИГРОВОГО ПРИЛОЖЕНИЯ КРЕСТИКИ - НОЛИКИ НА ЯЗЫКЕ ПРОГРАММИРОВАНИЯ С# Аннотация: Статья посвящена разработке игрового приложения крестики - нолики на языке программирования с#.

Ключевые слова: Приложение, крестики-нолики, с#, программирование.

Fedotov V.A.

student, 2year, faculty "Information Systems and Technology" Northern Arctic Federal University, Graduate School of Information

Technology and Automated Systems Russia, Arkhangelsk DEVELOPMENT OF THE GAME APPLICATION TIC-TAC-TOE IN C # PROGRAMMING LANGUAGE Annotation: The article is devoted to the development of the game application tic-tac-toe in the programming language C #.

Keywords: Application, tic-tac-toe, c #, programming.

1 РЕАЛИЗАЦИЯ

Язык C# является наиболее известной новинкой в области создания языков программирования. По сути, это язык программирования, созданный уже в 21-м веке. Явившись на свет в недрах Microsoft, он с первых своих шагов получил мощную поддержку. Язык признан международным сообществом.

Первым делом для реализации игры крестики-нолики нужно создать игровое поле размером 3*3, используя массив массивов, в соответствии с

рисунком 1._

private int n = 3; //Размер игрового поля public Cell[][] Map { get; } //Обозначение массива

public TicTacToeModel() //Создается массив массивов {

Map = Enumerable.Range(0, n) //Создание входной последовательности

.Select(i => Enumerable.Range(0, n) .Select(j => new Cell()) .ToArrayO) .ToArray();

}_

Рисунок 1 - Код для создания поля массива

Далее создаем новый класс Cell, в котором создаем метод State для получения одного из состояний ячейки, в соответствии с рисунком 2._

public class Cell : INotifyPropertyChanged {

public State State {get; private set;} = State.None; }_

Рисунок 2 - Состояние ячейки

Затем создаем новый метод enum для получения одного из трех (None,

X, O) состояний ячейки, в соответствии с рисунком 3._

public enum State {None, X, O}

Рисунок 3 - Получение информации о трех возможных состояниях клетки

Потом в Model.cs создаем метод, который позволяет сделать ход пользователю, в соответствии с рисунком 4._

public WinPlayer Switch(Cell cell) //Ход Х {

var state = step++ % 2 == t ? State.X : State.O; cell.SwitchTo(state); return WinTest() ? state == State.X ? WinPlayer.Player_X : WinPlayer.Player_O : step == 9 ? WinPlayer.Standoff : WinPlayer.Unknown; Рисунок 4 - Ход пользователя

Далее также в Model.cs создаем новый метод, который делает ход за компьютер, в соответствии с рисунком 5._

public WinPlayer RandomStep() //Рандомный ход компьютера 0 {

var k = rnd.Next(9 - step)+1; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if (Map[i][j].State == State.None && --k == 0) return Switch(Map[i][j]);

return WinPlayer.Standoff;

}_

Рисунок 5 - Ход компьютера

Дальше создаем новый метод WinTest(), который проверяет победную

стратегию крестика или нолика, в соответствии с рисунком 6._

public bool WinTest() //Проверка победы крестика или нолика

{

bool[] rows = { true, true, true }; for (int i = 0; i < n; i++) for (int j = 1; j < n; j++) rows[i] &= Map[i][j].State != State.None && Map[i][j].State == Map[i][0].State;

bool[] cols = { true, true, true }; for (int j = 0; j < n; j++) for (int i = 1; i < n; i++) cols[j] &= Map[i][j].State != State.None && Map[i][j].State == Map[0][j].State;

bool mainD = Map[0][0].State != State.None && Map[0][0].State == Map[1][1].State && Map[0][0].State == Map[2][2].State;

bool collateralD = Map[2][0].State != State.None && Map[2][0].State == Map[1][1].State && Map[2][0].State == Map[0][2].State;

return rows.Any(x=>x) || cols.Any(x => x) || mainD || collateralD;

}_

Рисунок 6 - Проверка победной стратегии

Далее создаем новый метод X_or_0, который дает возможность

пользователю выбирать за кого играть, в соответствии с рисунком 7._

public void X_or_0(int newT=> t = newT; //Переключение между X и 0 Рисунок 7 - Выбор крестика или нолика

Далее создаем новый метод Message для вывода сообщения о победе крестика или нолика, или ничьей, в соответствии с рисунком 8._

public string Message //Вывод сообщения о победе {

get => message;

set

{

message = value;

MessageVisibility = (value == "") ? Visibility.Collapsed : Visibility.Visible;

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs (nameof(MessageVisibility)));

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs (nameof(Message)));

}

}

public Visibility MessageVisibility { get; private set; } =

Visibility.Collapsed; Рисунок 8 - Сообщение о победе или ничьей

Для перезапуска игры создаем новый метод NewGame(), в соответствии с рисунком 9._

public void NewGame() //Новая игра {

for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) Map[i][j].SwitchTo(State.None); step = 0; Message = "";

}_

Рисунок 9 - Метод для новой игры

Для подсчета времени, сколько длится игра, можно установить таймер, который будет останавливаться после выигрыша крестика или нолика и обнуляться после каждого перезапуска игры. Для этого в Xaml.cs создадим новый метод Dt Tick, в соответствии с рисунком 10._

private void Dt_Tick(object sender, EventArgs e) // Таймер {

tblTimer.Text = (DateTime.Now -

startTime).TotalSeconds.ToString("F1");

}_

Рисунок 10 - Таймер 2 ИНТЕРФЕЙС

При запуске данного проекта «Крестики - нолики» запускается стартовое окно, которое имеет вид, в соответствии с рисунком 11.

Рисунок 11 - Стартовое окно

Настройки окна имеют вид, в соответствии с рисунком 12._

TexЮptюш.TextFormattmgMode-,Display" MinWidth="450" MinHeight="450" Width="400" Height="400" ^Мй^'^ЛЬ" ShowInTaskbar="True" Margin="2" Foreground="{x:Null}"> <Window.Background> <ImageBrush ImageSource="Image/FON.jpg"/> </Window.Background> <Grid>

<Button x:Name="button1" Width="250" Height="50" Content="New

Game"

Qick="button1_Qick" //Кнопка «NewGame» на стартовом окне HorizontalAlignment="Center" //Выравнивание по горизонтали VerticalAlignment="Center" //Выравнивание по вертикали FontSize="36" //Размер шрифта 0pacity="0.8" //Прозрачность Foreground="MidnightBlue" //Цвет текста Background="MintCream" //Цвет кнопки BorderBrush="{x:Null}" //Отсутствие рамки кнопки FontWeight="Bold" //Начертание текста - полужирный FontFamily="Peace Sans"> //Шрифт текста </Button> </Grid>

Рисунок 12 - Настройки окна

При нажатии на кнопку «NewGame» выполняется переход уже на игровое окно, в котором находится игровое поле, а также кнопки выбора игры за X или 0, кнопки рестарт, выхода и вернуться назад на стартовое окно.

Игровое окно имеет вид, в соответствии с рисунком 13.

* "Пс-Тас-Тае — □ X

Рисунок 13 - Игровое окно

_Оформление окна имеет код, в соответствии с рисунком 14._

TexЮptюш.TextFormattmgMode-,Display" MmWidth="450" MinHeight="450" Width="500" Height="550" ^Мй^'^ЛЬ" ShowInTaskbar="True" Margin="2"> <Window.Background> <ImageBrush ImageSource="Image/FON12.jpg"/> </Window.Background> Рисунок 14 - Оформление окна

При нажатии на игровое поле, появляется крестик или нолик, в соответствии с тем, кого выбрал игрок, как изображено на рисунке 15.

I "Пс-Тас-Тое -ОХ

Рисунок 15 - Изображения крестика и нолика

Сами изображения крестика или нолика реализуются, в соответствии с

рисунком 16 и рисунком 17._

<DataTemplate x:Key-,dtState.X">

<Image Source="Image/Cross.png" Opacity="1"> <Image.Triggers> <EventTrigger RoutedEvent-,Image.Loaded"> <BeginStoryboard> <Storyboard>

<DoubleAnimation Storyboard.TargetProperty="Opacity"

From="1"

^="1" Duration="0:0:0.2"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Image.Triggers> </Image> </Grid> </DataTemplate>

Рисунок 16 - Реализация крестика

<DataTemplate x:Key-,dtState.O"> <Grid>

<Image Source="Image/Cross1.png" Opacity="1"> <Image.Triggers> <EventTrigger RoutedEvent="Image.Loaded"> <BeginStoryboard> <Storyboard>

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

<DoubleAnimation Storyboard.TargetProperty="Opacity"

From="1"

^="1" Duration="0:0:0.2" BeginTime="0:0:0.2"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Image.Triggers> </Image> </Grid> </DataTemplate> Рисунок 17 - Реализация нолика

Кнопка рестарт, которая перезапускает игру, используя метод

NewGame(), имеет код, изображенный на рисунке 18._

^ШЬП x:Name="button1" Width="120" Height="40" Content="Restart" aick="button1_aick" Margin="10,10,365,470" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="28" Foreground="White" BorderBrush="{x:Null}" Background="{x:Null}" FontWeight="Bold" FontFamily="Peace Sans">

</Button>_

Рисунок 18 - Кнопка рестарт

Кнопка Р1ауегХ дает возможность выбора играть за крестик. Кнопка

имеет код, изображенный на рисунке 19._

^ШЬП x:Name="button3" Width="110" Height="40" Content="Player X" aick="button3_aick" Margin="-40,45,330,435" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="22" Foreground="White" BorderBrush="{x:Null}" Background="{x:Null}" FontWeight="Bold" FontFamily="Peace Sans">

</Button>_

Рисунок 19 - Кнопка PlayerX

Кнопка Р1ауег0 дает возможность выбора играть за нолик. Кнопка имеет

код, изображенный на рисунке 20._

^ШЬП x:Name="button4" Width="110" Height="40" Content="Player 0" Qick="button4_Qick" Margin="60,45,190,435" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="22" Foreground="White" BorderBrush="{x:Null}" Background="{x:Null}" FontWeight="Bold" FontFamily="Peace Sans">

</Button>_

Рисунок 20 - Кнопка Player0

_Кнопка Exit закрывает приложение. Код изображен на рисунке 21._

<Button x:Name-"button2" Width="120" Height-40" Content-'Exit" Click="button2_Click" Margin="340,460,40,20" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="28" Foreground="White" BorderBrush="{x:Null}" Background="{x:Null}" FontWeight="Bold" FontFamily-"Peace Sans">

</Button>_

Рисунок 21 - Кнопка Exit

Для связывания Cell[][] Map (Создание поля) из model.cs с MainWindow.xaml в MainWindow.xaml используется код, изображенный на

рисунке 22._

<ItemsControl ItemsSource="{Binding Map}" HorizontalAlignment-'Center" VerticalAlignment="Center"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel>

<ItemsControl.ItemTemplate> <DataTemplate> <ItemsControl ItemsSource="{Binding}"> <ItemsControl.ItemTemplate> <DataTemplate> <Border Background="#FAFAD2" MouseDown="Cell_MouseDown" CornerRadius="20" 0pacity="0.8" Width="100" Height="100" Margin-'1" Padding="15"> <ContentControl Content-"{Binding State}" ContentTemplateSelector-"{StaticResource dtCell}"/> </Border> </DataTemplate>

</ItemsControl.ItemTemplate> </ItemsControl> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> Рисунок 22 - Отображение игрового поля

Далее для отображения надписи о выигрыше крестика или нолика, или

ничьей для связи используется код, изображенный на рисунке 23._

<Border Visibility-'{Binding MessageVisibility}" HorizontalAlignment="Center" VerticalAlignment="Center" MouseDown="Message_MouseDown" > <Border.Background> <ImageBrush/> </Border.Background> <TextBlock Text="{Binding Message}" Width="500" Height="320" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" FontSize="56" Foreground="MintCream" FontWeight="Bold"> <TextBlock.BitmapEffect> <DropShadowBitmapEffect/> </TextBlock.BitmapEffect> </TextBlock> </Border>

Рисунок 23 - Отображение надписи выигрыша/ничьей

Для визуального отображения таймера используем код, изображенный

на рисунке 24._

<TextBlock Name="tblTimer" HorizontalAlignment="Right" VerticalAlignment="Top" FontSize="20" Width="30" Height="30"

Margin="10"/>_

Рисунок 24 - Таймер 3 тестирование

Тестирование происходило в два этапа. Для начала проверялся разработанный функционал игры, соответственно на работоспособность кода, кнопок, алгоритма программы. Во втором этапе тестирования проверялся

интерфейс, который должен быть доступен и понятен каждому.

Таким образом, в процессе тестирования, сопровождающимся процессом разработки, на начальном этапе разработки удалось устранить недостатки и усовершенствовать приложение.

заключение

Программа предоставляет возможность играть с компьютером, который действует согласно созданному алгоритму. В приложении учтены моменты, позволяющие пользователю легко освоить программу, для этого необходимо создать удобный и простой интерфейс, который является «визитной карточкой» приложения. В приложение можно внести некоторые доработки, например, добавить «интеллект» для хода компьютера.

Использованные источники:

1. Барков, И.А. Объектно-ориентированное программирование : учебник / И.А. Барков. — Санкт-Петербург : Лань, 2019. — 700 с. — ISBN 978-5-81143586-9. — Текст : электронный // Электронно-библиотечная система «Лань» : [сайт]. — URL: https://elanbook.com/book/119661 (дата обращения: 28.08.2019). — Режим доступа: для авториз. пользователей.

2. Залогова, Л.А. Основы объектно-ориентированного программирования на базе языка С# : учебное пособие / Л.А. Залогова. — Санкт-Петербург : Лань, 2018. — 192 с. — ISBN 978-5-8114-3093-2. — Текст : электронный // Электронно-библиотечная система «Лань» : [сайт]. — URL: https://e.lanbook.com/book/106731 (дата обращения: 28.08.2019). — Режим доступа: для авториз. пользователей.

Приложение А (Обязательное) Исходный код Windowl.xaml <Window x:Class="TicTacToe.Window1" xmlns-"http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microso^.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns: mc="http: //schemas .openxmlformats. org/markup-compatibility/2006"

xmlns: local-'clr-namespace: TicTacToe"

mc:Ignorable="d"

Title-'Windowl"

TextOptions.TextFormattingMode="Display" MinWidth-"450" MinHeight-"450" Width-"450" Height-"400" Visibility-"Visible" ShowInTaskbar-"True" Margin-"2" Foreground-"{x:Null}"> <Window.Background> <ImageBrush ImageSource-"Image/FON.jpg"/> </Window.Background>

<Grid>

<Button x:Name-"button1" Width-"250" Height-"50" Content-"New Game" Click-"button1_Click"

HorizontalAlignment-"Center" VerticalAlignment-"Center" FontSize-"36" 0pacity-"0.8"

Foreground-"MidnightBlue" Background-"MintCream" BorderBrush-"{x:Null}" FontWeight-"Bold" FontFamily-"Peace Sans"> </Button> </Grid> </Window>

Приложение Б (Обязательное) Исходный код Window1.xaml.cs using System.Windows; namespace TicTacTo { public partial class Window1 : Window { public Window1(){ InitializeComponent();

}

private void button1_Click(object sender, RoutedEventArgs e){ MainWindow taskWindow - new MainWindow(); taskWindow.Show();

Close(); }

}

}

Приложение В (Обязательное) Исходный код MainWindow.xaml <Window x:Qass=,TicTacToe.MainWindow" xmlns=мhttp://schemas.microsoft.com/winfx/2006/xaml/presentationм xmlns:x=мhttp://schemas.microsoft.com/winfX/2006/xaml" xmlns:d=мhttp://schemas.microsoft.com/expression/blend/2008м xmlns: mc=мhttp: //schemas .openxmlformats. org/markup-compatibility/2006м

xmlns: local="clr-namespace: TicTacToe"

mc:Ignorable=мdм

Title="Tic-Tac-Toe"

TextOptions.TextFormattingMode=мDisplayм MinWidth=м450м MinHeight=м450м Width=м500м Height="550" Visibility="Visible" ShowInTaskbar=мTrueм Margin=м2м> <Window.Background>

<ImageBrush ImageSource=мImage/FON12.jpgм/> </Window.Background>

<Window.Resources> <local:CellDataTemplateSelector x:Key=мdtCellм/> <DataTemplate x:Key=мdtState.Xм> <Grid>

<Image Source="Image/Cross.png" Opacity=м1м> <Image.Triggers> <EventTrigger RoutedEvent=мImage.Loadedм> <BeginStoryboard> <Storyboard>

<DoubleAnimation Storyboard.TargetProperty=мOpacityм From="0" ^="1" Duration=м0:0:0.2м/> </Storyboard> </BeginStoryboard> </EventTrigger> </Image.Triggers>

</Image> </Grid> </DataTemplate>

<DataTemplate x:Key="dtState.O"> <Grid>

<Image Source=мImage/Тaught.pngм Opacity=м1м> <Image.Triggers> <EventTrigger RoutedEvent="Image.Loaded"> <BeginStoryboard>

<Storyboard>

<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" То="1" Duration="0:0:0.2" BeginTime="0:0:0.2"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Image.Triggers> </Image> </Grid> </DataTemplate> <DataTemplate x:Key="dtState.None"/> </Window.Resources> <Grid>

<Button x:Name="button1" Width="120" Height="40" Content="Restart" aick="button1_aick" Margin="10,10,365,470" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="28" Foreground="White" BorderBrush="{x:Null}" Background="{x:Null}" FontWeight="Bold" FontFamily="Peace Sans"> </Button>

<Ви«оп x:Name="button2" Width="120" Height="40" Content="Exit" СНск="Ьи«оп2_СНск"

Margin="340,460,40,20" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="28" Foreground="White" BorderBrush="{x:Null}" Background="{x:Null}" FontWeight="Bold" FontFamily="Peace Sans"> </Button>

<Button x:Name="button3" Width="110" Height="40" Content="Player X" Click="button3_aick"

Margin="-40,45,330,435" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="22" Foreground="White"

BorderBmsh="{x:Null}" Background="{x:Null}" FontWeight="Bold" FontFamily="Peace Sans"> </Button>

<Button x:Name="button4" Width="110" Height="40" Content="Player 0" Click="button4_Click"

Margin="60,45,190,435" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="22" Foreground="White" BorderBrush="{x:Null}" Background="{x:Null}" FontWeight="Bold" FontFamily="Peace Sans"> </Button>

<Button x:Name="button5" Width="100" Height="40" Content="Back" Click="button5_Click"

Margin="17,460,376.6,20" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="28" Foreground="White" BorderBrush=" {x:Null}" Background="{x:Null}" FontWeight="Bold" FontFamily="Peace Sans"> </Button>

<ItemsControl ItemsSource="{Binding Map}" HorizontalAlignment="Center" VerticalAlignment="Center"> <ItemsControl.ItemsPanel>

<ItemsPanelTemplate> <StackPanel Orientation="Horizontal"/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <ItemsControl ItemsSource=" {Binding} "> <ItemsControl.ItemTemplate> <DataTemplate> <Border Background="#FAFAD2" MouseDown="Cell MouseDown"

CornerRadius="20" 0pacity="0.8" Width="100" Height="100" Margin="1" Padding="15"> <ContentControl Content="{Binding State}" ContentTemplateSelector="{StaticResource dtCell}"/> </Border> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>

<Border Visibility="{Binding MessageVisibility}" HorizontalAlignment="Center" VerticalAlignment="Center" MouseDown="Message_MouseDown" > <Border.Background> <ImageBrush/> </Border.Background> <TextBlock Text="{Binding Message}" Width="500" Height="320" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" FontSize="56" Foreground="MintCream" FontWeight="Bold"> <TextBlock.BitmapEffect> <DropShadowBitmapEffect/> </TextBlock.BitmapEffect> </TextBlock> </Border>

<TextBlock Name="tblTimer" HorizontalAlignment="Right" VerticalAlignment="Top"

FontSize="20" Width="30" Height="30" Мш^т="107> </Grid> </Window>

Приложение Г (Обязательное) Исходный код MainWindow.xaml.cs

using System;

using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Threading;

namespace TicTacToe {

/// <summary>

/// Логика взаимодействия для MamWmdow.xaml /// </summary> public partial class MainWindow : Window { DispatcherTimer dt = new DispatcherTimer(); DateTime startTime;

private TicTacToeModel model = new TicTacToeModel(); public MainWindow(){ InitializeComponent(); DataContext = model; dt.Tick += Dt_Tick;

dt.Interval = TimeSpan.FromMilliseconds(25);

startTime = DateTime.Now;

dt.Start();

}

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

private void Cell_MouseDown(object sender, MouseButtonEventArgs e) //Вывод сообщения о победе {

var cell = (sender as Border).DataContext as Cell; if (cell.State == State.None){ var winTest = model.Switch(cell); if (winTest == WinPlayer.Unknown) winTest = model.RandomStep(); if (winTest != WinPlayer.Unknown && winTest != WinPlayer.Standoff){

model.Message = winTest + " победил "; dt.Stop();

}

else if (winTest == WinPlayer.Standoff)

{

model.Message = "Ничья"; dt.Stop();

}

}

}

private void Dt_Tick(object sender, EventArgs e) // Таймер {

tblTimer.Text - (DateTime.Now -

startTime).TotalSeconds.ToString("F1");

}

private void Message_MouseDown(object sender,

MouseButtonEventArgs e) //При клике в область Message начало новой игры {

model.NewGame();

}

private void button1_Click(object sender, RoutedEventArgs e)

//Кнопка начала новой игры {

model.NewGame(); startTime - DateTime.Now; dt.Start();

}

private void button2_Click(object sender, RoutedEventArgs e) //Кнопка выхода

{

Close();

}

private void button3_Click(object sender, RoutedEventArgs e) //Игра за

крестик {

model.NewGame(); model.X_or_0(0);

}

private void button4_Click(object sender, RoutedEventArgs e) //Игра за

нолик

{

model.NewGame(); model.X_or_0( 1);

}

private void button5_Click(object sender, RoutedEventArgs e) //Кнопка

выхода из игры {

Window1 taskWindow - new Window1(); taskWindow.Show();

Close(); }

}

public class Cell : INotifyPropertyChanged {

public State State { get; private set; } = State.None;

public void SwitchTo(State state) {

State = state;

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("State"));

// PropertyChanged?.Invoke(this, new

PropertyChangedEventArgs("Uru")); }

public event PropertyChangedEventHandler PropertyChanged; }

public enum State { None, X, O }

public class CellDataTemplateSelector : DataTemplateSelector

{

public override DataTemplate SelectTemplate(object item,

DependencyObject container)

{

DataTemplate resource(string s) => (container as FrameworkElement).FindResource(s) as DataTemplate;

if (item != null && item is State)

{

var state = (State)item; if (state == State.None) return resource("dtState.None"); else if (state == State.X) return resource("dtState.X");

else if (state == State.O) return resource("dtState.O"); }

return null;

}

} }

Приложение Д (Обязательное) Исходный код TicTacToeModel.cs

using System;

using System.ComponentModel; using System.Linq; using System.Windows;

namespace TicTacToe {

internal class TicTacToeModel : INotifyPropertyChanged {

private int step - 0, t - 0;

private int n - 3;

private string message;

private Random rnd - new Random();

public event PropertyChangedEventHandler PropertyChanged;

public Cell[][] Map { get; } //Создание поля для игры

public string Message //Вывод сообщения о победе {

get -> message;

set {

message - value;

MessageVisibility - (value -- "") ? Visibility.Collapsed : Visibility.Visible;

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MessageVisibility))); PropertyChanged?.Invoke(this, new

PropertyChangedEventArgs(nameof(Message))); }

}

public Visibility MessageVisibility { get; private set; } -Visibility.Collapsed;

public TicTacToeModel() //Создается массив массивов {

Map - Enumerable.Range(0, n) .Select(i -> Enumerable.Range(0, n) .Select(j -> new Cell()) .ToArray()) .ToArray();

}

public void NewGame() //Новая игра {

for (int i - 0; i < n; i++) for (int j - 0; j < n; j++)

Map[i][j].SwitchTo(State.None); step = 0; Message = "";

}

public WinPlayer Switch(Cell cell) //Ход Х {

var state = step++ % 2 == t ? State.X : State.O; cell.SwitchTo(state); return WinTest()

? state == State.X ? WinPlayer.Player_X : WinPlayer.Player_O : step == 9 ? WinPlayer.Standoff : WinPlayer.Unknown;

}

public WinPlayer RandomStep() //Рандомный ход компьютера 0 {

var k = rnd.Next(9 - step)+1; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) if (Map[i][j].State == State.None && --k == 0) return Switch(Map[i][j]); return WinPlayer.Standoff;

}

public bool WinTest() //Проверка победы крестика или нолика {

bool[] rows = { true, true, true }; for (int i = 0; i < n; i++) for (int j = 1; j < n; j++)

rows[i] &= Map[i][j].State != State.None && Map[i][j].State ==

Map[i][0].State;

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

bool[] cols = { true, true, true }; for (int j = 0; j < n; j++) for (int i = 1 ; i < n; i++) cols[j] &= Map[i][j].State != State.None && Map[i][j].State == Map[0][j].State;

bool mainD = Map[0][0].State != State.None && Map[0][0].State == Map[1][1].State && Map[0][0].State == Map[2][2].State;

bool collateralD = Map[2][0].State != State.None && Map[2][0].State == Map[1][1].State && Map[2][0].State == Map[0][2].State;

return rows.Any(x=>x) || cols.Any(x => x) || mainD || collateralD;

}

public void X_or_0(int newT) => t = newT; //Переключение между X и 0 enum WinPlayer { Unknown, Player_X, Player_O, Standoff } //Перечисление

i Надоели баннеры? Вы всегда можете отключить рекламу.