AdditionalPylons

tictactoe typst

Nov 23rd, 2025
268
0
Never
9
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.18 KB | None | 0 0
  1. #let player = "x"
  2. #let computer = "o"
  3.  
  4. #set table(columns: (2em,2em,2em),rows: (2em,2em,2em), align: center)
  5. #set page(width: 10em,height: 12em)
  6. #show link: underline
  7. #show link: it => text(blue,it)
  8. #show: it => align(center,it)
  9.  
  10. #let get-page(state) = link(label(state))[.]
  11. #let fill_comp(c) = {
  12. if c == "." {return computer}
  13. return c
  14. }
  15. #let get-best-move(state) = {
  16. assert(state.len()==9)
  17. // immediate win opportunities
  18. for i in range(3) {
  19. let row = state.slice(i*3,count :3)
  20. if row.matches(computer).len() == 2 and row.matches(".").len() == 1 {
  21. return state.slice(0,i*3)+computer*3+state.slice((i+1)*3)
  22. }
  23. }
  24. for i in range(3) {
  25. let col = state.at(i)+state.at(i+3)+state.at(i+6)
  26. if col.matches(computer).len() == 2 and col.matches(".").len() == 1 {
  27. return state.slice(0,i)+computer+state.slice(i+1,count :2)+computer+state.slice(i+4,count :2)+computer+state.slice(i+7)
  28. }
  29. }
  30. let diag1 = state.at(0)+state.at(4)+state.at(8)
  31. let diag2 = state.at(2)+state.at(4)+state.at(6)
  32. if diag1.matches(computer).len() == 2 {
  33. return computer+state.slice(1,4)+computer+state.slice(5,8)+computer
  34. }
  35. if diag2.matches(computer).len() == 2 {
  36. return state.slice(0,2)+computer+state.at(3)+computer+state.at(5)+computer+state.slice(7)
  37. }
  38.  
  39. // if no immediate win, close player wins
  40. for i in range(3) {
  41. let row = state.slice(i*3,count :3)
  42. if row.matches(player).len() == 2 and row.matches(".").len() == 1 {
  43. return state.slice(0,i*3)+fill_comp(row.at(0))+fill_comp(row.at(1))+fill_comp(row.at(2))+state.slice((i+1)*3)
  44. }
  45. }
  46. for i in range(3) {
  47. let col = state.at(i)+state.at(i+3)+state.at(i+6)
  48. if col.matches(player).len() == 2 and col.matches(".").len() == 1 {
  49. return state.slice(0,i)+fill_comp(state.at(i))+state.slice(i+1,count :2)+fill_comp(state.at(i+3))+state.slice(i+4,count :2)+fill_comp(state.at(i+6))+state.slice(i+7)
  50. }
  51. }
  52. if diag1.matches(player).len() == 2 and diag1.matches(".").len() == 1 {
  53. return fill_comp(state.at(0))+state.slice(1,4)+fill_comp(state.at(4))+state.slice(5,8)+fill_comp(state.at(8))
  54. }
  55. if diag2.matches(player).len() == 2 and diag2.matches(".").len() == 1 {
  56. return state.slice(0,2)+fill_comp(state.at(2))+state.at(3)+fill_comp(state.at(4))+state.at(5)+fill_comp(state.at(6))+state.slice(7)
  57. }
  58.  
  59. // arbitrary placement if nothing found
  60. for i in range(9){
  61. if state.at(i) == "."{
  62. return state.slice(0,i)+computer+state.slice(i+1)
  63. }
  64. }
  65.  
  66. state // fallback if tie
  67. }
  68. #let winner(state) = {
  69. for i in range(3) {
  70. let row = state.slice(i*3,count :3) // :3
  71. if row.matches(row.at(0)).len() == 3 {
  72. return row.at(0)
  73. }
  74. }
  75. for i in range(3) {
  76. let col = state.at(i)+state.at(i+3)+state.at(i+6)
  77. if col.matches(col.at(0)).len() == 3 {
  78. return col.at(0)
  79. }
  80. }
  81. let diag = state.at(0)+state.at(4)+state.at(8)
  82. if diag.matches(diag.at(0)).len() == 3 {
  83. return diag.at(0)
  84. }
  85. let diag = state.at(2)+state.at(4)+state.at(6)
  86. if diag.matches(diag.at(0)).len() == 3 {
  87. return diag.at(0)
  88. }
  89. return "."
  90. }
  91. #let tictactoe(state,norefs: false) = [
  92. #if winner(state)!="." {norefs=true}
  93. #let symbols = ("","","","","","","","","")
  94. #for i in range(9) {
  95. if state.at(i) == "." {
  96. if norefs {symbols.at(i)="."}
  97. else {symbols.at(i) = get-page(get-best-move(state.slice(0,i)+player+state.slice(i+1)))}
  98. } else {
  99. symbols.at(i) = state.at(i)
  100. }
  101. }
  102. #figure(
  103. table(..symbols)
  104. )
  105. #label(state)
  106. ]
  107.  
  108. #let generate(state,used:()) = {
  109. if state in used {return ([],used)}
  110. let c = []
  111. assert(state.len()==9,message:"err "+state)
  112.  
  113. c+=tictactoe(state)
  114. if state.matches(".").len()<=0 {return (c+[Tie. \ #link(label("........."))[Go back] #pagebreak()],used+(state,))}
  115. if winner(state)!="."{return (c+[Winner: #winner(state) \ #link(label("........."))[Go back] #pagebreak()],used+(state,))}
  116. for i in range(9){
  117. if state.at(i)=="."{
  118. let v = generate(get-best-move(state.slice(0,i)+player+state.slice(i+1)),used:used+(state,))
  119. c+=v.at(0)
  120. used=v.at(1)
  121. }
  122. }
  123. c+=pagebreak()
  124. (c,used+(state,))
  125. }
  126. #generate(".........").at(0)
Advertisement
Comments
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
Add Comment
Please, Sign In to add comment