Прошу критики кода, крестики-нолики - C (СИ)
Формулировка задачи:
Всем привет.
Только начал изучать язык программирования Си, да и программирование в общем.
Есть задача - написать игру крестики-нолики.
Предлагаю свой вариант, прошу критики.
Пока что без варианта игры против компьютера. Хотелось бы узнать как лучше всего написать для него хоть немножечко интеллекта.
Что не правильно я использовал, что лучше не использовать/использовать и так далее. Заранее спасибо.
#include <stdio.h>
#include <locale.h>
#include <stdlib.h>
void menu();
void instruction();
bool winner();
void inputBoard();
void resetArray();
void computer();
void player();
int menuNum = 0; //выбор пункта в меню
char board[9] = {49, 50, 51, 52, 53, 54, 55, 56, 57}; // заполнение массива от 1 до 9.
int count = 0; // счетчик количества цикла, (ничья)
char nameOne[15], nameTwo[15]; // массив символов для имен игроков
int ex; // выйти из программы или продолжить
main()
{
setlocale(LC_ALL, "Russian");
do{
system("cls");
menu();
if (menuNum == 1) computer();
else if (menuNum == 2) player();
else if (menuNum == 3) {instruction(); goto label;}
else exit(1);
inputBoard();
count = 0;
printf("Хотите сыграть еще раз? (1 - да. 0 - нет) - ");
scanf("%d", &ex);
}while(ex == 1);
label:
printf("Спасибо, что воспользовались программой. Счастливого дня.\n");
}
void menu()
{
puts("\t\tДобро пожаловать в игру крестики-нолики.");
puts("Выберите пункт из меню:\n");
puts("1 - играть с компьютером");
puts("2 - играть с другим игроком");
puts("3 - показать инструкцию");
puts("0 - выход из программы");
printf("Ваш выбор - ");
scanf("%d", &menuNum);
}
void instruction()
{
puts("1. Игрок A ходит крестиками 'X' игрок B ходит '0' по очереди.");
puts("1. Побеждает тот, у кого выставленные им символы трижды пересекаются");
puts("1. либо по горизонтали, либо по вертикали, либо по диагонали.");
}
bool winner()
{
if(((board[0] == 'X') && (board[1] == 'X') && (board[2] == 'X' )) ||
((board[3] == 'X') && (board[4] == 'X') && (board[5] == 'X' )) ||
((board[6] == 'X') && (board[7] == 'X') && (board[8] == 'X' )) ||
((board[0] == 'X') && (board[3] == 'X') && (board[6] == 'X' )) ||
((board[1] == 'X') && (board[4] == 'X') && (board[7] == 'X' )) ||
((board[2] == 'X') && (board[5] == 'X') && (board[8] == 'X' )) ||
((board[0] == 'X') && (board[4] == 'X') && (board[8] == 'X' )) ||
((board[2] == 'X') && (board[4] == 'X') && (board[6] == 'X' )))
return true;
if(((board[0] == '0') && (board[1] == '0') && (board[2] == '0' )) ||
((board[3] == '0') && (board[4] == '0') && (board[5] == '0' )) ||
((board[6] == '0') && (board[7] == '0') && (board[8] == '0' )) ||
((board[0] == '0') && (board[3] == '0') && (board[6] == '0' )) ||
((board[1] == '0') && (board[4] == '0') && (board[7] == '0' )) ||
((board[2] == '0') && (board[5] == '0') && (board[8] == '0' )) ||
((board[0] == '0') && (board[4] == '0') && (board[8] == '0' )) ||
((board[2] == '0') && (board[4] == '0') && (board[6] == '0' )))
return false;
}
void inputBoard() // заполнение и изменения доски
{ system("cls");
printf("\t\t\tИграют %s и %s\n", nameOne, nameTwo);
for(int i = 0; i < 9; i++)
{
printf(" %c |", board[i]);
if ((i == 2) || (i == 5))
{
printf("\n");
printf("----+----+-----\n");
}
}
if (count == 9) printf("\n\nНичья. Попробуйте еще раз.\n");
if(winner() == true)
printf("\n\n%s играл за крестики и победил, поздравляем!\n", nameOne);
else if(winner() == false)
printf("\n\n%s играл за нолики и победил, поздравляем!\n", nameTwo);
}
void resetArray() //заполнить массив к стандартным значениям.
{
if (ex == 1)
{
int j = 0;
for(int i = 49; i <= 57; i++)
{
board[j] = i;
j++;
}
}
}
void computer(){ // игра против компьютера
printf("Computer");
}
void player() // игра против игрока
{
int clickBoard = 0; count = 0;
resetArray();
printf("Введите имя первого игрока - ");
scanf("%s", &nameOne);
printf("Введите имя второго игрока - ");
scanf("%s", &nameTwo);
for(int i = 1; i <= 9; i++)
{
inputBoard();
// Если i не четное.
(i & 1) ? printf("\n\nСейчас ходит %s - ", nameOne) : printf("\n\nСейчас ходит %s - ", nameTwo);
repeat:
scanf("%d", &clickBoard);
if(i & 1) // если i не парное, то ...
{
if ((board[clickBoard-1] == 'X') || (board[clickBoard-1] == '0'))
{
puts("Вы указали на занятую клетку, попробуйте ещё раз.");
goto repeat;
}
board[clickBoard-1] = 'X';
}
else if(!(i & 1)) // если i парное, то...
{
if ((board[clickBoard-1] == 'X') || (board[clickBoard-1] == '0'))
{
puts("Вы указали на занятую клетку, попробуйте ещё раз.");
goto repeat;
}
board[clickBoard-1] = '0';
}
if(winner() == true) // если условие с крестиками истинно, то закончить цикл.
break;
else if(winner() == false)
break;
count++;
}
}Решение задачи: «Прошу критики кода, крестики-нолики»
textual
Листинг программы
Проблемы с анализом неправильного ввода в scanf хорошо известны... В таких случаях лучше все таки читать строку, а не число.