Cursussen/Courses Codesnippets     Top 
B4A-chess - Setting up the board


1. Chess components
A chess game consists of a board with 64 squares organized in 8 rows and 8 columns.
The squares have a light or dark background color.
The rows are numbered from 8 to 1 and the columns are indicated by letters from a to h.
Each player gets 16 white or black chess pieces.
Each chess piece has a name (from left to right on the top or bottom row): rook, knight, bishop, queen, king, bishop, knight, rook
The row below or above these pieces is filled with 8 pawns of the same color.
The squares in between are empty.


2. Store information
To keep track of all these pieces you can use a two-dimensional array.
The first dimension indicates the row and the second dimension indicates the column.
One cell contains the shorthand piece information.
Some examples:
- the information from the black rook in a8 will be stored as board(0,0) = "BR1"
- the black king from e8 is in board(0,4) = "BK1"
- the white bishop from c1 is in board(7,2) = "WB1"
- the white knight from g1 is in board(7,6) = "WN2" (the N stands for knight because the K is used for the king)
The index numbers for the rows and columns start from 0 (because it is an array) and go to 7.


3. Fill the board array
In the designer the MainPage layout is modified. We add a "pnlmain" panel. This panel will contain the 64 panels for the squares (or cells).
In the B4XMainPage tab we add the following code.
In the Class_Globals routine we write:
	Private pnlmain As Panel
	Private board(8,8) As String
	Private bpcs1 As List = Array As String("BR1","BN1","BB1","BQ1","BK1","BB2","BN2","BR2")
	Private bpcs2 As List = Array As String("BP1","BP2","BP3","BP4","BP5","BP6","BP7","BP8")
	Private wpcs1 As List = Array As String("WR1","WN1","WB1","WQ1","WK1","WB2","WN2","WR2")
	Private wpcs2 As List = Array As String("WP1","WP2","WP3","WP4","WP5","WP6","WP7","WP8")
	Private rnumbers As String = "87654321"
	Private cletters As String = "abcdefgh"
	Private wfiles As List = Array As String("white_rook.png","white_knight.png","white_bishop.png", _
											 "white_queen.png","white_king.png","white_bishop.png", _
											 "white_knight.png","white_rook.png","white_pawn.png")
	Private bfiles As List = Array As String("black_rook.png","black_knight.png","black_bishop.png", _
											 "black_queen.png","black_king.png","black_bishop.png", _
											 "black_knight.png","black_rook.png","black_pawn.png")
	Private grid(8,8) As String
We add the subroutine setup_board with this code:
Private Sub setup_board
	pnlmain.RemoveAllViews
	For r = 0 To 7
		For c = 0 To 7
			Private pnl As Panel = set_panel(r,c)
			If r = 0 Then
				pnl.GetView(0).As(Label).Text = bpcs1.Get(c)
			End If
			If r = 1 Then
				pnl.GetView(0).As(Label).Text = bpcs2.Get(c)
			End If
			If r = 6 Then
				pnl.GetView(0).As(Label).Text = wpcs2.Get(c)
			End If
			If r = 7 Then
				pnl.GetView(0).As(Label).Text = wpcs1.Get(c)
			End If
			If r > 1 And r < 6 Then
				pnl.GetView(0).As(Label).Text = "EEE"
			End If
			pnlmain.AddView(pnl,30dip+(c*40dip),30dip+(r*40dip),40dip,40dip)
			board(r,c) = pnl.GetView(0).As(Label).Text
			grid(r,c) = cletters.SubString2(c,c+1) & rnumbers.SubString2(r,r+1)
		Next
	Next
End Sub
Private Sub set_panel(prow As Int,pcol As Int) As Panel
	Private pnl As Panel
	pnl.Initialize("pnl")
	pnl.Tag = prow&pcol
	Private lbl As Label
	lbl.Initialize("")
	pnl.AddView(lbl,0,0,40dip,40dip)
	Return pnl
End Sub
For the empty panels we use the piece info "EEE".
Each panel is 40dip wide and 40dip high and contains a label with the piece info.
Let's try to run this code and see what happens.
The result looks like this:
So now we have a textual representation of a chess board.
We also have a grid array with the letter and number indications. This grid will be used in the notes section.
To keep track of where each piece is you can write a log subroutine.
Here are two routines: one for the board and one for the grid.
Private Sub show_board_log
	Private logstr As String
	For r = 0 To 7
		For c = 0 To 7
			logstr = logstr & board(r,c) & " "
		Next
		Log(logstr)
		logstr = ""
	Next
End Sub
Private Sub show_grid_log
	Private logstr As String
	For r = 0 To 7
		For c = 0 To 7
			logstr = logstr & grid(r,c) & " "
		Next
		Log(logstr)
		logstr = ""
	Next
End Sub


4. Images on the board
Now let's show the chess piece images in the panels from the main board panel.
We start with the background color from the squares. The bottom left square has a dark background.
You could also check if the queen is on its color: the white queen starts on a light background.
In the set_panel subroutine add the following line below the line to set the tag:
	pnl.Color = get_color(prow,pcol)
And the get_color subroutine looks like this:
Public Sub get_color(crow As Int, ccol As Int) As Int
	Private clr As Int
	If ccol Mod 2 = 0 Then
		If crow Mod 2 > 0 Then
			clr = Colors.ARGB(255,148,195,255)	'black
		Else
			clr = Colors.ARGB(255,241,250,255)	'white
		End If
	Else
		If crow Mod 2 > 0 Then
			clr = Colors.ARGB(255,241,250,255)
		Else
			clr = Colors.ARGB(255,148,195,255)
		End If
	End If
	Return clr
End Sub
And this is what it looks like:
The next step is to replace the text labels with chess piece images. We will hide the labels because we need them in the rest of the programming code. Add a line below the lbl.initialize line:
	lbl.Visible = False
With the subroutine fill_imagemap the imagemap will be filled with the image of every chess piece.
Here's the code:
Private Sub fill_imagemap
	For i = 0 To 7
		imagemap.Put(bpcs1.Get(i),bfiles.Get(i))
	Next
	For i = 0 To 7
		imagemap.Put(bpcs2.Get(i),bfiles.Get(8))
	Next
	For i = 0 To 7
		imagemap.Put(wpcs1.Get(i),wfiles.Get(i))
	Next
	For i = 0 To 7
		imagemap.Put(wpcs2.Get(i),wfiles.Get(8))
	Next
	imagemap.Put("EEE","empty.png")
	Log("images: " & imagemap)
End Sub
The subroutine that puts the images in the squares is as follows:
private Sub put_bitmap_in_cell(cellrow As Int, cellcol As Int, pnl As Panel,pce As String)
	cnvscell.Initialize(pnl)
	cnvscell.DrawRect(BorderRect, Colors.Black, False, 1dip)
	Dim bmp As Bitmap
	bmp.Initialize(File.DirAssets, imagemap.Get(pce))
	cnvscell.DrawBitmap(bmp, Null, DestRect)
End Sub
For this code to work we need to declare and initialize some variables.
In the Class_Globals routine add the following lines:
	Private cnvscell As Canvas
	Private imagemap As Map
	Private DestRect As Rect
	Private BorderRect As Rect
In the B4XPage_Created below the title or load layout line :
	imagemap.Initialize
	DestRect.Initialize(5dip, 5dip, 40dip - 5dip, 40dip - 5dip)
	BorderRect.Initialize(0dip,0dip,40dip,40dip)
	fill_imagemap
	setup_board
	show_board_log
	show_grid_log
We call the subroutine put_bitmap_in_cell in the routine setup_board below the grid(r,c) line:
			put_bitmap_in_cell(r,c,pnl,board(r,c))
Before we can test the code we have so far we need to provide the image files.
You can download an image from the internet that contains all the piece images and then cut them out (a size of 80 pixels wide and high is good). Save each image and give it the name you find in the wfiles and bfiles array lists (see above).
Don't forget to make an image for the empty squares!
You can also find a zip-file with the image files here: chess_pieces.
Add the files in the B4A IDE Files Manager panel.
Now we are ready to test the code. This is the result:
You can draw the sides with this code:
Public Sub set_sides(cnv As Canvas, tfont As Typeface)
	cnv.DrawRect(TurnRect, Colors.ARGB(255,244,244,194), True, 1dip)
	cnv.DrawText(turncolor & " to move",140dip,20dip,tpfont,16,Colors.Blue,"LEFT")
	For r = 1 To 8
		Dim strnum As String = rnumbers.SubString2(r-1,r)
		cnv.DrawText(strnum,10dip,15dip+(r*40dip),tpfont,20,Colors.Gray,"LEFT")
		For c = 1 To 8
			If r = 8 Then
				Dim strlet As String = cletters.SubString2(c-1,c)
				cnv.DrawText(strlet,10dip+(c*40dip)-5dip,10dip+(9*40dip),tfont,20,Colors.Gray,"LEFT")
			End If
		Next
	Next
End Sub
Declarations for this code to work:
	Private TurnRect As Rect
	Private turncolor As String = "white"
	Private tpfont As Typeface
	Private cnvs As Canvas
Initializations:
	TurnRect.Initialize(140dip, 3dip, 240dip, 26dip)
	tpfont = Typeface.DEFAULT
	cnvs.Initialize(pnlmain)
Call to the subroutine as the last line in the subroutine setup_board:
	set_sides(cnvs,tpfont)
Now the chess board is complete.