1 / 1 / 0
Регистрация: 13.01.2016
Сообщений: 18
1

Крестики нолики на двоих Haskell

25.03.2017, 18:22. Показов 4069. Ответов 42
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Не могу понять, почему ошибка, вроде все нормально по синтаксису. Изначально, программа была создана с искусственным интеллектом.
Помогите, пожалуйста, доработать игру. Может какие-то есть идеи?

Ошибка такая:Syntax error in expression (unexpected `}', possibly due to bad layout)

Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
{-^
Крестики-нолики.
Игра «крестики-нолики» на доске 3 х 3. Пронумеруем клетки следующим образом:
 
 1 | 2 | 3 
---+---+---
 4 | 5 | 6 
---+---+---
 7 | 8 | 9 
 
Тогда позиция во время игры может быть представлена как data Pos = Pos [Integer] [Integer], 
где первый список содержит позиции игрока компьютера O, 
а второй — позиции противника человека Х.  
-}
 
module Main where
 
import Data.List               
import Random
 
data Pos = Pos [Integer] [Integer] deriving Show --директива позволяет использовать тип как строки 
 
-- ^ функция validPos :: Pos -> Bool, которая проверяет необходимые условия правильности позиции.
validPos :: Pos -> Bool
validPos (Pos [][]) = True
validPos (Pos ol xl) = res where          
  sp = (xl++ol)  
  res = all (\a -> a == True) [maximum sp < 10, minimum sp > 0, nub sp == sp, True] --nub удаляет все повторяющиеся эл-ты
-- ^ Test
validPosTest = [validPos (Pos [][]),  validPos (Pos [1,0,-1] [4,5,11]),
                validPos (Pos [1,6,5] [4,5,11]), validPos (Pos [1,4] [5,7,9])]
                
-- ^ функция vacant :: Pos -> [Integer], которая возвращает пустые клетки для данной позиции. 
vacant :: Pos -> [Integer]
vacant (Pos ol xl) = res where
  sp = (xl++ol) 
  res = drop (length sp)(nub (sp ++ [1..9]))
vacantTest = [vacant (Pos [1,5] [2])]
 
 
-- ^ функция play :: Integer -> Pos -> Pos, которая возвращает позицию, 
-- где текущий игрок компьютер ставит свой знак в заданную клетку.
play :: Integer -> Pos -> Pos
play m (Pos o x)  = (Pos o ([m]++o))
playTest  = [play 1 (Pos [5] [2]),  play 3 (Pos [1,5] [2])]
 
 
play' :: Integer -> Pos -> Pos --для игрока человака
play' m (Pos o x) = (Pos o ([m]++x)) 
playTest'  = [play' 1 (Pos [5] [2]),  play' 3 (Pos [1,5] [2])]
 
-- ^Строки, столбцы, диагонали доски 3Х3
rcd :: [[Integer]]
rcd = [[1,2,3], [4,5,6], [7,8,9], [1,4,7], [2,5,8], [3,6,9], [1,5,9], [3,5,7]]
 
-- ^Функция won :: Pos -> Bool, которая определяет, выиграл ли игрок компьютер. 
-- Например: won (Pos [1,5] [2,3]) == False; won (Pos [1,4,5,7] [2,3,9]) == True.
won :: Pos -> Bool
won (Pos xl o) = length (filter (\f -> (length f) == (length xl)) (map (\n -> nub (xl++n)) rcd)) > 0
wonTest = [won (Pos [1,5] [2,3]), won (Pos [1,4,5,7] [2,3,9]), won (Pos [9,7,1,5] [2,3,9])]
 
won' :: Pos -> Bool --выигал ли игрок человек
won' (Pos o xl) = length (filter (\f -> (length f) == (length xl)) (map (\n -> nub (xl++n)) rcd)) > 0
wonTest' = [won (Pos [1,5] [2,3]), won (Pos [1,4,5,7] [2,3,9]), won (Pos [9,7,1,5] [2,3,9])]
 
{-^
Н. Нильсон "Принципы исскуственного интеллекта" c. 100
Статическая оценочная функция. Задается тремя условиями:
 1) Если в позиции Pos не выигрывает ни один из игроков, то scope(Pos) - 
   (число строк, столбцов и диагоналей, на данный момент целиком свободных 
    для игрока max (comp)) - (число строк, столбцов и диагоналей, на данный момент целиком свободных для игрока min). Т.е. число строк, столбцов и диагоналей, на игровой доске 3Х3, в которых
    игрок min не поставил пока ни одного знака.
 2) Если в Pos выигрыш получает max, то scope(Pos) = очень большому числу
 3) Если в Pos выигрыш получает min, то scope(Pos) = очень большому отрицательному числу
-}
 
score :: Pos -> Integer
score (Pos ol xl) = 
  if won (Pos ol xl) 
  then 1000000000  -- max (comp) победил
  else if won' (Pos ol xl)
       then -1000000000 -- max проиграл
       else (rcdEmpty xl) - (rcdEmpty ol) 
--
rcdEmpty :: [Integer] -> Integer --оценка ситуации
rcdEmpty l = (sum $ concat (map (\m -> map (\r -> if (elem m r) then 0 else 1) rcd) l))
 
scoreTest  = [score (Pos [5] [1]), score (Pos [5] [4]), score (Pos [4] [5]),
              score (Pos [4] [2]), score (Pos [1] [4]), score (Pos [9,5] [2,7])]
 
 
 
 
-- Сравнение позиций для сортировки функцией sortBy
cmpPos :: (Pos, Integer) -> (Pos, Integer) -> Ordering
cmpPos p1 p2 = if (snd p1) > (snd p2) then GT else LT --snd выбирает второй из пары
 
 
 
-- ^Программа, которая  в интерактивном режиме играет с человеком, 
--  отображая изменение состояния игрового поля.
 
replace :: Eq a => [a] -> [a] -> [a] -> [a] -- заменяет в s find на repl
replace [] _ _ = []
replace s find repl =
  if take (length find) s == find
  then repl ++ (replace (drop (length find) s) find repl)
  else [head s] ++ (replace (tail s) find repl)
 
{-^
Для вывода позиции на экран преобразует стуктуру данных Pos в
строковое представление номеров, нулей и крестов.
Первый список это будут ходы компа которые обозначим символом O.
-}
 
makeStringPos2 :: Pos -> String
makeStringPos2 (Pos o x) = res where
  empty =  "\n123\n456\n789\n"
  res = add' (add' empty x "X") o "O"
 
makeStringPos1 :: Pos -> String
makeStringPos1 (Pos o x) = res where
  empty =  "\n 1 | 2    | 3 \n---+---+---\n 4 | 5 | 6 \n---+---+---\n 7 | 8 | 9 \n"
  res = add' (add' empty x "X") o "O"
 
add' :: String -> [Integer] -> String -> String
add' s [] a = s
add' s (r:rs) a = add' (replace s (show r) a) rs a
 
game :: Pos -> IO ()
game (Pos x o) = do  
  putStr "hod dostup: "
  putStrLn $ show (vacant (Pos x o))
  putStrLn (makeStringPos1 (Pos x o))        
  if null$ vacant (Pos x o)
    then
    if won (Pos x o) 
    then do putStrLn "Player2!  ;)" 
    else if won' (Pos x o)
         then do  putStrLn "PLayer1 is winner! ;("
         else do  putStrLn "ok ichelyash' :)"
    else do
    putStrLn "PLayer1:"
    pos <- getLine 
    let newPos = play' ((read pos)::Integer) (Pos x o)
    putStrLn (show newPos)                
    if validPos newPos
      then do 
      if won' newPos 
        then do 
        putStrLn (makeStringPos1 newPos)
        putStrLn "PLayer1 is winner! ;(";
      else do
      if (null $ vacant newPos) == False
             then do
 
    let newPos2 = play ((read pos)::Integer) (Pos x o)
    putStrLn (show newPos2)                
    if validPos newPos2
      then do 
      if won newPos2 
        then do 
        putStrLn (makeStringPos2 newPos2)
        putStrLn "Humans is winner! ;("
                 else do game newPos2 
             else do putStrLn (makeStringPos1 newPos); putStrLn "ok ichelyash' :)"
      else do putStrLn("\nInvalid course! Repeat!\n"); game (Pos x o)
main = do
putStrLn ""  
game (Pos [][])
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.03.2017, 18:22
Ответы с готовыми решениями:

Крестики-нолики
Добрый день. Не могли бы вы помочь с игрой крестики-нолики на поле 3х3 человек против человека?

Крестики-нолики: плохо прорисовываются "нолики"
Я, наверное, всех уже достал своей игрой, но я опять напоролся на подводный камень. Игра -...

Крестики нолики
Помогите создать метод, который будет проверять победили крестики или нолики, только интересует как...

Крестики нолики
Здравствуйте. Никак не получается определить, кто победил, всегда выводит ничью. Почему? ...

42
Модератор
5046 / 3275 / 526
Регистрация: 01.06.2013
Сообщений: 6,802
Записей в блоге: 9
25.03.2017, 18:54 2
Лучший ответ Сообщение было отмечено pitbul как решение

Решение

У вас там где то строчка пропущена. И форматирование съехало, что в Haskell важно. Я нагуглил практически тоже, но сообщения не переведены с английского.
Кликните здесь для просмотра всего текста
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
{-^
Лабораторная 7. Вариант 6. Крестики-нолики. Минимаксный подход.
 
Игра «крестики-нолики» на доске 3 х 3. Пронумеруем клетки следующим образом:
 
 1 | 2 | 3 
---+---+---
 4 | 5 | 6 
---+---+---
 7 | 8 | 9 
 
Тогда позиция во время игры может быть представлена как data Pos = Pos [Integer] [Integer], 
где первый список содержит позиции игрока компьютера O, 
а второй — позиции противника человека Х.  
-}
 
module Main where
 
import Data.List         
import System.Random
 
 
data Pos = Pos [Integer] [Integer] deriving Show
 
-- ^ функция validPos :: Pos -> Bool, которая проверяет необходимые условия правильности позиции.
validPos :: Pos -> Bool
validPos (Pos [][]) = True
validPos (Pos ol xl) = res where          
  sp = (xl++ol)  
  res = all (\a -> a == True) [maximum sp < 10, minimum sp > 0, nub sp == sp, True] 
-- ^ Test
validPosTest = [validPos (Pos [][]),  validPos (Pos [1,0,-1] [4,5,11]),
                validPos (Pos [1,6,5] [4,5,11]), validPos (Pos [1,4] [5,7,9])]
               
-- ^ функция vacant :: Pos -> [Integer], которая возвращает пустые клетки для данной позиции. 
vacant :: Pos -> [Integer]
vacant (Pos ol xl) = res where
  sp = (xl++ol) 
  res = drop (length sp)(nub (sp ++ [1..9]))
vacantTest = [vacant (Pos [1,5] [2])]
 
-- ^ функция play :: Integer -> Pos -> Pos, которая возвращает позицию, 
-- где текущий игрок компьютер ставит свой знак в заданную клетку.
play :: Integer -> Pos -> Pos
play m (Pos o x) = (Pos ([m]++o) x)
playTest  = [play 1 (Pos [5] [2]),  play 3 (Pos [1,5] [2])]
 
play' :: Integer -> Pos -> Pos
play' m (Pos o x) = (Pos o ([m]++x)) 
playTest'  = [play' 1 (Pos [5] [2]),  play' 3 (Pos [1,5] [2])]
 
-- ^Строки, столбцы, диагонали доски 3Х3
rcd :: [[Integer]]
rcd = [[1,2,3], [4,5,6], [7,8,9], [1,4,7], [2,5,8], [3,6,9], [1,5,9], [3,5,7]]
 
-- ^Функция won :: Pos -> Bool, которая определяет, выиграл ли игрок компьютер. 
-- Например: won (Pos [1,5] [2,3]) == False; won (Pos [1,4,5,7] [2,3,9]) == True.
won :: Pos -> Bool
won (Pos xl o) = length (filter (\f -> (length f) == (length xl)) (map (\n -> nub (xl++n)) rcd)) > 0
wonTest = [won (Pos [1,5] [2,3]), won (Pos [1,4,5,7] [2,3,9]), won (Pos [9,7,1,5] [2,3,9])]
 
won' :: Pos -> Bool
won' (Pos o xl) = length (filter (\f -> (length f) == (length xl)) (map (\n -> nub (xl++n)) rcd)) > 0
wonTest' = [won (Pos [1,5] [2,3]), won (Pos [1,4,5,7] [2,3,9]), won (Pos [9,7,1,5] [2,3,9])]
 
{-^
Н. Нильсон "Принципы исскуственного интеллекта" c. 100
Статическая оценочная функция. Задается тремя условиями:
 1) Если в позиции Pos не выигрывает ни один из игроков, то scope(Pos) - 
   (число строк, столбцов и диагоналей, на данный момент целиком свободных 
    для игрока max (comp)) - (число строк, столбцов и диагоналей, на данный момент целиком свободных 
    для игрока min). Т.е. число строк, столбцов и диагоналей, на игровой доске 3Х3, в которых
    игрок min не поставил пока ни одного знака.
 2) Если в Pos выигрыш получает max, то scope(Pos) = очень большому числу
 3) Если в Pos выигрыш получает min, то scope(Pos) = очень большому отрицательному числу
-}
 
score :: Pos -> Integer
score (Pos ol xl) = 
  if won (Pos ol xl) 
  then 1000000000  -- max (comp) победил
  else if won' (Pos ol xl)
       then -1000000000 -- max проиграл
       else (rcdEmpty xl) - (rcdEmpty ol) 
--
rcdEmpty :: [Integer] -> Integer
rcdEmpty l = (sum $ concat (map (\m -> map (\r -> if (elem m r) then 0 else 1) rcd) l))
 
scoreTest  = [score (Pos [5] [1]), score (Pos [5] [4]), score (Pos [4] [5]),
              score (Pos [4] [2]), score (Pos [1] [4])]
 
-- max
evalMax :: Pos -> Integer
evalMax pos = 
  maximum (map (\y -> evalMin y) (map (\x -> (play x pos)) (vacant pos)) )
 
evalMax' pos = 
  (map (\y -> (y, evalMin y)) (map (\x -> (play x pos)) (vacant pos)) )
  
-- min
evalMin :: Pos -> Integer
evalMin pos = 
  minimum (map (\y -> score y) (map (\x -> (play' x pos)) (vacant pos)) )
 
evalMin' pos = (map (\y -> score y) (map (\x -> (play' x pos)) (vacant pos)) )
 
-- Последний ход компьютера?
lastPlay :: Pos -> Integer
lastPlay (Pos o x) = head o
 
-- Сравнение позиций для сортировки функцией sortBy
cmpPos :: (Pos, Integer) -> (Pos, Integer) -> Ordering
cmpPos p1 p2 = if (snd p1) > (snd p2) then GT else LT
 
-- ^Функция bestMove :: Pos -> Integer, Возвращающую клетку в которую нужно сделать лучший ход. 
--  Например: bestMove (Pos [1,5] [2,3]) == 4.
bestMove :: Pos -> Integer
bestMove (Pos ol xl) =  lastPlay (fst (last (sortBy (\s1 s2 -> cmpPos s1 s2) (evalMax' (Pos ol xl)))))
 
bestMoveTest = [bestMove (Pos [1,5] [2,3]), bestMove (Pos [1,4,8] [3,5,7]), bestMove (Pos [1,2] [7,8])]
 
-- ^Программа, которая  в интерактивном режиме играет с человеком, 
--  отображая изменение состояния игрового поля.
 
replace :: Eq a => [a] -> [a] -> [a] -> [a]
replace [] _ _ = []
replace s find repl =
  if take (length find) s == find
  then repl ++ (replace (drop (length find) s) find repl)
  else [head s] ++ (replace (tail s) find repl)
 
{-^
Для вывода позиции на экран преобразует стуктуру данных Pos в
строковое представление номеров, нулей и крестов. 
Первый список это будут ходы компа которые обозначим символом O.
-}
 
makeStringPos :: Pos -> String
makeStringPos (Pos o x) = res where
  empty =  "\n123\n456\n789\n"
  res = add' (add' empty x "X") o "O"
 
makeStringPos' :: Pos -> String
makeStringPos' (Pos o x) = res where
  empty =  "\n 1 | 2 | 3 \n---+---+---\n 4 | 5 | 6 \n---+---+---\n 7 | 8 | 9 \n"
  res = add' (add' empty x "X") o "O"
 
add' :: String -> [Integer] -> String -> String
add' s [] a = s
add' s (r:rs) a = add' (replace s (show r) a) rs a
 
game :: Pos -> IO ()
game (Pos x o) = do  
  putStr "Vacant course: "
  putStrLn $ show (vacant (Pos x o))
  putStrLn (makeStringPos' (Pos x o))        
  if null$ vacant (Pos x o)
    then
    if won (Pos x o) 
    then do putStrLn "Winner comp ;)" 
    else if won' (Pos x o)
         then do  putStrLn "Winner humman ;("
         else do  putStrLn "Drawn game :)"
    else do
    putStrLn "Your course:"
    pos <- getLine 
    let newPos = play' ((read pos)::Integer) (Pos x o)
    putStrLn (show newPos)                
    if validPos newPos
      then do 
      if won' newPos 
        then do 
        putStrLn (makeStringPos' newPos)
        putStrLn "Winner humman ;("
        else if (null $ vacant newPos) == False
             then do
               let forHumPos = (play (bestMove newPos) newPos)
               putStr "Comp course: "
               putStrLn $ show (lastPlay forHumPos)    
               if won forHumPos                               
                 then  do  putStrLn (makeStringPos' forHumPos) ; putStrLn "Winner comp ;)"
                 else do game forHumPos 
             else do putStrLn (makeStringPos' newPos); putStrLn "Drawn game :)"
      else do putStrLn("\nInvalid course! Repeat!\n"); game (Pos x o)
                       
main = do
    putStrLn "Daggers-Zeroes games."  
    game (Pos [][])
это работает.
2
1 / 1 / 0
Регистрация: 13.01.2016
Сообщений: 18
26.03.2017, 09:09  [ТС] 3
СПАСИБО
Правда, не знал, что форматирование как-то влияет

Добавлено через 39 минут
Я убрал строчки, которые относятся к искусственному интеллекту. Я хочу сделать, чтобы по очереди 2 игрока вводили значения
0
Антикодер
1804 / 869 / 48
Регистрация: 15.09.2012
Сообщений: 3,081
26.03.2017, 11:06 4
Обновил свой репозиторий AXT GL Tic tac toe.
Но код ещё сыроват:
Неправильно обрабатываются повторные нажатия на клетку.
Не написан режим игры с компьютером.

Возможно в ближайшее время доработаю. Компилирую в Linux.
2
Модератор
5046 / 3275 / 526
Регистрация: 01.06.2013
Сообщений: 6,802
Записей в блоге: 9
26.03.2017, 12:29 5
Цитата Сообщение от pitbul Посмотреть сообщение
Я хочу сделать, чтобы по очереди 2 игрока вводили значения
Кликните здесь для просмотра всего текста
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
module Main(main) where
 
import Data.List         
 
data Pos = Pos [Int] [Int] deriving Show
 
-- ^ функция validPos :: Pos -> Bool, которая проверяет необходимые условия правильности позиции.
validPos :: Pos -> Bool
validPos (Pos [][]) = True
validPos (Pos ol xl) = res where          
  sp = xl++ol
  res = and [maximum sp < 10, minimum sp > 0, nub sp == sp, True] 
               
-- ^ функция vacant :: Pos -> [Int], которая возвращает пустые клетки для данной позиции. 
vacant :: Pos -> [Int]
vacant (Pos ol xl) = res where
  sp = xl++ol 
  res = drop (length sp)(nub (sp ++ [1..9]))
 
-- ^ функция play :: Int -> Pos -> Pos, которая возвращает позицию, 
-- где текущий игрок компьютер ставит свой знак в заданную клетку.
play :: Int -> Pos -> Pos
play m (Pos o x) = Pos (m:o) x
 
play' :: Int -> Pos -> Pos
play' m (Pos o x) = Pos o (m:x)
 
-- ^Строки, столбцы, диагонали доски 3Х3
rcd :: [[Int]]
rcd = [[1,2,3], [4,5,6], [7,8,9], [1,4,7], [2,5,8], [3,6,9], [1,5,9], [3,5,7]]
 
-- ^Функция isWon :: [Int] -> Bool, которая определяет, выиграл ли игрок компьютер. 
isWon :: [Int] -> Bool 
isWon x = any (all (`elem` x)) rcd
 
replace :: Eq a => [a] -> [a] -> [a] -> [a]
replace [] _ _ = []
replace s find repl =
  if take (length find) s == find
  then repl ++ replace (drop (length find) s) find repl
  else head s : replace (tail s) find repl
 
{-^
Для вывода позиции на экран преобразует стуктуру данных Pos в
строковое представление номеров, нулей и крестов. 
Первый список это будут ходы компа которые обозначим символом O.
-}
 
makeStringPos' :: Pos -> String
makeStringPos' (Pos o x) = res where
  empty =  "\n 1 | 2 | 3 \n---+---+---\n 4 | 5 | 6 \n---+---+---\n 7 | 8 | 9 \n"
  res = add' (add' empty x "X") o "O"
 
add' :: String -> [Int] -> String -> String
add' s [] _ = s
add' s (r:rs) a = add' (replace s (show r) a) rs a
 
gamerChar :: Bool -> Char 
gamerChar False = 'O'
gamerChar _     = 'X'
 
game :: Bool -> Pos -> IO ()
game bGamer (Pos x o) 
        | isWon o = showPos >> putStrLn "Winner gamer X" 
        | isWon x = showPos >> putStrLn "Winner gamer O"
        | null$ vacant (Pos x o) = showPos >> putStrLn "Drawn game :)"
        | otherwise = do
    putStr "Vacant course: "
    print $ vacant $ Pos x o
    showPos        
    putStrLn $ "Your course, gamer " ++ (gamerChar bGamer :" :")
    pos <- getLine 
    let newPos = (if bGamer then play' else play) (read pos ::Int) (Pos x o)
    if validPos newPos
      then game (not bGamer) newPos
      else putStrLn "\nInvalid course! Repeat!\n" >> game bGamer (Pos x o)
  where showPos = putStrLn (makeStringPos' (Pos x o))
    
main :: IO ()   
main = do
    putStrLn "Daggers-Zeroes games."  
    game True (Pos [][])
Переделал, выкинул AI. Ломать не строить ...
1
1 / 1 / 0
Регистрация: 13.01.2016
Сообщений: 18
26.03.2017, 13:38  [ТС] 6
Класс)) работает, спасибо
Сам точно не сделал, привык к императивным языкам.

Еще есть вопросик: есть вид крестиков-ноликов, которые исполнены на поле NxM. Соответственно M,N задаются юзером.
Это непросто будет сделать, на данном коде? Придется, наверное, код полностью переписывать?
0
Модератор
5046 / 3275 / 526
Регистрация: 01.06.2013
Сообщений: 6,802
Записей в блоге: 9
26.03.2017, 14:25 7
Цитата Сообщение от pitbul Посмотреть сообщение
есть вид крестиков-ноликов, которые исполнены на поле NxM. Соответственно M,N задаются юзером.
Это непросто будет сделать, на данном коде?
Выигрышные комбинации там жёстко заданы для 3х3. Сделать можно и такое, но я воздержусь. Изучайте Haskell и напишите сами. Вот вам и стимул.
0
1 / 1 / 0
Регистрация: 13.01.2016
Сообщений: 18
26.03.2017, 14:42  [ТС] 8
думаю до 25 мая не успею)
0
Модератор
5046 / 3275 / 526
Регистрация: 01.06.2013
Сообщений: 6,802
Записей в блоге: 9
26.03.2017, 15:04 9
pitbul, успеете, если правильно подойти к изучению.
Выбираете учебник - Лучший учебник для начинающих доступный на русском
До монад читаете. Вам для этой задачи про них знать не требуется. Достаточно, там где ввод-вывод блок do использовать. Как строка вводится видите (с использованием <- ). Как с синтаксисом разобрались и со списками работать научились, так напишите свою функцию определения есть ли выигрыш. Сигнатура у неё будет
Haskell
1
2
3
isWon :: Int -- размер игрового поля
    -> [Int] -- номера ячеек заполненные игроком
    -> Bool  -- Есть ли выигрыш
А дальше дело пойдёт.
0
1 / 1 / 0
Регистрация: 13.01.2016
Сообщений: 18
26.03.2017, 15:43  [ТС] 10
Я думаю будут большие трудности с представление пользователю самого поля.
Для 3х3 прописано так:
Кликните здесь для просмотра всего текста
Haskell
1
2
3
-- ^Строки, столбцы, диагонали доски 3Х3
rcd :: [[Int]]
rcd = [[1,2,3], [4,5,6], [7,8,9], [1,4,7], [2,5,8], [3,6,9], [1,5,9], [3,5,7]]


Для динамической доски так уже не пропишешь, ведь.
0
Модератор
5046 / 3275 / 526
Регистрация: 01.06.2013
Сообщений: 6,802
Записей в блоге: 9
26.03.2017, 15:59 11
Цитата Сообщение от pitbul Посмотреть сообщение
Для динамической доски так уже не пропишешь, ведь.
И я про то. Напишите функцию по типу как я выше привёл. Всё решаемо. Хотя, я, к примеру, даже не знаю засчитывается ли в таких крестиках-ноликах выигрыш только по большим диагоналям или по любым. И от таких крестиков-ноликов уже будет недалеко до Рэндзю.
0
1 / 1 / 0
Регистрация: 13.01.2016
Сообщений: 18
26.03.2017, 17:28  [ТС] 12
Я думаю да. Это будет что-то подобное, если игроку удалось выстроить цепочку из 5 элементов, то он выиграл.

Добавлено через 45 минут
Я правильно понял? Int должен формировать поле, прямо в функции isWon
Haskell
1
2
3
isWon :: Int -- размер игрового поля
    -> [Int] -- номера ячеек заполненные игроком
    -> Bool  -- Есть ли выигрыш
0
Модератор
5046 / 3275 / 526
Регистрация: 01.06.2013
Сообщений: 6,802
Записей в блоге: 9
26.03.2017, 17:50 13
Цитата Сообщение от pitbul Посмотреть сообщение
Я правильно понял? Int должен формировать поле, прямо в функции isWon
Это уж какой алгоритм изобретёте. Int ничего не формирует, это тип - целое число. В данном случае первый аргумент функции. Размер поля как то в функцию передать надо. Можно, вот так - аргументом. Можно через замыкание (во всяком учебнике по Haskell описывается). Может вы решите рассчитать таблицу rcd предварительно, хотя смысла в этом нет. Вызов такой функции
Haskell
1
isWin boardDim [23,34,56,87,111,92]
где boardDim определите где то как размер поля, допустим 15.
1
Антикодер
1804 / 869 / 48
Регистрация: 15.09.2012
Сообщений: 3,081
27.03.2017, 01:25 14
Цитата Сообщение от pitbul Посмотреть сообщение
Еще есть вопросик: есть вид крестиков-ноликов, которые исполнены на поле NxM. Соответственно M,N задаются юзером.
Это непросто будет сделать, на данном коде? Придется, наверное, код полностью переписывать?
Хотелось бы понять, возможно ли построить такую игру, чтобы при этом типы были достаточно безопасными, например, чтобы невозможно было выйти за границы поля на уровне типов.

Тип
Haskell
1
data Pos = Pos [Integer] [Integer] deriving Show
позволяет написать функцию, которая может выйти за пределы поля.
Я обернул тип Int в RangeCoor, чтобы установить границы поля
AXT Tic tac toe: Types.hs
1
Модератор
5046 / 3275 / 526
Регистрация: 01.06.2013
Сообщений: 6,802
Записей в блоге: 9
27.03.2017, 01:34 15
Цитата Сообщение от XRuZzz Посмотреть сообщение
Хотелось бы понять, возможно ли построить такую игру, чтобы при этом типы были достаточно безопасными, например, чтобы невозможно было выйти за границы поля на уровне типов.
https://habrahabr.ru/post/253157/
2
Антикодер
1804 / 869 / 48
Регистрация: 15.09.2012
Сообщений: 3,081
28.03.2017, 20:35 16
AXT Крестики-нолики
Немного доработал: изменил структуру проекта, добавил возможность играть с компьютером, который ставит нолик в случайной клетке и т.д. и т. п.
Из-за изменения структуры, старые ссылки на конкретные файлы стали теперь не рабочими.

Есть смысл посмотреть, как решала эту задачку "секретная" альфа-группа:
Neongreen: Haskell-EX: Tic tac toe
Вроде бы никто не использует список строк в качестве игрового поля, как я. Мне кажется, что от этого код становится нагляднее, а главное программировать интереснее...
Может конечно есть более эталонные проекты "Крестиков" для самообразования... Но я пока смотреть не буду, пока не напишу алгоритмы игры с компьютером.
1
1 / 1 / 0
Регистрация: 13.01.2016
Сообщений: 18
28.03.2017, 21:55  [ТС] 17
А какой собственно командой запустить main.hs?
0
Антикодер
1804 / 869 / 48
Регистрация: 15.09.2012
Сообщений: 3,081
28.03.2017, 22:04 18
Цитата Сообщение от pitbul Посмотреть сообщение
А какой собственно командой запустить main.hs?
Попробуйте
Bash
1
runhaskell main.hs
А мой проект, так просто запустить не получится, там нужно файл stack.yaml создавать как минимум.
1
Модератор
5046 / 3275 / 526
Регистрация: 01.06.2013
Сообщений: 6,802
Записей в блоге: 9
28.03.2017, 23:49 19
Цитата Сообщение от pitbul Посмотреть сообщение
Класс)) работает
Цитата Сообщение от pitbul Посмотреть сообщение
А какой собственно командой запустить main.hs?

Не по теме:

Как то одно с другим ... вызывает когнитивный диссонанс. :)

Вы бы написали что за компилятор/интерпретатор Haskell вы установили. И какая у вас ОС.
А если ничего не установили, то читаете https://www.ohaskell.guide/setup.html и устанавливаете stack - это утилита, которая вам, поможет и свежий компилятор скачать, и, в том числе и выполнить программу. stack-ом сейчас большинство Haskell-истов и пользуется.
С использованием stack без создания проекта выполните команду stack runhaskell main, хотя имена исходных файлов в Haskell принято писать с заглавной буквы.

Некоторые пользуются интерпретатором hugs. Если дальше этой задачи вы не пойдёте, то он вам сгодиться. Устанавливать то что называется Haskell Platform, или устанавливать утилиту cabal (не её библиотеки которыми пользуется stack, а сам исполняемый файл cabal) сейчас худшая альтернатива.
0
agregationcompo
29.03.2017, 13:28     Крестики нолики на двоих Haskell
  #20

Не по теме:

Любопытно. Код на JS на порядки короче

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<html>
<head>
<style>
 table,tr,td{
  border: 1px solid black;
}
 td{width: 30px; height: 30px}
 
</style>
 
</head>
<body>
 
<table >
 <tr id="line0"> <td></td> <td></td> <td></td> </tr>
 <tr id="line1"> <td></td> <td></td> <td></td> </tr>
 <tr id="line2"> <td></td> <td></td> <td></td> </tr>
</table>
 
<script>
 
getCells=function(line, f){
 return [].map.call(line.children, f)
}
withAllSels=function(f){
 ;[].forEach.call(line0.children, f)
 ;[].forEach.call(line1.children, f)
 ;[].forEach.call(line2.children, f)
}
check=function(){
 var result, l0, l1, l2
;[
l0=getCells(line0, function(x){return x}),
l1=getCells(line1, function(x){return x}),
l2=getCells(line2, function(x){return x}),
[l0[0], l1[0], l2[0]],
[l0[1], l1[1], l2[1]],
[l0[2], l1[2], l2[2]],
[l0[0], l1[1], l2[2]],
[l0[2], l1[1], l2[0]]
].some(function(l){return result=/XXX|OOO/.test(l.map(function(x){return x.innerHTML}).join(""))})
return result
}
 
current="X"
withAllSels(function(x){x.onclick=function(){
 if(this.innerHTML) return
 this.innerHTML=current
 if(check()) return document.write(current+" wins")
 if(current==="X") return current="O"; current="X"
}})
 
 
</script>
</body>
</html>
Вот что получается всякий раз, когда код на хаскеле чуть сложней хелловорда:)

0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.03.2017, 13:28

Крестики-нолики
Мне надо сделать игру крестики-нолики, как бы... игра простая, в интернете бесконечное количество...

Крестики-нолики
Напишите функцию tic_tac_toe(field), которая принимает на вход список списков 3х3 — поле игры в...

Крестики-нолики
Написал крестики-нолики. Критику пожалуйста) uses GraphABC; var pole:array of integer; ...

Крестики Нолики
вот задали написать игру , скажите нормально впринципе написал или нет , и один вопрос немогу...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru