Last active
August 16, 2019 14:48
-
-
Save stereosteve/b857ff1ff975e32fe0d821b5821b2ece to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const Mark = enum(u2) { | |
Empty, | |
X, | |
O, | |
}; | |
const Game = struct { | |
board: [3][3]Mark, | |
turn: Mark, | |
pub fn init() Game { | |
return Game{ | |
.board = [3][3]Mark{ | |
[3]Mark{ .Empty, .Empty, .Empty }, | |
[3]Mark{ .Empty, .Empty, .Empty }, | |
[3]Mark{ .Empty, .Empty, .Empty }, | |
}, | |
.turn = .X, | |
}; | |
} | |
pub fn print(self: Game) void { | |
std.debug.warn("\n---------\n"); | |
for (self.board) |row| { | |
for (row) |cell, column_index| { | |
const m = switch (cell) { | |
.X => "X", | |
.O => "O", | |
.Empty => "-", | |
}; | |
const sep = if (column_index == 2) "\n" else " | "; | |
std.debug.warn("{}{}", m, sep); | |
} | |
} | |
std.debug.warn("---------\n"); | |
} | |
fn checkWinner(self: Game) Mark { | |
for (self.board) |row, i| { | |
if (row[0] != .Empty and row[0] == row[1] and row[0] == row[2]) | |
return row[0]; | |
if (self.board[0][i] != .Empty and self.board[0][i] == self.board[1][i] and self.board[0][i] == self.board[2][i]) | |
return self.board[0][i]; | |
} | |
const mid = self.board[1][1]; | |
if (mid != .Empty and self.board[0][0] == mid and self.board[2][2] == mid) | |
return mid; | |
if (mid != .Empty and self.board[0][2] == mid and self.board[2][0] == mid) | |
return mid; | |
return .Empty; | |
} | |
fn isBoardFull(self: Game) bool { | |
for (self.board) |row| { | |
for (row) |cell| { | |
if (cell == .Empty) { | |
return false; | |
} | |
} | |
} | |
return true; | |
} | |
fn makeMove(self: *Game, cell_number: usize) !void { | |
var i: usize = 0; | |
for (self.board) |row, row_index| { | |
for (row) |cell, column_index| { | |
i += 1; | |
if (i != cell_number) continue; | |
if (cell != .Empty) return error.CellFull; | |
self.board[row_index][column_index] = self.turn; | |
self.turn = if (self.turn == .X) Mark.O else Mark.X; | |
} | |
} | |
} | |
}; | |
test "checkWinner" { | |
const testing = std.testing; | |
{ | |
var g = Game.init(); | |
testing.expect(g.checkWinner() == .Empty); | |
g.board[0][0] = .X; | |
g.board[0][1] = .X; | |
g.board[0][2] = .X; | |
g.print(); | |
testing.expect(g.checkWinner() == .X); | |
} | |
{ | |
var g = Game.init(); | |
testing.expect(g.checkWinner() == .Empty); | |
g.board[0][0] = .X; | |
g.board[1][0] = .X; | |
g.board[2][0] = .X; | |
g.print(); | |
testing.expect(g.checkWinner() == .X); | |
} | |
{ | |
var g = Game.init(); | |
testing.expect(g.checkWinner() == .Empty); | |
g.board[0][0] = .O; | |
g.board[1][1] = .O; | |
g.board[2][2] = .O; | |
g.print(); | |
testing.expect(g.checkWinner() == .O); | |
} | |
{ | |
var g = Game.init(); | |
testing.expect(g.checkWinner() == .Empty); | |
var i: usize = 1; | |
while (i < 10) { | |
try g.makeMove(i); | |
i += 1; | |
} | |
g.print(); | |
testing.expect(g.isBoardFull()); | |
} | |
} | |
pub fn main() void { | |
var bytes: [100]u8 = undefined; | |
var g = Game.init(); | |
g.print(); | |
while (true) { | |
std.debug.warn("\n{} Enter square 1 - 9: ", g.turn); | |
const got = std.io.readLineSlice(bytes[0..]) catch |err| { | |
std.debug.warn("Invalid number, try again. \n"); | |
continue; | |
}; | |
const n = std.fmt.parseUnsigned(u8, got, 10) catch |err| { | |
std.debug.warn("Invalid number, try again. \n"); | |
continue; | |
}; | |
if (n < 1 or n > 9) { | |
std.debug.warn("Invalid number, try again. \n"); | |
continue; | |
} | |
g.makeMove(n) catch |err| { | |
std.debug.warn(" Cell already occupied: {} \n", err); | |
}; | |
g.print(); | |
const winner = g.checkWinner(); | |
if (winner != .Empty) { | |
std.debug.warn("\n !!! Winner: {} !!! \n", winner); | |
break; | |
} | |
if (g.isBoardFull()) { | |
std.debug.warn("\n Stalemate \n"); | |
break; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment