tictactoe.c

Denna kod är public domain. Om ni hittar fel eller vill ändra något i koden blir jag jätteglad om ni skickar dessa ändringar till jesper [at] fantasi [punkt] se.


/*
 * Tic Tac Toe - Tre i rad.
 * Flytta markören och placera ut pjäser genom att skicka kommandon till spelet.
 * Varje kommando består av ett tecken som definieras nedan. Skriv kommandon
 * och tryck enter för att skicka dem till spelet.
 */

#include<stdio.h>

/* Kommandon för att styra spelet. */
#define RIGHT  's'
#define LEFT   'a'
#define UPP    'e'
#define DOWN   'd'
#define ENTER  'f'

/* Antal rutor på en rad. Planen är alltid kvadratisk. */
#define SIDE  3

/* Hjälpmakron */
#define INC(pos) (++pos == SIDE) ? --pos : pos
#define DEC(pos) (pos-- == 0) ? ++pos : pos

/* ANSI-koder för att flytta markören och byta färger. */
#define CLEAR_SCREEN     "\033[2J"
#define HOME             "\033[H"
#define MOVE_DOWN        "\033[B"
#define MOVE_RIGHT       "\033[C"
#define GREEN_TEXT       "\033[32m"
#define RED_TEXT         "\033[31m"

/* En bool är bra att ha. */
typedef enum bool
{
    FALSE = 0,
    TRUE
} bool;

/* Spelplanen. */
static int board[SIDE][SIDE];

/*
 * Ritar ut spelplanen.
 */
static void paintboard()
{
    int x, y;

    printf(HOME);
    printf(GREEN_TEXT);

    for (x = 0; x < SIDE; x++)
        printf("+---");
    printf("+\n");

    for (y = 0; y < SIDE; y++)
    {
        for (x = 0; x < SIDE; x++)
            printf("|   ");
        printf("|\n");
        for (x = 0; x < SIDE; x++)
        {
            printf("| ");
            printf(RED_TEXT);
            printf("%c ",(board[x][y] == 0) ? ' ' :
                   (board[x][y] == 1) ? 'X' : 'Y');
            printf(GREEN_TEXT);
        }
        printf("|\n");
        for (x = 0; x < SIDE; x++)
            printf("|   ");
        printf("|\n");
        for (x = 0; x < SIDE; x++)
            printf("+---");
        printf("+\n");
    }
}

/*
 * Flytta markören till position {x,y}.
 */
static void moveto(int x, int y)
{
    int i;

    printf(HOME);

    /* Alla rutor är fyra tecken breda och höga. *
     * +2 för att flytta till mitten av rutan.   */
    x *= 4; x += 2;
    y *= 4; y += 2;

    for (i = 0; i < x; i++)
        printf(MOVE_RIGHT);

    for (i = 0; i < y; i++)
        printf(MOVE_DOWN);
}

/*
 * Returnerar TRUE om spelare p har gjort ett vinnande drag.
 */
static bool winner(int p)
{
    int i;
    int diag1 = 0;
    int diag2 = 0;

    for (i = 0; i < SIDE; i++)
    {
        int j;
        int linesum = 0;
        int colsum = 0;

        for (j = 0; j < SIDE - 1; j++)
        {
            if (board[i][j] == board[i][j + 1])
                linesum++;
            if (board[j][i] == board[j + 1][i])
                colsum++;
        }

        if ((linesum == SIDE - 1) && (board[i][0] == p))
            return TRUE;

        if ((colsum == SIDE - 1) && (board[0][i] == p))
            return TRUE;

        if (i != 0 && board[i][i] == board[i - 1][i - 1])
            diag1++;
        if (i != 0 && board[i][SIDE - (i + 1)] == board[i - 1][SIDE - i])
            diag2++;
    }
    return ((diag1 == SIDE - 1) && (board[0][0] == p)) ||
           ((diag2 == SIDE - 1) && (board[0][SIDE - 1] == p));
}

/*
 * Här startar programmet.
 */
int main(void)
{
    int player;
    int x_pos, y_pos;
    int i, j;

    for (i = 0; i < 3; i++)
        for (j = 0; j < 3; j++)
            board[j][i] = 0;

    printf(CLEAR_SCREEN);

    /* Loopen läser in kommandon från tangentbordet tills vi har en vinnare. */
    x_pos = 1;
    y_pos = 1;
    player = 2;
    while (!winner(player))
    {
        int ch;

        paintboard();
        moveto(x_pos,y_pos);
        ch = getchar();
        switch(ch)
        {
            case LEFT:  DEC(x_pos); break;
            case RIGHT: INC(x_pos); break;
            case UPP:   DEC(y_pos); break;
            case DOWN:  INC(y_pos); break;
            case ENTER:
                if (board[x_pos][y_pos] == 0)
                {
                    player = 3 - player;
                    board[x_pos][y_pos] = player;
                }
                break;
        }
    }

    paintboard();
    printf("The winner is player %d\n",player);
    return 0;
}