COMP1917 Computing 1
Session 2, 2016

Lab - Week 5


In this lab you will be writing a program to scan and print a Tic-Tac-Toe (Noughts and Crosses) board, and determine whether the game has been won (and by which player).
  1. Create a directory called lab5, and cd to this directory.

  2. Write a program ttt.c that scans a Tic-Tac-Toe board from standard input, stores it in a 2D array and prints it to standard output. When scanning the board, you should assume that 0 stands for NOUGHTS, 1 for CROSSES and 2 for an EMPTY cell. Your program should use two functions
    void  scanBoard( int board[SIZE][SIZE] );
    void printBoard( int board[SIZE][SIZE] );
    
    You should use the file ttt.c in this lab5 directory as a starting point. Here's how the input and output of your program should look:
    $ ./ttt
    Please enter the board:
    2 1 0
    0 1 1
    2 0 2
    Here is the board:
     . X O
     O X X
     . O .
    
  3. Now change the SIZE of the board to 4 or 5, by editing the #define statement at the top of the file. Does your program work properly for the larger boards? Try to write your code so that it does.

  4. Now extend your program so that, after printing the board, it figures out whether the game has been won and prints "Crosses Win", "Noughts Win" or "No Winner", as appropriate. You should do this by implementing a function
    int getWinner( int board[SIZE][SIZE] );
    
    which returns either NOUGHTS, CROSSES or NONE. Try to write your code so that it works for any SIZE of board. [Note: you do not need to consider the case where both players have achieved a full row, column or diagonal at the same time, since this can never occur in an actual game.]

  5. Show your work to your tutor and submit it using
    $ give cs1917 lab5 ttt.c
    
    The give script will test your program on the sample inputs provided in the lab5 directory. You should also test your program on some other inputs of your own invention.

  6. Bonus Challenge: In this challenge you are going to implement a simplified version of Game of Life.

    How to GoL:

    For this you are going to need two constants. The first, WORLD_SIZE is the number of cells, each represented by a character on your screen, that your world contains. Each of these cells may either be LIVE or DEAD. You will also want GENERATIONS, which will simply be the number of generations your program will simulate.

    Your world will be simulated in two buffers (or arrays). The first will be last, which represents the state of all the cells in the previous generation. Based on the state of the cells in this array, you need to generate the state of the array curr, which represents the state of all the cells in the following generation.

    There are a few rules that determine whether a cell is LIVE or DEAD in a given generation, as follows. For all cells where n is the index for a cell in that array:

    1. If last[n] is DEAD: if last[n] is adjacent to one or two LIVE cells: curr[n] becomes LIVE; otherwise it remains DEAD.
    2. If last[n] is LIVE: if last[n] is not adjacent to exactly one LIVE cell: curr[n] becomes DEAD; otherwise it remains LIVE.

    The first generation is given in the sample code.

    The major part of the engine has already been written for you and available here. Your task is to write function void iterate(char *last, char *next) that populates the buffer next based on last according to the above rules. You can find a sample output for default state here. Additionally, you can modify the initial state of the buffer (see the line // Add life) to generate different patterns, or change the WORLD_SIZE or the number of GENERATIONS to simulate. You can also see how changing the rules for generating each generation change the ways that patterns are produced.

    PS: Credit for this awesome challenge goes to Curtis Millar. Say thanks if you see him.