Форум программистов, компьютерный форум, киберфорум
8Observer8
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

Консольные Крестики-нолики на C# на одном компьютере

Запись от 8Observer8 размещена 11.07.2019 в 19:56. Обновил(-а) 8Observer8 07.12.2025 в 19:25
Показов 21499 Комментарии 7
Метки .net, c#, gamedev

Содержание блога

Консольные Крестики-нолики. Прикрепил архив с проектом в Visual Studio и EXE.

Играть в C# песочнице: https://www.onlinegdb.com/fork/yWZ3O512a

Исходники на GitHub

Исходники

Program.cs

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Tic_Tac_Toe_Console
{
    class Program
    {
        static void Main(string[] args)
        {
            new Game();
        }
    }
}
Game.cs

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
using System;
 
namespace Tic_Tac_Toe_Console
{
    class Game
    {
        private char[,] _field = new char[3, 3] {
                { ' ', ' ', ' ' },
                { ' ', ' ', ' ' },
                { ' ', ' ', ' ' },
            };
 
        private bool _isXMove = true;
 
        private readonly string _coordErrorMessage = "Координаты должны быть: [0, 2]";
 
        public Game()
        {
            Draw();
 
            int row, col;
            do
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Write("\n Введите номер ряда: [0, 2]\n (или -1 для выхода): ");
                Console.ForegroundColor = ConsoleColor.White;
                if (!int.TryParse(Console.ReadLine(), out row))
                {
                    ShowError(_coordErrorMessage);
                    continue;
                }
                if (row == -1) break;
 
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Write("\n Введите номер столбца: [0, 2]\n (или -1 для выхода): ");
                Console.ForegroundColor = ConsoleColor.White;
                if (!int.TryParse(Console.ReadLine(), out col))
                {
                    ShowError(_coordErrorMessage);
                    continue;
                }
                if (col == -1) break;
 
                Update(row, col);
                Draw();
            } while (true);
 
        }
 
        private void Update(int row, int col)
        {
            if (row == -1 || col == -1)
            {
                return;
            }
 
            if (0 <= row && row <= 2 &&
                0 <= col && col <= 2)
            {
                if (_field[row, col] == ' ')
                {
                    _field[row, col] = _isXMove ? 'X' : 'O';
 
                    if (IsWinner('X'))
                    {
                        Draw();
                        EndGame("Крестики");
                    }
                    else if (IsWinner('O'))
                    {
                        Draw();
                        EndGame("Нолики");
                    }
 
                    _isXMove = !_isXMove;
                }
                else
                {
                    ShowError("По этим координатам уже сделан ход.");
                }
            }
            else
            {
                ShowError(_coordErrorMessage);
                return;
            }
        }
 
        private void Draw()
        {
            Console.Clear();
 
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("\n Крестики-Нолики\n");
            Console.ForegroundColor = ConsoleColor.Magenta;
 
            ShowField();
 
            // Устанавливаем цвет рисования белым
            Console.ForegroundColor = ConsoleColor.White;
        }
 
        private void ShowField()
        {
            Console.WriteLine(string.Format("  {0} | {1} | {2}", _field[0, 0], _field[0, 1], _field[0, 2]));
            Console.WriteLine(" ---+---+---");
            Console.WriteLine(string.Format("  {0} | {1} | {2}", _field[1, 0], _field[1, 1], _field[1, 2]));
            Console.WriteLine(" ---+---+---");
            Console.WriteLine(string.Format("  {0} | {1} | {2}", _field[2, 0], _field[2, 1], _field[2, 2]));
        }
 
        private void ShowError(string message)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("\n " + message);
            Console.WriteLine(" Нажмите любую клавишу");
 
            Console.ReadKey();
        }
 
        private bool IsWinner(char player)
        {
            return (
                // Rows
                (_field[0, 0] == player && _field[0, 1] == player && _field[0, 2] == player) ||
                (_field[1, 0] == player && _field[1, 1] == player && _field[1, 2] == player) ||
                (_field[2, 0] == player && _field[2, 1] == player && _field[2, 2] == player) ||
                // Columns
                (_field[0, 0] == player && _field[1, 0] == player && _field[2, 0] == player) ||
                (_field[0, 1] == player && _field[1, 1] == player && _field[2, 1] == player) ||
                (_field[0, 2] == player && _field[1, 2] == player && _field[2, 2] == player) ||
                // Diagonals
                (_field[0, 0] == player && _field[1, 1] == player && _field[2, 2] == player) ||
                (_field[0, 2] == player && _field[1, 1] == player && _field[2, 0] == player)
            );
        }
 
        private void ClearField()
        {
            for (int row = 0; row < 3; row++)
            {
                for (int col = 0; col < 3; col++)
                {
                    _field[row, col] = ' ';
                }
            }
        }
 
        private void EndGame(string player)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine(string.Format("\n Победили {0}!", player));
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("\n Нажмите любую клавишу для продолжения");
            Console.ReadKey();
            ClearField();
        }
    }
}


Примечание. Перед тем как запустить EXE нужно в консоле выполнить команду: chcp 65001 иначе будут выводиться знаки ??????? вместо текста на русском:

Название: 53b39287-3fce-43ad-bfcb-55e3c7088b66.png
Просмотров: 1912

Размер: 1.3 Кб

Команда chcp 65001 переключает консоль в UTF-8.

Способ номер 2. Можно добавить следующие две строки в метод Main. Я проверял, работает:

C#
1
2
3
4
5
6
7
static void Main()
{
    Console.OutputEncoding = System.Text.Encoding.UTF8;
    Console.InputEncoding = System.Text.Encoding.UTF8;
 
    new Game();
}
Инструкция по запуску игры с помощью консоли:
  • Скачать и установить .NET: https://dotnet.microsoft.com/en-us/download
  • Открыть CMD и набрать команду создания нового проекта: dotnet new console -n Tic-Tac-Toe
  • Скопировать код выше в созданную папку
  • Запустить проект командой из директории проекта: dotnet run (Либо создать EXE с помощью команды: dotnet build)
  • В качестве легковесного редактора кода можно использовать Sublime Text 4: https://www.sublimetext.com/download

Я скопировал C# код выше в ChatGPT и попросил его перевести на JavaScript: https://plnkr.co/edit/r14HOc81r9e1EAWE.

Исходники (получилось неиграбельно)
PHP/HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<!doctype html>
 
<html>
 
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Tic-Tac-Toe Console</title>
</head>
 
<body>
    <script>
 
      class Game {
          constructor() {
              this.field = [
                  [' ', ' ', ' '],
                  [' ', ' ', ' '],
                  [' ', ' ', ' ']
              ];
 
              this.isXMove = true;
              this.coordErrorMessage = "Координаты должны быть: [0, 2]";
 
              this.draw();
 
              let row, col;
              while (true) {
                  row = parseInt(prompt("\nВведите номер ряда [0, 2]\n(или -1 для выхода):"));
                  if (row === -1) break;
                  if (isNaN(row)) {
                      this.showError(this.coordErrorMessage);
                      continue;
                  }
 
                  col = parseInt(prompt("\nВведите номер столбца [0, 2]\n(или -1 для выхода):"));
                  if (col === -1) break;
                  if (isNaN(col)) {
                      this.showError(this.coordErrorMessage);
                      continue;
                  }
 
                  this.update(row, col);
                  this.draw();
              }
          }
 
          update(row, col) {
              if (row === -1 || col === -1) return;
 
              if (row >= 0 && row <= 2 && col >= 0 && col <= 2) {
                  if (this.field[row][col] === ' ') {
                      this.field[row][col] = this.isXMove ? 'X' : 'O';
 
                      if (this.isWinner('X')) {
                          this.draw();
                          this.endGame("Крестики");
                      } else if (this.isWinner('O')) {
                          this.draw();
                          this.endGame("Нолики");
                      }
 
                      this.isXMove = !this.isXMove;
                  } else {
                      this.showError("По этим координатам уже сделан ход.");
                  }
              } else {
                  this.showError(this.coordErrorMessage);
              }
          }
 
          draw() {
              console.clear();
              console.log("\n Крестики-Нолики\n");
              this.showField();
          }
 
          showField() {
              console.log(`  ${this.field[0][0]} | ${this.field[0][1]} | ${this.field[0][2]}`);
              console.log(" ---+---+---");
              console.log(`  ${this.field[1][0]} | ${this.field[1][1]} | ${this.field[1][2]}`);
              console.log(" ---+---+---");
              console.log(`  ${this.field[2][0]} | ${this.field[2][1]} | ${this.field[2][2]}`);
          }
 
          showError(message) {
              console.log("\n" + message);
              alert(message + "\nНажмите OK для продолжения.");
          }
 
          isWinner(player) {
              const f = this.field;
              return (
                  // Rows
                  (f[0][0] === player && f[0][1] === player && f[0][2] === player) ||
                  (f[1][0] === player && f[1][1] === player && f[1][2] === player) ||
                  (f[2][0] === player && f[2][1] === player && f[2][2] === player) ||
                  // Columns
                  (f[0][0] === player && f[1][0] === player && f[2][0] === player) ||
                  (f[0][1] === player && f[1][1] === player && f[2][1] === player) ||
                  (f[0][2] === player && f[1][2] === player && f[2][2] === player) ||
                  // Diagonals
                  (f[0][0] === player && f[1][1] === player && f[2][2] === player) ||
                  (f[0][2] === player && f[1][1] === player && f[2][0] === player)
              );
          }
 
          clearField() {
              for (let r = 0; r < 3; r++)
                  for (let c = 0; c < 3; c++)
                      this.field[r][c] = ' ';
          }
 
          endGame(player) {
              console.log(`\n Победили ${player}!`);
              alert(`Победили ${player}!\nНажмите OK чтобы продолжить.`);
              this.clearField();
          }
      }
 
      new Game();
 
    </script>
 
</body>
 
</html>


Для веб-версии на JavaScript проще всего сделать версию с GUI. Я попросил Gemini добавить GUI на HTML, CSS, и Bootstrap: https://plnkr.co/edit/xjQRl4N9tG5iyMRq

Исходники (играбельно)
PHP/HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
<!doctype html>
 
<html>
 
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Tic-Tac-Toe GUI</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    <style>
        .game-cell {
            width: 100px;
            /* Fixed width for a cell */
            height: 100px;
            /* Fixed height for a cell */
            font-size: 3rem;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
            border: 2px solid #333;
            /* Darker border for better visibility */
            transition: background-color 0.2s;
        }
 
        .game-cell:hover {
            background-color: #f0f0f0;
        }
 
        /* Styling for the central 3x3 board */
        .board {
            width: 306px;
            /* 3 cells * 100px + 6px of border */
            margin: 0 auto;
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            border-collapse: collapse;
        }
 
        /* Remove border-radius on cells for a continuous grid look */
        .game-cell:nth-child(3n+1) {
            border-left: none;
        }
 
        .game-cell:nth-child(3n) {
            border-right: none;
        }
 
        .game-cell:nth-child(-n+3) {
            border-top: none;
        }
 
        .game-cell:nth-child(n+7) {
            border-bottom: none;
        }
    </style>
</head>
 
<body class="bg-light">
 
    <div class="container py-5">
        <h1 class="text-center mb-4 text-primary">Крестики-Нолики (Tic-Tac-Toe)</h1>
 
        <div class="card shadow-lg mx-auto" style="max-width: 400px;">
            <div class="card-body text-center">
                <p id="gameStatus" class="lead fw-bold mb-3">Ход: Крестики (X)</p>
                <button id="resetButton" class="btn btn-danger">Начать заново</button>
            </div>
        </div>
 
        <div id="gameBoard" class="board my-5">
        </div>
 
    </div>
 
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eRkSy03pIxXl8" crossorigin="anonymous"></script>
 
    <script>
        /* Modified JavaScript */
 
        class Game {
            constructor() {
                this.field = [
                    ['', '', ''],
                    ['', '', ''],
                    ['', '', '']
                ];
                this.isXMove = true;
                this.gameOver = false;
 
                this.boardElement = document.getElementById('gameBoard');
                this.statusElement = document.getElementById('gameStatus');
                this.resetButton = document.getElementById('resetButton');
 
                this.initializeGUI();
                this.draw();
            }
 
            initializeGUI() {
                // Clear previous board and generate new cells
                this.boardElement.innerHTML = '';
                for (let r = 0; r < 3; r++) {
                    for (let c = 0; c < 3; c++) {
                        const cell = document.createElement('div');
                        cell.className = 'game-cell bg-white';
                        cell.dataset.row = r;
                        cell.dataset.col = c;
                        cell.addEventListener('click', this.handleCellClick.bind(this));
                        this.boardElement.appendChild(cell);
                    }
                }
 
                this.resetButton.addEventListener('click', this.resetGame.bind(this));
            }
 
            handleCellClick(event) {
                if (this.gameOver) return;
 
                const cell = event.target;
                const row = parseInt(cell.dataset.row);
                const col = parseInt(cell.dataset.col);
 
                this.update(row, col, cell);
                this.draw();
            }
 
            update(row, col, cellElement) {
                if (this.field[row][col] === '') {
                    const player = this.isXMove ? 'X' : 'O';
                    this.field[row][col] = player;
 
                    // Update the GUI cell
                    cellElement.textContent = player;
                    cellElement.classList.add(player === 'X' ? 'text-success' : 'text-danger'); // Style X and O differently
 
                    if (this.isWinner(player)) {
                        this.endGame(player === 'X' ? "Крестики" : "Нолики");
                        return;
                    } else if (this.isDraw()) {
                        this.endGame("Ничья");
                        return;
                    }
 
                    this.isXMove = !this.isXMove;
                } else {
                    this.showError("По этим координатам уже сделан ход.");
                }
            }
 
            draw() {
                // Update the status display
                if (!this.gameOver) {
                    this.statusElement.textContent = `Ход: ${this.isXMove ? 'Крестики (X)' : 'Нолики (O)'}`;
                }
            }
 
            showError(message) {
                // Use a less intrusive method than alert, like updating the status temporarily
                console.warn(message);
                // You could also use a Bootstrap toast or modal here for better UX
            }
 
            isWinner(player) {
                const f = this.field;
                // Check rows, columns, and diagonals (logic remains the same)
                return (
                    // Rows
                    (f[0][0] === player && f[0][1] === player && f[0][2] === player) ||
                    (f[1][0] === player && f[1][1] === player && f[1][2] === player) ||
                    (f[2][0] === player && f[2][1] === player && f[2][2] === player) ||
                    // Columns
                    (f[0][0] === player && f[1][0] === player && f[2][0] === player) ||
                    (f[0][1] === player && f[1][1] === player && f[2][1] === player) ||
                    (f[0][2] === player && f[1][2] === player && f[2][2] === player) ||
                    // Diagonals
                    (f[0][0] === player && f[1][1] === player && f[2][2] === player) ||
                    (f[0][2] === player && f[1][1] === player && f[2][0] === player)
                );
            }
 
            isDraw() {
                return this.field.every(row => row.every(cell => cell !== '')) && !this.isWinner('X') && !this.isWinner('O');
            }
 
            resetGame() {
                this.field = [
                    ['', '', ''],
                    ['', '', ''],
                    ['', '', '']
                ];
                this.isXMove = true;
                this.gameOver = false;
 
                // Clear the GUI cells
                document.querySelectorAll('.game-cell').forEach(cell => {
                    cell.textContent = '';
                    cell.classList.remove('text-success', 'text-danger');
                });
 
                this.draw(); // Update status to reflect the start of a new game
            }
 
            endGame(result) {
                this.gameOver = true;
                if (result === "Ничья") {
                    this.statusElement.textContent = `Игра окончена: ${result}!`;
                } else {
                    this.statusElement.textContent = `Победили ${result}!`;
                }
            }
        }
 
        // Start the game when the page loads
        document.addEventListener('DOMContentLoaded', () => {
            new Game();
        });
    </script>
 
</body>
 
</html>
Изображения
   
Вложения
Тип файла: zip Tic-Tac-Toe-Console.zip (3.5 Кб, 1194 просмотров)
Тип файла: zip Tic-Tac-Toe-Console_CSharp.zip (28.0 Кб, 1148 просмотров)
Метки .net, c#, gamedev
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 7
Комментарии
  1. Старый комментарий
    Добавил перевод с C# на JavaScript с помощью ChatGPT
    Запись от 8Observer8 размещена 05.12.2025 в 00:31 8Observer8 вне форума
  2. Старый комментарий
    Крестики-нолики по интернету на двоих на JavaScript, HTML/CSS и Firebase: https://tic-tac-toe-network-v1-0-js.web.app/. Этот пример был сгенерирован с помощью ChatGPT.
    Запись от 8Observer8 размещена 05.12.2025 в 21:22 8Observer8 вне форума
    Обновил(-а) 8Observer8 06.12.2025 в 18:40
  3. Старый комментарий
    Я попросил ChatGPT написать туториал на основе JS-версии игры выше. Залил результат на два хостинга:

    Версия на английском сгенерировалась полностью, а на русском только половина. У туториале есть весь код, демка в браузере с игрой и инструкции, как установить Firebase Tools и т.д. Инструкцию не проверял.

    Сервис Firebase от Google отлично подходит для игр на двоих по интернету. У Firebase есть быстрая и бесплатная база данных RTDB (Firebase Run Time Database). Можно использовать RTDB, чтобы изучать работу с NoSQL базами данных, наподобие MongoDB. RTDB похожа на MongoDB. Программируя маленькие игры по сети типа Крестики-Нолики, Шашки, Шахматы, Го, Морской Бой и т.д. можно практиковаться с выбранным языком программирования, HTML, CSS, сетевым программированием, базами данных, программированием графики и т.д.
    Запись от 8Observer8 размещена 06.12.2025 в 19:19 8Observer8 вне форума
  4. Старый комментарий
    Добавил инструкцию по запуску примера из первого сообщения на C# с помощью .NET и консоли:

    Инструкция по запуску игры с помощью консоли:
    • Скачать и установить .NET: https://dotnet.microsoft.com/en-us/download
    • Открыть CMD и набрать команду создания нового проекта: dotnet new console -n Tic-Tac-Toe
    • Скопировать код выше в созданную папку
    • Запустить проект командой из директории проекта: dotnet run (Либо создать EXE с помощью команды: dotnet build)
    • В качестве легковесного редактора кода можно использовать Sublime Text 4: https://www.sublimetext.com/download

    Примечание: .NET 10 займёт на вашем компьютере 1.17 GB, а Sublime Text 4 всего лишь 53.63 MB. Это гораздо меньше, чем Visual Studio. Если, например, у вас слабый ноутбук и мало места на жёстком диске, то вы всё равно можете изучать программирование через практику на простых играх.
    Запись от 8Observer8 размещена 06.12.2025 в 19:29 8Observer8 вне форума
    Обновил(-а) 8Observer8 06.12.2025 в 19:37
  5. Старый комментарий
    Добавил ссылку для игры в песочнице на C#: https://www.onlinegdb.com/fork/yWZ3O512a
    Запись от 8Observer8 размещена 07.12.2025 в 19:04 8Observer8 вне форума
  6. Старый комментарий
    Я попросил Gemini добавить в версию на JavaScript добавить GUI на HTML, CSS, и Bootstrap: https://plnkr.co/edit/xjQRl4N9tG5iyMRq
    Запись от 8Observer8 размещена 07.12.2025 в 19:15 8Observer8 вне форума
    Обновил(-а) 8Observer8 08.12.2025 в 14:01
  7. Старый комментарий
    ChatGPT перевёл консольную игру c C# на Си без видимых на первый взгляд проблем: https://onlinegdb.com/SjmNWcEmcE

    C
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <string.h>
     
    // ANSI colors (ConsoleColor equivalents)
    #define GREEN   "\x1b[32m"
    #define WHITE   "\x1b[37m"
    #define YELLOW  "\x1b[33m"
    #define MAGENTA "\x1b[35m"
    #define RED     "\x1b[31m"
    #define RESET   "\x1b[0m"
     
    char field[3][3] = {
        { ' ', ' ', ' ' },
        { ' ', ' ', ' ' },
        { ' ', ' ', ' ' }
    };
     
    bool isXMove = true;
    const char *coordErrorMessage = "Координаты должны быть: [0, 2]";
     
    void Draw();
    void ShowField();
    void Update(int row, int col);
    void ShowError(const char *msg);
    bool IsWinner(char player);
    void ClearField();
    void EndGame(const char *player);
     
    void Game_Run()
    {
        Draw();
     
        int row, col;
        char line[256];
     
        while (1)
        {
            printf(GREEN "\n Введите номер ряда: [0, 2]\n (или -1 для выхода): " WHITE);
            if (!fgets(line, sizeof(line), stdin) || sscanf(line, "%d", &row) != 1) {
                ShowError(coordErrorMessage);
                continue;
            }
            if (row == -1) break;
     
            printf(GREEN "\n Введите номер столбца: [0, 2]\n (или -1 для выхода): " WHITE);
            if (!fgets(line, sizeof(line), stdin) || sscanf(line, "%d", &col) != 1) {
                ShowError(coordErrorMessage);
                continue;
            }
            if (col == -1) break;
     
            Update(row, col);
            Draw();
        }
    }
     
    void Update(int row, int col)
    {
        if (row == -1 || col == -1)
            return;
     
        if (row >= 0 && row <= 2 && col >= 0 && col <= 2)
        {
            if (field[row][col] == ' ')
            {
                field[row][col] = isXMove ? 'X' : 'O';
     
                if (IsWinner('X')) {
                    Draw();
                    EndGame("Крестики");
                }
                else if (IsWinner('O')) {
                    Draw();
                    EndGame("Нолики");
                }
     
                isXMove = !isXMove;
            }
            else {
                ShowError("По этим координатам уже сделан ход.");
            }
        }
        else {
            ShowError(coordErrorMessage);
        }
    }
     
    void Draw()
    {
        system("cls"); // Windows clear-screen
     
        printf(YELLOW "\n Крестики-Нолики\n\n" MAGENTA);
        ShowField();
        printf(WHITE);
    }
     
    void ShowField()
    {
        printf("  %c | %c | %c\n", field[0][0], field[0][1], field[0][2]);
        printf(" ---+---+---\n");
        printf("  %c | %c | %c\n", field[1][0], field[1][1], field[1][2]);
        printf(" ---+---+---\n");
        printf("  %c | %c | %c\n", field[2][0], field[2][1], field[2][2]);
    }
     
    void ShowError(const char *msg)
    {
        printf(RED "\n %s\n" WHITE, msg);
        printf(" Нажмите Enter...");
        getchar();
    }
     
    bool IsWinner(char p)
    {
        return
            // Rows
            (field[0][0] == p && field[0][1] == p && field[0][2] == p) ||
            (field[1][0] == p && field[1][1] == p && field[1][2] == p) ||
            (field[2][0] == p && field[2][1] == p && field[2][2] == p) ||
            // Columns
            (field[0][0] == p && field[1][0] == p && field[2][0] == p) ||
            (field[0][1] == p && field[1][1] == p && field[2][1] == p) ||
            (field[0][2] == p && field[1][2] == p && field[2][2] == p) ||
            // Diagonals
            (field[0][0] == p && field[1][1] == p && field[2][2] == p) ||
            (field[0][2] == p && field[1][1] == p && field[2][0] == p);
    }
     
    void ClearField()
    {
        for (int r = 0; r < 3; r++)
            for (int c = 0; c < 3; c++)
                field[r][c] = ' ';
    }
     
    void EndGame(const char *player)
    {
        printf(YELLOW "\n Победили %s!\n" WHITE, player);
        printf("\n Нажмите Enter для продолжения");
        getchar();
        ClearField();
    }
     
    int main()
    {
        Game_Run();
        return 0;
    }
    Запись от 8Observer8 размещена 10.12.2025 в 19:26 8Observer8 вне форума
    Обновил(-а) 8Observer8 10.12.2025 в 19:53
 
Новые блоги и статьи
Запись в регистр сведений независимо от заполненности табличной части
Maks 25.08.2026
Реализация из решения ниже выполнена на нетиповом документе с несколькими табличными частями, разработанного в КА2. Задача: Обеспечить запись документа в регистр сведений независимо от. . .
Ноутбук Альфария
kumehtar 24.08.2026
Встретился тут в сети ноутбук Альфария, примарха Альфа-Легиона. Хотя возможно, это ноутбук Омегона, разумеется. Ну как вам?
Мастера простых решений
DevAlt 23.08.2026
В сишарп стэках winforms, да и wpf существует сложная система связывания источниках данных и элементов формы(текстовые поля и метки), опирается все это на технологию событий и мета. . .
Цена ошибки
DevAlt 23.08.2026
Человек я беспокойный и потому заинтересовался OCaml, в чате форсили функторы модулей как суперфичу. Пытаясь отдуплить концепт, наткнулся на тутор с простым примером. А главный принцип обучения от. . .
Сегодня суббота, 22.08.2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины.
zorxor 22.08.2026
Сегодня суббота, 22. 08. 2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины. Кто Я, откуда Я пришел и куда Я иду? Эти вопросы не оставляют меня ни на секунду. Жизнь на планете Земля. . .
Жизня: рисунок укладки багажа, сделанный клодом
anaschu 21.08.2026
Сделал 15 снимков, он по снимкам сделал схему.
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru