<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Projects | 정진영의 포트폴리오</title><link>https://wjdwlsdud.github.io/en/projects/</link><atom:link href="https://wjdwlsdud.github.io/en/projects/index.xml" rel="self" type="application/rss+xml"/><description>Projects</description><generator>Hugo Blox Builder (https://hugoblox.com)</generator><language>en-us</language><lastBuildDate>Sun, 19 May 2024 00:00:00 +0000</lastBuildDate><image><url>https://wjdwlsdud.github.io/media/sharing.jpg</url><title>Projects</title><link>https://wjdwlsdud.github.io/en/projects/</link></image><item><title>Pacman</title><link>https://wjdwlsdud.github.io/en/projects/pacman/</link><pubDate>Sat, 01 Mar 2025 00:00:00 +0000</pubDate><guid>https://wjdwlsdud.github.io/en/projects/pacman/</guid><description>&lt;p&gt;This is the UC Berkeley Pacman AI project I completed as part of my Artificial Intelligence and Data Structures coursework. The core objective of this assignment was to implement fundamental Graph Search algorithms from scratch and apply them to solve tangible problems within the Pacman game environment.&lt;/p&gt;
&lt;p&gt;My work involved implementing generic search algorithms in &lt;strong&gt;search.py&lt;/strong&gt; and defining/solving specific Pacman problems in &lt;strong&gt;searchAgents.py&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="1-core-search-algorithm-implementation-searchpy"&gt;1. Core Search Algorithm Implementation (search.py)&lt;/h2&gt;
&lt;p&gt;First, I implemented four fundamental search algorithms that can be applied to any search problem.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DFS (Depth-First Search): Using a &lt;strong&gt;Stack&lt;/strong&gt;, this algorithm explores nodes as deeply as possible first. It was implemented as a graph search, using an &lt;strong&gt;explored&lt;/strong&gt; list to prevent cycles.&lt;/li&gt;
&lt;li&gt;BFS (Breadth-First Search): Using a &lt;strong&gt;Queue&lt;/strong&gt;, this algorithm explores the shallowest (closest) nodes first. It guarantees the shortest path when all edge costs are uniform.&lt;/li&gt;
&lt;li&gt;UCS (Uniform Cost Search): Using a &lt;strong&gt;PriorityQueue&lt;/strong&gt;, this algorithm prioritizes nodes by their total cumulative &amp;lsquo;cost&amp;rsquo;. It always explores the path with the lowest cost first, guaranteeing the shortest cost path.&lt;/li&gt;
&lt;li&gt;A* (A-Star) Search: Also uses a &lt;strong&gt;PriorityQueue&lt;/strong&gt;, but its priority is the sum of the &amp;lsquo;cumulative cost to date&amp;rsquo; ($g(n)$) and an &amp;rsquo;estimated cost to the goal&amp;rsquo; (heuristic, $h(n)$). This function is $f(n) = g(n) + h(n)$. As an informed search, it finds the optimal solution far more efficiently than UCS.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="2-defining-and-solving-pacman-problems-searchagentspy"&gt;2. Defining and Solving Pacman Problems (searchAgents.py)&lt;/h2&gt;
&lt;p&gt;Beyond just implementing the algorithms, I modeled complex problems Pacman faces as formal &amp;lsquo;search problems&amp;rsquo; and solved them.&lt;/p&gt;
&lt;p&gt;📍 The Corners Problem (CornersProblem)
The challenge is to find a path for Pacman to visit all four corners of the map.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;State Definition: To solve this, the state space couldn&amp;rsquo;t just be (x, y). I defined the state as &lt;strong&gt;(currentPosition, (visitedCornersTuple))&lt;/strong&gt;. For example, a state might be &lt;strong&gt;((5, 5), (True, False, False, True))&lt;/strong&gt;, tracking both the position and the visit-status of each corner.&lt;/li&gt;
&lt;li&gt;Goal Definition: The goal state is reached when all boolean values in the tuple state[1] are &lt;strong&gt;True&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Successor Function: As Pacman moves, the function checks if the new position is one of the corners. If it is, it generates a new state with the corresponding boolean in the tuple updated to &lt;strong&gt;True&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;💡 Corners Problem Heuristic (cornersHeuristic)&lt;/p&gt;
&lt;p&gt;I designed a heuristic for solving the Corners Problem using A* search.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Design: A heuristic must be admissible (never overestimates the true cost).&lt;/li&gt;
&lt;li&gt;Logic: The function calculates the Manhattan Distance from the &amp;lsquo;current position&amp;rsquo; to &amp;rsquo;every unvisited corner&amp;rsquo;. It then returns the maximum (max) value among these distances.&lt;/li&gt;
&lt;li&gt;Justification: This is admissible because Pacman must travel at least as far as the farthest remaining corner to complete the goal. This value serves as a safe lower bound on the true remaining cost.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🍔 All Food Heuristic (foodHeuristic)&lt;/p&gt;
&lt;p&gt;This heuristic was for the &lt;strong&gt;FoodSearchProblem&lt;/strong&gt;, which involves finding a path to eat all the food dots on the map.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Logic: Similar to the corners heuristic, I calculated the actual maze distance (&lt;strong&gt;mazeDistance&lt;/strong&gt;) from the &amp;lsquo;current position&amp;rsquo; to &amp;rsquo;every remaining food dot&amp;rsquo; and returned the maximum (max) value.&lt;/li&gt;
&lt;li&gt;Using &lt;strong&gt;mazeDistance&lt;/strong&gt;: Unlike Manhattan distance, &lt;strong&gt;mazeDistance&lt;/strong&gt; is a helper function that runs a BFS to find the true shortest path considering walls, providing a much more accurate (and still admissible) estimate.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;🎯 Closest Dot Search Agent&lt;/p&gt;
&lt;p&gt;Finding a path to eat all food is very complex (NP-hard). Therefore, I implemented a greedy algorithm that repeatedly finds and eats the closest food dot.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;findPathToClosestDot&lt;/strong&gt; Implementation: I defined a sub-problem called &lt;strong&gt;AnyFoodSearchProblem&lt;/strong&gt; (where the goal is to reach any single food dot).&lt;/li&gt;
&lt;li&gt;Using UCS: I applied &lt;strong&gt;UCS&lt;/strong&gt; to this sub-problem. This finds the path to the food dot with the lowest cost (i.e., the closest dot). (Since costs are uniform, &lt;strong&gt;BFS&lt;/strong&gt; would also have guaranteed the same result).&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Phone Book Application</title><link>https://wjdwlsdud.github.io/en/projects/mobile/</link><pubDate>Fri, 20 Dec 2024 00:00:00 +0000</pubDate><guid>https://wjdwlsdud.github.io/en/projects/mobile/</guid><description>&lt;p&gt;This is a simple mobile app I created for my &amp;ldquo;Mobile Programming&amp;rdquo; course in the 2024 fall semester. This project is a phonebook management app that utilizes fundamental Android features and a database.&lt;/p&gt;
&lt;p&gt;First, I designed a database named phoneDB and a table named phoneTBL. This table stores a name (VARCHAR(20)) and a phone number (VARCHAR(20)). I set a UNIQUE constraint on the name column to prevent duplicates. I included two initial data entries: &amp;ldquo;Hong Gil-dong&amp;rdquo; and my own contact information.&lt;/p&gt;
&lt;p&gt;The main features I implemented are as follows:&lt;/p&gt;
&lt;p&gt;Main Screen (Read Data): On app launch, the app queries the database and displays all saved user names in a ListView. An &amp;ldquo;Add&amp;rdquo; button and an options menu are placed at the bottom.&lt;/p&gt;
&lt;p&gt;Add Contact (Create): Tapping the &amp;ldquo;Add&amp;rdquo; button opens a separate Activity to receive name and phone number input. Upon completion, this information is passed back to the main Activity, saved to the database, and the ListView is immediately refreshed.&lt;/p&gt;
&lt;p&gt;Database Initialization (Delete All): Selecting &amp;ldquo;Initialize&amp;rdquo; from the options menu displays a confirmation dialog. If the user confirms, all content in the database is deleted, and the list is refreshed.&lt;/p&gt;
&lt;p&gt;Data Backup (Export): Through the &amp;ldquo;Backup&amp;rdquo; feature in the options menu, I implemented a function to save all names and phone numbers from the database as a .txt file (named after my student ID) to the /sdcard path.&lt;/p&gt;
&lt;p&gt;Phone App Integration (Intent): When a specific item in the list is clicked, the app retrieves that item&amp;rsquo;s phone number and uses an Intent to immediately launch the default Android phone app with the number pre-filled.&lt;/p&gt;
&lt;p&gt;Update &amp;amp; Delete: A long click on a list item navigates to a separate Activity where the selected item can be modified or deleted. I implemented confirmation dialogs for each action. Upon completion, the changes are reflected in the main Activity&amp;rsquo;s database and ListView in real-time.&lt;/p&gt;</description></item><item><title>Linux TCP chat program</title><link>https://wjdwlsdud.github.io/en/projects/linux/</link><pubDate>Wed, 26 Jun 2024 00:00:00 +0000</pubDate><guid>https://wjdwlsdud.github.io/en/projects/linux/</guid><description>&lt;p&gt;Based on what I learned in my Linux System Programming class, I implemented a simple multi-client TCP chat program as a project.&lt;/p&gt;
&lt;p&gt;It was a meaningful experience to directly apply the concepts of C socket communication and multithreading (pthreads). I&amp;rsquo;d like to summarize the project&amp;rsquo;s structure, core operating principles, and the key takeaways.&lt;/p&gt;
&lt;h2 id="1-project-overview"&gt;1. Project Overview&lt;/h2&gt;
&lt;p&gt;This program is a simple console-based (terminal) chatroom that allows a single server and multiple clients to chat in real-time over the TCP/IP protocol.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Technologies&lt;/strong&gt;: C Language, TCP/IP Socket Programming, pthread (Multithreading)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Core Features&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Server: Manages multiple client connections simultaneously.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Broadcasting: Transmits a message from one client to all other connected clients (except the sender).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Multi-Chat: Allows multiple users to send and receive messages at the same time.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="2-core-architecture-how-concurrency-is-achieved"&gt;2. Core Architecture: How Concurrency is Achieved&lt;/h2&gt;
&lt;p&gt;The core challenge of a chat program is handling multiple requests simultaneously. Functions like accept(), recv(), and fgets() are blocking by default. This means the entire program pauses and waits for an operation to complete before moving on.&lt;/p&gt;
&lt;p&gt;I used multithreading to solve this problem.&lt;/p&gt;
&lt;p&gt;⚙️ &lt;strong&gt;Server: Thread-per-Client Model&lt;/strong&gt;
The server needs to handle connection requests and receive messages from multiple clients at the same time.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The main thread waits for new client connections using the accept() function.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When a new client connects, it calls pthread_create() to create a new, dedicated thread (client_chat) just for that client.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This dedicated thread waits for messages from its client using the recv() function.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The main thread immediately loops back to accept() to wait for the next client.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In effect, the &amp;ldquo;connection handling&amp;rdquo; thread (main) and the &amp;ldquo;per-client message receiving&amp;rdquo; threads all run independently and concurrently.&lt;/p&gt;
&lt;p&gt;When a thread receives a message, it calls the send_msg function, which iterates through the clientList to broadcast the message to all other clients.&lt;/p&gt;
&lt;p&gt;💻 &lt;strong&gt;Client: Separation of Sending and Receiving Threads The client has its own major&lt;/strong&gt;
challenge: it must be able to receive messages from others in real-time, even while the user is typing their own message.&lt;/p&gt;
&lt;p&gt;If it were single-threaded, the program would block on fgets() (waiting for user input), making it impossible to call recv() and receive incoming messages.&lt;/p&gt;
&lt;p&gt;To solve this problem, the client program is also split into two threads:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Main Thread (main function): This thread is dedicated only to the &amp;ldquo;sending&amp;rdquo; role. It waits for the user&amp;rsquo;s keyboard input (fgets) and sends (send) the message to the server.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Receiving Thread (receive function): Created with pthread_create(), this thread is dedicated only to the &amp;ldquo;receiving&amp;rdquo; role. It blocks on recv(), waiting for messages to arrive from the server.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;By splitting the roles this way, the receive thread can display incoming messages from the server in real-time, even while the user is busy typing a new message in the main thread.&lt;/p&gt;
&lt;p&gt;You can check out the code via the link(s) attached above!&lt;/p&gt;</description></item></channel></rss>