HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

First Tic Tac Toe game

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
toetictacfirstgame

Problem

I've been learning Objective C for a few days so to test my skills I went ahead and made a simple Tic Tac Toe game using the console. I already have some experience with languages such as C++, Java and Python so I'm familiar with most of the concepts in Obj C.

How it works

  • The player chooses their token (x or o)



  • The player puts in the x and y coordinates of their token piece



  • The computer makes its move



  • Repeat 2 and 3 until someone wins



```
#import
#include

// Game class
@interface Game : NSObject{
BOOL isPlayersTurn;
// players tokens (x or o)
char playerToken;
char computerToken;
// 2d array stores tile values
char board[3][3];
}

@end

@implementation Game
-(id)init{
self = [super init];

isPlayersTurn = YES;

// choosing players token
while(!(playerToken=='x' || playerToken=='o')){
NSLog(@"Choose your token (must be either x or o)");
scanf("%c",&playerToken);
}
// computer token is opposite of player token
computerToken = playerToken=='x'?'o':'x';

// set tiles of board to empty
for(int i=0; i<3; i++){
for(int j=0; j<3; j++){
board[i][j] = ' ';
}
}

return self;
}

-(BOOL)finished{
// check if someone has won
for(int i = 0; i < 3; i++){
// checks columns and rows
if(board[i][0]==board[i][1]&&board[i][1]==board[i][2]&&board[i][0]!=' '){
return true;
}
if(board[0][i]==board[1][i]&&board[1][i]==board[2][i]&&board[0][i]!=' '){
return true;
}
// check diagonals
if(board[0][0]==board[1][1]&&board[1][1]==board[2][2]&&board[0][0]!=' '){
return true;
}
if(board[2][0]==board[1][1]&&board[1][1]==board[0][2]&&board[2][0]!=' '){
return true;
}
}

return false;

Solution

Some additional points:

In -(void)makeMoves, the initial values of

int x;
int y;


are undefined, and testing their values in all the three while loops
in that method is undefined behavior. Let's consider the last
loop as an example:

// loop through until random tile is chosen that isn't already taken
while(board[(int)y-1][(int)x-1]!=' '){
    x = arc4random()%3;
    y = arc4random()%3;
}
board[(int)y-1][(int)x-1] = computerToken;


The values of x and y are undefined when the loop is entered,
so this can easily crash your program or give a nonsensical result.

You should use a do { } while () loop instead:

do {
    x = arc4random() % 3;
    y = arc4random() % 3;
} while (board[(int)y-1][(int)x-1] != ' ')
board[(int)y-1][(int)x-1] = computerToken;


Now x and y are initialized before being tested. The same applies
to the other while-loops in that method.

But there is another error: The array indices in board[][]
run from 0 to 2, and that is exactly what arc4random() % 3
returns. Subtracting one from x and y is wrong here!
And the (int) cast is also not necessary:

do {
    x = arc4random() % 3;
    y = arc4random() % 3;
} while (board[y][x] != ' ')
board[y][x] = computerToken;


Also note that arc4random_uniform() is preferred over
arc4random when creating random integers in a range, to avoid
the so-called "modulo bias" (see e.g.
Why do people say there is modulo bias when using a random number generator?
or Arc4random modulo biased).

do {
    x = arc4random_uniform(3);
    y = arc4random_uniform(3);
} while (board[y][x] != ' ')
board[y][x] = computerToken;


This

// winner is person who just had their move
NSLog([isPlayersTurn?@"Computer":@"Player" stringByAppendingString:@" wins!"]);


is not correct, because the game can be a tie (nobody wins).

Finally: NSLog() prints a timestamp, process name and process id
which each output. I would use a simple printf() instead to
print to the console, e.g.

printf("Choose your x coordinate\n");

Code Snippets

int x;
int y;
// loop through until random tile is chosen that isn't already taken
while(board[(int)y-1][(int)x-1]!=' '){
    x = arc4random()%3;
    y = arc4random()%3;
}
board[(int)y-1][(int)x-1] = computerToken;
do {
    x = arc4random() % 3;
    y = arc4random() % 3;
} while (board[(int)y-1][(int)x-1] != ' ')
board[(int)y-1][(int)x-1] = computerToken;
do {
    x = arc4random() % 3;
    y = arc4random() % 3;
} while (board[y][x] != ' ')
board[y][x] = computerToken;
do {
    x = arc4random_uniform(3);
    y = arc4random_uniform(3);
} while (board[y][x] != ' ')
board[y][x] = computerToken;

Context

StackExchange Code Review Q#121347, answer score: 2

Revisions (0)

No revisions yet.