Create a tic-tac-toe game. How to write a bot that cannot be played at "tic-tac-toe", or Getting to know the minimax rule Choosing standard visual and non-visual components

How to write a bot that cannot be played at "tic-tac-toe", or acquaintance with the "minimax" rule

It is quite possible that after hundreds of tic-tac-toe games you wondered: what is the optimal algorithm? But if you are here, then you probably also tried to write an implementation of this game. We will go ahead and write a bot that will be impossible to beat at tic-tac-toe. Having predicted your question "why?", We will answer: thanks to the algorithm.

Like a professional chess player, this algorithm calculates the opponent's actions several moves ahead - until it reaches the end of the game, be it a victory, a defeat or a draw. Once in this final state, the AI \u200b\u200bwill award itself a positive number of points (in our case +10) for a win, a negative (-10) for a defeat, and a neutral (0) for a draw.

At the same time, the algorithm performs similar calculations for the player's moves. He will choose the move with the highest score if the AI \u200b\u200bis walking, and the move with the lowest score if the player is walking. Using this strategy, minimax avoids defeat.

Try this game.

The minimax algorithm is most easily described as a recursive function, which:

  1. returns a value if the final state is found (+10, 0, -10),
  2. goes through all empty cells on the field,
  3. calls the minimax function for each of them (recursion),
  4. evaluates the obtained values
  5. and returns the best of them.

If you are unfamiliar with recursion, then you should watch this lecture from the Harvard CS50 course:

To understand how the minimax works, let's write its implementation and simulate its behavior. We will deal with this in the next two sections.

Minimax implementation

We'll look at a situation where the game comes to an end (see the picture below). Since the minimax goes through all possible states of the game (and there are hundreds of thousands of them), it makes sense to consider the endgame - this way we will have to keep track of fewer recursive function calls (9 in total).

Let the AI \u200b\u200bplay with noughts and noughts.

To simplify the work with the field, we will declare it as an array of 9 elements with values \u200b\u200bequal to the contents of the cells. Fill it in with crosses and zeros like in the picture above and call it origBoard.

Var origBoard \u003d ["O", 1, "X", "X", 4, "X", 6, "O", "O"];

Then we will declare the variables aiPlayer and huPlayer and assign them the values \u200b\u200b"X" and "O" respectively.

In addition, we need a function that searches for winning combinations and returns the true value if the search is successful, and a function that stores the indices of the available cells.

/ * initial state of the board O | | X --------- X | | X --------- | O | O * / var origBoard \u003d ["O", 1, "X", "X", 4, "X", 6, "O", "O"]; // person var huPlayer \u003d “O”; // AI var aiPlayer \u003d “X”; // returns a list of indices of empty squares on the board function emptyIndices (board) (return board.filter (s \u003d\u003e s! \u003d "O" && s! \u003d "X");) // winning combinations based on indices function winning (board, player) (if ((board \u003d\u003d player && board \u003d\u003d player && board \u003d\u003d player) || (board \u003d\u003d player && board \u003d\u003d player && board \u003d\u003d player) || (board \u003d\u003d player && board \u003d\u003d player && board \u003d\u003d player) || (board \u003d\u003d player && board \u003d\u003d player && board \u003d\u003d player) || (board \u003d\u003d player && board \u003d\u003d player && board \u003d\u003d player) || (board \u003d\u003d player && board \u003d\u003d player && board \u003d\u003d player) || (board \u003d\u003d player && board \u003d\u003d player && board \u003d\u003d player) || (board \u003d\u003d player && board \u003d\u003d player && board \u003d\u003d player)) (return true;) else (return false;))

So let's define a minimax function with two arguments: newBoard (new field) and player (player). Then we find the indices of free cells on the field and pass them to the availSpots variable.

// main minimax function function minimax (newBoard, player) (// available cells var availSpots \u003d emptyIndices (newBoard);

In addition, we need to track the final states and return the appropriate values. If "zero" wins, you need to return -10, if "cross" - +10. If the size of the availSpots array is equal to zero, then there are no free cells, the game will end in a draw, and zero must be returned.

// check for terminal state (win / lose / draw) // and returning a value accordingly if (winning (newBoard, huPlayer)) (return (score: -10);) else if (winning (newBoard, aiPlayer)) ( return (score: 10);) else if (availSpots.length \u003d\u003d\u003d 0) (return (score: 0);)

After that, you need to collect points from each of the empty cells. To do this, create an array of moves, moves, and loop through all empty cells, placing the indices and points of each move into the move object.

Then we set the index of the empty cell, which was stored as a number in origBoard, equal to the index property of the move object. Then we go as the current player to an empty cell of the new field newBoard and call the minimax function from the other player and the resulting field newBoard. After that, you need to put the score property of the object returned by the minimax function into the score property of the move object.

If the minimax does not find a final state, it continues recursive deepening into the game until it reaches the terminal state. After that, it passes the points of this "level" of recursion one level higher.

Finally, the function discards the newBoard changes and puts the move object in the moves array.

// array for storing all objects var moves \u003d; // loop through available cells for (var i \u003d 0; i< availSpots.length; i++){ //create an object for each and store the index of that spot var move = {}; move.index = newBoard]; // совершить ход за текущего игрока newBoard] = player; //получить очки, заработанные после вызова минимакса от противника текущего игрока if (player == aiPlayer){ var result = minimax(newBoard, huPlayer); move.score = result.score; } else{ var result = minimax(newBoard, aiPlayer); move.score = result.score; } // очистить клетку newBoard] = move.index; // положить объект в массив moves.push(move); }

Then the minimax needs to choose the best move from the array of moves. He needs a move with the highest score if the AI \u200b\u200bis walking, and with the lowest score if it is a human move. Thus, if the value of player is equal to aiPlayer, the algorithm initializes the variable bestScore with a very small number and loops through the array of moves: if move has more score than bestScore, the algorithm remembers this move. In the case of moves with the same points, the algorithm remembers the first of them.

In the case when player is equal to huPlayer, everything is the same - only now the bestScore is initialized with a large number, and the minimax is looking for the move move with the least points.

As a result, minimax returns the object stored in bestMove.

// if this is an AI move, loop through the moves and choose the move with the most points var bestMove; if (player \u003d\u003d\u003d aiPlayer) (var bestScore \u003d -10000; for (var i \u003d 0; i< moves.length; i++){ if(moves[i].score > bestScore) (bestScore \u003d moves [i] .score; bestMove \u003d i;))) else (// otherwise, loop through the moves and select the move with the lowest score var bestScore \u003d 10000; for (var i \u003d 0; i< moves.length; i++){ if(moves[i].score < bestScore){ bestScore = moves[i].score; bestMove = i; } } } // вернуть выбранный ход (объект) из массива ходов return moves; }

In the next section, we will simulate the operation of our program to understand how it works.

Minimax in action

Using the diagram below, we will analyze the step-by-step model of the algorithm.

Note: In the diagram, large numbers indicate the ordinal number of the function call, and the levels indicate how many moves ahead the algorithm has gone.

  1. The algorithm is served by origBoard and aiPlayer. He makes a list of three found empty cells, checks the finiteness of the state, and loops through all empty cells. The algorithm then changes newBoard, placing aiPlayer in the first empty cell. Then it calls itself from newBoard and huPlayer and waits for the second call to return a value.
  2. While the first function call is still running, the second is started, creating a list of two empty cells, checking the state is finite and looping through all empty cells. Then the second call modifies newBoard, placing huPlayer in the first empty cell. After that, it calls itself from newBoard and aiPlayer and waits for the third call to return a value.

  3. Since the second call found two empty cells, minimax modifies newBoard, placing huPlayer in the second free cell. Then it calls itself from newBoard and aiPlayer.

  4. The algorithm compiles a list of empty cells and fixes the player's victory after checking the finiteness of the state. Therefore, it returns an object with an invoice field (-10).

    In the second function call, the algorithm gets the values \u200b\u200breturned from the bottom level by the third and fourth function calls. Since huPlayer's move yielded these two results, the algorithm chooses the smallest one. Since they are the same, the algorithm picks the first one and passes it to the first function call.

    At this point, the first call to the function has received aiPlayer's move to the first empty cell. It then modifies newBoard by placing aiPlayer in the second empty cell. After that it calls itself from newBoard and huPlayer.

  5. In the fifth function call, the algorithm compiles a list of empty cells and fixes the AI \u200b\u200bvictory after checking the finiteness of the state. Therefore, it returns an object with a score field of +10.

    After that, the first call changes newBoard, placing aiPlayer in the third empty cell. Then it calls itself from newBoard and huPlayer.

  6. The sixth call makes a list of two empty cells, checks the end of the state, and loops over all empty cells. It then modifies newBoard, placing huPlayer in the first empty cell. Then it calls itself from newBoard and aiPlayer and waits for the seventh call to return a value.
  7. The new call makes a list of one empty cell, checks the end of the state, and changes newBoard, placing aiPlayer in the empty cell. After that, it calls itself from newBoard and huPlayer and waits for this call to return a value.
  8. The eighth call makes an empty list of empty cells and fixes the victory of aiPlayer after checking the end of the state. Therefore, it returns an object with a score field of (+10), one level up, the seventh call.

    The seventh challenge received only one positive value from the lower levels. Since this value was received in the aiPlayer move, the algorithm returns the largest value received. Therefore, it returns a positive value (+10) one level up, the sixth call.

    Since the sixth call found two empty squares, minimax modifies newBoard by placing huPlayer in the second empty square. Then it calls itself from newBoard and aiPlayer.

  9. After that, the algorithm compiles a list of empty cells and fixes the victory of aiPlayer after checking the finiteness of the state. Therefore, it returns an object with a score field of (+10) one level higher.

    At this point, the sixth challenge must choose between the score (+10) that returned the seventh challenge and the score (-10) that returned the ninth challenge. Since huPlayer's move yielded these two results, the algorithm chooses the smallest one and returns it to a higher level as an object with count and index fields.

    Finally, all three legs of the first call are scored (-10, +10, -10). Since the aiPlayer move yielded these three results, the algorithm chooses the object containing the most points (+10) and its index (4).

In the above scenario, the minimax decides that the optimal choice is to move to the central square of the field.

The end!

By this point, you should have understood how the minimax algorithm works. Try writing an implementation yourself, or see an example on GitHub or CodePen and optimize it.

If you are interested in the topic of AI in games, we recommend reading our materials on this topic.

Greetings, dear friends! In this tutorial I will show you how you can make a browser game - tic-tac-toe, in javascript! You all know what this game is and how to play it, but let me remind you again:

Tic-tac-toe is a logic game between two players on a 3x3 square field (possibly larger). One plays with "noughts", and the second - "noughts".

P.S. as in all similar tutorials on javascript, at the end of the article you can download the source file, and also see the result of the work on a demo example!

Description of the game being created

Let's take a look at the features of the game:

  • the game starts immediately after loading the page;
  • the right to walk first is chosen at random (either you start walking, or the computer);
  • the sign that you will put is randomly selected (cross or zero);
  • if the player wins, the victory symbols (a line of crosses or zeroes) are highlighted in green;
  • if the player loses to the computer, then the line is highlighted in red;
  • there is a line of information above the field, where the result is displayed (victory or defeat).

Logics

I didn’t come up with complex (universal) algorithms for the playing field 3 by 3 cells, I went the other way - brute force! (more on that later). I have identified three main sequential stages on which all the logic rests:

Stage 1: check if the player won?

At this stage, we check if there are 3 cells (on the same line) filled with the same player's symbols (crosses or zeros). Those. no matter which move (even if the first one) is, we always first check whether the player won. This is how victory looks like:

Stage 2: check - can the computer win with the next move?

At this stage, we are looking for a line where there would be 2 cells filled by the computer and one empty cell - that is, we are trying to win due to the player's carelessness. This is how the defeat looks like (i.e. the victory of the computer):

Stage 3: we don't let you win!

Here we are looking for the same line as in the second stage, only 2 cells must be filled with the player's game signs, that is, at this stage we do not let the computer play by placing a sign in an empty cell. Each of the stages is independent function - you can see this in the js code below.

Implementation

The layout of the playing field is very simple - the main block contains a line of information (class - result) and 9 blocks representing cells (class - block) HTML markup of cells:

Your turn!

The helper class cell is necessary in order to accurately identify the desired cell on the playing field. CSS styles for the playing field:

Krestiki_noliki (width: 306px; margin: 0 auto;) .krestiki_noliki .block (width: 100px; height: 100px; border: 1px solid #ccc; cursor: pointer; float: left; text-align: center; font-size: 100px; line-height: 94px;)

Now let's take a look at all the JS code, after which I'll cover the main points:

$ (document) .ready (function () (var znak_user \u003d "O"; var znak_comp \u003d "X"; var rand_num \u003d Math.round ((Math.random () * (9 - 1) + 1)); if (rand_num\u003e 3) (var znak_comp \u003d "O"; var znak_user \u003d "X"; $ (". cell" + rand_num) .text (znak_comp);) var exit_flag \u003d false; var win_user_array \u003d ["123", " 456 "," 789 "," 147 "," 258 "," 369 "," 159 "," 357 "]; // Determine the player's victory function check_3_user (znak) (for (var i \u003d 0; i< 8; i++) { var first = "cell" + win_user_array[i].substr(0,1); var second = "cell" + win_user_array[i].substr(1,1); var third = "cell" + win_user_array[i].substr(2,1); if($("."+first).text() == znak && $("."+second).text() == znak && $("."+third).text() == znak){ $("."+first+",."+second+",."+third).css("background-color", "#83e2c3"); $(".result").text("Вы выиграли!"); $(".krestiki_noliki .block").unbind("click"); exit_flag = true; } } } //Определяем возможность победы компьютера function check_2_comp(znak){ for (var i = 0; i < 8; i++) { var first = "cell" + win_user_array[i].substr(0,1); var second = "cell" + win_user_array[i].substr(1,1); var third = "cell" + win_user_array[i].substr(2,1); if($("."+first).text() == znak && $("."+second).text() == znak && $("."+third).text() == "" && exit_flag == false){ $("."+third).text(znak); $("."+first+",."+second+",."+third).css("background-color", "#EF7C7C"); $(".result").text("Вы проиграли!"); $(".krestiki_noliki .block").unbind("click"); exit_flag = true; } if($("."+first).text() == znak && $("."+second).text() == "" && $("."+third).text() == znak && exit_flag == false){ $("."+second).text(znak); $("."+first+",."+second+",."+third).css("background-color", "#EF7C7C"); $(".result").text("Вы проиграли!"); $(".krestiki_noliki .block").unbind("click"); exit_flag = true; } if($("."+first).text() == "" && $("."+second).text() == znak && $("."+third).text() == znak && exit_flag == false){ $("."+first).text(znak); $("."+first+",."+second+",."+third).css("background-color", "#EF7C7C"); $(".result").text("Вы проиграли!"); $(".krestiki_noliki .block").unbind("click"); exit_flag = true; } } } //Определяем ход компьютера function check_2_user(znak){ for (var i = 0; i < 8; i++) { var first = "cell" + win_user_array[i].substr(0,1); var second = "cell" + win_user_array[i].substr(1,1); var third = "cell" + win_user_array[i].substr(2,1); if(exit_flag == false){ if($("."+first).text() == znak && $("."+second).text() == znak && $("."+third).text() == ""){ $("."+third).text(znak_comp); exit_flag = true; } } if(exit_flag == false){ if($("."+first).text() == znak && $("."+second).text() == "" && $("."+third).text() == znak){ $("."+second).text(znak_comp); exit_flag = true; } } if($("."+first).text() == "" && $("."+second).text() == znak && $("."+third).text() == znak){ $("."+first).text(znak_comp); exit_flag = true; } if(exit_flag) break; } } $(".krestiki_noliki .block").click(function(){ //Если клетка пустая if($(this).text() == ""){ $(this).text(znak_user); check_3_user(znak_user); check_2_comp(znak_comp); check_2_user(znak_user); if(exit_flag == false){ for (var i = 1; i < 10; i++) { if($(".cell"+i).text() == ""){ $(".cell"+i).text(znak_comp); break; } } }else exit_flag = false; } }); });

First, we declare variables: znak_user - in this variable we store the sign that the user will play (by default, the zero is stored there - this is the English booth "O"). znak_comp - in this variable we store the sign that the computer will play (by default, the cross is stored there - this is the English booth "X").

The logic is this: if the random number is greater than 3, then the computer plays with zeroes, and it (the computer) makes the first move.

You can change this logic as you like, for example, you can create several random numbers in order to make more options for who will be at least the first and which characters. exit_flag - this flag (variable) is responsible for exiting the function, that is, for example, when the computer has already made its move, and you need to exit the function and pass the move to the player. win_user_array - this array contains all winning options for filling cells. To make it clear, let's take a look at this picture:

Each element of the array is a string of three numbers, which is a winning combination, that is, for example, if you fill in the cells under the numbers 1, 2 and 3, you will win (or lose). As you can see, there are 8 winning options in total, our task is to sort out all these options. Then there are 3 functions:

  1. check_3_user ();
  2. check_2_comp ();
  3. check_2_user ();

The purpose of these functions is described (in three steps) in the Logic section (above). These functions are called by clicking on any of the cells in the field. A parameter (znak) is passed to each of the functions - this is the sign of the player or computer (cross or zero), for example, to the function that determines the player's victory (check_3_user), we pass the player's sign in order to find 3 identical signs on the same line.

After three functions (if the computer has not yet made a move), the computer will fill one of the free cells. Here, you can complicate the gameplay, for example, by making it so that if the central square is free (square number 5), then first place in it, if it is occupied, then place in one of the free corners (these are squares number 1, 3, 7 and 9) and so on - in general, here it is at your discretion.

That, in principle, is all that is required to create such a game.

Now you can watch the game on a demo example and download the source file (only 1 file).

06/08/2018 - thanks for your attention to the author of the letter: Patvakan Baghdasaryan, a bug has been fixed when the computer had several possible victory options and all its victory moves were painted over (from 4 to 6 cells, instead of 3).

That's all for me, I hope this tutorial was useful for you, I wish you good luck, bye!

Attention! This is an introductory version of the lesson, the materials of which may be incomplete.

Log in as a student

Log in as a student to access school materials

Creating 1C configurations: writing "Tic-tac-toe" part 1/3

We will learn playfully, and therefore our first project will be to create
game familiar from childhood - "Tic-tac-toe".

You ask how games have to do with 1C, accounting and trading? Almost none. But you need to start gradually and over time we will come to the automation of warehouses. For now, let's start small.

Before we start programming the Tic Tac Toe game, let's think about it.

We already know that a form has Elements, one of which is a Button. Buttons are capable of executing commands, and, at the same time, have properties that allow you to control their display on a form (for example, a title).

For example, you can use the button to create a field with nine active areas (those cells on which we click and fix the action, while displaying the inscriptions in the form of "O" and "X"). The button is more than suitable for this.

What do we need? Obviously, we need to remember our move and remember the computer's move. We also need to change the titles of the buttons: when we click, the title of the button is always "O", when the computer moves - "X".

And first we need to create a new database in which we will create our game. Let's do it.

Step # 1: create an empty base

Let's create an empty Tic-Tac-Toe base.

Detailed instructions

Let's run 1C shortcut to open the list of infobases available on the computer. You are reading an introductory version of the lesson, full lessons are found. We need to create a new database, so press the button " Add to":

The add window will open information base, in which you want to select the first item " Creation of an information base"and click the" Next "button:

In the next window, select the second item " Creating an infobase without configuration for developing a new configuration ..."and press the" Next "button again:

In the next window, we are offered to enter the name of the new base, under which it will be displayed in the list of bases. Let's introduce " Tic-tac-toe"and press the" Next "button:

In the next window, you must specify the path to an empty folder in which our database will be stored. In this case, I created a folder " Tic-tac-toe"in the" Base 1C "folder on the D drive:

In the next window, leave all the default settings and click the " Done":

After a short pause, the database is created and added to the list. There are two main modes of working with the base: 1C: Enterprise and Configurator:

In the configurator mode, we do the configuration and programming of the base, in the 1C: Enterprise mode, we look at what came of it.

Step # 2: open the configurator

Press the button " Configurator"to enter the configurator mode:

Step # 3: open the configuration tree

Let's execute the menu command " Configuration"->"Open configuration":

A configuration tree has opened before us, which contains various configuration sections. Since we haven't created anything yet, these sections are empty:

Step # 4: add processing

To place the logic of our game, we will use the "Processing" section. Press right click on section " Processing"and select the" Add "command:

A window for creating a new treatment has opened before us. Let's enter the name " Tic Tac Toe". The synonym will be substituted by itself. This is enough to save our processing (still empty) in the database. Press the" Close "button:

Step 5: debugging the program for the first time

You can check what happened from the user mode ( 1C: Enterprise). To get into it directly from the configurator, execute the menu command " Debugging"->"Start debugging":

Since we made a change to the database, we are asked if we agree to accept this change. This question will be asked to us constantly during the development process. We answer with consent (button " Yes"):

The base was launched in "1C: Enterprise" mode. You are reading an introductory version of the lesson, full lessons are found. But as we see it is still difficult to work with her - there is simply nothing to choose from. It's strange, because we have already created the processing and, in theory, it should appear on the yellow panel.

STEP 1. CONFIGURATION OF FORM PARAMETERS 1. To customize the shape, set its size
510 dots horizontal and 480 dots
vertical. Maximum and minimum
specify the size equal to the same values.
2. Name the shape with the word Tic Tac Toe.
3. For the background of the form, use the file from the folder
Images under the name background.png, and place it
in the center of the form.
4. For the pictogram in the title bar
use use file from folder
Images under the name menu4.ico.
5. The background color of the form must be set
MintCream.

STEP 2. ADDING A BUTTON AND A SHAPE

1. For placed elements, change
the font size is 12 and the background is set
transparent.

1. Create a menu bar with items in
according to those indicated in the image.

STEP 3. ADDING A MENU LINE TO A FORM

1. In the File menu, create a command
Output.
2. For
commands
Output
prescribe
program code the same as in
previous application.

STEP 3. ADDING A MENU LINE TO A FORM

1. In the menu item Game, create a command
New game.
2. For the team New game we will register
program code further through
a few steps.

STEP 3. ADDING A MENU LINE TO A FORM

1. In the menu item Help, create a command
About the program.
2. For the About command, create a new
form and write the program code
the same as in the previous
application.

1. By dragging the PictureBox onto the form
resize it to 100x100.
2. Set a transparent background.
3. Place the PictureBox as shown in
picture above the first cell of the game field.

STEP 4. ADDING PICTUREBOX OBJECTS TO THE FORM

1
2
3
4
5
6
7
8
9
1. Above the rest of the cells we place
PictureBox objects, copies of the first
object, according to the numbering indicated on
Images.

1. Before writing the program code
necessary in the folder
\\ Visual Studio
2010 \\ Projects \\ Tic Tac Toe \\ Tic
noughts \\ bin \\ Debug \\ must be re-thrown
files x.png, 0.png, none.png from the Images folder.
2. Double click the left mouse on the first
PictureBox.

STEP 5. ADDING SOFTWARE CODE FOR PICTUREBOX OBJECTS

1. We create a two-dimensional array available for all elements in
created in the form of 3x3 elements consisting of integers. Immediately
fill it with zeros when declared. For empty cells we
we will use 0, for crosses - 1, and for zeroes - -1.

STEP 5. ADDING SOFTWARE CODE FOR PICTUREBOX OBJECTS

In the procedure when you click on the first
PictureBox, add an operator
choice
which the
will be
check the status
array cells. If the value
array cells will be 0, which is
it means there is neither "zero" nor
"Cross", then to this cell
array will be written 1 and in
PictureBox1
displayed
the image of the "cross", and if
array cell value will be
equals 1 then it contains
"Cross" and 0 is written into it, and
an empty cell is displayed.

STEP 5. ADDING SOFTWARE CODE FOR PICTUREBOX OBJECTS

1
2
3
4
5
6
7
8
9



For the rest of the cells in the field, add the code
similarly as in the first, only changing
PictureBox object number and cell address
array.
EXAMPLE for the second cell:

To the procedure when you click on the button
add
operator
cycle
which checks
all cells from the first to
the presence of empty cells. And if
the cell is empty,
then into it
is written "zero", namely in
array cell is written -1.
For convenience in further work
variables
I,
j
which
are used to iterate through loops
declare for the whole form.

STEP 6. ADDING A PROGRAM CODE FOR THE GO BUTTON

To display zeros on
game
field
necessary
add code to body
cycle of checking cells for emptiness.
Using a nested operator
branching
will be
take place
parsing the address of an array cell for
output zero in the correct
PictureBox.
We also add a break statement
for premature end
loop when found empty
cells.

STEP 6. ADDING A PROGRAM CODE FOR THE GO BUTTON

To indicate the state of the game
the interface element is used
Label1. Since the player always walks
first
then
at
download
applications
necessary
in
element
Label1
necessary
reflect
the phrase "your
move ".
For
of this
create
variable
otvet
which
let's assign this phrase. AND
when loading the form the variable
must be assigned to the element
Label1, to create the required
procedures
necessary
double click first
in shape

STEP 7. ADDING SOFTWARE CODE FOR MENU ITEM NEW GAME

When pressed on command, a new
the game will be reset
all cells in the array, replacing all
"Crosses" and "zeroes" on
empty cells. Also output
the inscription "your move"

STEP 8. CONCLUSION OF THE GAME RESULT

To check the results of moves
necessary
analyze
content of rows, columns and
diagonals. If all three elements
are equal to 1 then this is a player's victory, and
if three is -1 then this is defeat
player.
Victory Check Needed
spend
front
move
computer,
and
check
defeat after.
The last command of the procedure
will display the results
course.

STEP 8. CONCLUSION OF THE GAME RESULT

The program code for checking the user's victory:
if (znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1) otvet \u003d "You won";
if (znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1) otvet \u003d "You won";
if (znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1) otvet \u003d "You won";
if (znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1) otvet \u003d "You won";
if (znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1) otvet \u003d "You won";
if (znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1) otvet \u003d "You won";
if (znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1) otvet \u003d "You won";
if (znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1 && znacheniyeYacheyki \u003d\u003d 1) otvet \u003d "You won";
The program code for checking the user's victory:
if (znacheniyeYacheyki \u003d\u003d -1 & znacheniyeYacheyki \u003d\u003d -1 & znacheniyeYacheyki \u003d\u003d -1) otvet \u003d "You've lost";
if (znacheniyeYacheyki \u003d\u003d -1 & znacheniyeYacheyki \u003d\u003d -1 & znacheniyeYacheyki \u003d\u003d -1) otvet \u003d "You've lost";
if (znacheniyeYacheyki \u003d\u003d -1 & znacheniyeYacheyki \u003d\u003d -1 & znacheniyeYacheyki \u003d\u003d -1) otvet \u003d "You've lost";
if (znacheniyeYacheyki \u003d\u003d -1 & znacheniyeYacheyki \u003d\u003d -1 & znacheniyeYacheyki \u003d\u003d -1) otvet \u003d "You've lost";
if (znacheniyeYacheyki \u003d\u003d -1 & znacheniyeYacheyki \u003d\u003d -1 & znacheniyeYacheyki \u003d\u003d -1) otvet \u003d "You've lost";
if (znacheniyeYacheyki \u003d\u003d -1 & znacheniyeYacheyki \u003d\u003d -1 & znacheniyeYacheyki \u003d\u003d -1) otvet \u003d "You've lost";
label1.Text \u003d otvet;

STEP 9 IMPROVING PLAYABILITY

To improve "playability"
instead of sequential output
the first empty ones that come across
cells of "zeroes", we implement
output through a random generator
numbers.
To do this, add
one boolean variable
uslovie, and change the loop type from For
on While, since we don't know
exact number of repetitions
random number generator so far
it will not fall into an empty cell.

MINISTRY OF BRANCH OF RUSSIA

federal state budget educational institution higher professional education

"Vologda State University"

Department of Automation and Computer Engineering

Explanatory note to the course project for the discipline

Programming and the basics of algorithms

"Tic-tac-toe"

Completed student of group EM-21

Butorova L.Yu.

Accepted Rzheutskaya S. Yu.

INTRODUCTION

1. ANALYSIS OF THE PROBLEM AND DETERMINATION OF REQUIREMENTS FOR THE DEVELOPED PROGRAM

1 The purpose of the program, its users, the main functions and goals that are pursued in the development

2 Overview of known programs that perform similar functions

3 Theoretical foundations of development

4 Choice of development tools

DESIGN PART OF DEVELOPMENT

1 User interface development

2.2 Development of data structures (in external and main memory)

2.3 Design and analysis of algorithms

IMPLEMENTING THE PROGRAM IN C ++ LANGUAGE

1 Program architecture

2 Selection of standard visual and non-visual components

TEST RESULTS

CONCLUSION

Bibliography

Applications

INTRODUCTION

Tic-tac-toe is a logic game between two opponents on a square field of 3 by 3 cells or larger (up to an "endless field"). One of the players plays with "crosses", the other - with "noughts". This game became popular long before the advent of computers, only before it was played with a simple piece of paper and a pen. The traditional Chinese game uses black and white stones.

In this course work, the basic rules and the standard size of the field of play (3x3 cells) are preserved. For the convenience of the game, the right of the first move is reserved for the user, that is, "crosses".

Tic-tac-toe is a program that is designed to entertain the user, therefore its interface, in this course work, is made in a game style with a combination of positive colors that exacerbate the emotional part of the gameplay.

There are three types in the game: X versus 0 - user versus user, “Level 1 with a computer” - for those who are just mastering the basics of the world game, and Level 2 with a computer - for those who are absolutely sure of their victory. At levels 1 and 2, there are three possible outcomes: "win", "loss" and "draw". The winning is fixed if the vertical, horizontal or diagonal is completely filled with crosses or zeroes.

If the free squares of the field are over, but no one has won, then the game is considered to have ended in a “draw”.

1. ANALYSIS OF THE PROBLEM AND DETERMINATION OF REQUIREMENTS FOR THE DEVELOPED PROGRAM

program cross stitch interface

1.1 The purpose of the program, its users, the main functions and goals that are pursued during development

The purpose of this program is, first of all, for the entertainment of users, in order to brighten up the waiting time of a person, because any work needs rest, and this simple game will help to relax and escape from everyday affairs. Also "tic-tac-toe" belongs to the class of intellectual and logical games, which are designed to train logical thinking, allow you to concentrate attention and develop memory.

The target audience of users are children and adolescents, as well as adults. The main criteria for using the product are the ability to read the text written in the program and the ability to select the necessary task for the computer using the buttons.

Hence, we can conclude that the main tasks are: the task of entertainment and the task of developing the logical potential of a person.

1.2 Overview of known programs that perform similar functions

On the Internet, you can find a large number of works that implement this game. Currently, there are many analogues of this game that have departed from the original standards. Examples of such programs are "Tic-tac-toe on an infinite field" and "Tic-tac-toe 3D". Also, in many games "crosses" and "noughts" are replaced by other symbols, such as, for example, "stones".

My course project is a PC application. The game is intended both for one user, whose rival is artificial intelligence (or computer), and for two users. It is presented on a classic 3x3 field.

The most interesting and unusual, in my opinion, was the game "Tic-Tac-Toe 3D". Therefore, I chose her for comparison.

Three-dimensional tic-tac-toe is much more interesting than on paper or on a regular field. There are more opportunities to win and lose, and draws are less common. You can play alone - against the computer - or together with a friend. And the most unusual thing here is that to win, you can make a combination of three balls of your color (black or white), not only on any one level, but also along the plane of the walls and even along the diagonal of the entire field (Fig. 1.1).

Figure: 1.1

Among the wide variety of games on a similar theme, one can single out in each work a unique implementation of the plan. Each project differs from others in its individuality.

1.3 Theoretical foundations of development

Analysis

For each side there are well-known algorithms that guarantee a draw for any opponent's game, and if his opponent makes a mistake, they can win. Thus, the game is in a state "No man's death"<#"877528.files/image002.gif">

Figure 1.2. Game situations tree

A partial tree of game situations, shown in Figure 1.2 for a tic-tac-toe game. A tree of game situations for the game of tic-tac-toe, where the player for the "crosses" goes first and acts according to the above algorithm, and the player for the "noughts" can act as he pleases another), consists of 50 nodes.

1.4 Choice of development tools

To implement our tasks, an integrated application development environment is required. Therefore, the development of the project was carried out in the Microsoft Visual Studio 2008 programming environment.

Microsoft Visual Studio - product line of Microsoft including an integrated development environment software and a number of other tools. These products allow you to develop as console applications and GUI applications , including with support for Windows Forms technology as well as websites , web services as in native , and in a controlled codes for all platforms supported by Windows , Windows Mobile , Windows CE .NET Framework , Xbox , Windows Phone .NET Compact Framework and Silverlight .

2. DESIGN PART OF DEVELOPMENT

2.1 User interface development

When creating a gaming application, it is necessary to take into account one, perhaps, of the main components of the success of the product - the interface. The user interface of the program should, first of all, be clear and attractive to the user. You need to try to remove all the moments that will distract the user or cause him discomfort. The entire program interface can be divided into two components.

) Main menu of the program

Figure: 2.1 - Main menu of the program

The main menu is designed so that the user can integrate into the gaming atmosphere, so the interface is executed in colorful, playful colors. Through the menu, you can go to the playing field, see the rules of the game, or exit the game.

) Playing field

Fig 2.2 - The playing field

The playing field contains the immediate area for the game, where the player and the computer put their icons. Before starting the game, the user must select the type of game, such as "X versus 0", "Level 1 with a computer" or "Level 2 with a computer", otherwise the program will display a message about what to do. A button that will help the player return to the main menu. At the end, additional windows will pop up that will inform the participant about the results of the fight.

Figure: 2.3 - additional game outcome windows

2.2 Development of data structures (in external and RAM)

The random access memory is used for a one-dimensional array, consisting of 9 elements, which stores the states of the playing field, where each cell of the array corresponds to a cell on the playing field. Memory is also used for static variables: level number, turn order.

It requires 803 KB of free memory to work.

.3 Design and analysis of algorithms

To implement the game thinking algorithm, you must set the static array gcnew array (nine); in which the states of the playing field will be stored, where each cell of the array corresponds to a cell. “0” - corresponds to an empty cell, if a player entered the cell, that is, “X”, the value “1” is recorded and if the computer made a move, that is, “O”, the value is “2”. Initially, all elements of the array are equal to "0". It is necessary to set a static variable lvl, which stores the level data. There are 3 levels in this game: lvl takes on the value "1" if the user has chosen the type of game "X versus O", value "2" if "level 1 with a computer", and value "3" if "level 2 with a computer ". The variable player - stores the order of the move ("true" - the player's move, "false" - the computer's move). Since the right of the first move is granted to the user, at the beginning game player \u003d true. The static variable flag stores information about whether there are empty cells on the playing field or not: if flag \u003d true - that is, false - there are no empty cells. The verification algorithm must contain an enumeration of the parameters of the array x and put forward its own solution, which will be optimal for the further game. This program features 2 levels of playing with a computer. In level 1, the task of the computer is not to beat the opponent. therefore this function returns a random value of the cell where the computer will go. In [Appendix 1] the code of this algorithm is presented. Figure 2.4 shows a block diagram of the code implementation.

The most winning move at the beginning of the game is to move to the center of the field. In the dif_level () function, at the beginning, the condition is checked: if the player did not go to the central field, then the computer goes there. Otherwise, if the player went to the center, then the check (2) function is called to check the combination of the computer and, if there is an opportunity to win, then return the cell number. If the computer cannot win on the next move, then the check (1) function is called: checking the player's combination. Returns the number of the cell, which the player would have won. If there is no such combination, then the low_level () function is called.

Figure 2.4. - Block diagram

Figure 2.5. - Block diagram

3. IMPLEMENTATION OF THE PROGRAM IN C ++ LANGUAGE

.1 Program architecture

This program implements 3 forms: the main menu (Fig.2.1.), The playing field (Fig.2.2) and the help field (game rules); 12 panels, 9 of which are basic. Also, at the end of the game, a pictureBox appears with the result, there are 5 of them in total (Figure 2.3).

As a basis, you can take the handlers for pressing the panels, of which there are exactly 9 on the playing field. Each handler calls several functions. At the beginning there is a condition that if the user selects the type of game "X versus 0", the cells are simply filled with values \u200b\u200b1 or 2 (cross or zero). Next are the functions: progress indication (CrossZero ()), which changes the cross to zero and vice versa, blocking occupied cells by checkingArray (), finding the winner winner (). All possible winnings are considered in the winner () function, therefore, if any of the players line up 3 of their pieces (a cross or a zero) vertically, horizontally or diagonally, he will win. Otherwise, if the field is full, but none of the players lined up a row, then the function (_friend ()) is called - a check for a draw, which checks whether there are free cells on the field or not. If fr \u003d true, then there are no free cells on the field. If the value has changed, then there is a free cell on the field.

The second condition works if the second or third type of game is selected. Then the function is called, in which the computer's move move (int n) is performed. The number of the cell on which the player clicked is transmitted to it. Next are the following functions: progress indication (CrossZero ()), blocking occupied cells by checkingArray (). Then the winner () function is called, which checks if the player won with this move or not. If not, then the presence of free cells is checked. If there are free cells, then the computer runs. Further, depending on which level the player "1" or "2" has chosen, the following functions are called: low_level (), dif_level (). The low_level () function chooses where to put the zero at random, and the dif_level () function presents a special algorithm for the computer to win. Next are the following functions: progress indication (CrossZero ()), blocking occupied cells by checkingArray (). Then the winner () function is called, which checks whether the computer won with this move or not. If not, then the presence of free cells is checked. If there are free cells, then the player moves.

.2 Selection of standard visual and non-visual components

To implement this work, the following components were selected:

1) Form1, with the specified parameters Text \u003d Tic-Tac-Toe, ControlBox \u003d False

2) f2, with the specified parameters BackColor, Text \u003d Game

) comboBox1 with the given Items parameters:

X versus 0

1st level with computer

2nd level with computer

4) panel, with the specified BackColor parameters, and different values \u200b\u200bof the Visible and Enabled parameters. For some panels, events such as Click were written.

5) button, with the specified parameters Font, Fore Color, BackColor, Text, for all buttons such events as Click were written.

6) label, with the specified parameters BackColor, Font, Fore Color, Text.

) pictureBox, with the specified Image parameters, SizeMode \u003d StretchImage.

) textBox, with the specified parameters BackColor, Font, Fore Color, Text \u003d ””.

4. TEST RESULTS

Let's test the program by going through 3 types of games.

Trying the actions of the main menu buttons. The buttons are working properly. Let's try to start the game without choosing a game type. The program displays an error message and asks to select the type of game. (Fig.4.1)

Figure 4.1.

Let's choose the 1st type of game - "X against 0", ie user versus user. At this stage of the game, the user can also play with himself. (Fig.4.2)

Figure 4.2.

During the game "Level 1 with a computer" the computer does not set itself the goal of winning the participant. He just puts zeroes in free places fields. At this stage, the user can easily beat the computer. Although at this level other scenarios are also possible.

Figure 4.3.

Game type "Level 2 with a computer". At this stage, the game analyzes all the moves and tries to choose the most optimal move. All three scenarios are also possible here, since the computer makes its first move to any free cell. Most often the game comes down to a draw.

Figure 4.4.

The program works successfully for all test variants, without errors.

CONCLUSION

It is safe to say that the task set at the beginning of the work has been completed. In the course of development, a project of a remix of the famous game "Tic-Tac-Toe" was planned and developed. The game meets the specified requirements and performs its functions. The work implements various types of games and difficulty levels.

In the course of the work, new programming methods were mastered in an integrated development environment. The old knowledge of working with the C ++ language was consolidated. In preparation for the course work, various methods and algorithms for the implementation of this game were analyzed.

Despite the seeming simplicity of this program, it is fraught with a number of complexities that are implemented using all the basic techniques of Visual C ++.

The features of this program are:

Well-structured algorithm;

Intuitive interface;

Ease of use;

Completely understandable user manual;

Lack of unnecessary additions.

BIBLIOGRAPHY

1.http: //www.pravilaigr.ru/xo.php

2.http: //2igroka.com/stuff/sportivnye/krestiki_noliki_3d/15-1-0-14

3.https://www.draw.io/

Http://pol-video.ru/QPW9QHEO2GU/uroki_s_krestiki-noliki_ch1.html

ATTACHMENT 1

private: int low_level () (// procedure for a light opponent; :: Random ^ rand \u003d gcnew System :: Random (); (\u003d rand-\u003e Next (0,8);

) while (x [r]! \u003d 0); r;

APPENDIX 2

private: bool check (int n) (k \u003d -1; // checks all combinations and returns the correct move (x \u003d\u003d n) (((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 2; ((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 1; ((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 6; ((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 3; ((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 8; ((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 4;

) (x \u003d\u003d n) (((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 0; ((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 7; ((x \u003d \u003d n) && (x \u003d\u003d 0)) k \u003d 4;

) (x \u003d\u003d n) (((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 4; ((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 6; ((x \u003d \u003d n) && (x \u003d\u003d 0)) k \u003d 8; ((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 5;

) (x \u003d\u003d n) (((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 0; ((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 5; ((x \u003d \u003d n) && (x \u003d\u003d 0)) k \u003d 4;

) (x \u003d\u003d n) (((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 0; ((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 3; ((x \u003d \u003d n) && (x \u003d\u003d 0)) k \u003d 1; ((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 2;

) (x \u003d\u003d n) (((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 2;

) (x \u003d\u003d n) (((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 8; ((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 7;

) (x \u003d\u003d n) (((x \u003d\u003d n) && (x \u003d\u003d 0)) k \u003d 6;

) (k! \u003d - 1) return true; else return false;

APPENDIX 3

private: int dif_level () (// difficult opponent

// return check (2); (x \u003d\u003d 0) return (4); (check (2)) return k; else (check (1)) return k; else low_level ();

ATTACHMENT 4

private: void CrossZero () (// changes the cross to zero (progress indicator) (player) (-\u003e Visible \u003d true; -\u003e Visible \u003d false;

) else (-\u003e Visible \u003d true; -\u003e Visible \u003d false;

): void checkingArray () (// function of checking if there is something in a cell, if there is, then you cannot click on this cell anymore. (x \u003d\u003d 1) (panel1-\u003e BackgroundImage \u003d panel11-\u003e BackgroundImage; panel1- \u003e Enabled \u003d false;) (x \u003d\u003d 2) (panel1-\u003e BackgroundImage \u003d panel10-\u003e BackgroundImage; panel1-\u003e Enabled \u003d false;) (x \u003d\u003d 1) (panel2-\u003e BackgroundImage \u003d panel11-\u003e BackgroundImage; panel2- \u003e Enabled \u003d false;) (x \u003d\u003d 2) (panel2-\u003e BackgroundImage \u003d panel10-\u003e BackgroundImage; panel2-\u003e Enabled \u003d false;) (x \u003d\u003d 1) (panel3-\u003e BackgroundImage \u003d panel11-\u003e BackgroundImage; panel3- \u003e Enabled \u003d false;) (x \u003d\u003d 2) (panel3-\u003e BackgroundImage \u003d panel10-\u003e BackgroundImage; panel3-\u003e Enabled \u003d false;) (x \u003d\u003d 1) (panel4-\u003e BackgroundImage \u003d panel11-\u003e BackgroundImage; panel4- \u003e Enabled \u003d false;) (x \u003d\u003d 2) (panel4-\u003e BackgroundImage \u003d panel10-\u003e BackgroundImage; panel4-\u003e Enabled \u003d false;) (x \u003d\u003d 1) (panel5-\u003e BackgroundImage \u003d panel11-\u003e BackgroundImage; panel5- \u003e Enabled \u003d false;) (x \u003d\u003d 2) (panel5-\u003e BackgroundImage \u003d panel10-\u003e BackgroundImage; panel5-\u003e Enabled \u003d false;) (x \u003d\u003d 1) (panel6-\u003e B ackgroundImage \u003d panel11-\u003e BackgroundImage; panel6-\u003e Enabled \u003d false;) (x \u003d\u003d 2) (panel6-\u003e BackgroundImage \u003d panel10-\u003e BackgroundImage; panel6-\u003e Enabled \u003d false;) (x \u003d\u003d 1) (panel7-\u003e BackgroundImage \u003d panel11-\u003e BackgroundImage; panel7-\u003e Enabled \u003d false;) (x \u003d\u003d 2) (panel7-\u003e BackgroundImage \u003d panel10-\u003e BackgroundImage; panel7-\u003e Enabled \u003d false;) (x \u003d\u003d 1) (panel8-\u003e BackgroundImage \u003d panel11-\u003e BackgroundImage; panel8-\u003e Enabled \u003d false;) (x \u003d\u003d 2) (panel8-\u003e BackgroundImage \u003d panel10-\u003e BackgroundImage; panel8-\u003e Enabled \u003d false;) (x \u003d\u003d 1) (panel9-\u003e BackgroundImage \u003d panel11-\u003e BackgroundImage; panel9-\u003e Enabled \u003d false;) (x \u003d\u003d 2) (panel9-\u003e BackgroundImage \u003d panel10-\u003e BackgroundImage; panel9-\u003e Enabled \u003d false;)

): bool winner () (// check the winner and lock all remaining cells.

// bool flag \u003d false; (((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 2)) || ((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d \u003d 2)) || ((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 2)) || ((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 2 )) || ((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 2)) || ((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 2)) || ((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 2)) || ((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 2))) ( (lvl \u003d\u003d 1) (picturePo-\u003e Visible \u003d true;) (picturePr-\u003e Visible \u003d true;) -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; true;

) (((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 1)) || ((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 1)) || ((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 1)) || ((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 1)) || (( x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 1)) || ((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 1)) || ((x \u003d \u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 1)) || ((x \u003d\u003d x) && (x \u003d\u003d x) && (x \u003d\u003d 1))) ((lvl \u003d\u003d 1) (picturePx-\u003e Visible \u003d true;) (picturePobeda-\u003e Visible \u003d true;) -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; -\u003e Enabled \u003d false; true;

): void _friend () (fr \u003d true; (int i \u003d 0; i< 9; i++) if (x[i] == 0) {fr = false; break;}(fr) { pictureN->Visible \u003d true;)

): void move (int n) (// computer move function \u003d false; [n] \u003d 1; \u003d! player; (); (); (winner ()) () ((int i \u003d 0; i< 9; i++) if (x[i] == 0) flag = true;(flag){(lvl == 2) = 2; = 2;= !player;();();();

): System :: Void button1_Click (System :: Object ^ sender, System :: EventArgs ^ e) (// new game\u003e Visible \u003d false;\u003e Visible \u003d false;\u003e Visible \u003d false;\u003e Visible \u003d false;\u003e Visible \u003d false; \u003d comboBox1-\u003e Text; (typeGame \u003d\u003d "") (:: Show ("Choose the type of game first!");

) else ((typeGame \u003d\u003d "X versus 0") lvl \u003d 1; (typeGame \u003d\u003d "1st level with computer") lvl \u003d 2; (typeGame \u003d\u003d "2nd level with computer") lvl \u003d 3; (); \u003d true; (int i \u003d 0; i< 9; i++) x[i] = 0;->BackgroundImage \u003d panel12-\u003e BackgroundImage; -\u003e BackgroundImage \u003d panel12-\u003e BackgroundImage; -\u003e BackgroundImage \u003d panel12-\u003e BackgroundImage; -\u003e BackgroundImage \u003d panel12-\u003e BackgroundImage; -\u003e BackgroundImage \u003d panel12-\u003e BackgroundImage; -\u003e BackgroundImage \u003d panel12-\u003e BackgroundImage; -\u003e BackgroundImage \u003d panel12-\u003e BackgroundImage; -\u003e BackgroundImage \u003d panel12-\u003e BackgroundImage; -\u003e BackgroundImage \u003d panel12-\u003e BackgroundImage; -\u003e Enabled \u003d true; -\u003e Enabled \u003d true; -\u003e Enabled \u003d true; -\u003e Enabled \u003d true; -\u003e Enabled \u003d true; -\u003e Enabled \u003d true; -\u003e Enabled \u003d true; -\u003e Enabled \u003d true; -\u003e Enabled \u003d true;

): System :: Void panel1_MouseClick (System :: Object ^ sender, System :: Windows :: Forms :: MouseEventArgs ^ e) (n \u003d 0; (lvl \u003d\u003d 1) ((player) (\u003d 1;

) \u003d! player; (); (); ();

): System :: Void panel2_MouseClick (System :: Object ^ sender, System :: Windows :: Forms :: MouseEventArgs ^ e) (n \u003d 1; (lvl \u003d\u003d 1) ((player) (\u003d 1;

) \u003d! player; (); (); ();

) else if ((lvl \u003d\u003d 2) || (lvl \u003d\u003d 3)) ((n);

): System :: Void panel3_MouseClick (System :: Object ^ sender, System :: Windows :: Forms :: MouseEventArgs ^ e) (n \u003d 2; (lvl \u003d\u003d 1) ((player) (\u003d 1;

) \u003d! player; (); (); ();

) else if ((lvl \u003d\u003d 2) || (lvl \u003d\u003d 3)) ((n);

): System :: Void panel4_MouseClick (System :: Object ^ sender, System :: Windows :: Forms :: MouseEventArgs ^ e) (n \u003d 3; (lvl \u003d\u003d 1) ((player) (\u003d 1;

) \u003d! player; (); (); ();

) else if ((lvl \u003d\u003d 2) || (lvl \u003d\u003d 3)) ((n);

): System :: Void panel5_MouseClick (System :: Object ^ sender, System :: Windows :: Forms :: MouseEventArgs ^ e) (n \u003d 4; (lvl \u003d\u003d 1) ((player) (\u003d 1;

) \u003d! player; (); (); ();

) else if ((lvl \u003d\u003d 2) || (lvl \u003d\u003d 3)) ((n);

): System :: Void panel6_MouseClick (System :: Object ^ sender, System :: Windows :: Forms :: MouseEventArgs ^ e) (n \u003d 5; (lvl \u003d\u003d 1) ((player) (\u003d 1;

) \u003d! player; (); (); ();

) else if ((lvl \u003d\u003d 2) || (lvl \u003d\u003d 3)) ((n);

): System :: Void panel7_MouseClick (System :: Object ^ sender, System :: Windows :: Forms :: MouseEventArgs ^ e) (n \u003d 6; (lvl \u003d\u003d 1) ((player) (\u003d 1;

) \u003d! player; (); (); ();

) else if ((lvl \u003d\u003d 2) || (lvl \u003d\u003d 3)) ((n);

): System :: Void panel8_MouseClick (System :: Object ^ sender, System :: Windows :: Forms :: MouseEventArgs ^ e) (n \u003d 7; (lvl \u003d\u003d 1) ((player) (\u003d 1;

) \u003d! player; (); (); ();

) else if ((lvl \u003d\u003d 2) || (lvl \u003d\u003d 3)) ((n);

): System :: Void panel9_MouseClick (System :: Object ^ sender, System :: Windows :: Forms :: MouseEventArgs ^ e) (n \u003d 8; (lvl \u003d\u003d 1) ((player) (\u003d 1;

) \u003d! player; (); (); ();

) else if ((lvl \u003d\u003d 2) || (lvl \u003d\u003d 3)) ((n);

): System :: Void button2_Click (System :: Object ^ sender, System :: EventArgs ^ e) (();

): System :: Void picturePx_Click (System :: Object ^ sender, System :: EventArgs ^ e) (\u003e Visible \u003d false;

): System :: Void picturePo_Click (System :: Object ^ sender, System :: EventArgs ^ e) (\u003e Visible \u003d false;

): System :: Void picturePobeda_Click (System :: Object ^ sender, System :: EventArgs ^ e) (\u003e Visible \u003d false;

): System :: Void picturePr_Click (System :: Object ^ sender, System :: EventArgs ^ e) (\u003e Visible \u003d false;

): System :: Void pictureN_Click (System :: Object ^ sender, System :: EventArgs ^ e) (\u003e Visible \u003d false;