//--------------------------------------------------------------------------- #include #pragma hdrstop #include "Unit1.h" #include "Unit2.h" #include "Unit3.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "IWBaseControl" #pragma link "IWBaseHTMLControl" #pragma link "IWCompMenu" #pragma link "IWControl" #pragma link "IWVCLBaseControl" #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { int bnum = 0; for(int i = 0; i < 9; i++){ for(int j = 0; j < 9; j++){ if (Square[bnum] == NULL) { //if button [i + j] is not yet created Square[bnum] = new NumBox; Square[bnum]->Parent = this; Square[bnum]->Top = 10 + i*35; Square[bnum]->Left = 10 + j*35; bnum++; } } } //show Color selection Boxes and labels, set default recommended values. ColorLabel1->Visible = true; ColorLabel2->Visible = true; ColorLabel3->Visible = true; ColorBox1->Visible = true; ColorBox2->Visible = true; ColorBox3->Visible = true; ColorBox1->Selected = clSilver; Edit1->Visible = true; Label1->Visible = true; //Update instructions label Instruct->Caption = "Please set the initial number placement for the puzzle. \nClick on \"Start Game\" to make the initial numbers unchangeable"; Edit1->SetFocus(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { if (!Form1->GameInPlay) {//if a game is not yet in play for (int i = 0; i < 81; i++) { if (Square[i]->Text != "") { Square[i]->SetStarter(true);//this square is a starting value of the puzzle //and should not be changed Square[i]->Font->Style = Square[i]->Font->Style << fsBold; Square[i]->SetStartColor(); } else { Square[i]->SetStarter(false);//ensures all other squares are properly } //initialized to NOT starter values } Form1->GameInPlay = true; //sets boolean to tell us a game is in progress Button2->Caption = "Reset Game"; Instruct->Caption = "Press \"Reset Game\" to clear the board of all numbers except the puzzle's initial given numbers."; CheckButton->Visible = true; //make game clock objects visible Image2->Visible = true; GameTimeS->Visible = true; GameTimeM->Visible = true; GameTimeH->Visible = true; GT_1->Visible = true; GT_2->Visible = true; //start game timer GameTimeTimer->Enabled = true; Edit1->SetFocus(); } else if (Form1->GameInPlay) {//if a game is already in play for (int i = 0; i < 81; i++) {//for every square in game if (!Square[i]->GetStarter()) { //if the square is not a starter square Square[i]->Text = ""; //erase the contents of the square } } } } //--------------------------------------------------------------------------- void __fastcall TForm1::ColorBox1Select(TObject *Sender) { for (int i = 0; i < 81; i++) { if (Square[i]->GetStarter()) { Square[i]->SetStartColor(); } } } //--------------------------------------------------------------------------- void __fastcall TForm1::ColorBox2Select(TObject *Sender) { for (int i = 0; i < 81; i++) { if (!Square[i]->GetStarter()) { Square[i]->SetNumsColor(); } } } //--------------------------------------------------------------------------- void __fastcall TForm1::ColorBox3Select(TObject *Sender) { for (int i = 0; i < 81; i++) { Square[i]->SetGridColor(); } } //--------------------------------------------------------------------------- /*Button Event to check the state of the puzzle and see if it is an acceptable solution, or if there are violations of the rules (or the entire grid is not yet filled, and thus the game is unfinished */ void __fastcall TForm1::CheckButtonClick(TObject *Sender) { if (GameInPlay) { //does't run calculation if a game isn't already going //(if perhaps user clicks the button while it is not visible bool error = false; //toggle on if an error is found //Check if any game spaces remain blank for (int i = 0; i < 81; i++) { if (Square[i]->Text == "" ) { ShowMessage("Not all game spaces are filled."); return; //do not do remainder if game is not completely filled } } //Check Rows for (int i = 0; i < 81; i += 9) {//jumps 1 row of 9 at a time for (int j = i; j < i+9; j++) {//checks each in a row of 9... int temp = StrToInt(Square[j]->Text); for (int k = i; k < i+9; k++) {//...against the rest of the row, except it's own position if (StrToInt(Square[k]->Text) == temp && k != j) { error = true; } } } } //End of Row checking loop //Check Columns for (int i = 0; i < 9; i++) { for (int j = i; j < 81; j += 9) { int temp = StrToInt(Square[j]->Text); for (int k = i; k < 81; k += 9) { if (StrToInt(Square[k]->Text) == temp && k != j) { error = true; } } } }//End of Column checking loop //Check 3x3 cubes //take 2 int temp; int quad = 0; int mult = 0; while (mult < 3){ for (int i = 0 + quad*3 + (27 * mult); i < 21 + quad*3 + (27*mult); i += 9) { for (int j = i; j < i+3; j++) { temp = StrToInt(Square[j]->Text); for (int x = 0 + quad*3 + (27 * mult); x < 20 + quad*3 + (27*mult); x+=9) { for (int y = x; y < x+3; y++) { if (temp == Square[y]->Text && y != j) { error = true; } } } } } quad++; if (quad == 3) { mult++; quad = 0; } }//end 3x3 cube checking //Brute-Force method! GO! /* int temp; //quadrant 1 for (int i = 0; i < 20; i += 9) { for (int j = i; j < i+3; j++) { temp = StrToInt(Square[j]->Text); for (int x = 0; x < 20; x+=9) { for (int y = x; y < x+3; y++) { if (temp == Square[y]->Text && y != j) { error = true; } } } } } //quadrant 2 for (int i = 3; i < 23; i += 9) { for (int j = i; j < i+3; j++) { temp = StrToInt(Square[j]->Text); for (int x = 3; x < 23; x+=9) { for (int y = x; y < x+3; y++) { if (temp == Square[y]->Text && y != j) { error = true; } } } } } for (int i = 6; i < 26; i += 9) { for (int j = i; j < i+3; j++) { temp = StrToInt(Square[j]->Text); for (int x = 6; x < 26; x+=9) { for (int y = x; y < x+3; y++) { if (temp == Square[y]->Text && y != j) { error = true; } } } } } for (int i = 27; i < 47; i += 9) { for (int j = i; j < i+3; j++) { temp = StrToInt(Square[j]->Text); for (int x = 27; x < 47; x+=9) { for (int y = x; y < x+3; y++) { if (temp == Square[y]->Text && y != j) { error = true; } } } } } */ if (error) { ShowMessage("There are errors in your solution."); } else { ShowMessage("Congratulations! Your solution is appropriate!"); GameTimeTimer->Enabled = false; } Edit1->SetFocus(); }//end if(GameInPlay) } //--------------------------------------------------------------------------- void __fastcall TForm1::Image1Click(TObject *Sender) { //Display message box to double check with user, warning that current game will be lost if(MessageBox(this->Handle, "Are you sure you want to start a new game?\nAll data about the current game will be lost.", "Start new game?", MB_YESNO|MB_ICONQUESTION) == IDYES) { //Reset text of all game squares and toggle GameInPlay variable, resetting to false for (int i = 0; i < 81; i++) { Square[i]->Text = ""; GameInPlay = false; //reset game clock GameTimeTimer->Enabled = false; GameTimeTimer->Tag = 0; GameTimeS->Caption = "00"; GameTimeM->Caption = "00"; GameTimeH->Caption = "00"; Button2->Caption = "Start Game"; } } } //--------------------------------------------------------------------------- void __fastcall TForm1::Image1MouseEnter(TObject *Sender) { Image1->Height += 5; Image1->Top -= 2.5; Image1->Width += 5; Image1->Left -= 2.5; } //--------------------------------------------------------------------------- void __fastcall TForm1::Image1MouseLeave(TObject *Sender) { Image1->Height -= 5; Image1->Top += 2.5; Image1->Width -= 5; Image1->Left += 2.5; } //--------------------------------------------------------------------------- void __fastcall TForm1::Exit1Click(TObject *Sender) { if (GameInPlay) { if (MessageBox(this->Handle, "Are you sure you want to exit? Your game in progress will not be saved.", "Exit without saving?", MB_YESNO | MB_ICONWARNING) == ID_YES) { Close(); } } else if(!GameInPlay) { Close(); } } //--------------------------------------------------------------------------- void __fastcall TForm1::ProgramInfo1Click(TObject *Sender) { ShowMessage("Program: Jason Racine's Sudoku Machine\n" "Programmer: Jason Racine\n" "Date: October 1, 2009\n\n" "Details: \nProgram to enable the user to play a game of sudoku\n" "and make use of the interface to color and lock\n" "puzzle numbers, and calculate whether their solution\n" "to the problem is acceptable."); } //--------------------------------------------------------------------------- void __fastcall TForm1::GameRules1Click(TObject *Sender) { Form3->ShowModal(); } //--------------------------------------------------------------------------- void __fastcall TForm1::NewGame1Click(TObject *Sender) { Image1Click(Sender); } //--------------------------------------------------------------------------- void __fastcall TForm1::Setup1Click(TObject *Sender) { Timer1->Enabled = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::Timer1Timer(TObject *Sender) { if (Timer1->Tag == 0) { Timer1->Interval = 5000; //creates slight delay for reading on screen instructions //make arrow image visible and position next to Button1 Arrow->Visible = True; Arrow->Top = Button1->Top; Arrow->Left = Button1->Left + Button1->Width; //hide Button2 so arrow can be clearly seen Button2->Visible = false; //display instructions Instruct->Caption = "Click on \"Create Grid\" Button to create the play area"; Timer1->Tag = 1;//next step } else if (Timer1->Tag == 1) { Button2->Visible = true; //put Button2 back to visible now that arrow is gone //position arrow near grid of game spaces Arrow->Top = 10; Arrow->Left = 330; //change instruction text Instruct->Caption = "Enter the initial numbers for the puzzle on the grid."; Timer1->Tag = 2;//next step } else if (Timer1->Tag == 2) { //position arrow next to Button2 Arrow->Top = Button2->Top; Arrow->Left = Button2->Left + Button2->Width; //change instruction text Instruct->Caption = "Once initial numbers are set, click \"Start Game\"" " to lock the numbers in and begin solving the puzzle."; Timer1->Tag = 3;//next step } else if (Timer1->Tag == 3) { Arrow->Visible = false; //take away arrow graphic //reset instructions and set focus to number entry field. Instruct->Caption = "Please set the initial number placement for the puzzle. \nClick on \"Start Game\" to make the initial numbers unchangeable"; Edit1->SetFocus(); //reset timer attributes Timer1->Tag = 0; Timer1->Interval = 1; Timer1->Enabled = false; } } //--------------------------------------------------------------------------- void __fastcall TForm1::GameTimeTimerTimer(TObject *Sender) { GameTimeTimer->Tag = StrToInt(GameTimeTimer->Tag) + 1; //logic for seconds if (StrToInt(GameTimeTimer->Tag) > 0 && StrToInt(GameTimeTimer->Tag) < 10) { switch (GameTimeTimer->Tag){ case 1: GameTimeS->Caption = "01"; break; case 2: GameTimeS->Caption = "02"; break; case 3: GameTimeS->Caption = "03"; break; case 4: GameTimeS->Caption = "04"; break; case 5: GameTimeS->Caption = "05"; break; case 6: GameTimeS->Caption = "06"; break; case 7: GameTimeS->Caption = "07"; break; case 8: GameTimeS->Caption = "08"; break; case 9: GameTimeS->Caption = "09"; break; default: break; } } else if (StrToInt(GameTimeTimer->Tag) < 60) { GameTimeS->Caption = GameTimeTimer->Tag; } else if(StrToInt(GameTimeTimer->Tag) == 60) { GameTimeTimer->Tag = 0; GameTimeS->Caption = "00"; GameTimeM->Caption = StrToInt(GameTimeM->Caption) + 1; } switch (StrToInt(GameTimeM->Caption)){ case 1: GameTimeM->Caption = "01"; break; case 2: GameTimeM->Caption = "02"; break; case 3: GameTimeM->Caption = "03"; break; case 4: GameTimeM->Caption = "04"; break; case 5: GameTimeM->Caption = "05"; break; case 6: GameTimeM->Caption = "06"; break; case 7: GameTimeM->Caption = "07"; break; case 8: GameTimeM->Caption = "08"; break; case 9: GameTimeM->Caption = "09"; break; default: break; } if(StrToInt(GameTimeM->Caption) > 59) { GameTimeH->Caption = StrToInt(GameTimeH->Caption) + 1; GameTimeM->Caption = "00"; } } //---------------------------------------------------------------------------