Time for an 2014 update…

This commit is contained in:
Ingy döt Net 2014-01-17 05:32:22 +00:00
parent 372c577f83
commit 09687c4926
2520 changed files with 34227 additions and 7318 deletions

View file

@ -1,48 +1,44 @@
import std.stdio, std.string, std.algorithm, std.conv,
std.random, std.ascii, std.array, std.range;
import std.stdio, std.string, std.algorithm, std.conv, std.random,
std.ascii, std.array, std.range, std.math;
struct GameBoard {
dchar[9] board = "123456789";
enum : char { human = 'X', computer = 'O' }
enum : dchar { human = 'X', computer = 'O' }
enum Game { going, humanWins, computerWins, draw }
const pure nothrow invariant() {
int nHuman = 0, nComputer = 0;
foreach (immutable i, immutable c; board)
if (c.isDigit)
assert(i == c - '1'); // in correct position?
else
assert(i == c - '1'); // In correct position?
else {
assert(c == human || c == computer);
(c == human ? nHuman : nComputer)++;
}
assert(abs(nHuman - nComputer) <= 1);
}
string toString() const pure {
return format("%(%-(%s|%)\n-+-+-\n%)", board.dup.chunks(3));
return format("%(%-(%s|%)\n-+-+-\n%)", board[].chunks(3));
}
bool isAvailable(in int i) const pure nothrow {
if (i < 0 || i >= 9)
return false;
return board[i].isDigit;
return i >= 0 && i < 9 && board[i].isDigit;
}
int[] availablePositions() const pure nothrow {
// not pure not nothrow:
//return 9.iota.filter!(i => board[i].isDigit).array;
int[] result;
foreach (immutable i; 0 .. 9)
if (isAvailable(i))
result ~= i;
return result;
return 9.iota.filter!(i => isAvailable(i)).array;
}
Game winner() const pure nothrow {
immutable wins = [[0, 1, 2], [3, 4, 5], [6, 7, 8],
[0, 3, 6], [1, 4, 7], [2, 5, 8],
[0, 4, 8], [2, 4, 6]];
static immutable wins = [[0, 1, 2], [3, 4, 5], [6, 7, 8],
[0, 3, 6], [1, 4, 7], [2, 5, 8],
[0, 4, 8], [2, 4, 6]];
foreach (immutable win; wins) {
immutable bw0 = board[win[0]];
if (bw0.isDigit)
continue; // nobody wins on this one
continue; // Nobody wins on this one.
if (bw0 == board[win[1]] && bw0 == board[win[2]])
return bw0 == GameBoard.human ?
@ -53,16 +49,16 @@ struct GameBoard {
return availablePositions.empty ? Game.draw: Game.going;
}
bool finished() const pure nothrow {
bool isFinished() const pure nothrow {
return winner != Game.going;
}
int computerMove() const // random move
int computerMove() const // Random move.
out(res) {
assert(res >= 0 && res < 9 && isAvailable(res));
} body {
// return choice(availablePositions());
return randomCover(availablePositions, rndGen).front;
// return availablePositions.choice;
return availablePositions[uniform(0, $)];
}
}
@ -71,7 +67,7 @@ GameBoard playGame() {
GameBoard board;
bool playsHuman = true;
while (!board.finished) {
while (!board.isFinished) {
board.writeln;
int move;
@ -85,7 +81,7 @@ GameBoard playGame() {
return board;
} while (!board.isAvailable(move));
} else
move = board.computerMove();
move = board.computerMove;
assert(board.isAvailable(move));
writefln("\n%s chose %d", playsHuman ? "You" : "I", move + 1);
@ -99,21 +95,21 @@ GameBoard playGame() {
void main() {
writeln("Tic-tac-toe game player.\n");
"Tic-tac-toe game player.\n".writeln;
immutable outcome = playGame.winner;
final switch (outcome) {
case GameBoard.Game.going:
writeln("Game stopped.");
"Game stopped.".writeln;
break;
case GameBoard.Game.humanWins:
writeln("\nYou win!");
"\nYou win!".writeln;
break;
case GameBoard.Game.computerWins:
writeln("\nI win.");
"\nI win.".writeln;
break;
case GameBoard.Game.draw:
writeln("\nDraw");
"\nDraw".writeln;
break;
}
}

View file

@ -0,0 +1,105 @@
-module(tic_tac_toe).
-export( [task/0] ).
task() -> io:fwrite( "Result: ~p.~n", [turn(player(random:uniform()), board())] ).
board() -> [{X, erlang:integer_to_list(X)} || X <- lists:seq(1, 9)].
board_tuples( Selections, Board ) -> [lists:keyfind(X, 1, Board) || X <- Selections].
computer_move( Player, Board ) ->
[N | _T] = lists:flatten( [X(Player, Board) || X <- [fun computer_move_win/2, fun computer_move_block/2, fun computer_move_middle/2, fun computer_move_random/2]] ),
N.
computer_move_block( Player, Board ) -> computer_move_two_same_player( player(false, Player), Board ).
computer_move_middle( _Player, Board ) ->
{5, Y} = lists:keyfind( 5, 1, Board ),
computer_move_middle( is_empty(Y) ).
computer_move_middle( true ) -> [5];
computer_move_middle( false ) -> [].
computer_move_random( _Player, Board ) ->
Ns = [X || {X, Y} <- Board, is_empty(Y)],
[lists:nth( random:uniform(erlang:length(Ns)), Ns )].
computer_move_two_same_player( Player, Board ) ->
Selections = [X || X <- three_in_row_all(), is_two_same_player(Player, X, Board)],
computer_move_two_same_player( Player, Board, Selections ).
computer_move_two_same_player( _Player, _Board, [] ) -> [];
computer_move_two_same_player( _Player, Board, [Selection | _T] ) -> [X || {X, Y} <- board_tuples(Selection, Board), is_empty(Y)].
computer_move_win( Player, Board ) -> computer_move_two_same_player( Player, Board ).
is_empty( Square ) -> Square =< "9". % Do not use < "10".
is_finished( Board ) -> is_full( Board ) orelse is_three_in_row( Board ).
is_full( Board ) -> [] =:= [X || {X, Y} <- Board, is_empty(Y)].
is_three_in_row( Board ) ->
Fun = fun(Selections) -> is_three_in_row_same_player( board_tuples(Selections, Board) ) end,
lists:any( Fun, three_in_row_all() ).
is_three_in_row_same_player( Selected ) -> three_in_row_player( Selected ) =/= no_player.
is_two_same_player( Player, Selections, Board ) -> is_two_same_player( Player, [{X, Y} || {X, Y} <- board_tuples(Selections, Board), not is_empty(Y)] ).
is_two_same_player( Player, [{_X, Player}, {_Y, Player}] ) -> true;
is_two_same_player( _Player, _Selected ) -> false.
player( Random ) when Random > 0.5 -> "O";
player( _Random ) -> "X".
player( true, _Player ) -> finished;
player( false, "X" ) -> "O";
player( false, "O" ) -> "X".
result( Board ) -> result( is_full(Board), Board ).
result( true, _Board ) -> draw;
result( false, Board ) ->
[Winners] = [Selections || Selections <- three_in_row_all(), three_in_row_player(board_tuples(Selections, Board)) =/= no_player],
"Winner is " ++ three_in_row_player( board_tuples(Winners, Board) ).
three_in_row_all() -> three_in_row_horisontal() ++ three_in_row_vertical() ++ three_in_row_diagonal().
three_in_row_diagonal() -> [[1,5,9], [3,5,7]].
three_in_row_horisontal() -> [[1,2,3], [4,5,6], [7,8,9]].
three_in_row_vertical() -> [[1,4,7], [2,5,8], [3,6,9]].
three_in_row_player( [{_X, Player}, {_Y, Player}, {_Z, Player}] ) -> three_in_row_player( not is_empty(Player), Player );
three_in_row_player( _Selected ) -> no_player.
three_in_row_player( true, Player ) -> Player;
three_in_row_player( false, _Player ) -> no_player.
turn( finished, Board ) -> result( Board );
turn( "X"=Player, Board ) ->
N = computer_move( Player, Board ),
io:fwrite( "Computer, ~p, selected ~p~n", [Player, N] ),
New_board = [{N, Player} | lists:keydelete(N, 1, Board)],
turn( player(is_finished(New_board), Player), New_board );
turn( "O"=Player, Board ) ->
[turn_board_write_horisontal(X, Board) || X <- three_in_row_horisontal()],
Ns = [X || {X, Y} <- Board, is_empty(Y)],
Prompt = lists:flatten( io_lib:format("Player, ~p, select one of ~p: ", [Player, Ns]) ),
N = turn_next_move( Prompt, Ns ),
New_board = [{N, Player} | lists:keydelete(N, 1, Board)],
turn( player(is_finished(New_board), Player), New_board ).
turn_board_write_horisontal( Selections, Board ) ->
Tuples = [lists:keyfind(X, 1, Board) || X <- Selections],
[io:fwrite( "~p ", [Y]) || {_X, Y} <- Tuples],
io:fwrite( "~n" ).
turn_next_move( Prompt, Ns ) ->
{ok,[N]} = io:fread( Prompt, "~d" ),
turn_next_move_ok( lists:member(N, Ns), Prompt, Ns, N ).
turn_next_move_ok( true, _Prompt, _Ns, N ) -> N;
turn_next_move_ok( false, Prompt, Ns, _N ) -> turn_next_move( Prompt, Ns ).

View file

@ -0,0 +1,474 @@
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
//Make sure the name of the class is the same as the .java file name.
//If you change the class name you should change the class object name in runGUI method
public class ticTacToeCallum implements ActionListener {
static JFrame frame;
static JPanel contentPane;
static JLabel lblEnterFirstPlayerName, lblEnterSecondPlayerName, lblFirstPlayerScore, lblSecondPlayerScore;
static JButton btnButton1, btnButton2, btnButton3, btnButton4, btnButton5, btnButton6, btnButton7, btnButton8, btnButton9, btnClearBoard, btnClearAll, btnCloseGame;
static JTextField txtEnterFirstPlayerName, txtEnterSecondPlayerName;
static Icon imgicon = new ImageIcon("saveIcon.JPG");
Font buttonFont = new Font("Arial", Font.PLAIN, 20);
//to adjust the frame size change the values in pixels
static int width = 600;
static int length = 400;
static int firstPlayerScore = 0;
static int secondPlayerScore = 0;
static int playerTurn = 1;
static int roundComplete = 0;
static int button1 = 1, button2 = 1, button3 = 1, button4 = 1, button5 = 1, button6 = 1, button7 = 1, button8 = 1, button9 = 1; // 1 is true, 0 is false
public ticTacToeCallum(){
frame = new JFrame("Tic Tac Toe ^_^");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = new JPanel();
contentPane.setLayout(new GridLayout(6, 3, 10, 10));
contentPane.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
btnButton1 = new JButton("");
btnButton1.setFont(buttonFont);
btnButton1.setAlignmentX(JButton.CENTER_ALIGNMENT);
btnButton1.setIcon(imgicon);
btnButton1.setActionCommand("CLICK1");
btnButton1.addActionListener(this);
contentPane.add(btnButton1);
btnButton2 = new JButton("");
btnButton2.setFont(buttonFont);
btnButton2.setAlignmentX(JButton.CENTER_ALIGNMENT);
btnButton2.setIcon(imgicon);
btnButton2.setActionCommand("CLICK2");
btnButton2.addActionListener(this);
contentPane.add(btnButton2);
btnButton3 = new JButton("");
btnButton3.setFont(buttonFont);
btnButton3.setAlignmentX(JButton.CENTER_ALIGNMENT);
btnButton3.setIcon(imgicon);
btnButton3.setActionCommand("CLICK3");
btnButton3.addActionListener(this);
contentPane.add(btnButton3);
btnButton4 = new JButton("");
btnButton4.setFont(buttonFont);
btnButton4.setAlignmentX(JButton.CENTER_ALIGNMENT);
btnButton4.setIcon(imgicon);
btnButton4.setActionCommand("CLICK4");
btnButton4.addActionListener(this);
contentPane.add(btnButton4);
btnButton5 = new JButton("");
btnButton5.setFont(buttonFont);
btnButton5.setAlignmentX(JButton.CENTER_ALIGNMENT);
btnButton5.setIcon(imgicon);
btnButton5.setActionCommand("CLICK5");
btnButton5.addActionListener(this);
contentPane.add(btnButton5);
btnButton6 = new JButton("");
btnButton6.setFont(buttonFont);
btnButton6.setAlignmentX(JButton.CENTER_ALIGNMENT);
btnButton6.setIcon(imgicon);
btnButton6.setActionCommand("CLICK6");
btnButton6.addActionListener(this);
contentPane.add(btnButton6);
btnButton7 = new JButton("");
btnButton7.setFont(buttonFont);
btnButton7.setAlignmentX(JButton.CENTER_ALIGNMENT);
btnButton7.setIcon(imgicon);
btnButton7.setActionCommand("CLICK7");
btnButton7.addActionListener(this);
contentPane.add(btnButton7);
btnButton8 = new JButton("");
btnButton8.setFont(buttonFont);
btnButton8.setAlignmentX(JButton.CENTER_ALIGNMENT);
btnButton8.setIcon(imgicon);
btnButton8.setActionCommand("CLICK8");
btnButton8.addActionListener(this);
contentPane.add(btnButton8);
btnButton9 = new JButton("");
btnButton9.setFont(buttonFont);
btnButton9.setAlignmentX(JButton.CENTER_ALIGNMENT);
btnButton9.setIcon(imgicon);
btnButton9.setActionCommand("CLICK9");
btnButton9.addActionListener(this);
contentPane.add(btnButton9);
lblEnterFirstPlayerName = new JLabel("Enter First Player's Name");
contentPane.add(lblEnterFirstPlayerName);
txtEnterFirstPlayerName = new JTextField("");
contentPane.add(txtEnterFirstPlayerName);
lblFirstPlayerScore = new JLabel("Score: " + firstPlayerScore);
contentPane.add(lblFirstPlayerScore);
lblEnterSecondPlayerName = new JLabel("Enter Second Player's Name");
contentPane.add(lblEnterSecondPlayerName);
txtEnterSecondPlayerName = new JTextField("");
contentPane.add(txtEnterSecondPlayerName);
lblSecondPlayerScore = new JLabel("Score: " + secondPlayerScore);
contentPane.add(lblSecondPlayerScore);
btnClearBoard = new JButton("Clear Board");
btnClearBoard.setAlignmentX(JButton.CENTER_ALIGNMENT);
btnClearBoard.setIcon(imgicon);
btnClearBoard.setActionCommand("CLICKClearBoard");
btnClearBoard.addActionListener(this);
contentPane.add(btnClearBoard);
btnClearAll = new JButton("Clear All");
btnClearAll.setAlignmentX(JButton.CENTER_ALIGNMENT);
btnClearAll.setIcon(imgicon);
btnClearAll.setActionCommand("CLICKClearAll");
btnClearAll.addActionListener(this);
contentPane.add(btnClearAll);
btnCloseGame = new JButton("Close Game");
btnCloseGame.setAlignmentX(JButton.CENTER_ALIGNMENT);
btnCloseGame.setIcon(imgicon);
btnCloseGame.setActionCommand("CLICKCloseGame");
btnCloseGame.addActionListener(this);
contentPane.add(btnCloseGame);
frame.setContentPane(contentPane);
frame.pack();
frame.setSize(width,length);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event) {
String eventName = event.getActionCommand();
if (eventName.equals("CLICK1")) {
if (button1 == 1){
if (playerTurn == 1){
btnButton1.setForeground(Color.RED);
btnButton1.setText("X");
playerTurn = 2;
button1 = 0;
} else if (playerTurn == 2) {
btnButton1.setForeground(Color.GREEN);
btnButton1.setText("O");
playerTurn = 1;
button1 = 0;
}
}
} else if (eventName.equals ("CLICK2")) {
if (button2 == 1){
if (playerTurn == 1){
btnButton2.setForeground(Color.RED);
btnButton2.setText("X");
playerTurn = 2;
button2 = 0;
} else if (playerTurn == 2) {
btnButton2.setForeground(Color.GREEN);
btnButton2.setText("O");
playerTurn = 1;
button2 = 0;
}
}
} else if (eventName.equals ("CLICK3")) {
if (button3 == 1){
if (playerTurn == 1){
btnButton3.setForeground(Color.RED);
btnButton3.setText("X");
playerTurn = 2;
button3 = 0;
} else if (playerTurn == 2) {
btnButton3.setForeground(Color.GREEN);
btnButton3.setText("O");
playerTurn = 1;
button3 = 0;
}
}
} else if (eventName.equals ("CLICK4")) {
if (button4 == 1){
if (playerTurn == 1){
btnButton4.setForeground(Color.RED);
btnButton4.setText("X");
playerTurn = 2;
button4 = 0;
} else if (playerTurn == 2) {
btnButton4.setForeground(Color.GREEN);
btnButton4.setText("O");
playerTurn = 1;
button4 = 0;
}
}
} else if (eventName.equals ("CLICK5")) {
if (button5 == 1){
if (playerTurn == 1){
btnButton5.setForeground(Color.RED);
btnButton5.setText("X");
playerTurn = 2;
button5 = 0;
} else if (playerTurn == 2) {
btnButton5.setForeground(Color.GREEN);
btnButton5.setText("O");
playerTurn = 1;
button5 = 0;
}
}
} else if (eventName.equals ("CLICK6")) {
if (button6 == 1){
if (playerTurn == 1){
btnButton6.setForeground(Color.RED);
btnButton6.setText("X");
playerTurn = 2;
button6 = 0;
} else if (playerTurn == 2) {
btnButton6.setForeground(Color.GREEN);
btnButton6.setText("O");
playerTurn = 1;
button6 = 0;
}
}
} else if (eventName.equals ("CLICK7")) {
if (button7 == 1){
if (playerTurn == 1){
btnButton7.setForeground(Color.RED);
btnButton7.setText("X");
playerTurn = 2;
button7 = 0;
} else if (playerTurn == 2) {
btnButton7.setForeground(Color.GREEN);
btnButton7.setText("O");
playerTurn = 1;
button7 = 0;
}
}
} else if (eventName.equals ("CLICK8")) {
if (button8 == 1){
if (playerTurn == 1){
btnButton8.setForeground(Color.RED);
btnButton8.setText("X");
playerTurn = 2;
button8 = 0;
} else if (playerTurn == 2) {
btnButton8.setForeground(Color.GREEN);
btnButton8.setText("O");
playerTurn = 1;
button8 = 0;
}
}
} else if (eventName.equals ("CLICK9")) {
if (button9 == 1){
if (playerTurn == 1){
btnButton9.setForeground(Color.RED);
btnButton9.setText("X");
playerTurn = 2;
button9 = 0;
} else if (playerTurn == 2) {
btnButton9.setForeground(Color.GREEN);
btnButton9.setText("O");
playerTurn = 1;
button9 = 0;
}
}
} else if (eventName.equals ("CLICKClearBoard")) {
btnButton1.setText("");
btnButton2.setText("");
btnButton3.setText("");
btnButton4.setText("");
btnButton5.setText("");
btnButton6.setText("");
btnButton7.setText("");
btnButton8.setText("");
btnButton9.setText("");
button1 = 1;
button2 = 1;
button3 = 1;
button4 = 1;
button5 = 1;
button6 = 1;
button7 = 1;
button8 = 1;
button9 = 1;
playerTurn = 1;
roundComplete = 0;
} else if (eventName.equals ("CLICKClearAll")) {
btnButton1.setText("");
btnButton2.setText("");
btnButton3.setText("");
btnButton4.setText("");
btnButton5.setText("");
btnButton6.setText("");
btnButton7.setText("");
btnButton8.setText("");
btnButton9.setText("");
firstPlayerScore = 0;
lblFirstPlayerScore.setText("Score: " + firstPlayerScore);
secondPlayerScore = 0;
lblSecondPlayerScore.setText("Score: " + secondPlayerScore);
txtEnterFirstPlayerName.setText("");
txtEnterSecondPlayerName.setText("");
button1 = 1;
button2 = 1;
button3 = 1;
button4 = 1;
button5 = 1;
button6 = 1;
button7 = 1;
button8 = 1;
button9 = 1;
playerTurn = 1;
roundComplete = 0;
} else if (eventName.equals ("CLICKCloseGame")) {
System.exit(0);
}
score();
}
public static void score(){
if (roundComplete == 0){
if (btnButton1.getText().equals(btnButton2.getText()) && btnButton1.getText().equals(btnButton3.getText())){
if (btnButton1.getText().equals("X")){
firstPlayerScore += 1;
lblFirstPlayerScore.setText("Score: " + firstPlayerScore);
roundComplete = 1;
} else if (btnButton1.getText().equals("O")){
secondPlayerScore += 1;
lblSecondPlayerScore.setText("Score: " + secondPlayerScore);
roundComplete = 1;
}
}
if (btnButton1.getText().equals(btnButton4.getText()) && btnButton1.getText().equals(btnButton7.getText())){
if (btnButton1.getText().equals("X")){
firstPlayerScore += 1;
lblFirstPlayerScore.setText("Score: " + firstPlayerScore);
roundComplete = 1;
} else if (btnButton1.getText().equals("O")){
secondPlayerScore += 1;
lblSecondPlayerScore.setText("Score: " + secondPlayerScore);
roundComplete = 1;
}
}
if (btnButton1.getText().equals(btnButton5.getText()) && btnButton1.getText().equals(btnButton9.getText())){
if (btnButton1.getText().equals("X")){
firstPlayerScore += 1;
lblFirstPlayerScore.setText("Score: " + firstPlayerScore);
roundComplete = 1;
} else if (btnButton1.getText().equals("O")){
secondPlayerScore += 1;
lblSecondPlayerScore.setText("Score: " + secondPlayerScore);
roundComplete = 1;
}
}
if (btnButton7.getText().equals(btnButton8.getText()) && btnButton7.getText().equals(btnButton9.getText())){
if (btnButton7.getText().equals("X")){
firstPlayerScore += 1;
lblFirstPlayerScore.setText("Score: " + firstPlayerScore);
roundComplete = 1;
} else if (btnButton7.getText().equals("O")){
secondPlayerScore += 1;
lblSecondPlayerScore.setText("Score: " + secondPlayerScore);
roundComplete = 1;
}
}
if (btnButton7.getText().equals(btnButton5.getText()) && btnButton7.getText().equals(btnButton3.getText())){
if (btnButton7.getText().equals("X")){
firstPlayerScore += 1;
lblFirstPlayerScore.setText("Score: " + firstPlayerScore);
roundComplete = 1;
} else if (btnButton7.getText().equals("O")){
secondPlayerScore += 1;
lblSecondPlayerScore.setText("Score: " + secondPlayerScore);
roundComplete = 1;
}
}
if (btnButton3.getText().equals(btnButton6.getText()) && btnButton3.getText().equals(btnButton9.getText())){
if (btnButton3.getText().equals("X")){
firstPlayerScore += 1;
lblFirstPlayerScore.setText("Score: " + firstPlayerScore);
roundComplete = 1;
} else if (btnButton3.getText().equals("O")){
secondPlayerScore += 1;
lblSecondPlayerScore.setText("Score: " + secondPlayerScore);
roundComplete = 1;
}
}
if (btnButton4.getText().equals(btnButton5.getText()) && btnButton4.getText().equals(btnButton6.getText())){
if (btnButton4.getText().equals("X")){
firstPlayerScore += 1;
lblFirstPlayerScore.setText("Score: " + firstPlayerScore);
roundComplete = 1;
} else if (btnButton4.getText().equals("O")){
secondPlayerScore += 1;
lblSecondPlayerScore.setText("Score: " + secondPlayerScore);
roundComplete = 1;
}
}
if (btnButton2.getText().equals(btnButton5.getText()) && btnButton2.getText().equals(btnButton8.getText())){
if (btnButton2.getText().equals("X")){
firstPlayerScore += 1;
lblFirstPlayerScore.setText("Score: " + firstPlayerScore);
roundComplete = 1;
} else if (btnButton2.getText().equals("O")){
secondPlayerScore += 1;
lblSecondPlayerScore.setText("Score: " + secondPlayerScore);
roundComplete = 1;
}
}
}
if (roundComplete == 1){
button1 = 0;
button2 = 0;
button3 = 0;
button4 = 0;
button5 = 0;
button6 = 0;
button7 = 0;
button8 = 0;
button9 = 0;
}
}
/**
* Create and show the GUI.
*/
private static void runGUI() {
ticTacToeCallum greeting = new ticTacToeCallum();
}
//Do not change this method
public static void main(String[] args) {
/* Methods that create and show a GUI should be run from an event-dispatching thread */
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
runGUI();
}
});
}
}

View file

@ -1,4 +1,5 @@
module TicTacToe
ROWS = [[1,2,3],[4,5,6],[7,8,9],[1,4,7],[2,5,8],[3,6,9],[1,5,9],[3,5,7]]
class Game
def initialize(player1Class, player2Class)
@ -9,9 +10,8 @@ module TicTacToe
puts "#{@players[@turn]} goes first."
@players[@turn].marker = "X"
@players[nextTurn].marker = "O"
@winning_rows = [[1,2,3],[4,5,6],[7,8,9],[1,4,7],[2,5,8],[3,6,9],[1,5,9],[3,5,7]]
end
attr_reader :free_positions, :winning_rows, :board
attr_reader :free_positions, :board, :turn
def play
loop do
@ -22,10 +22,10 @@ module TicTacToe
@free_positions.delete(idx)
# check for a winner
@winning_rows.each do |row|
ROWS.each do |row|
if row.all? {|idx| @board[idx] == player.marker}
puts "#{player} wins!"
print
print_board
return
end
end
@ -33,7 +33,7 @@ module TicTacToe
# no winner, is board full?
if @free_positions.empty?
puts "It's a draw."
print
print_board
return
end
@ -42,7 +42,7 @@ module TicTacToe
end
def nextTurn
(@turn + 1) % 2
1 - @turn
end
def nextTurn!
@ -53,12 +53,9 @@ module TicTacToe
@players[nextTurn]
end
def print
puts [1,2,3].map {|i| @board[i].nil? ? i : @board[i]}.join("|")
puts "-+-+-"
puts [4,5,6].map {|i| @board[i].nil? ? i : @board[i]}.join("|")
puts "-+-+-"
puts [7,8,9].map {|i| @board[i].nil? ? i : @board[i]}.join("|")
def print_board
display =lambda{|row| row.map {|i| @board[i] ? @board[i] : i}.join("|")}
puts display[[1,2,3]], "-+-+-", display[[4,5,6]], "-+-+-", display[[7,8,9]]
end
end
@ -71,20 +68,13 @@ module TicTacToe
end
class HumanPlayer < Player
def initialize(game)
super(game)
end
def select
@game.print
@game.print_board
loop do
print "Select your #{marker} position: "
selection = $stdin.gets.to_i
if not @game.free_positions.include?(selection)
puts "Position #{selection} is not available. Try again."
next
end
return selection
selection = gets.to_i
return selection if @game.free_positions.include?(selection)
puts "Position #{selection} is not available. Try again."
end
end
@ -94,50 +84,45 @@ module TicTacToe
end
class ComputerPlayer < Player
def initialize(game)
super(game)
end
def group_row(row, opponent)
markers = {self.marker => [], opponent.marker => [], nil => []} .
merge(row.group_by {|idx| @game.board[idx]})
#p [row, markers].inspect
def group_row(row)
markers = row.group_by {|idx| @game.board[idx]}
markers.default = []
markers
end
def select
index = nil
opponent = @game.opponent
opponent_marker = @game.opponent.marker
# look for winning rows
@game.winning_rows.each do |row|
markers = group_row(row, opponent)
if markers[self.marker].length == 2 and markers[nil].length == 1
for row in ROWS
markers = group_row(row)
next if markers[nil].length != 1
if markers[self.marker].length == 2
return markers[nil].first
elsif markers[opponent_marker].length == 2
idx = markers[nil].first
end
end
# look for opponent's winning rows to block
@game.winning_rows.each do |row|
markers = group_row(row, opponent)
if markers[opponent.marker].length == 2 and markers[nil].length == 1
return markers[nil].first
end
end
return idx if idx
# need some logic here to get the computer to pick a smarter position
# simply pick a position in order of preference
[5].concat([1,3,7,9].shuffle).concat([2,4,6,8].shuffle).each do |pos|
return pos if @game.free_positions.include?(pos)
([5] + [1,3,7,9].shuffle + [2,4,6,8].shuffle).find do |pos|
@game.free_positions.include?(pos)
end
end
def to_s
"Computer"
"Computer#{@game.turn}"
end
end
end
TicTacToe::Game.new(TicTacToe::ComputerPlayer, TicTacToe::ComputerPlayer).play
TicTacToe::Game.new(TicTacToe::HumanPlayer, TicTacToe::ComputerPlayer).play
include TicTacToe
Game.new(ComputerPlayer, ComputerPlayer).play
puts
Game.new(HumanPlayer,ComputerPlayer).play