This Scheme program shows iteration, recursion, compound statements, variable and list manipulation. It allows for the user to play against another player, vs a basic AI (that does more than just random moves), control an AI vs AI match, or switch it up at any time.
#lang Scheme ; Connect Four by Jack P. Oakley ; This program defines an AI to play connect four ; This connect four can be played between two people, two AIs, or one of each ;****************************************************************************** ; JPOGame global variable: * ; PURPOSE: Contain current status of the game board * ;****************************************************************************** (define JPOGame '( "X" (" " " " " " " " " " " " " ") (" " " " " " " " " " " " " ") (" " " " " " " " " " " " " ") (" " " " " " " " " " " " " ") (" " " " " " " " " " " " " ") (" " " " " " " " " " " " " ") ) ) ;****************************************************************************** ; JPOStartGame function: * ; PURPOSE: Initializes the game state * ; IN: none * ; OUT: returns true, displays text to show the game has been reset * ;****************************************************************************** (define (JPOStartGame) (set! JPOGame '( "X" (" " " " " " " " " " " " " ") (" " " " " " " " " " " " " ") (" " " " " " " " " " " " " ") (" " " " " " " " " " " " " ") (" " " " " " " " " " " " " ") (" " " " " " " " " " " " " ") ) ) (display "New Game Begins, board reset ") #t ) ;****************************************************************************** ; JPOMarkMove function: * ; PURPOSE: Allows the player to choose their move * ; IN: integer representing the column of a chosen move * ; OUT: returns the chosen column * ;****************************************************************************** (define (JPOMarkMove Col) (if (equal? (JPOGetCell (cdr JPOGame) 1 Col) " " ) (set! JPOGame (cons (if (equal? (car JPOGame) "X" ) "O" "X" ) (JPOSetCell (cdr JPOGame) 1 Col (car JPOGame)) ) ) (if (equal? (JPOGetCell (cdr JPOGame) 2 Col) " " ) (set! JPOGame (cons (if (equal? (car JPOGame) "X" ) "O" "X" ) (JPOSetCell (cdr JPOGame) 2 Col (car JPOGame)) ) ) (if (equal? (JPOGetCell (cdr JPOGame) 3 Col) " " ) (set! JPOGame (cons (if (equal? (car JPOGame) "X" ) "O" "X" ) (JPOSetCell (cdr JPOGame) 3 Col (car JPOGame)) ) ) (if (equal? (JPOGetCell (cdr JPOGame) 4 Col) " " ) (set! JPOGame (cons (if (equal? (car JPOGame) "X" ) "O" "X" ) (JPOSetCell (cdr JPOGame) 4 Col (car JPOGame)) ) ) (if (equal? (JPOGetCell (cdr JPOGame) 5 Col) " " ) (set! JPOGame (cons (if (equal? (car JPOGame) "X" ) "O" "X" ) (JPOSetCell (cdr JPOGame) 5 Col (car JPOGame)) ) ) (set! JPOGame (cons (if (equal? (car JPOGame) "X" ) "O" "X" ) (JPOSetCell (cdr JPOGame) 6 Col (car JPOGame)) ) ) ) ) ) ) ) Col ) ;****************************************************************************** ; JPOShowGame function: * ; PURPOSE: Shows the current state of the game board to the player * ; IN: none * ; OUT: returns true, displays the game state * ;****************************************************************************** (define (JPOShowGame) (begin (newline) (display " |---------------------------|") (newline) (display " | ") (display (JPOGetCell (cdr JPOGame) 6 1)) (display " | ") (display (JPOGetCell (cdr JPOGame) 6 2)) (display " | ") (display (JPOGetCell (cdr JPOGame) 6 3)) (display " | ") (display (JPOGetCell (cdr JPOGame) 6 4)) (display " | ") (display (JPOGetCell (cdr JPOGame) 6 5)) (display " | ") (display (JPOGetCell (cdr JPOGame) 6 6)) (display " | ") (display (JPOGetCell (cdr JPOGame) 6 7)) (display " |") (newline) (display " |---------------------------|") (newline) (display " | ") (display (JPOGetCell (cdr JPOGame) 5 1)) (display " | ") (display (JPOGetCell (cdr JPOGame) 5 2)) (display " | ") (display (JPOGetCell (cdr JPOGame) 5 3)) (display " | ") (display (JPOGetCell (cdr JPOGame) 5 4)) (display " | ") (display (JPOGetCell (cdr JPOGame) 5 5)) (display " | ") (display (JPOGetCell (cdr JPOGame) 5 6)) (display " | ") (display (JPOGetCell (cdr JPOGame) 5 7)) (display " |") (newline) (display " |---------------------------|") (newline) (display " | ") (display (JPOGetCell (cdr JPOGame) 4 1)) (display " | ") (display (JPOGetCell (cdr JPOGame) 4 2)) (display " | ") (display (JPOGetCell (cdr JPOGame) 4 3)) (display " | ") (display (JPOGetCell (cdr JPOGame) 4 4)) (display " | ") (display (JPOGetCell (cdr JPOGame) 4 5)) (display " | ") (display (JPOGetCell (cdr JPOGame) 4 6)) (display " | ") (display (JPOGetCell (cdr JPOGame) 4 7)) (display " |") (newline) (display " |---------------------------|") (newline) (display " | ") (display (JPOGetCell (cdr JPOGame) 3 1)) (display " | ") (display (JPOGetCell (cdr JPOGame) 3 2)) (display " | ") (display (JPOGetCell (cdr JPOGame) 3 3)) (display " | ") (display (JPOGetCell (cdr JPOGame) 3 4)) (display " | ") (display (JPOGetCell (cdr JPOGame) 3 5)) (display " | ") (display (JPOGetCell (cdr JPOGame) 3 6)) (display " | ") (display (JPOGetCell (cdr JPOGame) 3 7)) (display " |") (newline) (display " |---------------------------|") (newline) (display " | ") (display (JPOGetCell (cdr JPOGame) 2 1)) (display " | ") (display (JPOGetCell (cdr JPOGame) 2 2)) (display " | ") (display (JPOGetCell (cdr JPOGame) 2 3)) (display " | ") (display (JPOGetCell (cdr JPOGame) 2 4)) (display " | ") (display (JPOGetCell (cdr JPOGame) 2 5)) (display " | ") (display (JPOGetCell (cdr JPOGame) 2 6)) (display " | ") (display (JPOGetCell (cdr JPOGame) 2 7)) (display " |") (newline) (display " |---------------------------|") (newline) (display " | ") (display (JPOGetCell (cdr JPOGame) 1 1)) (display " | ") (display (JPOGetCell (cdr JPOGame) 1 2)) (display " | ") (display (JPOGetCell (cdr JPOGame) 1 3)) (display " | ") (display (JPOGetCell (cdr JPOGame) 1 4)) (display " | ") (display (JPOGetCell (cdr JPOGame) 1 5)) (display " | ") (display (JPOGetCell (cdr JPOGame) 1 6)) (display " | ") (display (JPOGetCell (cdr JPOGame) 1 7)) (display " | ") (newline) (display " |---------------------------|") (newline) #t ) ) ;****************************************************************************** ; JPOMakeMove function: * ; PURPOSE: Marks a move chosen by the AI * ; IN: none * ; OUT: returns the chosen column * ;****************************************************************************** (define (JPOMakeMove) (JPOMarkMove (JPOChooseMove) ) ) ;****************************************************************************** ; JPOChooseMove function: * ; PURPOSE: Logic that runs the AI move choice * ; IN: none * ; OUT: returns the chosen column * ;****************************************************************************** (define (JPOChooseMove) (if (equal? (JPOIsEmpty (cdr JPOGame)) #t ) 4 (if (equal? (JPOIsBestFirstMove (cdr JPOGame)) #t ) 6 (if (> (JPOCheckWins 7) 0 ) (JPOCheckWins 7) (if (> (JPOCheckTripBlocks 7) 0 ) (JPOCheckTripBlocks 7) (if (> (JPOCheckBlocks 7) 0 ) (JPOCheckBlocks 7) (if (> (JPOCheckDoubleLinks 7) 0 ) (JPOCheckDoubleLinks 7) (if (> (JPOCheckLinks 7) 0 ) (JPOCheckLinks 7) (JPOMakeRandom (+ (random 7) 1 ) ) ) ) ) ) ) ) ) ) ;****************************************************************************** ; JPOMakeRandom function: * ; PURPOSE: The AI makes a random legal move * ; IN: integer of the column to start looking (for recursion) * ; OUT: returns the chosen column * ;****************************************************************************** (define (JPOMakeRandom Col) (if (equal? (JPOLegalMoveP Col) #t ) Col (JPOMakeRandom (+ (random 7) 1 ) ) ) ) ;****************************************************************************** ; JPOCheckWins function: * ; PURPOSE: Checks to see if any column will result in a win * ; IN: integer representing the column of a potential move * ; OUT: returns a column that results in a win or 0 if no win is available * ;****************************************************************************** (define (JPOCheckWins Col) (if (<= Col 0 ) 0 (if (equal? (JPOWillWinP Col) #t ) Col (JPOCheckWins (- Col 1)) ) ) ) ;****************************************************************************** ; JPOCheckBlocks function: * ; PURPOSE: Checks to see if any column will result in a block * ; IN: integer representing the column of a potential move * ; OUT: returns a column that results in a block or 0 if no block is available * ;****************************************************************************** (define (JPOCheckBlocks Col) (if (<= Col 0 ) 0 (if (equal? (JPOWillBlock Col) #t ) Col (JPOCheckBlocks (- Col 1)) ) ) ) ;****************************************************************************** ; JPOCheckLinks function: * ; PURPOSE: Checks to see if any column will result in a link to a prev. move * ; IN: integer representing the column of a potential move * ; OUT: returns a column that results in a link or 0 if no link is available * ;****************************************************************************** (define (JPOCheckLinks Col) (if (<= Col 0 ) 0 (if (equal? (JPOWillLink Col) #t ) Col (JPOCheckLinks (- Col 1)) ) ) ) ;****************************************************************************** ; JPOIsEmpty function: * ; PURPOSE: Checks to see if the board is empty * ; IN: game board matrix * ; OUT: returns boolean of whether board is empty or not * ;****************************************************************************** (define (JPOIsEmpty Matrix) (if (and (equal? (JPOGetCell Matrix 1 1) " " ) (equal? (JPOGetCell Matrix 1 2) " " ) (equal? (JPOGetCell Matrix 1 3) " " ) (equal? (JPOGetCell Matrix 1 4) " " ) (equal? (JPOGetCell Matrix 1 5) " " ) (equal? (JPOGetCell Matrix 1 6) " " ) (equal? (JPOGetCell Matrix 1 7) " " ) ) #t #f ) ) ;****************************************************************************** ; JPOIsBestFirstMove function: * ; PURPOSE: Checks to see if the opponent played a particular move as opening * ; IN: game board matrix * ; OUT: returns boolean of whether board the move was made or not * ;****************************************************************************** (define (JPOIsBestFirstMove Matrix) (if (and (equal? (JPOGetCell Matrix 1 1) " " ) (equal? (JPOGetCell Matrix 1 2) " " ) (equal? (JPOGetCell Matrix 1 3) " " ) (equal? (JPOGetCell Matrix 1 4) "X" ) (equal? (JPOGetCell Matrix 1 5) " " ) (equal? (JPOGetCell Matrix 1 6) " " ) (equal? (JPOGetCell Matrix 1 7) " " ) ) #t #f ) ) ;****************************************************************************** ; JPOLegalMoveP function: * ; PURPOSE: Checks to see if a move is legal * ; IN: integer representing a column * ; OUT: returns boolean of legality of chosen column * ;****************************************************************************** (define (JPOLegalMoveP Col) (if (equal? (JPOGetCell (cdr JPOGame) 6 Col) " " ) #t #f ) ) ;****************************************************************************** ; JPOWinP function: * ; PURPOSE: Checks to see if given column resulted in a win * ; IN: integer representing the column of the last move * ; OUT: returns boolean of last move being a win * ;****************************************************************************** (define (JPOWinP Col) (if (equal? (car JPOGame) "X" ) (JPOWasWin 6 Col "O") (JPOWasWin 6 Col "X") ) ) ;****************************************************************************** ; JPOWasWin function: * ; PURPOSE: recursive helper function for JPOWinP to check each row in column * ; IN: integer for row, column, string of last player's turn * ; OUT: returns boolean of last move being a win * ;****************************************************************************** (define (JPOWasWin Row Col Piece) (if (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (JPOWasWin (- Row 1) Col Piece) (JPOWinSucceed Row Col Piece) ) ) ;****************************************************************************** ; JPOWinSucceed function: * ; PURPOSE: helper function for JPOWasWin to check each win possibility * ; IN: integer for row, column, string of last player's turn * ; OUT: returns boolean of last move being a win * ;****************************************************************************** (define (JPOWinSucceed Row Col Piece) (if (or (and (>= Col 4) (equal? Piece (JPOGetCell (cdr JPOGame) Row (- Col 3)) ) (equal? Piece (JPOGetCell (cdr JPOGame) Row (- Col 2)) ) (equal? Piece (JPOGetCell (cdr JPOGame) Row (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) Piece ) ) (and (>= Col 3) (<= Col 6) (equal? Piece (JPOGetCell (cdr JPOGame) Row (- Col 2)) ) (equal? Piece (JPOGetCell (cdr JPOGame) Row (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) Piece ) (equal? Piece (JPOGetCell (cdr JPOGame) Row (+ Col 1)) ) ) (and (>= Col 2) (<= Col 5) (equal? Piece (JPOGetCell (cdr JPOGame) Row (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) Piece ) (equal? Piece (JPOGetCell (cdr JPOGame) Row (+ Col 1)) ) (equal? Piece (JPOGetCell (cdr JPOGame) Row (+ Col 2)) ) ) (and (<= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) Piece ) (equal? Piece (JPOGetCell (cdr JPOGame) Row (+ Col 1)) ) (equal? Piece (JPOGetCell (cdr JPOGame) Row (+ Col 2)) ) (equal? Piece (JPOGetCell (cdr JPOGame) Row (+ Col 3)) ) ) (and (>= Row 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) Piece ) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 1) Col) ) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 2) Col) ) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 3) Col) ) ) (and (<= Row 3) (<= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) Piece ) (equal? Piece (JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1)) ) (equal? Piece (JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2)) ) (equal? Piece (JPOGetCell (cdr JPOGame) (+ Row 3) (+ Col 3)) ) ) (and (<= Row 3) (>= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) Piece ) (equal? Piece (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) (equal? Piece (JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2)) ) (equal? Piece (JPOGetCell (cdr JPOGame) (+ Row 3) (- Col 3)) ) ) (and (>= Row 4) (>= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) Piece ) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1)) ) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2)) ) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 3) (- Col 3)) ) ) (and (>= Row 4) (<= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) Piece ) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1)) ) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2)) ) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 3) (+ Col 3)) ) ) (and (<= Row 4) (>= Row 2) (<= Col 5) (>= Col 2) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) Piece ) (equal? Piece (JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1)) ) (equal? Piece (JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2)) ) ) (and (<= Row 5) (>= Row 3) (<= Col 6) (>= Col 3) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2)) ) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) Piece ) (equal? Piece (JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1)) ) ) (and (<= Row 5) (>= Row 3) (<= Col 5) (>= Col 2) (equal? Piece (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) Piece ) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1)) ) (equal? Piece (JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2)) ) ) (and (<= Row 4) (>= Row 2) (<= Col 6) (>= Col 3) (equal? Piece (JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2)) ) (equal? Piece (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) Piece ) (equal? Piece (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) ) ) #t #f ) ) ;****************************************************************************** ; JPOWillWinP function: * ; PURPOSE: Determines if a given column will result in a win for curr. player * ; IN: integer for column * ; OUT: returns boolean of move being a win * ;****************************************************************************** (define (JPOWillWinP Col) (if (equal? (JPOGetCell (cdr JPOGame) 1 Col) " " ) (JPOFindWin 1 Col) (if (equal? (JPOGetCell (cdr JPOGame) 2 Col) " " ) (JPOFindWin 2 Col) (if (equal? (JPOGetCell (cdr JPOGame) 3 Col) " " ) (JPOFindWin 3 Col) (if (equal? (JPOGetCell (cdr JPOGame) 4 Col) " " ) (JPOFindWin 4 Col) (if (equal? (JPOGetCell (cdr JPOGame) 5 Col) " " ) (JPOFindWin 5 Col) (if (equal? (JPOGetCell (cdr JPOGame) 6 Col) " " ) (JPOFindWin 6 Col) #f ) ) ) ) ) ) ) ;) ;****************************************************************************** ; JPOFindWin function: * ; PURPOSE: determine if a given row and column will result in a win * ; IN: integer for row, column * ; OUT: returns boolean of given move being a win * ;****************************************************************************** (define (JPOFindWin Row Col) (if (or (and (>= Col 4) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (- Col 3)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (- Col 2)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) ) (and (>= Col 3) (<= Col 6) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (- Col 2)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (+ Col 1)) ) ) (and (>= Col 2) (<= Col 5) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (+ Col 1)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (+ Col 2)) ) ) (and (<= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (+ Col 1)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (+ Col 2)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (+ Col 3)) ) ) (and (>= Row 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) Col) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 2) Col) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 3) Col) ) ) (and (<= Row 3) (<= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 3) (+ Col 3)) ) ) (and (<= Row 3) (>= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 3) (- Col 3)) ) ) (and (>= Row 4) (>= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 3) (- Col 3)) ) ) (and (>= Row 4) (<= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 3) (+ Col 3)) ) ) (and (<= Row 4) (>= Row 2) (<= Col 5) (>= Col 2) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2)) ) ) (and (<= Row 5) (>= Row 3) (<= Col 6) (>= Col 3) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1)) ) ) (and (<= Row 5) (>= Row 3) (<= Col 5) (>= Col 2) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2)) ) ) (and (<= Row 4) (>= Row 2) (<= Col 6) (>= Col 3) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) ) ) #t #f ) ) ;****************************************************************************** ; JPOWillBlock function: * ; PURPOSE: determines if given column will result in a block * ; IN: integer for column * ; OUT: returns boolean of column resulting in a block * ;****************************************************************************** (define (JPOWillBlock Col) (if (equal? (JPOGetCell (cdr JPOGame) 1 Col) " " ) (JPOFindBlock 1 Col (if (equal? (car JPOGame) "X" ) "O" "X" ) ) (if (equal? (JPOGetCell (cdr JPOGame) 2 Col) " " ) (JPOFindBlock 2 Col (if (equal? (car JPOGame) "X" ) "O" "X" ) ) (if (equal? (JPOGetCell (cdr JPOGame) 3 Col) " " ) (JPOFindBlock 3 Col (if (equal? (car JPOGame) "X" ) "O" "X" ) ) (if (equal? (JPOGetCell (cdr JPOGame) 4 Col) " " ) (JPOFindBlock 4 Col (if (equal? (car JPOGame) "X" ) "O" "X" ) ) (if (equal? (JPOGetCell (cdr JPOGame) 5 Col) " " ) (JPOFindBlock 5 Col (if (equal? (car JPOGame) "X" ) "O" "X" ) ) (if (equal? (JPOGetCell (cdr JPOGame) 6 Col) " " ) (JPOFindBlock 6 Col (if (equal? (car JPOGame) "X" ) "O" "X" ) ) #f ) ) ) ) ) ) ) ;****************************************************************************** ; JPOFindBlock function: * ; PURPOSE: determines if given row and column will result in a block * ; IN: integer for row, column, string of opponent's piece * ; OUT: returns boolean of move resulting in a block * ;****************************************************************************** (define (JPOFindBlock Row Col OppPiece) (if (or (and (>= Col 3) (equal? OppPiece (JPOGetCell (cdr JPOGame) Row (- Col 2)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) Row (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) ) (and (>= Col 2) (<= Col 6) (equal? OppPiece (JPOGetCell (cdr JPOGame) Row (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) Row (+ Col 1)) ) ) (and (<= Col 5) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) Row (+ Col 1)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) Row (+ Col 2)) ) ) (and (>= Row 3) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 1) Col) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 2) Col) ) ) (and (<= Row 4) (<= Col 5) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2)) ) ) (and (<= Row 4) (>= Col 3) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2)) ) ) (and (>= Row 3) (>= Col 3) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2)) ) ) (and (>= Row 3) (<= Col 5) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2)) ) ) (and (<= Row 5) (>= Row 2) (<= Col 6) (>= Col 2) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1)) ) ) (and (<= Row 5) (>= Row 2) (<= Col 6) (>= Col 2) (equal? OppPiece (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1)) ) ) ) #t #f ) ) ;****************************************************************************** ; JPOWillLink function: * ; PURPOSE: determines if given column will result in a link * ; IN: integer for column * ; OUT: returns boolean of column resulting in a link * ;****************************************************************************** (define (JPOWillLink Col) (if (equal? (JPOGetCell (cdr JPOGame) 1 Col) " " ) (JPOFindLink 1 Col) (if (equal? (JPOGetCell (cdr JPOGame) 2 Col) " " ) (JPOFindLink 2 Col) (if (equal? (JPOGetCell (cdr JPOGame) 3 Col) " " ) (JPOFindLink 3 Col) (if (equal? (JPOGetCell (cdr JPOGame) 4 Col) " " ) (JPOFindLink 4 Col) (if (equal? (JPOGetCell (cdr JPOGame) 5 Col) " " ) (JPOFindLink 5 Col) (if (equal? (JPOGetCell (cdr JPOGame) 6 Col) " " ) (JPOFindLink 6 Col) #f ) ) ) ) ) ) ) ;) ;****************************************************************************** ; JPOFindLink function: * ; PURPOSE: determines if given row and column will result in a link * ; IN: integer for row, column * ; OUT: returns boolean of move resulting in a link * ;****************************************************************************** (define (JPOFindLink Row Col) (if (or (and (>= Row 2) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) Col) ) ) (and (>= Col 2) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) ) (and (<= Col 6) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (+ Col 1)) ) ) (and (<= Row 5) (<= Col 6) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1)) ) ) (and (<= Row 5) (>= Col 2) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) ) (and (>= Row 2) (>= Col 2) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1)) ) ) (and (>= Row 2) (<= Col 6) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1)) ) ) ) #t #f ) ) ;****************************************************************************** ; JPOCheckDoubleLink function: * ; PURPOSE: recursively go through each column searching for links of 2 * ; IN: integer for column * ; OUT: returns integer of column that has links of 2, 0 if none * ;****************************************************************************** (define (JPOCheckDoubleLinks Col) (if (<= Col 0 ) 0 (if (equal? (JPOWillDoubleLink Col) #t ) Col (JPOCheckDoubleLinks (- Col 1)) ) ) ) ;****************************************************************************** ; JPOWillDoubleLink function: * ; PURPOSE: determines if given column will result in a link of 2 * ; IN: integer for column * ; OUT: returns boolean of column resulting in a link of 2 * ;****************************************************************************** (define (JPOWillDoubleLink Col) (if (equal? (JPOGetCell (cdr JPOGame) 1 Col) " " ) (JPOFindDoubleLink 1 Col) (if (equal? (JPOGetCell (cdr JPOGame) 2 Col) " " ) (JPOFindDoubleLink 2 Col) (if (equal? (JPOGetCell (cdr JPOGame) 3 Col) " " ) (JPOFindDoubleLink 3 Col) (if (equal? (JPOGetCell (cdr JPOGame) 4 Col) " " ) (JPOFindDoubleLink 4 Col) (if (equal? (JPOGetCell (cdr JPOGame) 5 Col) " " ) (JPOFindDoubleLink 5 Col) (if (equal? (JPOGetCell (cdr JPOGame) 6 Col) " " ) (JPOFindDoubleLink 6 Col) #f ) ) ) ) ) ) ) ;) ;****************************************************************************** ; JPOFindDoubleLink function: * ; PURPOSE: determines if given row and column will result in a link of 2 * ; IN: integer for row, column * ; OUT: returns boolean of move resulting in a link of 2 * ;****************************************************************************** (define (JPOFindDoubleLink Row Col) (if (or (and (>= Row 3) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) Col) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 2) Col) ) ) (and (>= Col 3) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (- Col 2)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) ) (and (<= Col 5) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (+ Col 1)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (+ Col 2)) ) ) (and (<= Row 4) (<= Col 5) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2)) ) ) (and (<= Row 4) (>= Col 3) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2)) ) ) (and (>= Row 3) (>= Col 3) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2)) ) ) (and (>= Row 3) (<= Col 5) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1)) ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2)) ) ) (and (>= Col 2) (<= Col 6) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) Row (+ Col 1)) ) ) (and (>= Row 2) (<= Row 5) (>= Col 2) (<= Col 6) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1)) ) ) (and (>= Row 2) (<= Row 5) (>= Col 2) (<= Col 6) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? (car JPOGame) (JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1)) ) ) ) #t #f ) ) ;****************************************************************************** ; JPOCheckTripBlocks function: * ; PURPOSE: Checks to see if any column will result in a block of 3 * ; IN: integer representing the column of a potential move * ; OUT: returns a column that results in a block of 3 or 0 if none * ;****************************************************************************** (define (JPOCheckTripBlocks Col) (if (<= Col 0 ) 0 (if (equal? (JPOWillTripBlock Col) #t ) Col (JPOCheckTripBlocks (- Col 1)) ) ) ) ;****************************************************************************** ; JPOWillTripBlock function: * ; PURPOSE: determines if given column will result in a block of 3 * ; IN: integer for column * ; OUT: returns boolean of column resulting in a block of 3 * ;****************************************************************************** (define (JPOWillTripBlock Col) (if (equal? (JPOGetCell (cdr JPOGame) 1 Col) " " ) (JPOFindTripBlock 1 Col (if (equal? (car JPOGame) "X" ) "O" "X" ) ) (if (equal? (JPOGetCell (cdr JPOGame) 2 Col) " " ) (JPOFindTripBlock 2 Col (if (equal? (car JPOGame) "X" ) "O" "X" ) ) (if (equal? (JPOGetCell (cdr JPOGame) 3 Col) " " ) (JPOFindTripBlock 3 Col (if (equal? (car JPOGame) "X" ) "O" "X" ) ) (if (equal? (JPOGetCell (cdr JPOGame) 4 Col) " " ) (JPOFindTripBlock 4 Col (if (equal? (car JPOGame) "X" ) "O" "X" ) ) (if (equal? (JPOGetCell (cdr JPOGame) 5 Col) " " ) (JPOFindTripBlock 5 Col (if (equal? (car JPOGame) "X" ) "O" "X" ) ) (if (equal? (JPOGetCell (cdr JPOGame) 6 Col) " " ) (JPOFindTripBlock 6 Col (if (equal? (car JPOGame) "X" ) "O" "X" ) ) #f ) ) ) ) ) ) ) ;****************************************************************************** ; JPOFindTripBlock function: * ; PURPOSE: determines if given row and column will result in a block of 3 * ; IN: integer for row, column, string of opponent's piece * ; OUT: returns boolean of move resulting in a block of 3 * ;****************************************************************************** (define (JPOFindTripBlock Row Col OppPiece) (if (or (and (>= Col 4) (equal? OppPiece (JPOGetCell (cdr JPOGame) Row (- Col 3)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) Row (- Col 2)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) Row (- Col 1)) ) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) ) (and (<= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) Row (+ Col 1)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) Row (+ Col 2)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) Row (+ Col 3)) ) ) (and (>= Row 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 1) Col) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 2) Col) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 2) Col) ) ) (and (<= Row 3) (<= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (+ Row 1) (+ Col 1)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (+ Row 2) (+ Col 2)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (+ Row 3) (+ Col 3)) ) ) (and (<= Row 3) (>= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (+ Row 1) (- Col 1)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (+ Row 2) (- Col 2)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (+ Row 3) (- Col 3)) ) ) (and (>= Row 4) (>= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 1) (- Col 1)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 2) (- Col 2)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 3) (- Col 3)) ) ) (and (>= Row 4) (<= Col 4) (equal? (JPOGetCell (cdr JPOGame) Row Col) " " ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 1) (+ Col 1)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 2) (+ Col 2)) ) (equal? OppPiece (JPOGetCell (cdr JPOGame) (- Row 3) (+ Col 3)) ) ) ) #t #f ) ) ;****************************************************************************** ; JPOGetCell function: * ; PURPOSE: recursively navigate by row to specified cell and return its item * ; IN: integer for row,column, list for game board * ; OUT: returns string of item at specified location * ;****************************************************************************** (define (JPOGetCell Matrix Row Column) (if (<= Row 1 ) (JPOGetItem (car Matrix) Column) (JPOGetCell (cdr Matrix) (- Row 1) Column) ) ) ;****************************************************************************** ; JPOGetCell function: * ; PURPOSE: recursively navigate by column to specified cell to return its item* ; IN: integer for column, list for row * ; OUT: returns string of item at specified location * ;****************************************************************************** (define (JPOGetItem Row Column) (if (<= Column 1 ) (car Row) (JPOGetItem (cdr Row) (- Column 1)) ) ) ;****************************************************************************** ; JPOSetCell function: * ; PURPOSE: recursively navigate by row to specified cell and update its item * ; IN: integer for row,column, list for game board, string for item * ; OUT: returns list of updated game board * ;****************************************************************************** (define (JPOSetCell Matrix Row Column Item) (if (<= Row 1 ) (cons (JPOSetItem (car Matrix) Column Item) (cdr Matrix) ) (cons (car Matrix) (JPOSetCell (cdr Matrix) (- Row 1) Column Item) ) ) ) ;****************************************************************************** ; JPOSetCell function: * ; PURPOSE: recursively navigate by column to specified cell to update its item* ; IN: integer for column, list for row, string for item * ; OUT: returns list of updated game board * ;****************************************************************************** (define (JPOSetItem Row Column Item) (if (<= Column 1 ) (cons Item (cdr Row) ) (cons (car Row) (JPOSetItem (cdr Row) (- Column 1) Item) ) ) ) ;****************************************************************************** ; Menu function: * ; PURPOSE: Display user menu and obtain player choice * ; IN: none * ; OUT: returns integer of chosen menu option * ;****************************************************************************** (define (Menu) (define column -1) (newline) (display "Choose an option:") (newline) (display "[1] Start New Game (Start Over)") (newline) (display "[2] Make a move") (newline) (display "[3] Have AI make a move") (newline) (display "[4] Check if last move was a win") (newline) (display "[5] Quit") (newline) (define choice (read)) (if (= choice 1) (JPOStartGame) (if (= choice 2) (begin (display "Please enter a column for the move (1-7): ") (set! column (read)) (JPOMarkMove column) ) (if (= choice 3) (display (JPOMakeMove)) (if (= choice 4) (begin (display "Enter the column number of the last move (1-7): ") (set! column (read)) (display (JPOWinP column)) ) 5 ) ) ) ) (JPOShowGame) choice ) ;****************************************************************************** ; PlayGame function: * ; PURPOSE: Runs recursive loop of game * ; IN: integer of choice * ; OUT: none * ;****************************************************************************** (define (PlayGame choice) (if (= choice 5) (display "Have a wonderful day!") (PlayGame (Menu)) ) ) ;****************************************************************************** ; Driving Code: * ; PURPOSE: Handles input/output and function calls * ;****************************************************************************** (display "Connect Four") (newline) (display "This game allows two players, player vs AI, or two AIs to battle each other in a game of Connect Four.") (newline) (newline) (PlayGame 0) ;-----Test Code Beyond Here----- ;(JPOStartGame) ; nothing much#t ;(JPOShowGame) ;(JPOIsEmpty (cdr JPOGame)) ;(JPOMarkMove 1) ;(JPOMarkMove 2) ;(JPOMarkMove 3) ;(JPOMarkMove 4) ;(JPOMarkMove 5) ;(JPOMarkMove 6) ;(JPOMarkMove 7) ;(JPOShowGame) ;(JPOFindWin 1 4) ;(JPOMakeMove) ;(JPOShowGame)