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

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

Запись от 8Observer8 размещена 11.07.2019 в 19:56. Обновил(-а) 8Observer8 07.12.2025 в 19:25
Показов 20371 Комментарии 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
Просмотров: 1232

Размер: 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 Кб, 1178 просмотров)
Тип файла: zip Tic-Tac-Toe-Console_CSharp.zip (28.0 Кб, 1146 просмотров)
Метки .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
 
Новые блоги и статьи
Рефакторинг программы уравнивания.
Massaraksh7 26.05.2026
Пример по предыдущей записи в блоге. Но, надо заметить, что, во-первых, там оптимизация не только математики, но и работы с базой данных, и с графами, а во-вторых, это ещё не всё.
Использование TThread в Lazarus для математических вычислений.
Massaraksh7 25.05.2026
Производя рефакторинг своих программ на предмет ускорения их работы, обратил внимание на такой аспект, как сокращение времени матвычислений. Дело в том, что приходится работать с большими матрицами. . .
Модель здравосохранения 18. Чем здоровее работник, тем быстрее выгорает
anaschu 24.05.2026
Имитационная модель корпоративного здравоохранения: что показывает математика Сегодня в модели рабочего коллектива на AnyLogic появились три новые механики — выгорание через накопленную усталость,. . .
Модель здравосохранения 17. Планы на выгорание
anaschu 23.05.2026
Вот конкретная схема реализации: В классе Работник добавить: накопленнаяУсталость — растёт каждый час работы, снижается в перерывы и болезни коэффициентПрезентеизма — снижает продуктивность. . .
Изменение цветов в палитре gif файла aka фавикона
russiannick 23.05.2026
Изменение цветов в палитре gif файла, юзаемого как фавиконка в составе html-файла, помещенная в base64, средствами нативного Java Script, навеянное сном в майский день. Для работы необходим браузер,. . .
Модель здравосохранения 16. Слишком хорошие и здоровые сотрудники уходят, недовольные зарплатой
anaschu 23.05.2026
Отладка увольнений и настройка производительности Сегодня во второй половине дня разобрались с механикой увольнений и настроили коэффициент сложности заданий. Вот что было сделано. . . .
Как я стал коммунистом))) Модель сохранения здоровья сотрудников, запись блога номер 15
anaschu 23.05.2026
Внезапно хорошее здоровье сотрудников не нужно капиталистам?))
Модель здравоСохранения 15. Как мы чинили AnyLogic модель рабочего коллектива: сочленение диаграммы состояний болезней и поломок в ресурспул
anaschu 23.05.2026
Как мы чинили AnyLogic модель рабочего коллектива Сегодня разобрались с пятью багами, из-за которых модель либо падала с ошибкой, либо давала совершенно бессмысленные результаты. Каждый баг был. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru