using System;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
namespace ttt
{
///
/// Provides methods for playing the tic-tac-toe boardgame
///
///
[WebService(Namespace = "http://harbormist.com/",
Description = "A web service which provides a TicTacToe game. " +
"[Programmers: Charlie Chambers, Jay Patel.]")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class TicTacToe : System.Web.Services.WebService
{
private ArrayList triplets = new ArrayList();
public const char USER_PIECE = 'X';
public const char COMP_PIECE = 'O';
public const char EMPT_PIECE = '_';
static public int NUM_CELLS = 9;
public TicTacToe()
{
InitializeComponent();
triplets = new ArrayList();
triplets.Add(new Triplet(0, 1, 2));
triplets.Add(new Triplet(3, 4, 5));
triplets.Add(new Triplet(6, 7, 8));
triplets.Add(new Triplet(0, 3, 6));
triplets.Add(new Triplet(1, 4, 7));
triplets.Add(new Triplet(2, 5, 8));
triplets.Add(new Triplet(0, 4, 8));
triplets.Add(new Triplet(2, 4, 6));
}
#region Component Designer generated code
//Required by the Web Services Designer
private IContainer components = null;
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
}
///
/// Clean up any resources being used.
///
protected override void Dispose(bool disposing)
{
if (disposing && components != null)
{
components.Dispose();
}
base.Dispose(disposing);
}
#endregion
[WebMethod(Description = "Given a string of 9 characters representing the state of the board, each of which is one of: \n" +
" TicTacToe.USER_PIECE, TicTacToe.COMP_PIECE, or TicTacToe.EMPT_PIECE," +
" and an integer index from 0 to 8, representing the user move from the given board, " +
" This returns a similar string with a new 'O' move in place"
)]
public string respondToUserMove(String boardState, int userMoveIndex)
{
//first put in user move, if allowed
if (boardState[userMoveIndex] != EMPT_PIECE) return boardState; //can't move there, so return same board
if (boardState.Length != NUM_CELLS) return "" + EMPT_PIECE + EMPT_PIECE + EMPT_PIECE + EMPT_PIECE + EMPT_PIECE + EMPT_PIECE + EMPT_PIECE + EMPT_PIECE + EMPT_PIECE;
if (userMoveIndex >= NUM_CELLS || userMoveIndex < 0) return boardState;
//don't let the user move if the game is won or lost
foreach (Triplet t in triplets)
{
if (t.isWon(boardState) || t.isLost(boardState)) return boardState;
}
// user move is legal, so add it
String afterUser = boardState.Substring(0, userMoveIndex);
afterUser += USER_PIECE;
if (afterUser.Length < NUM_CELLS) afterUser += boardState.Substring(userMoveIndex + 1);
//has the user just won? if so, computer gets no move
foreach (Triplet t in triplets)
{
if (t.isWon(afterUser)) return afterUser;
}
//are there no spaces for the computer to move?
if (afterUser.IndexOf(EMPT_PIECE) == -1) return afterUser;
//now to find the computer move...
//first, two explicit conditions that we are fudging.
if (afterUser.Equals(
TicTacToe.USER_PIECE + TicTacToe.EMPT_PIECE + TicTacToe.EMPT_PIECE +
TicTacToe.EMPT_PIECE + TicTacToe.COMP_PIECE + TicTacToe.EMPT_PIECE +
TicTacToe.EMPT_PIECE + TicTacToe.EMPT_PIECE + TicTacToe.USER_PIECE
))
{
return ("" +
TicTacToe.USER_PIECE + TicTacToe.COMP_PIECE + TicTacToe.EMPT_PIECE +
TicTacToe.EMPT_PIECE + TicTacToe.COMP_PIECE + TicTacToe.EMPT_PIECE +
TicTacToe.EMPT_PIECE + TicTacToe.EMPT_PIECE + TicTacToe.USER_PIECE
);
}
if (afterUser.Equals(
TicTacToe.EMPT_PIECE + TicTacToe.EMPT_PIECE + TicTacToe.USER_PIECE +
TicTacToe.EMPT_PIECE + TicTacToe.COMP_PIECE + TicTacToe.EMPT_PIECE +
TicTacToe.USER_PIECE + TicTacToe.EMPT_PIECE + TicTacToe.EMPT_PIECE
))
{
return ("" +
TicTacToe.EMPT_PIECE + TicTacToe.COMP_PIECE + TicTacToe.USER_PIECE +
TicTacToe.EMPT_PIECE + TicTacToe.COMP_PIECE + TicTacToe.EMPT_PIECE +
TicTacToe.USER_PIECE + TicTacToe.EMPT_PIECE + TicTacToe.EMPT_PIECE
);
}
int[] weights = new int[NUM_CELLS];
for (int i = 0; i < NUM_CELLS; i++) weights[i] = 0; //initialize weights to 0 expicitly
foreach (Triplet t in triplets)
{
weights = t.addWeight(afterUser, weights); // add the influence of each triplet
}
//find the highest weight value that is a legal move
int heighestWeight = -1;
int bestMoveCell = 0;
for (int i = 0; i < NUM_CELLS; i++)
{
if (weights[i] > heighestWeight && afterUser.Substring(i, 1) == ("" + EMPT_PIECE))
{//upgrade to better, empty-cell moves
bestMoveCell = i;
heighestWeight = weights[i];
}
}
String afterComputer = afterUser.Substring(0, bestMoveCell);
afterComputer += COMP_PIECE;
if (afterComputer.Length < NUM_CELLS) afterComputer += afterUser.Substring(bestMoveCell + 1);
return afterComputer;
}
[WebMethod(Description = "Given a string of 9 characters representing the state of the board, " +
" each of which is one of: \n" +
" TicTacToe.USER_PIECE, TicTacToe.COMP_PIECE, or TicTacToe.EMPT_PIECE," +
" This returns a status line (e.g. 'You lose', or 'You win') to explain " +
" the status of the game to the user."
)]
public string getStatus(String boardState)
{
foreach (Triplet t in triplets) //we will check every "way" of winning
{
if (t.isWon(boardState)) return "You win.";
if (t.isLost(boardState)) return "You lose.";
}
if (boardState.IndexOf(EMPT_PIECE) == -1) return "Stalemate."; //no empty squares
return "Your turn"; //barring everything else, we are waiting for the user
}
}
}