Игра Tic Tac Toe в C застрял в цикле при поиске случайного числа для противника - PullRequest
0 голосов
/ 10 ноября 2018

Я начал C, и я пытаюсь написать крестики-нолики с оппонентом, который ищет случайное число от 1 до 9, а затем заполняет слот буквой «O». Однако, когда случайное число обнаруживает занятый слот, оно продолжит заполнять другие пустые слоты, не давая игроку хода. Как мне решить эту проблему?

Я сделал два массива, один для экрана игры, один для памяти слотов.

Я сожалею, что не смог выбросить код, так как думал, что это все важно, и есть ли лучший способ сделать это? Извините за мой стиль письма, если он немного сбивает с толку, и я думаю, что есть неважные переменные.

Вот мой код:

#include <stdio.h>
#include <stdlib.h> 
#include <time.h>

char values[3][4] = {  // screen board
    {46, 46, 46,'\n'},
    {46, 46, 46,'\n'},
    {46, 46, 46,'\n'}
};

double memory[3][4] = { // memory board to put values
    {0, 0, 0,'\n'},
    {0, 0, 0,'\n'},
    {0, 0, 0,'\n'}
};

int player(int i, char values[3][4]) {
    int input;

    printf("enter position: ");
    scanf("%i", &input);

    int x = (((input) / 3.3) - 3) * -1; //  important math to convert to num
    int y = (input + 2) % 3;            //  important math to convert to num

    if (memory[x][y] == 0) {
        values[x][y] = 'X';
        memory[x][y] = 1;

        printf("%s", values);
        getchar();
        return 0;
        getchar();
    } else {
        printf("Wrong!, choose another line\n");
        printf("%s", values);

        getchar();

        player(i, values);
    }
}


int opponent(char values[3][4]) {  //function opponent
    int count = 0;
    srand(time(NULL));

    int random = (rand() % 9) + 1;   // create random number

    for (count = 0; count < 9; count++) {
        int x = (((random) / 3.3) - 3) * -1;
        int y = (random + 2) % 3;

        if (memory[x][y] == 0) {  // if memory is empty, do the following, loop stucks here
            values[x][y] = 'O';
            memory[x][y] = 2;

            printf("Opponent Move\n");
            printf("%s", values);

            count++;

            return 0;
        } else {            // if memory is not 0, do this. Error starts here
            getchar();
            printf("Move is %i", random);

            opponent(values);       // it calls itself to do a loop, 
        }
    }
}

int main() {
    int input;
    int i = 2;;

    for (i = 2; i < 9; i++) {   
        player(i, values);  //Player goes first
        getchar();
        opponent(values);   
    }
}

1 Ответ

0 голосов
/ 10 ноября 2018

Вместо двух независимых values и memory используйте массив enum для представления игровой карты.

enum Square { VACANT, X, O } squares[3][3], move = X;

Инициализируется согласно Инициализация статических переменных в C .

Возможно, вам нужна функция, чтобы определить, выиграл ли игрок,

/* Checks if the player who's move it was won. */
static int is_win(void) {
    return (squares[0][0]==move && squares[0][1]==move && squares[0][2]==move)||
        (squares[1][0]==move && squares[1][1]==move && squares[1][2]==move)||
        (squares[2][0]==move && squares[2][1]==move && squares[2][2]==move);
    /* Etc. */
}

А также функция печати на плате

static const char letters[] = { '/', 'X', 'O' };

static void print_board(void) {
    printf("%c %c %c\n%c %c %c\n%c %c %c\n",
        letters[squares[0][0]], letters[squares[0][1]], letters[squares[0][2]],
        letters[squares[1][0]], letters[squares[1][1]], letters[squares[1][2]],
        letters[squares[2][0]], letters[squares[2][1]], letters[squares[2][2]]);
}

Код, который у вас есть, затеняет глобальное состояние с помощью параметров функций. Это очень запутанно. Подумайте, нужен ли вам параметр для работы функции. Когда у вас сложные состояния, которые определены в нескольких файлах, вероятно, лучше всего иметь игровой объект с агломерацией, но для простых игр я думаю, что хорошо иметь глобальное состояние.

Вместо того, чтобы играть до 7 ходов, используйте простой конечный автомат, чтобы отслеживать состояние игры. Можно typedef функции ( Как работают указатели функций в C? ) player и opponent и помещать их в статический массив, чтобы значительно упростить игровой цикл. Рассмотрим,

/* Move returns whether we should continue. */
typedef int (*Move)(void);

/* Implements Move. */
static int player(void) {
    printf("player:\n");
    /* FIXME: player move. */
    return is_win() ? 0 : (move = O, 1);
}

/* Implements Move. */
static int opponent(void) {
    printf("opp:\n");
    /* FIXME: Chose randomly from all of it's allowed moves? */
    return is_win() ? 0 : (move = X, 1);
}

static const Move states[] = { 0, &player, &opponent };

Тогда твой главный просто,

int main(void) {
    while(states[move]()) print_board();
    printf("%c wins.\n", letters[move]);
    return 0;
}

Редактировать: Определенно есть состояние, где это ничья, возможно, когда не осталось ходов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...