2010-11-20 51 views
0

J'écris un jeu de tic-tac-toe comme un projet parallèle pour obtenir un peu plus d'expérience pratique avec Racket. Voici une fonction qui vérifie s'il y a une ligne verticale ou horizontale (le code qui vérifie les lignes diagonales est une fonction qui appelle celui-ci):Quoi de plus simple, écrivez ce code pour déterminer le gagnant d'un jeu de tic-tac-toe?

(define (has-line? moves) 
    (let ((positions (flatten (map string->list moves)))) 
    (ormap 
    (lambda (char) 
     (>= 
     (count 
     (lambda (lchar) 
      (char-ci=? lchar char)) 
     positions) 
     3)) 
    '(#\a #\b #\C#\1 #\2 #\3))) 

Cette fonction obtient une liste de chaînes qui représentent la les espaces que le joueur actuel a choisis avec les lettres représentant la colonne et les nombres représentant la rangée. L'approche que je prends est de voir s'il y a des ensembles de 3 (3 positions qui sont toutes dans la colonne a, 3 positions qui sont toutes dans la ligne 2, etc.).

Il pourrait y avoir une meilleure façon de déterminer le gagnant, mais je suis plus curieux de savoir comment mettre en œuvre ce qui précède mieux. Ce que je fais en ce moment c'est de transformer la liste des positions en une liste de caractères (donc '("a1" "b2") devient '(#\a #\1 #\b #\2) et de compter chaque personnage.) Ce code fonctionne, mais il semble qu'il devrait y avoir un moyen plus simple de le faire. ?

+2

Chers cieux ... Je suis arrivé ici avant Eli J'espère avoir quelque chose utile à sa y ... –

Répondre

2

Votre solution est à la fois magnifique et terrible, elle est remarquablement concise, mais votre représentation me semble encline à l'erreur en ce qu'elle sépare les lignes et les colonnes de manière ad hoc. et je voudrais écrire quelque chose comme (ci-dessous) Avantages:..! il est moins sujette aux erreurs, et il généralise à un carré de taille arbitraire

#lang racket 

;; size of the tic-tac-toe square: 
(define side 3) 

;; a move is (make-move row col) 
(struct move (row col)) 

;; is the move in the given row? 
(define ((in-row x) move) 
    (= (move-row move) x)) 

;; is the move in the given column? 
(define ((in-col x) move) 
    (= (move-col move) x)) 

;; does the list of moves have three in a row or three in a column? 
(define (has-line? moves) 
    (for/or ([i (in-range side)]) 
     ;; three in this row? 
    (or (= side (length (filter (in-row i) moves))) 
     ;; three in this column? 
     (= side (length (filter (in-col i) moves)))))) 


(require rackunit) 

(check-equal? (has-line? (list (move 1 1) (move 2 1) (move 0 0) (move 0 1))) 
       #t) 
(check-equal? (has-line? (list (move 1 1) (move 2 1) (move 0 0))) 
       #f) 
(check-equal? (has-line? (list (move 1 1) (move 0 1) (move 0 0) (move 2 1))) 
       #t) 
+0

Pour l'anecdote, je n'ai vraiment pas besoin de généraliser à un carré de taille arbitraire. Compte tenu de ma mise en œuvre, il est facile pour moi de le faire fonctionner avec un carré de taille différente si besoin est. Cela dit, je suis intéressé à le rendre moins sujette aux erreurs. Est-il possible d'améliorer cet extrait avec cela en tête? –

+0

Bien sûr, en choisissant une représentation telle que celle que j'ai illustrée. Pas la réponse que tu voulais, hein? :) –

+0

Eh bien, j'essayais surtout de faire un remue-méninges, donc c'est * la * réponse que je voulais. Je n'utiliserais pas le code personnellement. Il n'y a pas forcément quelque chose de mal avec ça. Il semble y avoir beaucoup plus de pièces mobiles. Cela dit, je vois certaines choses que je pourrais utiliser pour améliorer ma fonction. :-) –