Untitled

mail@pastecode.io avatar
unknown
c_cpp
2 years ago
9.4 kB
24
Indexable
Never
//---------------------------------------------------------------------------


#include "stdio.h"
#include <vcl.h>
#pragma hdrstop

#include "MouseInMaze.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

TForm1 *Form1;

#define MAXSIZE 30
#define possible_direction 8

int ** maze;  //二微陣列存迷宮
int m, n, top;

struct offset  //用來存方位的移動值
{
	int dx;
	int dy;
};

enum direction{N, NE, E, SE, S, SW, W, NW}; //列舉8個方位

struct position  //用來存點的位置+移動的方位
{
	int x;
	int y;
	int dir;
};


struct offset move[possible_direction];  //用move這個陣列去存可能的移動位置
struct position *stack;


void push(struct position data) //stack中push的概念
{
	if(top == (m*n-1))
	{
		Form1->Memo1->Lines->Add("Stack is full!");
	}
	else
	{
		stack[++top] = data;
	}
}

struct position pop()  //stack中pop的概念
{
	if(top == -1)
	{
		Form1->Memo1->Lines->Add("Stack is empty!");
	}
	else
	{
		return stack[top--];
	}
}


void path(int m, int n)
{
	int mark[300][300];
	String str = "";
	stack = new struct position[m*n];
	struct position step;
	boolean found = false;
	int i, j, u, v;
	int count = 0;

	//用另一個mark陣列存maze的值,這個陣列是記錄哪邊走過用的
	for(i = 0; i < m; i++)
	{
		for(j = 0; j < n; j++)
		{
			mark[i][j] = maze[i][j];
        }
    }

	//初始化
	step.x = 1; step.y = 0; step.dir = E;
	push(step);

	//走迷宮的邏輯
	//從方位0走到7,只要可以走就更新位置,如果不能走就退回前一步
	//因為mark有去紀錄有沒有走過,所以就會退回前一步,再走沒走過的地方
	//找到的話就把路徑顯示出來
	while(top != -1)
	{
		step = pop();
		while((step.dir <= NW) && (!found))
		{
            count++;
			u = step.x + move[step.dir].dx;
			v = step.y + move[step.dir].dy;
			int x = step.dir;
			Form1->Memo2->Lines->Add("● Step" + IntToStr(count) + ": (u, v, dir) = " + IntToStr(u) + ", " + IntToStr(v) + ", " + IntToStr(x));
			if((u == m-1) && (v == n))
			{
				found = true;
				str += "(" +IntToStr(step.x) + "," + IntToStr(step.y) + ")";
				while (top != -1)
				{
					Form1->StringGrid1->Cells[step.y][step.x] = "●";
					Form1->StringGrid2->Cells[step.y][step.x] = "●";
					step = pop();
					str = "(" + IntToStr(step.x) + "," + IntToStr(step.y) + ")-->" + str;
				}
				Form1->Memo2->Lines->Add(str);
			}
			else if((maze[u][v]==0) && (mark[u][v]==0))
			{
				mark[u][v] = 1;
				step.dir += 1;
				push(step);
				step.x = u; step.y = v; step.dir = 0;
				Form1->StringGrid1->Cells[step.y][step.x] = "*";
                Form1->StringGrid2->Cells[step.y][step.x] = "*";
			}
			else
			{
				step.dir += 1;
			}
        }
    }
}



//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	//初始化
	move[N].dx = -1; move[N].dy = 0;
	move[NE].dx = -1; move[NE].dy = 1;
	move[E].dx = 0; move[E].dy = 1;
	move[SE].dx = 1; move[SE].dy = 1;
	move[S].dx = 1; move[S].dy = 0;
	move[SW].dx = 1; move[SW].dy = -1;
	move[W].dx = 0; move[W].dy = -1;
	move[NW].dx = -1; move[NW].dy = -1;
}
//---------------------------------------------------------------------------


//讀檔用
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	FILE *fp;     // Define fp as a pointer pointing to some file (with data type FILE) in HD
	String out;
	int i, j;
	AnsiString infile;   // Use builder's string (AnsiString) to ease the conversion (into const char *)


	if (OpenDialog1->Execute())
	{
		infile = OpenDialog1->FileName;
		fp = fopen(infile.c_str(), "r+");
		//c_str函数的傳回值是 const char *, 即把AnsiString轉成const char *給fopen使用
		fscanf(fp, "%d %d", &m, &n);    // Read in two integers m & n
		Memo2->Lines->Add("(m, n) = (" + IntToStr(m) + ", " + IntToStr(n) + ")");
		maze = new int * [m];
		for(i = 0; i < m; i++)
		{
			maze[i] = new int [n];
		}
		// Read in m*n 0/1/2's into maze[][]
		for(i = 0; i < m; i++)
		{
			for(j = 0; j < n; j++)
			{
				fscanf(fp, "%d", &maze[i][j]);
			}
        }
		fclose(fp);

		for(i = 0; i < m; i++)
		{
			out = "";
			for(j = 0; j < n; j++)
			{
				out += " " + IntToStr(maze[i][j]);
			}
			Form1->Memo2->Lines->Add(out);
		}
	}

	Memo1->Lines->Add("Maze Loaded!");
    Memo2->Lines->Add("––––– Maze Loaded –––––");
	Memo1->Lines->Add("You Can Now Click On Button 'Show Maze In String Grid'!");
	Button2->Enabled = True;
}
//---------------------------------------------------------------------------

//顯示迷宮用
void __fastcall TForm1::Button2Click(TObject *Sender)
{
	Memo1->Lines->Add("'Show Maze In String Grid' Clicked!");
	Memo1->Lines->Add("Check It At Page 'Maze By Icon/Color'!");
	Memo1->Lines->Add("You Can Now Click On Button 'Find A Tour In Maze'!");
	int i, j;
	int grid_size = StrToInt(Edit1->Text);
	for(i = 0; i < m; i++)
	{
		for(j = 0; j < n; j++)
		{
			StringGrid1->Cells[j][i] = maze[i][j];
			StringGrid2->Cells[j][i] = maze[i][j];
		}
	}

	StringGrid1->RowCount = m;  StringGrid1->ColCount = n;
	StringGrid1->DefaultDrawing = true;  StringGrid1->FixedCols=0;  StringGrid1->FixedRows=0;
	for (i=0; i<m; i++) StringGrid1->RowHeights[i] = grid_size;
	for (i=0; i<n; i++) StringGrid1->ColWidths[i] = grid_size;

	StringGrid2->RowCount = m;  StringGrid2->ColCount = n;
	StringGrid2->DefaultDrawing = true;  StringGrid2->FixedCols=0;  StringGrid2->FixedRows=0;
	for (i=0; i<m; i++) StringGrid2->RowHeights[i] = grid_size;
	for (i=0; i<n; i++) StringGrid2->ColWidths[i] = grid_size;

	StringGrid1->Refresh();
    StringGrid2->Refresh();

	Button3->Enabled = True;
}
//---------------------------------------------------------------------------

//迷宮判斷過程的顯示(美化)
void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect,
		  TGridDrawState State)
{
	AnsiString text = StringGrid1->Cells[ACol][ARow];
	if(text == "0")
	{
		StringGrid1->Canvas->Brush->Color = TColor RGB(246,234,190);
		StringGrid1->Canvas->FillRect(Rect);
	}
	else if(text == "●")
	{
		StringGrid1->Canvas->Brush->Color = TColor RGB(246,234,190);
		StringGrid1->Canvas->FillRect(Rect);
		StringGrid1->Canvas->TextRect(Rect, Rect.Left+10, Rect.Top+10, text);
	}
	else if(text == "*")
	{
		StringGrid1->Canvas->Brush->Color = TColor RGB(246,234,190);
		StringGrid1->Canvas->FillRect(Rect);
		StringGrid1->Canvas->TextRect(Rect, Rect.Left+10, Rect.Top+10, text);
	}
	else
	{
		StringGrid1->Canvas->Brush->Color = TColor RGB(94,69,75);
		StringGrid1->Canvas->FillRect(Rect);
	}

}
//---------------------------------------------------------------------------

//找路徑用
void __fastcall TForm1::Button3Click(TObject *Sender)
{
	Memo1->Lines->Add("Find A Tour In Maze Clicked!");
	Memo1->Lines->Add("Track The Steps At 'Track' Or Check The Graph At 'Maze By Icon/Color'!");
	Memo2->Lines->Add("");
    Memo2->Lines->Add("––––– Start Of Trace –––––");
	path(m,n);
	Memo2->Lines->Add("––––– End Of Trace –––––");
}
//---------------------------------------------------------------------------

//可以顯示每個Grid的大小和值
void __fastcall TForm1::StringGrid1Click(TObject *Sender)
{
	TRect Recto = StringGrid1->CellRect(StringGrid1->Col, StringGrid1->Row);

	int width = Recto.Width();
	int height = Recto.Height();

	Label2->Caption = "Size: " + IntToStr(width) + " * " + IntToStr(height);
	Label3->Caption = "Cell: [" + IntToStr(StringGrid1->Col) + ", " + IntToStr(StringGrid1->Row)+ "] = " + StringGrid1->Cells[StringGrid1->Col][StringGrid1->Row];
}
//---------------------------------------------------------------------------

//迷宮判斷過程的顯示(美化)
void __fastcall TForm1::StringGrid2DrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect,
          TGridDrawState State)
{
	AnsiString text = StringGrid1->Cells[ACol][ARow];
	if(text == "0")
	{
		StringGrid2->Canvas->Brush->Color = TColor RGB(255,255,255);
		StringGrid2->Canvas->FillRect(Rect);
	}
	else if(text == "●")
	{
		StringGrid2->Canvas->Brush->Color = TColor RGB(210,180,140);
		StringGrid2->Canvas->FillRect(Rect);
	}
	else if(text == "*")
	{
		StringGrid2->Canvas->Brush->Color = TColor RGB(255,239,213);
		StringGrid2->Canvas->FillRect(Rect);
	}
	else
	{
		StringGrid2->Canvas->Brush->Color = TColor RGB(119,136,153);
		StringGrid2->Canvas->FillRect(Rect);
	}
}
//---------------------------------------------------------------------------

//可以顯示每個Grid的大小和值
void __fastcall TForm1::StringGrid2Click(TObject *Sender)
{
	TRect Recto = StringGrid2->CellRect(StringGrid2->Col, StringGrid2->Row);

	int width = Recto.Width();
	int height = Recto.Height();

	Label2->Caption = "Size: " + IntToStr(width) + " * " + IntToStr(height);
	Label3->Caption = "Cell: [" + IntToStr(StringGrid2->Col) + ", " + IntToStr(StringGrid2->Row)+ "] = " + StringGrid2->Cells[StringGrid2->Col][StringGrid2->Row];
}
//---------------------------------------------------------------------------