Assignments Office Hours Hall of Fame Notes
Assignments Office Hours Hall of Fame Notes

C++ TicTacToe

Assigned: 2019-10-09
Due Date: 2019-10-15 by 11:59PM U.S. Central Time

There are only two kinds of languages: the ones people complain about and the ones nobody uses.

— Bjarne Stroustrup, creator of C++

The folks at Minisoft were super impressed by your AI! You beat out all of their implementations tenfold, and management was pleased! However, they were just about to merge your AI into Mine-opoly when a troublesome email showed up from legal: some company called Orecull has slapped Minisoft with a class action lawsuit for using Java!

The next day when you get in to work, management lets you know that as a part of the settlement, Minisoft can no longer use Java going forward. But all is not lost; they found a language with a similar object-oriented design that is free for all to use: C++! Being the benevolent managers that they are, you have been given a task that you've already implemented before: writing a board checker for tic-tac-toe. Armed with your new C++ knowledge, you set off to show them what a dynamic 126-trained student can do!

Goals

Assignment Spec

Getting Started

Click here to generate your repository

IDE

For the C++ assignments this semester, we will be using the JetBrains C++ IDE: CLion. Unlike IntelliJ, there is no free version of CLion; however, you can apply for a student pack and download it free of charge. This application typically resolves in no more than a few minutes. Visit this link and use your Illinois email address. Once you verify by email, you should be able to log in to your JetBrains account, and download CLion. Make a private post on Piazza if you need help with this.

C++

C++ is a semi-object oriented language, and is somewhat similar to Java, except that it derives from C and has different memory management and compiliation processes, amongst other things. We teach C++ for the latter half of this class because you will soon be taking CS 225, a class taught entirely in C++.

This assignment focuses on strings, so learning a bit about the C++ std::string object will be useful.

Another important thing to note: C++ does not have a concept of null references/objects like Java does. The only thing that can be "null" in C++ is a pointer, which we have not yet covered in depth. For example, this Java code compiles just fine:

String moderatorName = null;

The above code compiles just fine. The following C++ code will not:

std::string moderator_name = NULL; // Error!
std::string moderator_name = nullptr; // Equally bad!

It is up to you to figure out how to design your code around this restriction.

C++ Header Files

A "header" in C++ is a file that contains a list of variable/method declarations. It provides a single place for the pre-processor to remember what signature a method should have, so when it's defined, it can ensure that it matches. Here's an example header file:

// File name: moderator.h

#ifndef MODERATOR_H
#define MODERATOR_H

#include <string>

using std::string;

namespace cs126 {
    string[] students;

    int GradeStudent(string student_netid);
    void EncourageStudents();
    bool AttendPizzaParty(int requested_slices);
}

#endif // MODERATOR_H

And an example implementation of it:

// File name: moderator.cpp

#include <iostream>
#include "moderator.h"

using std::cout;
using std::endl;

const int kMaxPizzaSlices = 3;

int GradeStudent(string student_netid) {
    return 100;
}

void EncourageStudents() {
    cout << "You can do it!" << endl;
}

bool AttendPizzaParty(int requested_slices) {
    return requested_slices <= kMaxPizzaSlices;
}

Some important things to note:

  1. The source file (moderator.cpp) includes the header file, not the other way around.
  2. The header file has inclusion guards (the #ifndef, #define, and #endif lines -- you may also see #pragma once). These prevent the header file from being preprocessed more than once, which would lead to compiler errors.

This is the intuition you should remember regarding header files:

  1. You must tell the compiler that a thing exists with a header file. In the above example, we tell the compiler about a function called GradeStudent that takes in a string and returns an int.
  2. Then, you must tell the compiler how that thing works with an implementation in a .cpp file. In this case, we provide the compiler with the definition of the function we declared earlier, so that when other parts of the codebase try to use the function declared in the .h file, the compiler knows how that function actually works.

Repeated again, but even more simply:

  1. .h/.hpp files say "this thing exists, and this is what I say it looks like" to the compiler
  2. .cpp files say "here's how this thing that I said exists actually functions" to the compiler

You must have both in order for your code to compile!

Specification

The provided function signature expects a description of the state of a tic-tac-toe board in the form of a std::string. This string should consist of 9 characters, one for each position of the board. The characters are ordered in groups of three characters (left-to-right) specifying top, middle, and bottom horizontals, as shown below:


                   0 | 1 | 2
                   ---------
 "012345678"  ->   3 | 4 | 5
                   ---------
                   6 | 7 | 8

The string is case-insensitive. Squares marked by player X are specified with an x or X, and squares marked by player O are marked with an o or O. Any other character is considered to be an empty square. For example, "o-XxxoO.z" describes this board:

 O |   | X
 ---------
 X | X | O
 ---------
 O |   |

Your implementation of EvaluateBoard should analyze the state of the specified board and return one of five Evaluation values. The values should be defined as a c++ enum. If you aren't familiar with C++ enums, here is a good reference to get started.

If the argument passed to the function doesn't correctly describe a board, your code should return InvalidInput. If the argument describes a board state, but one that is not reachable by playing a game of tic-tac-toe, then your code should return UnreachableState. If the function's argument describes a valid, reachable board state, then it should return Xwins, Owins, or NoWinner if the board is in a state where X has won, where O has won, or where no one has won, respectively.

Testing

Much like in the original assignment, this assignment has an emphasis on writing unit tests. Again, you should commit your tests first before implementing any code.

Your tests should be written using the Catch2 testing framework, in the src/main.cpp file. For this assignment, each assert should be in a separate test, since they are all independent test cases.

To learn more about Catch2, check out this tutorial.

Design and Style

You should be able to incorporate style feedback points from the feedback you got on the first week's assignment. However, since we're on a new language, there are some new style guidelines to follow. We follow the Google C++ Style Guide, which we encourage you to skim through before writing your code.