Tic tac toe

From CodeCodex

Revision as of 03:01, 11 February 2007 by Jdh30 (Talk | contribs)

Implementation

Java

© Part or all of this code is protected under copyright but is free to use and modify.

/*
 * @(#)TicTacToe.java	1.2 95/10/13 
 *
 * Copyright (c) 1994-1996 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
 * without fee is hereby granted. 
 * Please refer to the file http://java.sun.com/copy_trademarks.html
 * for further important copyright and trademark information and to
 * http://java.sun.com/licensing.html for further important licensing
 * information for the Java (tm) Technology.
 * 
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 * 
 * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
 * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
 * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
 * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
 * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
 * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
 * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").  SUN
 * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
 * HIGH RISK ACTIVITIES.
 */

import java.awt.*;
import java.awt.image.*;
import java.net.*;
import java.applet.*;

/**
 * A TicTacToe applet. A very simple, and mostly brain-dead
 * implementation of your favorite game! <p>
 *
 * In this game a position is represented by a white and black
 * bitmask. A bit is set if a position is ocupied. There are
 * 9 squares so there are 1<<9 possible positions for each
 * side. An array of 1<<9 booleans is created, it marks
 * all the winning positions.
 *
 * @version 	1.2, 13 Oct 1995
 * @author Arthur van Hoff
 * @modified 96/04/23 Jim Hagen : winning sounds
 */
public
class TicTacToe extends Applet {
    /**
     * White's current position. The computer is white.
     */
    int white;

    /**
     * Black's current position. The user is black.
     */
    int black;

    /**
     * The squares in order of importance...
     */
    final static int moves[] = {4, 0, 2, 6, 8, 1, 3, 5, 7};

    /**
     * The winning positions.
     */
    static boolean won[] = new boolean[1 << 9];
    static final int DONE = (1 << 9) - 1;
    static final int OK = 0;
    static final int WIN = 1;
    static final int LOSE = 2;
    static final int STALEMATE = 3;

    /**
     * Mark all positions with these bits set as winning.
     */
    static void isWon(int pos) {
	for (int i = 0 ; i < DONE ; i++) {
	    if ((i & pos) == pos) {
		won[i] = true;
	    }
	}
    }

    /**
     * Initialize all winning positions.
     */
    static {
	isWon((1 << 0) | (1 << 1) | (1 << 2));
	isWon((1 << 3) | (1 << 4) | (1 << 5));
	isWon((1 << 6) | (1 << 7) | (1 << 8));
	isWon((1 << 0) | (1 << 3) | (1 << 6));
	isWon((1 << 1) | (1 << 4) | (1 << 7));
	isWon((1 << 2) | (1 << 5) | (1 << 8));
	isWon((1 << 0) | (1 << 4) | (1 << 8));
	isWon((1 << 2) | (1 << 4) | (1 << 6));
    }

    /**
     * Compute the best move for white.
     * @return the square to take
     */
    int bestMove(int white, int black) {
	int bestmove = -1;
	
      loop:
	for (int i = 0 ; i < 9 ; i++) {
	    int mw = moves[i];
	    if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) {
		int pw = white | (1 << mw);
		if (won[pw]) {
		    // white wins, take it!
		    return mw;
		}
		for (int mb = 0 ; mb < 9 ; mb++) {
		    if (((pw & (1 << mb)) == 0) && ((black & (1 << mb)) == 0)) {
			int pb = black | (1 << mb);
			if (won[pb]) {
			    // black wins, take another
			    continue loop;
			}
		    }
		}
		// Neither white nor black can win in one move, this will do.
		if (bestmove == -1) {
		    bestmove = mw;
		}
	    }
	}
	if (bestmove != -1) {
	    return bestmove;
	}

	// No move is totally satisfactory, try the first one that is open
	for (int i = 0 ; i < 9 ; i++) {
	    int mw = moves[i];
	    if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) {
		return mw;
	    }
	}

	// No more moves
	return -1;
    }

    /**
     * User move.
     * @return true if legal
     */
    boolean yourMove(int m) {
	if ((m < 0) || (m > 8)) {
	    return false;
	}
	if (((black | white) & (1 << m)) != 0) {
	    return false;
	}
	black |= 1 << m;
	return true;
    }

    /**
     * Computer move.
     * @return true if legal
     */
    boolean myMove() {
	if ((black | white) == DONE) {
	    return false;
	}
	int best = bestMove(white, black);
	white |= 1 << best;
	return true;
    }

    /**
     * Figure what the status of the game is.
     */
    int status() {
	if (won[white]) {
	    return WIN;
	}
	if (won[black]) {
	    return LOSE;
	}
	if ((black | white) == DONE) {
	    return STALEMATE;
	}
	return OK;
    }

    /**
     * Who goes first in the next game?
     */
    boolean first = true;

    /**
     * The image for white.
     */
    Image notImage;

    /**
     * The image for black.
     */
    Image crossImage;

    /**
     * Initialize the applet. Resize and load images.
     */
    public void init() {
	notImage = getImage(getCodeBase(), "images/not.gif");
	crossImage = getImage(getCodeBase(), "images/cross.gif");
    }

    /**
     * Paint it.
     */
    public void paint(Graphics g) {
	Dimension d = size();
	g.setColor(Color.black);
	int xoff = d.width / 3;
	int yoff = d.height / 3;
	g.drawLine(xoff, 0, xoff, d.height);
	g.drawLine(2*xoff, 0, 2*xoff, d.height);
	g.drawLine(0, yoff, d.width, yoff);
	g.drawLine(0, 2*yoff, d.width, 2*yoff);

	int i = 0;
	for (int r = 0 ; r < 3 ; r++) {
	    for (int c = 0 ; c < 3 ; c++, i++) {
		if ((white & (1 << i)) != 0) {
		    g.drawImage(notImage, c*xoff + 1, r*yoff + 1, this);
		} else if ((black & (1 << i)) != 0) {
		    g.drawImage(crossImage, c*xoff + 1, r*yoff + 1, this);
		}
	    }
	}
    }

    /**
     * The user has clicked in the applet. Figure out where
     * and see if a legal move is possible. If it is a legal
     * move, respond with a legal move (if possible).
     */
    public boolean mouseUp(Event evt, int x, int y) {
	switch (status()) {
	  case WIN:
	  case LOSE:
	  case STALEMATE:
	    play(getCodeBase(), "audio/return.au");
	    white = black = 0;
	    if (first) {
		white |= 1 << (int)(Math.random() * 9);
	    }
	    first = !first;
	    repaint();
	    return true;
	}

	// Figure out the row/colum
	Dimension d = size();
	int c = (x * 3) / d.width;
	int r = (y * 3) / d.height;
	if (yourMove(c + r * 3)) {
	    repaint();

	    switch (status()) {
	      case WIN:
		play(getCodeBase(), "audio/yahoo1.au");
		break;
	      case LOSE:
		play(getCodeBase(), "audio/yahoo2.au");
		break;
	      case STALEMATE:
		break;
	      default:
		if (myMove()) {
		    repaint();
		    switch (status()) {
		      case WIN:
			play(getCodeBase(), "audio/yahoo1.au");
			break;
		      case LOSE:
			play(getCodeBase(), "audio/yahoo2.au");
			break;
		      case STALEMATE:
			break;
		      default:
			play(getCodeBase(), "audio/ding.au");
		    }
		} else {
		    play(getCodeBase(), "audio/beep.au");
		}
	    }
	} else {
	    play(getCodeBase(), "audio/beep.au");
	}
	return true;
    }

    public String getAppletInfo() {
	return "TicTacToe by Arthur van Hoff";
    }
}

Source: http://rintintin.colorado.edu/~epperson/Java/TicTacToe.java

OCaml

From the OCaml distribution:

module Array = StdLabels.Array

module Tictactoe = struct
  type t = [`base|`widget|`container|`box|`tictactoe]
  module Signals = struct
    module S = GtkSignal
    let tictactoe : ([>`tictactoe],_) S.t =
      { S.classe = `tictactoe; S.name = "tictactoe";
        S.marshaller = S.marshal_unit }
    let emit_tictactoe = S.emit_unit ~sgn:tictactoe
  end
  let create : unit -> t Gtk.obj =
    let _,tictactoe_new = GtkNew.make_new_widget
	~name:"Tictactoe" ~parent:GtkNew.VBOX ~signals:[Signals.tictactoe]
    in fun () -> GtkBase.Object.try_cast (tictactoe_new ()) "Tictactoe"
end

class tictactoe_signals obj = object
  inherit GContainer.container_signals obj
  method tictactoe =
    GtkSignal.connect ~sgn:Tictactoe.Signals.tictactoe obj ~after
end

exception Trouve

class tictactoe ?packing ?show () =
  let obj : Tictactoe.t Gtk.obj = Tictactoe.create () in
  let box = new GPack.box_skel obj in
object (self)
  inherit GObj.widget obj
  val mutable buttons = [||]
  val mutable buttons_handlers = [||]
  val label = GMisc.label ~text:"Go on!" ~packing:box#add ()
  method clear () =
    for i = 0 to 2 do
      for j = 0 to 2 do
	let button = buttons.(i).(j)
	and handler = buttons_handlers.(i).(j) in
	button#misc#handler_block handler;
	button#set_active false;
	button#misc#handler_unblock handler
      done
    done
  method connect = new tictactoe_signals obj
  method emit_tictactoe () =
    GtkSignal.emit_unit obj ~sgn:Tictactoe.Signals.tictactoe
  method toggle () =
    let rwins = [| [| 0; 0; 0 |]; [| 1; 1; 1 |]; [| 2; 2; 2 |];
                   [| 0; 1; 2 |]; [| 0; 1; 2 |]; [| 0; 1; 2 |];
                   [| 0; 1; 2 |]; [| 0; 1; 2 |] |]
    and cwins = [| [| 0; 1; 2 |]; [| 0; 1; 2 |]; [| 0; 1; 2 |];
                   [| 0; 0; 0 |]; [| 1; 1; 1 |]; [| 2; 2; 2 |];
                   [| 0; 1; 2 |]; [| 2; 1; 0 |] |] in
    label#set_text"Go on!";
    try
      for k = 0 to 7 do
	let rec aux i =
	  (i = 3) ||
	  (buttons.(rwins.(k).(i)).(cwins.(k).(i))#active) && (aux (i+1)) in
	if aux 0 then raise Trouve
      done
    with Trouve -> label#set_text "Win!!"; self#emit_tictactoe ()
	
  initializer
    let table =
      GPack.table ~rows:3 ~columns:3 ~homogeneous:true ~packing:box#add () in
    buttons <-
      Array.init 3 ~f:
	(fun i -> Array.init 3 ~f:
	    (fun j ->
	      GButton.toggle_button ~width:20 ~height:20
		~packing:(table#attach ~left:i ~top:j ~expand:`BOTH) ()));
    buttons_handlers <-
      Array.mapi buttons ~f:
	(fun i -> Array.mapi ~f:
	  (fun j button -> button #connect#toggled ~callback:self#toggle));
    GObj.pack_return self ~packing ~show;
    ()
end

let win (ttt : tictactoe)  _ =
  Printf.printf "Gagne!!\n" ;
  flush stdout;
  ttt #clear ()

let essai () =
  let window = GWindow.window ~title:"Tictactoe" ~border_width:10 () in
  window #connect#destroy ~callback:GMain.Main.quit;
  let ttt = new tictactoe ~packing:window#add () in
  ttt #connect#tictactoe ~callback:(win ttt);
  window #show ();
  GMain.Main.main ()

let _ = essai ()