Modeling Completing the Square with Algebra Tiles (Visual Strategy)
Loading the math board and drawing, please wait…
This example demonstrates completing the square using algebra tiles as a visual model, showing students how a quadratic expression can be rearranged into a perfect square plus a remainder. The key math concepts include solving quadratic equations by completing the square, using algebraic equivalence transformations, and understanding why adding a constant term requires adding the same amount of the corresponding negative terms to preserve equality. Construction and interaction are built from controlled, parameter-driven generation: the app uses RandomUniform to create task-specific coefficients, Take/Sequence/Max/Min and If to determine how many tile pieces are needed and how they are arranged. Geometry/UI placement and labeling rely on Corner, PixelsToPoint, centerBox, and Text, while assembling and manipulating objects uses Element together with Vector, Join, Zip, Flatten, and Translate. Answer workflows are handled via showanswer/showhint and scripts that reset and prepare input areas (e.g., scriptResetApp, scriptEmptyInputBoxes). Suitable for grades 9–12 for lesson exploration and practice focused on the strategy behind completing the square.
GeoGebra Commands & Parameters
RandomUniform(0, 0.99, 200) → allRandomSeeds, {0.6701327566780267, 0.6696444842365005, 0.5259546813852927, 0.34940432864623294, 0.15925969234486, 0.48692867137716483, 0.8114439458968032, 0.7678107285783305, 0.6159506454758904, 0.21449722663377002, 0.011000711186750311, 0.5805051189243565, 0.17910342927723494, 0.7097248746435941, 0.21157901792289321, 0.35434427416458486, 0.5207202170612151, 0.38706390416171044, 0.008425368798318641, 0.6814963727635439, 0.5685331676059519, 0.9139357291113133, 0.7596528585003112, 0.9373853736914356, 0.39108271029508834, 0.5320202108681036, 0.535104510463396, 0.03965300278995254, 0.7042905231091791, 0.6626407342139718, 0.6508093374293212, 0.5717144161560295, 0.6105136277734062, 0.6139963960525399, 0.45587163178868106, 0.5308805254508726, 0.6176963985890018, 0.7992325926479024, 0.5238586654936883, 0.15460380921453729, 0.7975555082110618, 0.677769385812476, 0.335663939701255, 0.3291758587251298, 0.5677393131913874, 0.2679215356243891, 0.5454228580509537, 0.21316407896001327, 0.5935958344284721, 0.48664783931207567, 0.025344776791282213, 0.07302113243459031, 0.48056461409311985, 0.22225669536195722, 0.21930007537863772, 0.7306349677713748, 0.048276431246294244, 0.008073144448070354, 0.8386628238827663, 0.09210887818067978, 0.5122001595937969, 0.869437767371328, 0.5072592558568431, 0.16376941228049396, 0.4881197081360499, 0.6729601726431405, 0.6453096462783551, 0.31529723515655456, 0.27885487770724526, 0.5056907103468128, 0.17497547336175662, 0.9409593493472015, 0.07145821157362801, 0.6528011293644177, 0.15253592838380758, 0.8681931626790238, 0.48662575241007006, 0.5054805418149233, 0.30431753083949603, 0.2682512542174228, 0.2602532033710515, 0.41605576689200285, 0.285287792508395, 0.6262626718706746, 0.04994938347908016, 0.47483494047359764, 0.47069814029797324, 0.7579004251389142, 0.08688805871067211, 0.4228517163713596, 0.522323863718066, 0.14686608946452162, 0.8456338712293238, 0.6965519715354358, 0.031698105297252525, 0.40161195549019707, 0.8815227828670839, 0.7845179917683117, 0.3732741446142837, 0.8011169014689244, 0.8168072827255961, 0.532565432102175, 0.4006751143386899, 0.8581170610216416, 0.8130953001955047, 0.09197550389732742, 0.4891015905736811, 0.09396275762285186, 0.9386182221208361, 0.5062411845163243, 0.4665683178228655, 0.012233300726354973, 0.42455539393564834, 0.7645076002614412, 0.1459272501674251, 0.23838680819942004, 0.3250248870875467, 0.19487807060615786, 0.338609437122015, 0.35005677622991943, 0.0004175773761937196, 0.7979345647634726, 0.9596801784666498, 0.7671281532418056, 0.5335080381066812, 0.15018651660737234, 0.13215143829155207, 0.5924352243964468, 0.5422186052791577, 0.5487149676336195, 0.20653267078163415, 0.6628194799004878, 0.7720444174777024, 0.4720187536009705, 0.5593257771290063, 0.6463700069031745, 0.5749653233993658, 0.967997821761309, 0.9315821204300584, 0.094940513058349, 0.6101759341731344, 0.7881235345923577, 0.4557389604380481, 0.6814956090620007, 0.06515948700767693, 0.6371485169132075, 0.9357401144666838, 0.019485878613899537, 0.3135110850166412, 0.7001993099515914, 0.4819195703513505, 0.1362852786065438, 0.20848469304754827, 0.19377230362340236, 0.19829001933727125, 0.124745392394947, 0.05849420122271827, 0.004018941493784478, 0.7057265334503312, 0.7261308192610645, 0.9627418576795753, 0.21475876293036886, 0.2100737957823506, 0.8040955879791455, 0.5217786293493667, 0.21889946697904342, 0.809429582381504, 0.9429453542117031, 0.42911908457070075, 0.6503702592588814, 0.6197688450130963, 0.23420081356496178, 0.6560396496080079, 0.2992905632687006, 0.03267309739159956, 0.47343736196329195, 0.43238175822066655, 0.25089855760503826, 0.8232163704684747, 0.6545222317246305, 0.5915633069666761, 0.4387547257202103, 0.15003384029277092, 0.5407042760008814, 0.12806890683642394, 0.61491229990349, 0.5132614007052617, 0.5715332955931061, 0.030446744084582287, 0.40411314398083237, 0.1793837756561156, 0.2812944301841019, 0.3022816764231499, 0.9256191898116755, 0.38506618638841567, 0.348540072204955, 0.5677463664116559, 0.8650301663692042, 0.47476907445474287, 0.407385353626585}Take(allRandomSeeds, randIndex, randIndex + numRandoms - 1) → currentRandomSeedsCorner(5) → layoutAppSizeonboardingTextOffset(Corner[onboardingText, 1], Corner[onboardingText, 3], onboardingCase, (xMin, yMin), (xMax, yMax), (800, 500)) → OnboardingTextOffsetElement({-10, -8, -6, 6, 8, 10}, 1 + floor((currentRandomSeeds(1) * 6))) → coeffBPixelsToPoint((xMin, yMin), (xMax, yMax), (800, 500), (120, 250)) → AnchorSquaredcenterBox(xHeight, xHeight, AnchorSquared) → squaredBoxElement(Remove[Sequence[-10, 10], {0, absCoeffB / 2^(2)}], 1 + floor((currentRandomSeeds(2) * 19))) → coeffCSequence(AnchorX + ((A * (xWidth + gap)), 0), A, 0, abs(absCoeffB) - 1) → anchorsXMax(Min[1, 1 + animateControl - ceil(animateControl)], 0) → animateCurrentIf(floor(animateControl) < absCoeffB, 0, If[floor(animateControl) ≟ absCoeffB, animateControl - absCoeffB, 1]) → animateStage3AIf(floor(animateControl) < absCoeffB, 0, If[floor(animateControl) ≟ absCoeffB, animateControl - absCoeffB, 1]) → animateStage3Vector(AnchorStage3 - AnchorStage1) → vShiftSequence(AnchorUnitStart + (A * (xWidth + gap, 0)) + (animateStage3A * vShift), A, 0, abs(absCoeffC)) → anchorUnitsSequence(AnchorSquared + ((0.5 * (xHeight + xWidth)) + gap + (A * (xWidth + gap)), 0), A, 0, floor(abs(absCoeffB) / 2) - 1) → anchorsXStage2ASequence(AnchorSquared - (0, (0.5 * (xHeight + xWidth)) + gap + (A * (xWidth + gap))), A, 0, floor(abs(absCoeffB) / 2) - 1) → anchorsXStage2BJoin({anchorsXStage2A, anchorsXStage2B}) → anchorsXStage2Zip(Vector[B - A], A, anchorsX, B, anchorsXStage2) → vMoveMin(ceil(animateControl), absCoeffB) → animateIndexBIf(animateIndexB ≤ absCoeffB / 2, 0, pi / 2) → rotateAngleTranslate(Rotate[centerBox[xWidth, xHeight, anchorsX(animateIndexB)], (animateCurrent * rotateAngle), anchorsX(animateIndexB)], (animateCurrent * vMove(animateIndexB))) → moveBoxBMin(If[isNegativeC, 0, (absCoeffB / 2)^(2)], absCoeffC) → numUnitsMoveFlatten(Sequence[Sequence[(x(anchorsXStage2A(i)), y(anchorsXStage2B(j))), i, 1, absCoeffB / 2], j, 1, absCoeffB / 2]) → anchorUnitsStage2If(floor(animateControl) < absCoeffB + 2, 0, If[floor(animateControl) ≟ absCoeffB + 2, animateControl - absCoeffB - 2, 1]) → animateStage4Flatten(Sequence[Sequence[anchorUnits(1) + ((A * (xWidth + gap)), ((-K) * (xWidth + gap))), A, 0, absCoeffB / 2 - 1], K, 1, absCoeffB / 2]) → anchorUnitsStage3If(floor(animateControl) < absCoeffB + 3, 0, If[floor(animateControl) ≟ absCoeffB + 3, animateControl - absCoeffB - 3, 1]) → animateStage5Translate(anchorUnitsStage3, Vector[((1 - animateStage5) * Vector[AnchorSubtractStage3 - AnchorStage3])]) → anchorsSubtractStage3Zip(Vector[B - A], A, anchorUnitsStage3, B, anchorUnitsStage2) → vMoveUnitsMax(Min[ceil(animateControl) - absCoeffB - 4, numUnitsMove], 0) → animateIndexStage6Zip(centerBox[xWidth, xWidth, A], A, anchorUnitsStage2) → unitsStage2FramesZip(Vector[B - A], A, anchorsSubtractStage3, B, anchorUnits) → vMoveSubtractTranslate(centerBox[xWidth, xWidth, anchorsSubtractStage3(animateIndexStage6)], (animateCurrent * vMoveSubtract(animateIndexStage6))) → moveSubtractBoxcenterBox(squareWidth, squareWidth, CenterSquare) → squareFrameText("x", AnchorSquared - (xHeight / 2, 0), true, true, -1, 0) → lblSideXZip(centerBox[xWidth, xWidth, A], A, anchorUnitsStage3) → unitsStage4Zip(centerBox[xWidth, xWidth, A + (animateStage5 * B)], A, anchorUnitsStage3, Vector[B], vMoveUnits) → unitsStage5Sequence(centerBox[xWidth, xWidth, anchorUnits(A)], A, 1, absCoeffC) → unitsStage1Zip(centerBox[xWidth, xWidth, A], A, Take[anchorsSubtractStage3, animateIndexStage6 + 1]) → subtractStage3If(floor(animateControl) < absCoeffB + 4 + numUnitsMove, 0, If[floor(animateControl) ≟ absCoeffB + 4 + numUnitsMove, animateControl - absCoeffB - 4 - numUnitsMove, 1]) → animateStage7Take(unitsStage1, 1, If[animateStage7 ≟ 0, animateIndexStage6 - 1, numUnitsMove]) → unitsSubtractStage5PixelsToPoint((xMin, yMin), (xMax, yMax), (800, 500), (If[animateControl ≤ 4, 310, 16], 60)) → PExprElement({("" * finalConstant), "", ("+" * finalConstant)}, sgn(finalConstant) + 2) → finalConstantLatexIf(absCoeffC < 0, ("" * absCoeffC), If[absCoeffC ≟ 0, "", ("+" * absCoeffC)]) → coeffCLatexText(fullExpression, PExpr, true, true, If[animateControl ≤ 4, 0, 1], -1) → displayExprSegment((((-xWidth)) / 2, ((-xHeight)) / 2), (xWidth / 2, xHeight / 2)) → templateSlashXSequence(centerBox[xWidth, xHeight, anchorsX(A)], A, animateIndexB + 1, abs(absCoeffB)) → xBlocksStartSequence(centerBox[If[A > abs(absCoeffB) / 2, xHeight, xWidth], If[A > abs(absCoeffB) / 2, xWidth, xHeight], anchorsXStage2(A)], A, 1, Min[ceil(animateControl) - 1, abs(absCoeffB)]) → xBlocksStage2Vector(AnchorStage1 - AnchorStage3) → vSlideSubtractAppend((1000, 1000), Take[anchorUnits, 1, Min[animateIndexStage6, numUnitsMove]]) → anchorsCrossesSequence(Translate[crossTemplate, anchorUnits(A)], A, 1, absCoeffC) → possibleCrossesFlatten(Take[possibleCrosses, 1, If[animateStage7 ≟ 0, animateIndexStage6 - 1, numUnitsMove]]) → displayCrossesSequence(centerBox[(1.4 * xWidth), (1.4 * xWidth), anchorUnits(A)], A, 1, absCoeffC) → possibleFadesTake(possibleFades, 1, If[animateStage7 ≟ 0, animateIndexStage6 - 1, numUnitsMove]) → fadeBoxesZip(centerBox[xWidth - (2 * borderWidth), xWidth - (2 * borderWidth), A], A, Take[anchorsSubtractStage3, animateIndexStage6 + 1]) → subtractStage3CentersTranslate(centerBox[xWidth - (2 * borderWidth), xWidth - (2 * borderWidth), anchorsSubtractStage3(animateIndexStage6)], (animateCurrent * vMoveSubtract(animateIndexStage6))) → moveSubtractCenterText(("\vphantom{x^2}" * LaTeX[((If[isNegativeB, "-", ""] * absCoeffB) * "x")]), CenterX + (0, ((-xHeight)) / 2), true, true, 0, -1) → captionSlideBText("x^2", AnchorSquared + (0, ((-xHeight)) / 2), true, true, 0, -1) → captionSquaredZip(centerBox[xWidth, xWidth, A], A, Join[{anchorUnitsStage3, anchorsSubtractStage3}]) → fadeCoverStage4Sequence(centerBox[xWidth - (2 * gap), xWidth - (2 * gap), anchorUnits(A)], A, 1, absCoeffC) → negativeUnitsStage1Sequence(centerBox[xWidth - (2 * gap), xHeight - (2 * gap), anchorsX(A)], A, animateIndexB + 1, abs(absCoeffB)) → negativeXStage1Translate(Rotate[centerBox[xWidth - (2 * gap), xHeight - (2 * gap), anchorsX(animateIndexB)], (animateCurrent * rotateAngle), anchorsX(animateIndexB)], (animateCurrent * vMove(animateIndexB))) → negativeMoveBoxPointToPixels((xMin, yMin), (xMax, yMax), (800, 500), CenterX) → CenterXPXPointToPixels((xMin, yMin), (xMax, yMax), (800, 500), AnchorUnitStart) → CenterUnitsPXSequence(centerBox[If[A > abs(absCoeffB) / 2, xHeight - (2 * gap), xWidth - (2 * gap)], If[A > abs(absCoeffB) / 2, xWidth - (2 * gap), xHeight - (2 * gap)], anchorsXStage2(A)], A, 1, Min[ceil(animateControl) - 1, abs(absCoeffB)]) → negativeXStage2Text(("\vphantom{x^2}" * LaTeX[(If[isNegativeC, "-", ""] * absCoeffC)]), CenterUnit + (0, ((-xHeight)) / 2), true, true, 0, -1) → captionSlideCText("\vphantom{4}x", AnchorSquared + (0, xHeight / 2), true, true, 0, 1) → lblTopAText(("" * coeffB / 2), AnchorSquared + ((0.5 * xHeight) + (xWidth * absCoeffB / 4), (0.5 * xHeight)), true, true, 0, 1) → lblTopBText(("" * coeffB / 2), AnchorSquared - ((0.5 * xHeight), (xHeight * 0.5) + (xWidth * absCoeffB / 4)), true, true, -1, 0) → lblSideB
AI Drawing Prompt Reference
Create a visual model for completing the square using algebra tiles. A large square in the center represents the quadratic term, with its side labeled 'x'. Based on random coefficients, rectangular tiles representing the linear term are placed to the right and below the square, and they can rotate and move to fill the square. Meanwhile, small square tiles representing the constant term are placed outside and gradually move in to complete the square. Throughout the process, an expression updates in a corner, showing the algebraic steps. All tiles are color-coded, with a grid background for easy observation of area changes.
The prompt above was compiled from the original drawing commands and is for reference only.