I have this board [10,10] for this project below and I can't move the piece on the board
this question is part of the other questions about Lisp, you can see on my profile
(defun board ()
"T in position x=0 and y=0"
'(
(T 25 54 89 21 8 36 14 41 96)
(78 47 56 23 5 NIL 13 12 26 60)
(0 27 17 83 34 93 74 52 45 80)
(69 9 77 95 55 39 91 73 57 30)
(24 15 22 86 1 11 68 79 76 72)
(81 48 32 2 64 16 50 37 29 71)
(99 51 6 18 53 28 7 63 10 88)
(59 42 46 85 90 75 87 43 20 31)
(3 61 58 44 65 82 19 4 35 62)
(33 70 84 40 66 38 92 67 98 97)
)
)
not the same but similar here the rows begin at 1 but in project is start by 0
and this function to print the board
(defun print-board (board)
(format T "~%")
(mapcar (lambda (x) (format T " ~A ~%" x)) board)
(format nil ""))
I have 8 movements implemented but I only put 4 examples for the question not to get too much code
(defun UP-LEFT (x y board)
"Function that receives 2 indexes and board, validate movement and move piece up and left"
(cond
((equal (validate-movements (- x 1) (- y 2) board) 0)
(move-piece x y -1 -2 board))
(T nil)))
(defun UP-RIGHT (x y board)
"receive 2 indexes and board, validate movement and move piece up and right"
(cond
((equal (validate-movements (+ x 1) (- y 2) board) 0)
(move-piece x y 1 -2 board))
(T nil)))
(defun LEFT-DOWN (x y board)
"Function that receives 2 indexes and board, validate movement and move piece left and down"
(cond
((equal (validate-movements (- x 2) (+ y 1) board) 0)
(move-piece x y -2 1 board))
(T nil)))
(defun LEFT-UP (x y board)
"Function that receives 2 indexes and board, validate movement and move piece left and up"
(cond
((equal (validate-movements (- x 2) (- y 1) board) 0)
(move-piece x y -2 -1 board))
(T nil)))
(defun DOWN-RIGHT (x y board)
"Function that receives 2 indexes and board, validate movement and move piece down and right"
(cond
((equal (validate-movements (+ x 1) (+ y 2) board) 0)
(move-piece x y 1 2 board))
(T nil)))
my doubt is in this move piece in board in axis (x,y)
(defun move-piece (x y dx dy board)
"Function that receives two indexes and board to move the piece on the board"
(mapcar
(lambda (L)
(cond
((atom L) L)
((and
(equal (nth 0 L) x)
(equal (nth 1 L) y))
(list (+ (nth 0 L) dx) (+ (nth 1 L) dy) (nth 2 L)
(nth 3 L) (nth 4 L) (nth 5 L) (nth 6 L)
(nth 7 L) (nth 8 L) (nth 9 L)))
(T L))) board))
and this function to validate movements
(defun validate-movements (x y board)
"Function that receives two indexes and board to validate movement"
(cond
((and
;; validation of rows and columns
(>= x 0)
(>= y 0)
(<= x 9)
(<= y 9)
(= (apply '+ (mapcar (lambda (L)
(cond
((atom L) 0)
((or (not(equal (nth 0 L ) x)) (not (equal (nth 1 L) y))) 0)
(T 1))) board)) 0)) 0)
(T nil )))
when I try to test the movements https://ideone.com/jaeCLu it's not move, because don´t return nothing and show nothing
what I´m doing wrong?
Let's take a look at the validation function. First, make sensible limebreaks: when a multiline form is closed, break the line.
(defun validate-movements (x y board)
"Function that receives two indexes and board to validate movement"
(cond ((and
;; validation of rows and columns
(>= x 0)
(>= y 0)
(<= x 9)
(<= y 9)
(= (apply '+
(mapcar (lambda (L)
(cond ((atom L) 0)
((or (not (equal (nth 0 L ) x))
(not (equal (nth 1 L) y)))
0)
(T 1)))
board))
0))
0)
(T nil )))
A condition that has only two possible outcomes is better handled through if
:
(defun validate-movements (x y board)
"Function that receives two indexes and board to validate movement"
(if (and
;; validation of rows and columns
(>= x 0)
(>= y 0)
(<= x 9)
(<= y 9)
(= (apply '+
(mapcar (lambda (L)
(cond ((atom L) 0)
((or (not (equal (nth 0 L ) x))
(not (equal (nth 1 L) y)))
0)
(T 1)))
board))
0))
0
nil))
Comparators like <=
can take more arguments:
(defun validate-movements (x y board)
"Function that receives two indexes and board to validate movement"
(if (and (<= 0 x 9)
(<= 0 y 9)
(= (apply '+
(mapcar (lambda (L)
(cond ((atom L) 0)
((or (not (equal (nth 0 L) x))
(not (equal (nth 1 L) y)))
0)
(T 1)))
board))
0))
0
nil))
Since your board is a list of lists (one 10-element sublist per line), a line will never be an atom:
(defun validate-movements (x y board)
"Function that receives two indexes and board to validate movement"
(if (and (<= 0 x 9)
(<= 0 y 9)
(= (apply '+
(mapcar (lambda (L)
(cond ((or (not (equal (nth 0 L) x))
(not (equal (nth 1 L) y)))
0)
(T 1)))
board))
0))
0
nil))
Again, a two-clause conditional is better an if
:
(defun validate-movements (x y board)
"Function that receives two indexes and board to validate movement"
(if (and (<= 0 x 9)
(<= 0 y 9)
(= (apply '+
(mapcar (lambda (L)
(if (or (not (equal (nth 0 L) x))
(not (equal (nth 1 L) y)))
0
1))
board))
0))
0
nil))
Now, I wanted to tell you how booleans are much easier to express logic with. However, that condition makes no sense to me: you seem to check that there is some line on the board that carries the x coordinate in its first field and the y coordinate in the second.
Maybe you wanted to check that the target coordinate is empty?
(defun target-valid-p (x y board)
(and (<= 0 x 9)
(<= 0 y 9)
(null (nth x (nth y board)))))
Next, the move function. Again, linebreaks:
(defun move-piece (x y dx dy board)
"Function that receives two indexes and board to move the piece on the board"
(mapcar (lambda (L)
(cond
((atom L) L)
((and (equal (nth 0 L) x)
(equal (nth 1 L) y))
(list (+ (nth 0 L) dx) (+ (nth 1 L) dy) (nth 2 L)
(nth 3 L) (nth 4 L) (nth 5 L) (nth 6 L)
(nth 7 L) (nth 8 L) (nth 9 L)))
(T L)))
board))
Your lines are never atoms:
(defun move-piece (x y dx dy board)
"Function that receives two indexes and board to move the piece on the board"
(mapcar (lambda (L)
(cond
((and (equal (nth 0 L) x)
(equal (nth 1 L) y))
(list (+ (nth 0 L) dx) (+ (nth 1 L) dy) (nth 2 L)
(nth 3 L) (nth 4 L) (nth 5 L) (nth 6 L)
(nth 7 L) (nth 8 L) (nth 9 L)))
(T L)))
board))
Two-branch conditional is if
:
(defun move-piece (x y dx dy board)
"Function that receives two indexes and board to move the piece on the board"
(mapcar (lambda (L)
(if (and (equal (nth 0 L) x)
(equal (nth 1 L) y))
(list (+ (nth 0 L) dx) (+ (nth 1 L) dy) (nth 2 L)
(nth 3 L) (nth 4 L) (nth 5 L) (nth 6 L)
(nth 7 L) (nth 8 L) (nth 9 L))
L))
board))
Use list*
and nthcdr
to update part of a list:
(defun move-piece (x y dx dy board)
"Function that receives two indexes and board to move the piece on the board"
(mapcar (lambda (L)
(if (and (equal (nth 0 L) x)
(equal (nth 1 L) y))
(list* (+ (nth 0 L) dx)
(+ (nth 1 L) dy)
(nthcdr 2 L))
L))
board))
Now it seems that you again just update the first two cells of the line. Maybe I didn't understand your data model, but I would have thought that you just want to update the cells at the given coordinates:
(defun move-piece (x y dx dy board)
(let ((new-board (copy-tree board))
(new-x (+ x dx))
(new-y (+ y dy))
(piece (nth x (nth y board))))
(setf (nth x (nth y new-board)) nil
(nth new-x (nth new-y new-board)) piece)
new-board))