Last active
December 31, 2015 12:58
-
-
Save WayneCui/7989380 to your computer and use it in GitHub Desktop.
井字棋游戏(Tic-tac-toe)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
REBOL [ | |
title: "A Tic Tac Toe Game to play with a clever computer." | |
] | |
tic-tac-toe: context [ | |
keypoints: [[ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] [ 1 4 7 ] [ 2 5 8 ][ 3 6 9 ] [ 1 5 9 ][ 3 5 7 ]] | |
center: 5 | |
corners: [ 1 3 7 9 ] | |
sides: [ 2 4 6 8 ] | |
validate-input: func [ input [block!] /local x y index ] [ | |
x: input/1 | |
y: input/2 | |
unless all [ x y integer? x integer? y x >= 1 x <= 3 y >= 1 y <= 3 ][ return false ] | |
index: (x - 1) * 3 + y | |
?? index | |
board/:index = '_ | |
] | |
test-over: func [ board [ block! ] /local fun f s t ][ | |
fun: func [ 'arg ][ | |
either letter = arg [ "You" ][ "I" ] | |
] | |
unless find board '_ [ print "tie!" return true ] | |
foreach point keypoints [ | |
case [ | |
all map-each i point [ board/:i = 'X ] [ print [ fun 'X "win!" ] return true ] | |
all map-each i point [ board/:i = 'O ] [ print [ fun 'O "win!" ] return true ] | |
] | |
] | |
] | |
test-over-2: func [ board [ block! ] /local fun f s t ][ | |
unless find board '_ [ return true ] | |
foreach point keypoints [ | |
case [ | |
all map-each i point [ board/:i = 'X ] [ return true ] | |
all map-each i point [ board/:i = 'O ] [ return true ] | |
] | |
] | |
] | |
computer-stratege: func [ /local copy-board temp ][ | |
temp: copy [] | |
find-all board '_ [ append temp index? board ] | |
;First, check if we can win in the next move | |
foreach i temp [ | |
copy-board: copy board | |
copy-board/:i: symbols/computer | |
if test-over-2 copy-board [ return i ] | |
] | |
;Second, check if the player could win on his next move, and block them. | |
foreach i temp [ | |
copy-board: copy board | |
copy-board/:i: symbols/player | |
if test-over-2 copy-board [ return i ] | |
] | |
;Third, try to take one of the corners, if they are free. | |
case [ | |
not empty? intersect corners temp [ first random intersect corners temp ] | |
find temp center [ center ] | |
true [ first random intersect sides temp ] | |
] | |
] | |
start: func [][ | |
print "Welcome to the tic tac toe game." | |
print "Let's begin!" | |
board: array/initial 9 '_ | |
player: random true ; 1 for player first, while 2 for computer first | |
until [ | |
letter: load uppercase ask "Do you want to be X or O? " | |
any [ letter = 'X letter = 'O ] | |
] | |
either letter = 'X [ | |
symbols: [ player X computer O ] | |
][ | |
symbols: [ player O computer X ] | |
] | |
probe new-line/all/skip board on 3 | |
until [ | |
either player [ | |
;player's move | |
until [ | |
input: load parse ask "Please enter [x, y]:" none | |
validate-input input | |
] | |
index: (input/1 - 1) * 3 + input/2 | |
board/:index: symbols/player | |
player: false | |
][ | |
;computer's move | |
index: computer-stratege | |
board/:index: symbols/computer | |
player: true | |
] | |
probe new-line/all/skip board on 3 | |
test-over board | |
] | |
if ( load ask "Try again? [Y/N]: ") = 'Y [ start ] | |
] | |
] | |
tic-tac-toe/start |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
REBOL [ | |
title: "A Tic Tac Toe Game for two human being players." | |
] | |
tic-tac-toe: context [ | |
get-input: has[ input coordinate ] [ | |
either to-logic player [ | |
print "It's player1's turn. (O)" | |
] [ | |
print "It's player2's turn. (X)" | |
] | |
input: ask "Please input [x y]:" | |
coordinate: load parse input none | |
] | |
validate: func [ coordinate [ block! ] /local x y index ] [ | |
x: coordinate/1 | |
y: coordinate/2 | |
unless all [ x y number? x number? y x >= 1 x <= 3 y >= 1 y <= 3 ][ | |
print "Wrong input [1 - 3]" | |
return false | |
] | |
index: (x - 1) * 3 + y | |
unless board/:index = '_ [ | |
print "Already in use" | |
return false | |
] | |
true | |
] | |
change-state: func [ coordinate [ block! ] /local index ] [ | |
index: (coordinate/1 - 1) * 3 + coordinate/2 | |
either to-logic player [ | |
board/:index: 'O | |
probe new-line/all/skip board on 3 | |
player: 0 | |
][ | |
board/:index: 'X | |
probe new-line/all/skip board on 3 | |
player: 1 | |
] | |
] | |
count-result: func [ /local rules result f s t ] [ | |
rules: [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] [ 1 4 7 ] [ 2 5 8 ] [ 3 6 9 ] [ 1 5 9 ] [ 3 5 7 ] ] | |
foreach rule rules [ | |
f: first rule | |
s: second rule | |
t: third rule | |
case [ | |
all [ board/:f = 'O board/:s = 'O board/:t = 'O ] [ print "Player 1 win!" return true ] | |
all [ board/:f = 'X board/:s = 'X board/:t = 'X ] [ print "Player 2 win!" return true ] | |
not find board '_ [ print "No one win!" return true ] | |
] | |
] | |
false | |
] | |
start: does [ | |
print "The Tic Tac Toe Game!" | |
print "Player 1 for O, Player 2 for X" | |
print "Let's begin!" | |
board: array/initial 9 '_ | |
probe new-line/all/skip board on 3 | |
player: 1 | |
until [ | |
until [ | |
coordinate: get-input | |
validate coordinate | |
] | |
change-state coordinate | |
count-result | |
] | |
input: ask "Play again? (Y/N)" | |
if input = "Y" [ start ] | |
] | |
] | |
tic-tac-toe/start |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment