How to Create a Tic-Tac-Toe Game in Batch Script
Building a fully functional grid-based game like Tic-Tac-Toe in the Windows Command Prompt is a great way to practice handling state, working with pseudo-arrays, and checking win conditions. Since Batch doesn’t support true two-dimensional arrays, the 3×3 board has to be represented using nine separate variables, with logic that evaluates different combinations to detect a winner.
In this guide, we’ll create a complete interactive Tic-Tac-Toe game for two players using a Batch script.
The Strategy: The 9-Cell Array
- Initialize 9 variables representing the board grid (
cell1throughcell9), filled initially with numbers 1-9 to act as input guides. - Establish a "Current Player" toggle variable (alternating between
XandO). - Draw the board utilizing the
echocommand and the cell variables. - Capture the human input (
1-9). - Validate the move (ensure the target cell isn't already
XorO). - Update the
cellvariable with the Current Player's mark. - Check all 8 possible victory conditions.
- Check for a Draw condition.
- Loop back to step 3.
Implementation Script
@echo off
setlocal EnableDelayedExpansion
title Batch Tic-Tac-Toe
color 0E
:: Initialize Game State
:Init
for /l %%I in (1,1,9) do set "cell%%I=%%I"
set "player=X"
set "turnCount=0"
:: 1. Draw the Board
:DrawBoard
cls
echo ======================
echo TIC-TAC-TOE : !player!'s turn
echo ======================
echo.
echo ^| ^|
echo !cell1! ^| !cell2! ^| !cell3!
echo _____^|_____^|_____
echo ^| ^|
echo !cell4! ^| !cell5! ^| !cell6!
echo _____^|_____^|_____
echo ^| ^|
echo !cell7! ^| !cell8! ^| !cell9!
echo ^| ^|
echo.
:: 2. Accept User Input
set "choice="
set /p "choice=Player !player!, choose a cell (1-9): "
:: 3. Validate Input
:: First confirm the input is a number 1-9
set "validInput=0"
for /l %%V in (1,1,9) do (
if "!choice!"=="%%V" set "validInput=1"
)
if "!validInput!"=="0" (
echo [^^!] Invalid selection. Enter a number from 1 to 9.
pause >nul
goto DrawBoard
)
:: Check if the cell is already taken (contains X or O)
if "!cell%choice%!"=="X" (
echo [^^!] Cell !choice! is already taken. Choose another.
pause >nul
goto DrawBoard
)
if "!cell%choice%!"=="O" (
echo [^^!] Cell !choice! is already taken. Choose another.
pause >nul
goto DrawBoard
)
:: 4. Process Valid Move
set "cell!choice!=!player!"
set /a "turnCount+=1"
:: 5. Check for Win after placing the mark
:: Horizontal
if "!cell1!"=="!cell2!" if "!cell2!"=="!cell3!" goto Victory
if "!cell4!"=="!cell5!" if "!cell5!"=="!cell6!" goto Victory
if "!cell7!"=="!cell8!" if "!cell8!"=="!cell9!" goto Victory
:: Vertical
if "!cell1!"=="!cell4!" if "!cell4!"=="!cell7!" goto Victory
if "!cell2!"=="!cell5!" if "!cell5!"=="!cell8!" goto Victory
if "!cell3!"=="!cell6!" if "!cell6!"=="!cell9!" goto Victory
:: Diagonal
if "!cell1!"=="!cell5!" if "!cell5!"=="!cell9!" goto Victory
if "!cell3!"=="!cell5!" if "!cell5!"=="!cell7!" goto Victory
:: 6. Check Draw (all 9 cells filled with no winner)
if !turnCount! equ 9 goto Draw
:: 7. Toggle Player
if "!player!"=="X" (
set "player=O"
) else (
set "player=X"
)
goto DrawBoard
:: 8. End States
:Victory
cls
echo ======================
echo TIC-TAC-TOE : FINAL
echo ======================
echo.
echo ^| ^|
echo !cell1! ^| !cell2! ^| !cell3!
echo _____^|_____^|_____
echo ^| ^|
echo !cell4! ^| !cell5! ^| !cell6!
echo _____^|_____^|_____
echo ^| ^|
echo !cell7! ^| !cell8! ^| !cell9!
echo ^| ^|
echo.
echo ======================
echo PLAYER !player! WINS^^!
echo ======================
goto Replay
:Draw
cls
echo ======================
echo TIC-TAC-TOE : FINAL
echo ======================
echo.
echo ^| ^|
echo !cell1! ^| !cell2! ^| !cell3!
echo _____^|_____^|_____
echo ^| ^|
echo !cell4! ^| !cell5! ^| !cell6!
echo _____^|_____^|_____
echo ^| ^|
echo !cell7! ^| !cell8! ^| !cell9!
echo ^| ^|
echo.
echo ======================
echo IT'S A DRAW^^!
echo ======================
goto Replay
:Replay
echo.
set "playAgain="
set /p "playAgain=Play Again? (Y/N): "
if /i "!playAgain!"=="Y" goto Init
echo Thanks for playing^^!
pause
exit /b
How It Works
- Virtual Arrays: Batch doesn't have arrays, but
set "cell!choice!=!player!"simulates one perfectly. Ifchoiceis5, the variablecell5is dynamically updated toX. - Delayed Expansion:
EnableDelayedExpansionis strictly required here. Without the!variable syntax, the board wouldn't redraw showing the updated cells on each loop iteration. - Indirect Variable Referencing: The expression
!cell%choice%!allows us to evaluate the value of a dynamically named variable. Sincechoiceis set before the current code block is parsed,%choice%expands at parse time to form the variable name (e.g.,cell5), and the outer!...!then retrieves that variable's current value at execution time. - Victory Conditions: Tic-Tac-Toe has exactly 8 win configurations. The script stacks horizontal, vertical, and diagonal
ifstatements. If a line consists entirely of identically matched variables (e.g.,cell1==cell2andcell2==cell3), a win is triggered. Because unplayed cells contain unique numbers (1–9), three unplayed cells in a row can never produce a false match.
Why Build Tic-Tac-Toe?
- Grid Simulation: Understanding how to map a 2D layout (X/Y coordinates) into a flat list of 9 linear variables is a crucial data-structure lesson.
- Game Loops and Recursion: Managing a central
:DrawBoardgame loop that gracefully handles successful logic, failure states (invalid inputs), and interrupt states (wins/draws). - Variable Masking: Displaying variables that continuously change type (from numeric
1-9guides to stringX/Ovalues) in exactly the same grid layout.
Conclusion
Building a fully-featured Tic-Tac-Toe game proves the logical depth available natively inside the Windows Command Prompt. By intelligently leveraging dynamic variable manipulation and comprehensive state-checking conditionals, a purely administrative scripting language transforms flawlessly into a visual, interactive gaming engine.