How Do You Write a Tic-Tac-Toe Program in Groovy?

Problem scenario
You want to code a Groovy 2.x program.  You want a program that reads user input, prints out processed output, uses closures (similar to functions in other languages) with and without return statements, handles some exceptions (non-standard input or input that is no longer valid based on what was previously entered), and uses classes.  How do you write a Tic-Tac-Toe (aka naughts and crosses) program in Groovy that has the above things?

Solution
This program was tested using Groovy 2.4.5.

/*  Written by www.continualintegration.com
Usage instructions: name this file tictactoe.groovy
Run it by using this: groovy tictactoe.groovy
*/

@groovy.transform.Canonical
class Program {   //create an object of nine strings. These will hold an "X" or an "O".  They represent the squares of the tictactoe board.
    String tl = ""
    String tm = ""
    String tr = ""
    String ml = ""
    String mm = ""
    String mr = ""
    String bl = ""
    String bm = ""
    String br = ""
}

programsv1 = new Program( " ", " ", " ", " ", " ", " ", " ", " ", " ")

def legend = { param2 -> println "***-------This is the legend for the grid -----***"
    println "tl is top-left square; tm is top-middle square"
    println "tr is top-right square; ml is middle-left square"
    println "mm is the center square; mr is the middle-right square"
    println "bl is the bottom-left square; bm is the bottom-middle square"
    println "br is the bottom-right square"
    println "***--------------------------------------------***"
              }

def current = { param1 -> println "Here is the current board:";
    println "_______";
    println "|${programsv1.tl}|${programsv1.tm}|${programsv1.tr}|";
    println "|${programsv1.ml}|${programsv1.mm}|${programsv1.mr}|";
    println "|${programsv1.bl}|${programsv1.bm}|${programsv1.br}|";
    println "-------";
   }

def inputter = { playermark -> def input = System.console().readLine "Player ${playermark} should decide where to make an ${playermark}: "
  varval = input
  return varval
  }

def checker = { varplace, programsv1, playermark -> if (programsv1."${varplace}" in ["X", "O"]) {  //check if empty or not
  println "That square has already been marked.  Please choose an empty square"
  return "GOELSEWHERE"}
  else{ return "PROCEED" }}

// below will check if square was entered according to the legend.  below closure does the change if the move was valid
def coolreal = { varplace, programsv1, playermark -> if (varplace in ["tl", "tm", "tr", "ml", "mm", "mr", "bl", "bm", "br"]) {
    z = checker.call(varplace, programsv1, playermark)
    if (z == "PROCEED") {programsv1."${varplace}" = "${playermark}"
                         return "NONEXIT"}
    else {varplace = inputter(playermark) //request valid input a second time
        if (varplace in ["tl", "tm", "tr", "ml", "mm", "mr", "bl", "bm", "br"]) {
           z = checker.call(varplace, programsv1, playermark)
           if (z == "PROCEED") {programsv1."${varplace}" = "${playermark}"
                                return "NONEXIT" }}}}
  else { println "Invalid input.  Please enter a square according to the legend."
    varplace = inputter(playermark) //request valid input a second time
        if (varplace in ["tl", "tm", "tr", "ml", "mm", "mr", "bl", "bm", "br"]) {
           z = checker.call(varplace, programsv1, playermark)
           if (z == "PROCEED") {programsv1."${varplace}" = "${playermark}"
                                return "NONEXIT" }}}}

def cool = { varplace, programsv1, playermark -> t = coolreal.call(varplace, programsv1, playermark)
  if (t != "NONEXIT") { t = coolreal.call(varplace, programsv1, playermark)
    if (t != "NONEXIT") { t = coolreal.call(varplace, programsv1, playermark)
      if (t != "NONEXIT") { t = coolreal.call(varplace, programsv1, playermark)
        if (t != "NONEXIT") { t = coolreal.call(varplace, programsv1, playermark)
          if (t != "NONEXIT") {
            println " "
            println "*******************************************"
            println " "
            println "Too many failed attempts at entering a valid, empty square. Program exiting."
            return "EXIT" }}}}}}

def checkifgo = { programsv1 -> flagdone = "UNSET" as String
   if (programsv1."tl" == programsv1."tm") { if (programsv1."tm" == programsv1."tr") { if (programsv1."tm" != " ") {
    flagdone = "SET"
    println "GAME OVER."
    println "Player ${programsv1.tl} wins! (See the top horizontal three in a row)." } } }
   if (flagdone == "UNSET") { if (programsv1."ml" == programsv1."mm") { if (programsv1."mm" == programsv1."mr") { if (programsv1."ml" != " ") {
    flagdone = "SET"
    println "GAME OVER."
    println "Player ${programsv1.ml} wins! (See the middle horizontal three in a row)."} } } }
   if (flagdone == "UNSET") { if (programsv1."bl" == programsv1."bm") { if (programsv1."bm" == programsv1."br") { if (programsv1."bl" != " ") {
      flagdone = "SET"
      println "GAME OVER."
      println "Player ${programsv1.bl} wins! (See the lower horizontal three in a row)."} } } }
   if (flagdone == "UNSET") { if (programsv1."tl" == programsv1."mm") { if (programsv1."mm" == programsv1."br") { if (programsv1."tl" != " ") {
      flagdone = "SET"
      println "GAME OVER."
      println "Player ${programsv1.tl} wins! (See the diagonal three in a row)."} } } }
   if (flagdone == "UNSET") { if (programsv1."tr" == programsv1."mm") { if (programsv1."mm" == programsv1."bl") { if (programsv1."tr" != " ") {
       flagdone = "SET"
       println "GAME OVER."
       println "Player ${programsv1.bl} wins! (See the diagonal three in a row)."} } } }
   if (flagdone == "UNSET") { if (programsv1."tr" == programsv1."mr") { if (programsv1."mr" == programsv1."br") { if (programsv1."tr" != " ") {
       flagdone = "SET"
       println "GAME OVER."
       println "Player ${programsv1.tr} wins! (See the right vertical three in a row)."} } } }
   if (flagdone == "UNSET") { if (programsv1."tl" == programsv1."ml") { if (programsv1."ml" == programsv1."bl") { if (programsv1."tl" != " ") {
       flagdone = "SET"
       println "GAME OVER."
       println "Player ${programsv1.ml} wins! (See the left vertical three in a row)."} } } }
   if (flagdone == "UNSET") { if (programsv1."tm" == programsv1."mm") { if (programsv1."mm" == programsv1."bm") { if (programsv1."tm" != " ") {
       flagdone = "SET"
       println "GAME OVER."
       println "Player ${programsv1.tm} wins! (See the middle vertical three in a row)."} } } }
   return flagdone
}

//vertical ways of winning
legend.call()
current.call()
playermark = "X"
varplace = inputter(playermark)
if (cool.call(varplace, programsv1, playermark) == "EXIT") { return }
current.call()

playermark = "O"
varplace = inputter(playermark)
if (cool.call(varplace, programsv1, playermark) == "EXIT") { return }
current.call()

playermark = "X"
varplace = inputter(playermark)
if (cool.call(varplace, programsv1, playermark) == "EXIT") { return }
current.call()

playermark = "O"
varplace = inputter(playermark)
if (cool.call(varplace, programsv1, playermark) == "EXIT") { return }
current.call()

legend.call()

playermark = "X"
varplace = inputter(playermark)
if (cool.call(varplace, programsv1, playermark ) == "EXIT") { return }
current.call()

varfin = checkifgo.call(programsv1)
if (varfin == "SET") { return }

playermark = "O"
varplace = inputter(playermark)
if (cool.call(varplace, programsv1, playermark) == "EXIT") { return }
current.call()

varfin = checkifgo.call(programsv1)
if (varfin == "SET") { return }

playermark = "X"
varplace = inputter(playermark)
if (cool.call(varplace, programsv1, playermark) == "EXIT") { return }
current.call()

varfin = checkifgo.call(programsv1)
if (varfin == "SET") { return }

playermark = "O"
varplace = inputter(playermark)
if (cool.call(varplace, programsv1, playermark) == "EXIT") { return }
current.call()

varfin = checkifgo.call(programsv1)
if (varfin == "SET") { return }

playermark = "X"
varplace = inputter(playermark)
if (cool.call(varplace, programsv1, playermark) == "EXIT") { return }
current.call()

varfin = checkifgo.call(programsv1)
if (varfin == "UNSET") { println "Cat's game aka tie game"
println "GAME OVER." }

Leave a comment

Your email address will not be published. Required fields are marked *