Исходник:
@echo off
cls
set FLAG_DIR=c:\scripts\xo
call :create_chars
:restart
echo Please wait...
call :sys_utils init "%0"
set cmdPrefix=$p%__PID%
rem ------- connecting --------
call :sys_utils enter_critical_section
cls
call :sys_utils fetch_flag ready_to_play
if "%RESULT%"=="" (
call :sys_utils set_flag ready_to_play %cmdPrefix%
set symbol=X
set symbol2=O
set server=1
) else (
set cmdPrefix=%RESULT%
call :sys_utils set_flag %RESULT%_client_ready ---
set symbol=O
set symbol2=X
set server=0
)
call :sys_utils leave_critical_section
if "%server%"=="0" goto client1
call :wait_for_client
call :sys_utils set_flag %cmdPrefix%_server_ready_too ---
goto skipClient1
:client1
call :wait_for_server
if "%serverFailure%"=="1" goto restart
:skipClient1
rem ------- connected --------
call :clear_field
if "%server%"=="1" (set curMode=your_turn) else (set curMode=enemy_turn)
:main_game_loop
cls
call :check_win
call :render_field
if "%winSymbol%"=="%symbol%" goto you_win
if "%winSymbol%"=="%symbol2%" goto enemy_win
if not "%curMode%"=="your_turn" goto skipTurn1
echo.
echo Your are "%symbol%"
echo.
set /p tmp=Please enter <nul
if "%f1%"=="1" set /p tmp=1, <nul
if "%f2%"=="2" set /p tmp=2, <nul
if "%f3%"=="3" set /p tmp=3, <nul
if "%f4%"=="4" set /p tmp=4, <nul
if "%f5%"=="5" set /p tmp=5, <nul
if "%f6%"=="6" set /p tmp=6, <nul
if "%f7%"=="7" set /p tmp=7, <nul
if "%f8%"=="8" set /p tmp=8, <nul
if "%f9%"=="9" set /p tmp=9, <nul
echo or 'q' for quit
echo.
set /p "tmp=Your turn: "
if "%tmp%"=="q" goto quit_game
if "%tmp%"=="Q" goto quit_game
call set varName=%%f%tmp%%%
if not "%varName%"=="%tmp%" goto main_game_loop
call set f%tmp%=%symbol%
call :sys_utils set_flag %cmdPrefix%_%symbol%_move f%tmp%
set curMode=enemy_turn
goto main_game_loop
:skipTurn1
if not "%curMode%"=="enemy_turn" goto skipTurn2
echo.
echo Waiting for another player
:wait_for_player0
set /p tmp=.<nul
ping -n 2 127.0.0.1 > nul
call :sys_utils fetch_flag %cmdPrefix%_%symbol2%_move
if "%RESULT%"=="" goto wait_for_player0
echo %RESULT%
if "%RESULT%"=="q" goto other_player_quit
call set %RESULT%=%symbol2%
set curMode=your_turn
goto main_game_loop
:skipTurn2
goto main_game_loop
:quit_game
call :sys_utils set_flag %cmdPrefix%_%symbol%_move q
exit
:other_player_quit
cls
echo Other player has left the game.
echo Press 'Enter' to search for another one.
pause > nul
goto restart
:you_win
echo.
echo You Win
echo.
echo Press 'Enter'
pause > nul
goto restart
:enemy_win
echo.
echo You Lose
echo.
echo Press 'Enter'
pause > nul
goto restart
:wait_for_client
echo Waiting for client
:wait_for_client1
set /p tmp=.<nul
ping -n 2 127.0.0.1 > nul
call :sys_utils fetch_flag %cmdPrefix%_client_ready
if "%RESULT%"=="" goto wait_for_client1
exit /b
:wait_for_server
echo Waiting for server
set serverFailure=0
set /a waitCnt=4
:wait_for_server1
set /a waitCnt-=1
if "%waitCnt%"=="0" (
set serverFailure=1
exit /b
)
set /p tmp=.<nul
ping -n 2 127.0.0.1 > nul
call :sys_utils fetch_flag %cmdPrefix%_server_ready_too
if "%RESULT%"=="" goto wait_for_server1
exit /b
:clear_field
set "f1=1"
set "f2=2"
set "f3=3"
set "f4=4"
set "f5=5"
set "f6=6"
set "f7=7"
set "f8=8"
set "f9=9"
exit /b
:create_chars
set "charX0= # # ^|"
set "charX1= # # ^|"
set "charX2= # ^|"
set "charX3= # # ^|"
set "charX4= # # ^|"
set "charX5=-------+"
set "charO0= ### ^|"
set "charO1= # # ^|"
set "charO2= # # ^|"
set "charO3= # # ^|"
set "charO4= ### ^|"
set "charO5=-------+"
set "charXW0=.#...#.^|"
set "charXW1=..#.#..^|"
set "charXW2=...#...^|"
set "charXW3=..#.#..^|"
set "charXW4=.#...#.^|"
set "charXW5=-------+"
set "charOW0=..###..^|"
set "charOW1=.#...#.^|"
set "charOW2=.#...#.^|"
set "charOW3=.#...#.^|"
set "charOW4=..###..^|"
set "charOW5=-------+"
for %%i in (1,2,3,4,5,6,7,8,9) do call :create_empty_char %%i
exit /b
:create_empty_char
set "char%10= ^|"
set "char%11= ^|"
set "char%12= %1 ^|"
set "char%13= ^|"
set "char%14= ^|"
set "char%15=-------+"
exit /b
:check_win
set winSymbol=.
call :check3 1 2 3
call :check3 4 5 6
call :check3 7 8 9
call :check3 1 4 7
call :check3 2 5 8
call :check3 3 6 9
call :check3 1 5 9
call :check3 3 5 7
exit /b
:check3
call set tmp1=%%f%1%%%%f%2%%%%f%3%%
call set tmp2=%%f%1%%%%f%1%%%%f%1%%
if "%tmp1%"=="%tmp2%" (
call set "winSymbol=%%f%1%%"
call set "f%1=%%f%1%%W"
call set "f%2=%%f%2%%W"
call set "f%3=%%f%3%%W"
)
exit /b
:render_field
call :render_line %f1% %f2% %f3%
call :render_line %f4% %f5% %f6%
call :render_line %f7% %f8% %f9%
exit /b
:render_line
call echo %%char%10%%%%char%20%%%%char%30%%
call echo %%char%11%%%%char%21%%%%char%31%%
call echo %%char%12%%%%char%22%%%%char%32%%
call echo %%char%13%%%%char%23%%%%char%33%%
call echo %%char%14%%%%char%24%%%%char%34%%
call echo %%char%15%%%%char%25%%%%char%35%%
exit /b
rem ----------------- atom --------------
:sys_utils
goto %1
exit /b
:init
if "%FLAG_DIR%"=="" set FLAG_DIR=.
set UNIQ_BAT_ID=%COMPUTERNAME%_%USERNAME%_%~n2
set /A CRITICAL_SECTION_LEVEL=0
call :enter_critical_section
call :test_flag --null-- $pid$
set /A __PID=%RESULT%
if [%__PID%]==[0] set /A __PID=10000000
if [%__PID%]==[] set /A __PID=10000000
if [%__PID%]==[99999999] set /A __PID=10000000
set /A __PID=__PID+1
call :set_flag --null-- $pid$ %__PID%
call :leave_critical_section
set UNIQ_BAT_ID=%UNIQ_BAT_ID%_pid%__PID%
exit /b
:set_flag
call :enter_critical_section
echo %3>"%FLAG_DIR%\%2"
call :leave_critical_section
exit /b
:remove_flag
call :enter_critical_section
if exist "%FLAG_DIR%\%2" del "%FLAG_DIR%\%2"
call :leave_critical_section
exit /b
:fetch_flag
call :enter_critical_section
set "RESULT="
if exist "%FLAG_DIR%\%2" (
set /p RESULT=<"%FLAG_DIR%\%2"
del "%FLAG_DIR%\%2"
)
call :leave_critical_section
exit /b
:test_flag
call :enter_critical_section
set "RESULT="
if exist "%FLAG_DIR%\%2" set /p RESULT=<"%FLAG_DIR%\%2"
call :leave_critical_section
exit /b
:enter_critical_section
set /A CRITICAL_SECTION_LEVEL=CRITICAL_SECTION_LEVEL+1
if not [%CRITICAL_SECTION_LEVEL%]==[1] exit /b
set /A __WAIT_CNT=500
:wait_enter_critical_section
set /A __WAIT_CNT=__WAIT_CNT-1
if [%__WAIT_CNT%]==[0] del "%FLAG_DIR%\$cs$_*"
if exist "%FLAG_DIR%\$cs$_*" goto wait_enter_critical_section
echo.>"%FLAG_DIR%\$cs$_%UNIQ_BAT_ID%"
set /A __CNT=0
for %%i in ( "%FLAG_DIR%\$cs$_*" ) do set /a __CNT=__CNT+1
if [%__CNT%]==[1] goto all_right_1
del "%FLAG_DIR%\$cs$_%UNIQ_BAT_ID%"
goto wait_enter_critical_section
:all_right_1
exit /b
:leave_critical_section
set /A CRITICAL_SECTION_LEVEL=CRITICAL_SECTION_LEVEL-1
if [%CRITICAL_SECTION_LEVEL%]==[0] del "%FLAG_DIR%\$cs$_%UNIQ_BAT_ID%"
exit /b
:EOF
|