Spring 2014, The College of Saint Rose

TicTacToe Demo

A working demo of TicTacToe will appear below. Click inside the applet to interact with it.

TicTacToe BlueJ Project

TicTacToe Source Code

The Java source code for TicTacToe is below. Click on a file name to download it.

### TicTacToe.java

```import java.awt.Color;
import objectdraw.*;

/* \$Id: TicTacToe.java 2264 2013-11-26 04:31:39Z terescoj \$ */

/**
* TicTacToe game to demonstrate two-dimensional arrays.
*
* Jim Teresco, CSIS 120, Siena College
* Based on example from CS 134, Williams College
* Updated for CSC 252, The College of Saint Rose
*
*/

public class TicTacToe extends WindowController {
// Top, left corner of grid
private static final int TOP = 40;
private static final int LEFT = 40;

// Number of rows in the grid
private static final int NUM_ROWS = 3;
private static final int NUM_COLS = NUM_ROWS;

// Size of each grid square
private static final int CELL_SIZE = 40;

// Size of the marks to draw in the grid and offset from square edge
private static final int MARK_SIZE = CELL_SIZE * 3 / 4;
private static final int MARK_OFFSET = (CELL_SIZE - MARK_SIZE) / 2;

// Length of the lines making up the grid
private static final int LINE_LENGTH = CELL_SIZE * NUM_ROWS;

// Denote value of a square to show who has played there.
private static final int EMPTY = 0;
private static final int X_MARK = 1;
private static final int O_MARK = 2;

// The grid contents
private int[][] marks = new int[NUM_ROWS][NUM_COLS];

// Whose turn it is next
private int nextMark = X_MARK;

// Whether the game has been won or not
private boolean gameOver = false;

// Next player label
private Text theLabel;

/**
* Begin execution by drawing an empty grid
*/
public void begin() {
for (int i = 1; i < NUM_ROWS; i++) {
new Line(LEFT, TOP + i * CELL_SIZE,
LEFT + LINE_LENGTH, TOP + i * CELL_SIZE, canvas);
new Line(LEFT + i * CELL_SIZE, TOP,
LEFT + i * CELL_SIZE, TOP + LINE_LENGTH, canvas);
}

theLabel = new Text("X's Turn", LEFT,
(NUM_ROWS + 2) * CELL_SIZE, canvas);
theLabel.setFontSize(32);

}

/**
* Draw an X with the given upper left hand corner to fill
* a space MARK_SIZE x MARK_SIZE in the Tic-Tac-Toe board
*
* @param left the x coordinate of the upper-left corner of the X
* @param top the y coordinate of the upper-left corner of the X
*/
private void drawX(int left, int top) {
new Line(left, top, left + MARK_SIZE, top + MARK_SIZE, canvas);
new Line(left + MARK_SIZE, top, left, top + MARK_SIZE, canvas);
}

/**
* Draw an O with the given upper left hand corner to fill
* a space MARK_SIZE x MARK_SIZE in the Tic-Tac-Toe board
*
* @param left the x coordinate of the upper-left corner of the O
* @param top the y coordinate of the upper-left corner of the O
*/
private void drawO(int left, int top) {
new FramedOval(left, top, MARK_SIZE, MARK_SIZE, canvas);
}

/**
* Draw the appropriate mark in the appropriate row/col in
* the Tic-Tac-Toe board
*
* @param row the row number (0, 1, 2) of the cell to mark
* @param col the column number (0, 1, 2) of the cell to mark
* @param mark what to mark, X_MARK or O_MARK
*/
private void drawMark(int row, int col, int mark) {
if (mark == X_MARK) {
drawX(LEFT + col * CELL_SIZE + MARK_OFFSET,
TOP + row * CELL_SIZE + MARK_OFFSET);
} else {
drawO(LEFT + col * CELL_SIZE + MARK_OFFSET,
TOP + row * CELL_SIZE + MARK_OFFSET);
}
}

/**
* Place the next mark at the click point and check for a win.
* If the click is within a cell of the Tic-Tac-Toe board and
* that cell is not already occupied, the current player's
* mark is placed in that cell and we check to see if the player
* has now won.
*
* @param point the Location where the mouse was pressed
*/
public void onMousePress(Location point) {
double x = point.getX();
double y = point.getY();

// Ignore clicks outside the grid
if (x > LEFT && x < LEFT + LINE_LENGTH &&
y > TOP && y < TOP + LINE_LENGTH) {

// Figure out which cell in the grid was clicked in
int col = (int) ((x - LEFT) / CELL_SIZE);
int row = (int) ((y - TOP) / CELL_SIZE);

// Make sure the grid is empty before adding a mark.
// Also make sure the game is not already over
if (marks[row][col] == EMPTY && !gameOver) {
// Add the mark
marks[row][col] = nextMark;

drawMark(row, col, nextMark);

// See if the game is won
if (checkGameWon(row, col, nextMark)) {
if (nextMark == X_MARK) {
theLabel.setText("X Wins!");
} else {
theLabel.setText("O Wins!");
}
gameOver = true;
}

// see if it's a tie
if (!gameOver && checkAllFilled()) {
theLabel.setText("It's a tie!");
gameOver = true;
}

if (!gameOver) {
// switch players
if (nextMark == X_MARK) {
nextMark = O_MARK;
theLabel.setText("O's Turn");
} else {
nextMark = X_MARK;
theLabel.setText("X's Turn");
}
}
}
}
}

/**
* Check to see if the game is won as a result of a mark being placed
* at position row, col.  The game is over if an entire row, column, or
* diagonal has the same pieces.
*
* @param row the row number (0, 1, 2) of the cell just marked
* @param col the column number (0, 1, 2) of the cell just marked
* @param matchMark the mark, X_MARK or O_MARK, just placed
*
* @return true if the current player now has won the game, false otherwise
*/
private boolean checkGameWon(int row, int col, int matchMark) {
return checkForRowWin(row, matchMark)
|| checkForColWin(col, matchMark)
|| checkForDiagWin(matchMark)
|| checkForDiag2Win(matchMark);
}

/**
* Check to see if the game is a tie: all positions are occupied,
* but no one has won.
*
* @return true if all positions are occupied
*/
private boolean checkAllFilled() {
for (int row = 0; row < NUM_ROWS; row++) {
for (int col = 0; col < NUM_COLS; col++) {
if (marks[row][col] == EMPTY) {
return false;
}
}
}
return true;
}

/**
* Check for a win in the given row by the player with the
* given mark.
*
* @param row the row number to check
* @param matchMark the mark, X_MARK or O_MARK, just placed
*
* @return whether the given row contains all matchMark entries
*/
private boolean checkForRowWin(int row, int matchMark) {
for (int col = 0; col < NUM_COLS; ++col) {
if (marks[row][col] != matchMark) {
return false;
}
}
return true;
}

/**
* Check for a win in the given column by the player with the
* given mark.
*
* @param col the column number to check
* @param matchMark the mark, X_MARK or O_MARK, just placed
*
* @return whether the given column contains all matchMark entries
*/
private boolean checkForColWin(int col, int matchMark) {
for (int row=0; row < NUM_ROWS; ++row) {
if (marks[row][col] != matchMark) {
return false;
}
}
return true;
}

/**
* Check for a win in the main diagonal by the player with the
* given mark.  This is the diagonal from the top left to bottom right.
*
* @param matchMark the mark, X_MARK or O_MARK, just placed
*
* @return whether the main diagonal contains all matchMark entries
*/
private boolean checkForDiagWin(int matchMark) {
for (int i = 0; i < NUM_COLS; ++i) {
if (marks[i][i] != matchMark) {
return false;
}
}
return true;
}

/**
* Check for a win in the off diagonal by the player with the
* given mark.  This is the diagonal from the bottom left to top right.
*
* @param matchMark the mark, X_MARK or O_MARK, just placed
*
* @return whether the off diagonal contains all matchMark entries
*/
private boolean checkForDiag2Win(int matchMark) {
for (int i = 0; i < NUM_ROWS; ++i) {
if (marks[i][NUM_ROWS-i-1] != matchMark) {
return false;
}
}
return true;
}

}
```
{"ft_lang_label":"__label__en","ft_lang_prob":0.6281429,"math_prob":0.974087,"size":7402,"snap":"2019-13-2019-22","text_gpt3_token_len":1991,"char_repetition_ratio":0.13544202,"word_repetition_ratio":0.28739002,"special_character_ratio":0.30883545,"punctuation_ratio":0.13457249,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.96430475,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2019-05-19T12:35:09Z\",\"WARC-Record-ID\":\"<urn:uuid:146a779f-d8ed-4b8b-89a6-78f01f158185>\",\"Content-Length\":\"11251\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:8886f5c2-99b3-4a8b-9f0e-0e695d3703aa>\",\"WARC-Concurrent-To\":\"<urn:uuid:b962694a-5dbd-42ab-9e93-f1bc03c6cf17>\",\"WARC-IP-Address\":\"199.223.244.7\",\"WARC-Target-URI\":\"http://courses.teresco.org/cs252_s14/examples/TicTacToe/\",\"WARC-Payload-Digest\":\"sha1:5LYFFMF6RMFC7Q6ZORH7IZCOC42ZFAZ7\",\"WARC-Block-Digest\":\"sha1:LMSOEJS5CIDMGQDSQWVXFJOP7NJVDC7S\",\"WARC-Identified-Payload-Type\":\"application/xhtml+xml\",\"warc_filename\":\"/cc_download/warc_2019/CC-MAIN-2019-22/CC-MAIN-2019-22_segments_1558232254882.18_warc_CC-MAIN-20190519121502-20190519143502-00421.warc.gz\"}"}