As of October, 2016, Embarcadero is offering a free release
of Delphi (Delphi
10.1 Berlin Starter Edition ). There
are a few restrictions, but it is a welcome step toward making
more programmers aware of the joys of Delphi. They do say
"Offer may be withdrawn at any time", so don't delay if you want
to check it out. Please use the
link to let me know if the link stops working.
Support DFF - Shop
If you shop at Amazon anyway, consider
using this link.
We receive a few cents from each
Support DFF - Donate
If you benefit from the website, in terms of
knowledge, entertainment value, or something otherwise useful,
consider making a donation via PayPal to help defray the
costs. (No PayPal account necessary to donate via credit
card.) Transaction is secure.
For over 15 years
Mensa Page-A-Day calendars have provided several puzzles a year
for my programming pleasure. Coding "solvers" is most fun,
but many programs also allow user solving, convenient for "fill
in the blanks" type. Below are Amazon links to the
two most recent years.
365 Puzzlers Calendar 2017
365 Puzzlers Calendar 2018
(Hint: If you can
wait, current year calendars are usually on sale in January.)
e-mail with your comments about this program (or anything else).
A basic game of checkers allowing human vs. human play
the mouse to drag checkers to valid destination squares.
Background & Techniques
I recently needed a checkerboard to help implement a checkers game called
"Fox and Hounds" as well as to help investigate a specific Knight's Tour
problem. With my usual optimism, I decided that having drawn the
board and pieces and the ability to move them, that implementing a
two-player version of American checkers would be a snap.
It would be except for rules about Kings and jumps that must be taken and multiple jumps and identifying
when no moves are available, etc., etc. But it's working now (I hope
In this implementation, a move is made by dragging a checker to a valid
location. A text label above the board will indicate whose turn and whether
a jump exists. Multiple jumps are made as a series of single jumps.
One late addition that was useful for debugging the program and might
useful to players as well is an "Undo" function. Pressing the
keyboard U key at any time before the game is over will undo the
latest move. Pressing the key multiple times will undo moves in
reverse order, backing up as far the initial position if desired.
Here is a summary of the the rules for "American" or "Straight" Checkers
as I understand them:
- Pieces move diagonally; up for black, down for red pieces in my
- Players alternate turns, Black moves first.
- Pieces are taken by "jumping", moving diagonally over an adjacent
piece of the opposite color to an adjacent empty square. If the jumping
piece has another jump available, the turn continues and that jump must
- If more than one jump is available at the start of a turn, any one
of them may be taken.
- When a checker reaches the opposite side of the board it become a
"king" and may move or jump diagonally in any direction.
- The game is over when one side captures all of the pieces, or his
opponent is trapped with no move available.
Non-programmers are welcome to read on, but may
want to skip to the bottom of this page to download
executable version of the program.
Notes for programmers
An earlier game board demo implemented the game of Reversi using three
different techniques, but that game only required clicking an empty cell to
make a move. For Checkers we need to allow the player select a piece
and drag it to another valid location. I chose a TStringlControl
for the board and TShape descendants (calle TPiece) to define
the checkers. Drag/drop exits allow the checkers to be moved and
dropped on valid destination cells. Here are some note
which might be relevant if you plan to improve (or fix) the program.
|The 24 checkers exist as an array of TPiece controls.
Each checker has properties defining its color, it's column and row
location on the board, it's current status (Normal, King,
or Removed), and its current move status (CanMove,
CanJump, or NoMove).|
|The board cells contain either the index of the piece it contains
or a "-1" value to indicate that the cell is empty. |
|Here are the methods used to manage moves during drag/drop
| PieceStartDrag method is called when dragging starts.
It does nothing in this version of the progam, but cold be used to implement, for
example, a checker image as the drag cursor instead of the default
drag icons. |
|BoardDragOver is called when the dragged piece is moving over
board. It converts the mouse location to the board column
and row and calls the ValidMove function to determine if the
piece can be accepted here. |
|BoardDragDrop: If the checker is over a valid
landing cell, this method is called when the player releases the
mouse button to end the drag. It call s procedure
MovePiece to actually move the checker.|
|And some common routines which could be customized for other checker
|SetPieceLoc(n,c,r:integer): Sets the location of
piece n to column c and row r. It is
called when the Reset button is clicked and pieces are being
restored to their home positions and from MovePiece wile a
piece is being moved.|
|MovePiece(n,c,r:integer): This is a busy procedure
with a number of tasks to perform. As it moves piece n to
column c and row r. it first checks to see if the move
was a jump|
| If a jump, the jumped piece is marked as "removed",
that cell is marked as empty, the score is updated and a check
is made to see if all opponent's pieces have been captured.
If all of the opponents pieces have been taken, a
"Congratulations" message is issued. |
|Whether a jump or normal move, the location of the checker
is updated and the old cell is marked as empty. |
|If the move landed the checker in the King row, it's status
|A call is made to the SetPossibleMoves procedure
determine the next move options. |
|If the current piece status is still "Canjump", the "Whoseturn"
variable is not updated. This will force the current
player's turn to continue. |
| If the global Gameover variable is true, there
is no move for your opponent, and a 'Congratulations"
message is given.|
|IsvalidLoc(loc:TPoint): Returns true if point
"Loc" is a valid location on the board. |
|IsNormalMove(n:integer; loc1,loc2:TPoint): A Boolean
function that returns true if a valid non-jump move can be made by
checker n from loc1 to loc2. (Valid
==> adjacent, in an allowed diagonal direction, and empty.)|
|IsJumpMove(n:integer; loc1,loc2:TPoint; var
jumpedloc:TPoint): A Boolean function that returns true if a
valid jump can be made by checker n from loc1
to loc2. (Valid ==> 2 squares away in an allowed diagonal
direction, intervening square occupied by opponent's piece, landing
location is empty.)|
|ValidMove(from,too:TPoint): Boolean function
called by BoardDragOver to decide whether or not the checker
can be dropped here. It is passed "from" and "too"
column/row addresses and calls IsValidLoc, IsNormalMove, and
IsJumpMove to make the determination. |
|SetPossibleMoves; Scans all pieces for the players
whose turn it is and sets the MoveStatus flag for each
one. It also sets global Boolean variables MustJump (a
jump move exists for the current player) and GameOver (no move exists
for the current player)|
Running/Exploring the Program
Suggestions for Further Explorations
control to replace default drag/drop icons.
sets/board sizes for other countries' rules. Initial
piece placement code needs to be generalized for board sizes other
Original Date: July 23, 2007
July 29, 2017