Intial commit
This commit is contained in:
43
tcl-dp/examples/tictactoe/README
Normal file
43
tcl-dp/examples/tictactoe/README
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
Tcl-DP: Tic Tac Toe
|
||||
|
||||
This creates a simple distributed Tic Tac Toe game, displayed using
|
||||
Tk widgets. It is an example of using a Tcl-DP distributed object.
|
||||
|
||||
playerX.tcl -- script for player X, must be run first
|
||||
playerO.tcl -- script for player O, must be run after playerX.tcl
|
||||
|
||||
The following two files are shared by player X and player O.
|
||||
|
||||
board.tcl -- definition of the distributed board class
|
||||
interface.tcl -- definition of user interface of Tk widgets
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
First, start player X...
|
||||
|
||||
Run wish.
|
||||
Type "source playerX.tcl" and answer the questions;
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Second, start player O...
|
||||
|
||||
Run wish, as another process.
|
||||
Type "source playerO.tcl" and answer the questions;
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Player X is the RPC server. Player O is the RPC client. (Hence,
|
||||
player X must be set up before player O.) Player X creates a Tic
|
||||
Tac Toe board object, which gets distributed to player O. Each
|
||||
player process locally updates its Tk interface, as the Tk
|
||||
widgets of the interface are not distributed objects.
|
||||
|
||||
Because the board is a distributed object, callbacks from user
|
||||
actions are very simple. Any changes to slots of the board
|
||||
object in a callback are automatically propagated to all
|
||||
processes.
|
||||
|
||||
|
||||
|
||||
107
tcl-dp/examples/tictactoe/board.tcl
Normal file
107
tcl-dp/examples/tictactoe/board.tcl
Normal file
@@ -0,0 +1,107 @@
|
||||
#
|
||||
# board.tcl -- Tcl/Tk script that defines a Tic Tac Toe board object.
|
||||
#
|
||||
# The board object is defined using Tcl scripting only.
|
||||
# Normally, objects are created in C (as structs), such as
|
||||
# with Tk widgets, and have a Tcl access interface.
|
||||
#
|
||||
# The board has one slot, state, which is a list of nine entries.
|
||||
# Each entry may be X, O, or S (space).
|
||||
#
|
||||
# board -- creator procedure, works like a Tk widget creator.
|
||||
#
|
||||
# usage : board name ?configure-options ...?
|
||||
#
|
||||
|
||||
package require dp 4.0
|
||||
|
||||
proc board {aBoard args} {
|
||||
|
||||
# Create a procedure to represent a new board object.
|
||||
# This new board object (procedure) will have the name of $aBoard;
|
||||
#
|
||||
dp_objectCreateProc board $aBoard;
|
||||
|
||||
# Give the new board object one slot, called state;
|
||||
#
|
||||
dp_objectSlotSet $aBoard state {S S S S S S S S S};
|
||||
|
||||
# Finish configuration of the new board object;
|
||||
#
|
||||
eval $aBoard configure $args;
|
||||
|
||||
return $aBoard;
|
||||
}
|
||||
|
||||
#
|
||||
# Method definitions for objects of class Tic Tac Toe board;
|
||||
#
|
||||
|
||||
# Distributed objects must have the methods of configure and slot-value,
|
||||
# according to Tcl-DP distributed object protocol;
|
||||
#
|
||||
# configure - configure the slots of board object;
|
||||
# slot-value - return value of one slot of board object;
|
||||
#
|
||||
# The methods configure and slot-value that are defined here
|
||||
# use the object utility procedures that come
|
||||
# with the Tcl-DP package;
|
||||
#
|
||||
|
||||
proc board.configure {aBoard args} {
|
||||
return [eval dp_objectConfigure board $aBoard $args];
|
||||
}
|
||||
|
||||
proc board.slot-value {aBoard slot} {
|
||||
return [dp_objectSlot $aBoard $slot];
|
||||
}
|
||||
|
||||
# In the following board methods, note the use of dp_setf and dp_getf
|
||||
# instead of objectSlotSet and objectSlot; dp_setf and dp_getf
|
||||
# are used for slot access to Tcl-DP distributed objects;
|
||||
#
|
||||
|
||||
# clear - clear entries of board;
|
||||
#
|
||||
|
||||
proc board.clear {aBoard} {
|
||||
dp_setf $aBoard state {S S S S S S S S S};
|
||||
return $aBoard;
|
||||
}
|
||||
|
||||
# entryGet - get entry at position x,y (0-2, 0-2);
|
||||
# entrySet - set entry at position x,y (0-2, 0-2);
|
||||
#
|
||||
|
||||
proc board.entryGet {aBoard x y} {
|
||||
set state [dp_getf $aBoard state];
|
||||
set position [expr ($x*3)+$y];
|
||||
return [lindex $state $position];
|
||||
}
|
||||
|
||||
proc board.entrySet {aBoard x y value} {
|
||||
set state [dp_getf $aBoard state];
|
||||
set position [expr ($x*3)+$y];
|
||||
dp_setf $aBoard state [lreplace $state $position $position $value];
|
||||
return $value;
|
||||
}
|
||||
|
||||
# print - pretty print board to stdout;
|
||||
#
|
||||
|
||||
proc board.print {aBoard} {
|
||||
for {set row 0} {$row <= 2} {incr row} {
|
||||
for {set col 0} {$col <= 2} {incr col} {
|
||||
set entry [$aBoard entryGet $col $row];
|
||||
case $entry in {
|
||||
{S} {set symbol " "}
|
||||
{default} {set symbol $entry}
|
||||
}
|
||||
puts stdout $symbol nonewline;
|
||||
}
|
||||
puts stdout "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
88
tcl-dp/examples/tictactoe/interface.tcl
Normal file
88
tcl-dp/examples/tictactoe/interface.tcl
Normal file
@@ -0,0 +1,88 @@
|
||||
|
||||
# interface.tcl -- Tcl/Tk script that defines the GUI interface
|
||||
# of the Tic Tac Toe game; Since both player X and player O
|
||||
# share the same interface, they both use this script.
|
||||
#
|
||||
|
||||
# The global variable player must be set up beforehand;
|
||||
#
|
||||
|
||||
wm title . "TTT - $player";
|
||||
|
||||
# The following procedure is the callback for when a user
|
||||
# presses a Tic Tac Toe GUI button;
|
||||
#
|
||||
|
||||
proc mark {col row} {
|
||||
global player;
|
||||
|
||||
# Get the current entry of the board of the given column and row.
|
||||
#
|
||||
set entry [.board entryGet $col $row];
|
||||
|
||||
if {[string compare S $entry] == 0} {
|
||||
|
||||
# Set the entry of the board to the player's symbol,
|
||||
# if the current entry is an S (space).
|
||||
#
|
||||
.board entrySet $col $row $player;
|
||||
|
||||
# Since the board is a distributed object, any slot changes to
|
||||
# it will get automatically distributed the other player.
|
||||
#
|
||||
|
||||
} else {
|
||||
|
||||
# Otherwise, complain to the user;
|
||||
#
|
||||
puts stdout "";
|
||||
puts stdout "Cannot mark that entry ($col,$row).";
|
||||
puts stdout "Already marked with an $entry.";
|
||||
}
|
||||
}
|
||||
|
||||
# Procedure to create a column of Tic Tac Toe GUI buttons;
|
||||
#
|
||||
|
||||
proc column {w i} {
|
||||
pack append $w \
|
||||
[frame $w.c$i] {left fillx filly};
|
||||
pack append $w.c$i \
|
||||
[button $w.c$i.0 -command "mark $i 0" -width 2] {top fillx} \
|
||||
[button $w.c$i.1 -command "mark $i 1" -width 2] {top fillx} \
|
||||
[button $w.c$i.2 -command "mark $i 2" -width 2] {top fillx};
|
||||
}
|
||||
|
||||
# Procedure to update the text of those Tic Tac Toe GUI buttons
|
||||
# according to the state of the distributed board object;
|
||||
#
|
||||
|
||||
proc DisplayUpdate {} {
|
||||
for {set row 0} {$row <= 2} {incr row} {
|
||||
for {set col 0} {$col <= 2} {incr col} {
|
||||
set entry [.board entryGet $col $row];
|
||||
case $entry in {
|
||||
{S} {set symbol " "}
|
||||
{default} {set symbol $entry}
|
||||
}
|
||||
.main.c$col.$row configure -text $symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Instantiate the interface;
|
||||
#
|
||||
|
||||
pack append . [frame .main] top;
|
||||
column .main 0;
|
||||
column .main 1;
|
||||
column .main 2;
|
||||
|
||||
pack append .main \
|
||||
[button .main.clear -text "Clear" -command ".board clear"] \
|
||||
{top fillx} \
|
||||
[button .main.quit -text "Quit" -command "exit"] \
|
||||
{top fillx};
|
||||
|
||||
|
||||
|
||||
47
tcl-dp/examples/tictactoe/playerO.tcl
Normal file
47
tcl-dp/examples/tictactoe/playerO.tcl
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
#
|
||||
# playerO.tcl -- Tcl/Tk script for player O, the RPC client.
|
||||
#
|
||||
# This script should be run after running the player X script.
|
||||
#
|
||||
|
||||
package require dp 4.0
|
||||
|
||||
set player O;
|
||||
puts stdout "Tic Tac Toe - player O";
|
||||
|
||||
# Get information from user;
|
||||
#
|
||||
|
||||
puts stdout "Enter the host address of player X: " nonewline;
|
||||
gets stdin host;
|
||||
puts stdout "Enter the port number of player X: " nonewline;
|
||||
gets stdin port;
|
||||
|
||||
# Connect to server (player X) as an RPC client;
|
||||
#
|
||||
|
||||
set server [dp_MakeRPCClient $host $port];
|
||||
|
||||
# Instead of creating a local board object, we ask the server to
|
||||
# distribute its board object to us;
|
||||
#
|
||||
|
||||
source board.tcl;
|
||||
set remFile [dp_RPC $server set dp_rpcFile]
|
||||
dp_RPC $server eval dp_DistributeObject .board $remFile board;
|
||||
|
||||
# Initialize the user interface;
|
||||
#
|
||||
|
||||
source interface.tcl;
|
||||
|
||||
# Trigger a user interface update whenever the state slot of
|
||||
# the distributed board object changes;
|
||||
#
|
||||
|
||||
dp_SetTrigger after .board state DisplayUpdate
|
||||
|
||||
|
||||
|
||||
|
||||
43
tcl-dp/examples/tictactoe/playerX.tcl
Normal file
43
tcl-dp/examples/tictactoe/playerX.tcl
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
#
|
||||
# playerX.tcl -- Tcl/Tk script for player X, the RPC server.
|
||||
#
|
||||
# This script should be run before running the player O script.
|
||||
#
|
||||
|
||||
package require dp 4.0
|
||||
|
||||
set player X;
|
||||
puts stdout "Tic Tac Toe - player X";
|
||||
|
||||
# Get information from user;
|
||||
#
|
||||
|
||||
puts stdout "Enter an unused port number (ex: 8765) : " nonewline;
|
||||
gets stdin port;
|
||||
|
||||
# Make an RPC server socket, which will be waiting for player O
|
||||
# to connect through the supplied port number;
|
||||
#
|
||||
|
||||
dp_MakeRPCServer $port
|
||||
|
||||
# Create a local board object that will get distributed to player O;
|
||||
#
|
||||
|
||||
source board.tcl;
|
||||
board .board;
|
||||
|
||||
# Initialize the user interface;
|
||||
#
|
||||
|
||||
source interface.tcl;
|
||||
|
||||
# Trigger a user interface update whenever the state slot of
|
||||
# the distributed board object changes;
|
||||
#
|
||||
|
||||
dp_SetTrigger after .board state DisplayUpdate
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user